From: Hsia-Jun Li <Randy.Li@synaptics.com> To: ffmpeg-devel@ffmpeg.org Cc: jramirez@baylibre.com Subject: [FFmpeg-devel] [PATCH] avcodec/v4l2_m2m_dec: resolve resolution change Date: Fri, 30 Jun 2023 11:04:07 +0800 Message-ID: <5d1fc70a-675a-0d18-87be-e6e00a8fc607@synaptics.com> (raw) It shouldn't allocate buffer before the resolution change event appeared in decoder setup. And it should not apply to new resolution before the buffer from the previous sequence is dequeued. Change-Id: Id04550b0f17e1501b670a3bcbdd860d5836259bf Signed-off-by: Hsia-Jun(Randy) Li<randy.li@synaptics.com> --- libavcodec/v4l2_context.c | 89 ++++++++++++++++++++++++++------------- libavcodec/v4l2_context.h | 6 +++ libavcodec/v4l2_m2m_dec.c | 14 +++--- 3 files changed, 73 insertions(+), 36 deletions(-) diff --git a/libavcodec/v4l2_context.c b/libavcodec/v4l2_context.c index a40be94690..87771601a9 100644 --- a/libavcodec/v4l2_context.c +++ b/libavcodec/v4l2_context.c @@ -169,30 +169,17 @@ static int v4l2_start_decode(V4L2Context *ctx) } /** - * handle resolution change event and end of stream event + * handle resolution change event * returns 1 if reinit was successful, negative if it failed * returns 0 if reinit was not executed */ -static int v4l2_handle_event(V4L2Context *ctx) +static int v4l2_handle_dyn_res_change(V4L2Context *ctx) { V4L2m2mContext *s = ctx_to_m2mctx(ctx); struct v4l2_format cap_fmt = s->capture.format; - struct v4l2_event evt = { 0 }; int ret; - ret = ioctl(s->fd, VIDIOC_DQEVENT, &evt); - if (ret < 0) { - av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQEVENT\n", ctx->name); - return 0; - } - - if (evt.type == V4L2_EVENT_EOS) { - ctx->done = 1; - return 0; - } - - if (evt.type != V4L2_EVENT_SOURCE_CHANGE) - return 0; + cap_fmt.type = s->capture.type; ret = ioctl(s->fd, VIDIOC_G_FMT, &cap_fmt); if (ret) { @@ -201,11 +188,13 @@ static int v4l2_handle_event(V4L2Context *ctx) } if (v4l2_resolution_changed(&s->capture, &cap_fmt)) { + s->capture.format.fmt.pix_mp.pixelformat = cap_fmt.fmt.pix_mp.pixelformat; s->capture.height = v4l2_get_height(&cap_fmt); s->capture.width = v4l2_get_width(&cap_fmt); s->capture.sample_aspect_ratio = v4l2_get_sar(&s->capture); } else { v4l2_start_decode(ctx); + ctx->pending_res_change = 0; return 0; } @@ -222,10 +211,41 @@ static int v4l2_handle_event(V4L2Context *ctx) return AVERROR(EINVAL); } + ctx->pending_res_change = 0; /* reinit executed */ return 1; } +/** + * capture resolution change event and end of stream event + * returns 1 or negative if it failed + * returns 0 if nothing went wrong + */ +static int v4l2_handle_event(V4L2Context *ctx) +{ + V4L2m2mContext *s = ctx_to_m2mctx(ctx); + struct v4l2_event evt = { 0 }; + int ret; + + ret = ioctl(s->fd, VIDIOC_DQEVENT, &evt); + if (ret < 0) { + av_log(logger(ctx), AV_LOG_ERROR, "%s VIDIOC_DQEVENT\n", ctx->name); + return errno; + } + + if (evt.type == V4L2_EVENT_EOS) { + ctx->done = 1; + return 0; + } + + if (evt.type != V4L2_EVENT_SOURCE_CHANGE) + return AVERROR(EINVAL); + + ctx->pending_res_change = 1; + + return 0; +} + static int v4l2_stop_decode(V4L2Context *ctx) { struct v4l2_decoder_cmd cmd = { @@ -342,16 +362,19 @@ start: /* 1. handle resolution changes */ if (pfd.revents & POLLPRI) { ret = v4l2_handle_event(ctx); - if (ret < 0) { - /* if re-init failed, abort */ - ctx->done = 1; - return NULL; - } if (ret) { - /* if re-init was successful drop the buffer (if there was one) - * since we had to reconfigure capture (unmap all buffers) - */ + /* if event handler failed, abort */ + ctx->done = 1; return NULL; + } else if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) { + if (!ctx->streamon) + ret = v4l2_handle_dyn_res_change(ctx); + if (ret == 1) + return NULL; + } else { + /* Poll the device again, we want the buffer with the flag + * that answer to the event */ + return v4l2_dequeue_v4l2buf(ctx, timeout); } } @@ -391,17 +414,23 @@ dequeue: return NULL; } - if (ctx_to_m2mctx(ctx)->draining && !V4L2_TYPE_IS_OUTPUT(ctx->type)) { + if (!V4L2_TYPE_IS_OUTPUT(ctx->type)) { int bytesused = V4L2_TYPE_IS_MULTIPLANAR(buf.type) ? buf.m.planes[0].bytesused : buf.bytesused; + +#ifdef V4L2_BUF_FLAG_LAST + if (buf.flags & V4L2_BUF_FLAG_LAST) { + if (ctx_to_m2mctx(ctx)->draining) + ctx->done = 1; + if (ctx->pending_res_change) + ret = v4l2_handle_dyn_res_change(ctx); + } +#endif if (bytesused == 0) { - ctx->done = 1; + if (ctx_to_m2mctx(ctx)->draining) + ctx->done = 1; return NULL; } -#ifdef V4L2_BUF_FLAG_LAST - if (buf.flags & V4L2_BUF_FLAG_LAST) - ctx->done = 1; -#endif } avbuf = &ctx->buffers[buf.index]; diff --git a/libavcodec/v4l2_context.h b/libavcodec/v4l2_context.h index 6f7460c89a..b30457c5ad 100644 --- a/libavcodec/v4l2_context.h +++ b/libavcodec/v4l2_context.h @@ -87,6 +87,12 @@ typedef struct V4L2Context { */ int streamon; + /** + * Pending resolution change event to handle. Only context for CAPTURE + * queue could set this flag. + */ + int pending_res_change; + /** * Either no more buffers available or an unrecoverable error was notified * by the V4L2 kernel driver: once set the context has to be exited. diff --git a/libavcodec/v4l2_m2m_dec.c b/libavcodec/v4l2_m2m_dec.c index 4944d08511..3c38fde700 100644 --- a/libavcodec/v4l2_m2m_dec.c +++ b/libavcodec/v4l2_m2m_dec.c @@ -40,6 +40,7 @@ static int v4l2_try_start(AVCodecContext *avctx) V4L2Context *const capture = &s->capture; V4L2Context *const output = &s->output; struct v4l2_selection selection = { 0 }; + AVFrame frame; int ret; /* 1. start the output process */ @@ -54,15 +55,16 @@ static int v4l2_try_start(AVCodecContext *avctx) if (capture->streamon) return 0; - /* 2. get the capture format */ - capture->format.type = capture->type; - ret = ioctl(s->fd, VIDIOC_G_FMT, &capture->format); + /* TODO wait event here */ + ret = ff_v4l2_context_dequeue_frame(capture, &frame, 10); if (ret) { - av_log(avctx, AV_LOG_WARNING, "VIDIOC_G_FMT ioctl\n"); - return ret; + if (ret == AVERROR(EAGAIN)) + ret = 0; + else + return ret; } - /* 2.1 update the AVCodecContext */ + /* 2 update the AVCodecContext */ avctx->pix_fmt = ff_v4l2_format_v4l2_to_avfmt(capture->format.fmt.pix_mp.pixelformat, AV_CODEC_ID_RAWVIDEO); capture->av_pix_fmt = avctx->pix_fmt; -- 2.17.1 _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
reply other threads:[~2023-06-30 3:04 UTC|newest] Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=5d1fc70a-675a-0d18-87be-e6e00a8fc607@synaptics.com \ --to=randy.li@synaptics.com \ --cc=ffmpeg-devel@ffmpeg.org \ --cc=jramirez@baylibre.com \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: link
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel This inbox may be cloned and mirrored by anyone: git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git # If you have public-inbox 1.1+ installed, you may # initialize and index your mirror using the following commands: public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \ ffmpegdev@gitmailbox.com public-inbox-index ffmpegdev Example config snippet for mirrors. AGPL code for this site: git clone https://public-inbox.org/public-inbox.git