I will add commit message and fix missing space before comment. On 11/21/2016 02:58 PM, Hans Verkuil wrote: > Same here: no commit message. > > On 18/11/16 12:25, Hugues Fruchet wrote: >> Signed-off-by: Hugues Fruchet <hugues.fruchet@xxxxxx> >> --- >> drivers/media/platform/sti/delta/delta-v4l2.c | 143 +++++++++++++++++++++++++- >> drivers/media/platform/sti/delta/delta.h | 23 +++++ >> 2 files changed, 165 insertions(+), 1 deletion(-) >> >> diff --git a/drivers/media/platform/sti/delta/delta-v4l2.c b/drivers/media/platform/sti/delta/delta-v4l2.c >> index a155883..c076849 100644 >> --- a/drivers/media/platform/sti/delta/delta-v4l2.c >> +++ b/drivers/media/platform/sti/delta/delta-v4l2.c >> @@ -106,7 +106,8 @@ static void delta_frame_done(struct delta_ctx *ctx, struct delta_frame *frame, >> vbuf->sequence = ctx->frame_num++; >> v4l2_m2m_buf_done(vbuf, err ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE); >> >> - ctx->output_frames++; >> + if (frame->info.size)/* ignore EOS */ > > Add space before '/*' > >> + ctx->output_frames++; >> } >> >> static void requeue_free_frames(struct delta_ctx *ctx) >> @@ -774,6 +775,132 @@ static int delta_s_selection(struct file *file, void *fh, >> return delta_g_selection(file, fh, s); >> } >> >> +static void delta_complete_eos(struct delta_ctx *ctx, >> + struct delta_frame *frame) >> +{ >> + struct delta_dev *delta = ctx->dev; >> + const struct v4l2_event ev = {.type = V4L2_EVENT_EOS}; >> + >> + /* Send EOS to user: >> + * - by returning an empty frame flagged to V4L2_BUF_FLAG_LAST >> + * - and then send EOS event >> + */ >> + >> + /* empty frame */ >> + frame->info.size = 0; >> + >> + /* set the last buffer flag */ >> + frame->flags |= V4L2_BUF_FLAG_LAST; >> + >> + /* release frame to user */ >> + delta_frame_done(ctx, frame, 0); >> + >> + /* send EOS event */ >> + v4l2_event_queue_fh(&ctx->fh, &ev); >> + >> + dev_dbg(delta->dev, "%s EOS completed\n", ctx->name); >> +} >> + >> +static int delta_try_decoder_cmd(struct file *file, void *fh, >> + struct v4l2_decoder_cmd *cmd) >> +{ >> + if (cmd->cmd != V4L2_DEC_CMD_STOP) >> + return -EINVAL; >> + >> + if (cmd->flags & V4L2_DEC_CMD_STOP_TO_BLACK) >> + return -EINVAL; >> + >> + if (!(cmd->flags & V4L2_DEC_CMD_STOP_IMMEDIATELY) && >> + (cmd->stop.pts != 0)) >> + return -EINVAL; >> + >> + return 0; >> +} >> + >> +static int delta_decoder_stop_cmd(struct delta_ctx *ctx, void *fh) >> +{ >> + const struct delta_dec *dec = ctx->dec; >> + struct delta_dev *delta = ctx->dev; >> + struct delta_frame *frame = NULL; >> + int ret = 0; >> + >> + dev_dbg(delta->dev, "%s EOS received\n", ctx->name); >> + >> + if (ctx->state != DELTA_STATE_READY) >> + return 0; >> + >> + /* drain the decoder */ >> + call_dec_op(dec, drain, ctx); >> + >> + /* release to user drained frames */ >> + while (1) { >> + frame = NULL; >> + ret = call_dec_op(dec, get_frame, ctx, &frame); >> + if (ret == -ENODATA) { >> + /* no more decoded frames */ >> + break; >> + } >> + if (frame) { >> + dev_dbg(delta->dev, "%s drain frame[%d]\n", >> + ctx->name, frame->index); >> + >> + /* pop timestamp and mark frame with it */ >> + delta_pop_dts(ctx, &frame->dts); >> + >> + /* release decoded frame to user */ >> + delta_frame_done(ctx, frame, 0); >> + } >> + } >> + >> + /* try to complete EOS */ >> + ret = delta_get_free_frame(ctx, &frame); >> + if (ret) >> + goto delay_eos; >> + >> + /* new frame available, EOS can now be completed */ >> + delta_complete_eos(ctx, frame); >> + >> + ctx->state = DELTA_STATE_EOS; >> + >> + return 0; >> + >> +delay_eos: >> + /* EOS completion from driver is delayed because >> + * we don't have a free empty frame available. >> + * EOS completion is so delayed till next frame_queue() call >> + * to be sure to have a free empty frame available. >> + */ >> + ctx->state = DELTA_STATE_WF_EOS; >> + dev_dbg(delta->dev, "%s EOS delayed\n", ctx->name); >> + >> + return 0; >> +} >> + >> +int delta_decoder_cmd(struct file *file, void *fh, struct v4l2_decoder_cmd *cmd) >> +{ >> + struct delta_ctx *ctx = to_ctx(fh); >> + int ret = 0; >> + >> + ret = delta_try_decoder_cmd(file, fh, cmd); >> + if (ret) >> + return ret; >> + >> + return delta_decoder_stop_cmd(ctx, fh); >> +} >> + >> +static int delta_subscribe_event(struct v4l2_fh *fh, >> + const struct v4l2_event_subscription *sub) >> +{ >> + switch (sub->type) { >> + case V4L2_EVENT_EOS: >> + return v4l2_event_subscribe(fh, sub, 2, NULL); >> + default: >> + return -EINVAL; >> + } >> + >> + return 0; >> +} >> + >> /* v4l2 ioctl ops */ >> static const struct v4l2_ioctl_ops delta_ioctl_ops = { >> .vidioc_querycap = delta_querycap, >> @@ -795,6 +922,10 @@ static int delta_s_selection(struct file *file, void *fh, >> .vidioc_streamoff = v4l2_m2m_ioctl_streamoff, >> .vidioc_g_selection = delta_g_selection, >> .vidioc_s_selection = delta_s_selection, >> + .vidioc_try_decoder_cmd = delta_try_decoder_cmd, >> + .vidioc_decoder_cmd = delta_decoder_cmd, >> + .vidioc_subscribe_event = delta_subscribe_event, >> + .vidioc_unsubscribe_event = v4l2_event_unsubscribe, >> }; >> >> /* >> @@ -1381,6 +1512,16 @@ static void delta_vb2_frame_queue(struct vb2_buffer *vb) >> struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); >> struct delta_frame *frame = to_frame(vbuf); >> >> + if (ctx->state == DELTA_STATE_WF_EOS) { >> + /* new frame available, EOS can now be completed */ >> + delta_complete_eos(ctx, frame); >> + >> + ctx->state = DELTA_STATE_EOS; >> + >> + /* return, no need to recycle this buffer to decoder */ >> + return; >> + } >> + >> /* recycle this frame */ >> delta_recycle(ctx, frame); >> } >> diff --git a/drivers/media/platform/sti/delta/delta.h b/drivers/media/platform/sti/delta/delta.h >> index 076e0fc..c8a315b 100644 >> --- a/drivers/media/platform/sti/delta/delta.h >> +++ b/drivers/media/platform/sti/delta/delta.h >> @@ -27,11 +27,19 @@ >> *@DELTA_STATE_READY: >> * Decoding instance is ready to decode compressed access unit. >> * >> + *@DELTA_STATE_WF_EOS: >> + * Decoding instance is waiting for EOS (End Of Stream) completion. >> + * >> + *@DELTA_STATE_EOS: >> + * EOS (End Of Stream) is completed (signaled to user). Decoding instance >> + * should then be closed. >> */ >> enum delta_state { >> DELTA_STATE_WF_FORMAT, >> DELTA_STATE_WF_STREAMINFO, >> DELTA_STATE_READY, >> + DELTA_STATE_WF_EOS, >> + DELTA_STATE_EOS >> }; >> >> /* >> @@ -237,6 +245,7 @@ struct delta_ipc_param { >> * @get_frame: get the next decoded frame available, see below >> * @recycle: recycle the given frame, see below >> * @flush: (optional) flush decoder, see below >> + * @drain: (optional) drain decoder, see below >> */ >> struct delta_dec { >> const char *name; >> @@ -371,6 +380,18 @@ struct delta_dec { >> * decoding logic. >> */ >> void (*flush)(struct delta_ctx *ctx); >> + >> + /* >> + * drain() - drain decoder >> + * @ctx: (in) instance >> + * >> + * Optional. >> + * Mark decoder pending frames (decoded but not yet output) as ready >> + * so that they can be output to client at EOS (End Of Stream). >> + * get_frame() is to be called in a loop right after drain() to >> + * get all those pending frames. >> + */ >> + void (*drain)(struct delta_ctx *ctx); >> }; >> >> struct delta_dev; >> @@ -497,6 +518,8 @@ static inline char *frame_type_str(u32 flags) >> return "P"; >> if (flags & V4L2_BUF_FLAG_BFRAME) >> return "B"; >> + if (flags & V4L2_BUF_FLAG_LAST) >> + return "EOS"; >> return "?"; >> } >> >> > > Regards, > > Hans >-- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html