From: Nuo Mi <nuomi2021@gmail.com> To: ffmpeg-devel@ffmpeg.org Cc: Frank Plowman <post@frankplowman.com>, Nuo Mi <nuomi2021@gmail.com> Subject: [FFmpeg-devel] [PATCH] avcodec/vvcdec: ff_vvc_frame_submit, avoid initializing task twice. Date: Sun, 21 Apr 2024 22:52:27 +0800 Message-ID: <TYSPR06MB6433019CEB35172181653C0DAA132@TYSPR06MB6433.apcprd06.prod.outlook.com> (raw) For some error bitstreams, a CTU belongs to two slices/entry points. If the decoder initializes and submmits the CTU task twice, it may crash the program or cause it to enter an infinite loop. Reported-by: Frank Plowman <post@frankplowman.com> --- libavcodec/vvc/dec.c | 7 +++++-- libavcodec/vvc/thread.c | 43 ++++++++++++++++++++++++++++------------- libavcodec/vvc/thread.h | 2 +- 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/libavcodec/vvc/dec.c b/libavcodec/vvc/dec.c index 6aeec27eaf..4f7d184e43 100644 --- a/libavcodec/vvc/dec.c +++ b/libavcodec/vvc/dec.c @@ -893,10 +893,13 @@ static int wait_delayed_frame(VVCContext *s, AVFrame *output, int *got_output) static int submit_frame(VVCContext *s, VVCFrameContext *fc, AVFrame *output, int *got_output) { - int ret; + int ret = ff_vvc_frame_submit(s, fc); + if (ret < 0) + return ret; + s->nb_frames++; s->nb_delayed++; - ff_vvc_frame_submit(s, fc); + if (s->nb_delayed >= s->nb_fcs) { if ((ret = wait_delayed_frame(s, output, got_output)) < 0) return ret; diff --git a/libavcodec/vvc/thread.c b/libavcodec/vvc/thread.c index 01c3ff75b1..3b27811db2 100644 --- a/libavcodec/vvc/thread.c +++ b/libavcodec/vvc/thread.c @@ -124,11 +124,17 @@ static void task_init(VVCTask *t, VVCTaskStage stage, VVCFrameContext *fc, const atomic_store(&t->target_inter_score, 0); } -static void task_init_parse(VVCTask *t, SliceContext *sc, EntryPoint *ep, const int ctu_idx) +static int task_init_parse(VVCTask *t, SliceContext *sc, EntryPoint *ep, const int ctu_idx) { + if (t->sc) { + // the task already inited, error bitstream + return AVERROR_INVALIDDATA; + } t->sc = sc; t->ep = ep; t->ctu_idx = ctu_idx; + + return 0; } static uint8_t task_add_score(VVCTask *t, const VVCTaskStage stage) @@ -758,24 +764,35 @@ static void submit_entry_point(VVCContext *s, VVCFrameThread *ft, SliceContext * frame_thread_add_score(s, ft, t->rx, t->ry, VVC_TASK_STAGE_PARSE); } -void ff_vvc_frame_submit(VVCContext *s, VVCFrameContext *fc) +int ff_vvc_frame_submit(VVCContext *s, VVCFrameContext *fc) { VVCFrameThread *ft = fc->ft; - for (int i = 0; i < fc->nb_slices; i++) { - SliceContext *sc = fc->slices[i]; - for (int j = 0; j < sc->nb_eps; j++) { - EntryPoint *ep = sc->eps + j; - for (int k = ep->ctu_start; k < ep->ctu_end; k++) { - const int rs = sc->sh.ctb_addr_in_curr_slice[k]; - VVCTask *t = ft->tasks + rs; - - task_init_parse(t, sc, ep, k); - check_colocation(s, t); + // We'll handle this in two passes: + // Pass 0 to initialize tasks with parser, this will help detect bit stream error + // Pass 1 to shedule location check and submit the entry point + for (int pass = 0; pass < 2; pass++) { + for (int i = 0; i < fc->nb_slices; i++) { + SliceContext *sc = fc->slices[i]; + for (int j = 0; j < sc->nb_eps; j++) { + EntryPoint *ep = sc->eps + j; + for (int k = ep->ctu_start; k < ep->ctu_end; k++) { + const int rs = sc->sh.ctb_addr_in_curr_slice[k]; + VVCTask *t = ft->tasks + rs; + if (pass) { + check_colocation(s, t); + } else { + const int ret = task_init_parse(t, sc, ep, k); + if (ret < 0) + return ret; + } + } + if (pass) + submit_entry_point(s, ft, sc, ep); } - submit_entry_point(s, ft, sc, ep); } } + return 0; } int ff_vvc_frame_wait(VVCContext *s, VVCFrameContext *fc) diff --git a/libavcodec/vvc/thread.h b/libavcodec/vvc/thread.h index 55bb4ea244..8ac59b2ecf 100644 --- a/libavcodec/vvc/thread.h +++ b/libavcodec/vvc/thread.h @@ -30,7 +30,7 @@ void ff_vvc_executor_free(struct AVExecutor **e); int ff_vvc_frame_thread_init(VVCFrameContext *fc); void ff_vvc_frame_thread_free(VVCFrameContext *fc); -void ff_vvc_frame_submit(VVCContext *s, VVCFrameContext *fc); +int ff_vvc_frame_submit(VVCContext *s, VVCFrameContext *fc); int ff_vvc_frame_wait(VVCContext *s, VVCFrameContext *fc); #endif // AVCODEC_VVC_THREAD_H -- 2.34.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".
next reply other threads:[~2024-04-21 14:53 UTC|newest] Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top 2024-04-21 14:52 Nuo Mi [this message] 2024-04-21 16:34 ` Frank Plowman 2024-04-25 14:05 ` Nuo Mi
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=TYSPR06MB6433019CEB35172181653C0DAA132@TYSPR06MB6433.apcprd06.prod.outlook.com \ --to=nuomi2021@gmail.com \ --cc=ffmpeg-devel@ffmpeg.org \ --cc=post@frankplowman.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