The branch, master has been updated
       via  3ef2ea890bcd4ea98469b01a77dbb5d9b3848942 (commit)
       via  084b67f6e3f1495732579ca7f9008cf98c3f38fe (commit)
       via  4b39d776c39f3a049932c8be0d46f48a4a3a0a7c (commit)
      from  0469d68acb52081ca8385b844b9650398242be0f (commit)


- Log -----------------------------------------------------------------
commit 3ef2ea890bcd4ea98469b01a77dbb5d9b3848942
Author:     James Almer <jamr...@gmail.com>
AuthorDate: Mon Aug 11 19:43:33 2025 -0300
Commit:     James Almer <jamr...@gmail.com>
CommitDate: Tue Aug 12 19:59:21 2025 +0000

    avcodec/apv_decode: set decoder as skip frame fill param capable
    
    No need to decode potentially huge frames just to get stream params.
    
    Signed-off-by: James Almer <jamr...@gmail.com>

diff --git a/libavcodec/apv_decode.c b/libavcodec/apv_decode.c
index f477cd37f3..27aaf7aac7 100644
--- a/libavcodec/apv_decode.c
+++ b/libavcodec/apv_decode.c
@@ -361,6 +361,9 @@ static int apv_decode(AVCodecContext *avctx, AVFrame 
*output,
         return err;
     }
 
+    if (avctx->skip_frame == AVDISCARD_ALL)
+        return 0;
+
     desc = av_pix_fmt_desc_get(avctx->pix_fmt);
     av_assert0(desc);
 
@@ -564,4 +567,5 @@ const FFCodec ff_apv_decoder = {
     .p.capabilities        = AV_CODEC_CAP_DR1 |
                              AV_CODEC_CAP_SLICE_THREADS |
                              AV_CODEC_CAP_FRAME_THREADS,
+    .caps_internal         = FF_CODEC_CAP_SKIP_FRAME_FILL_PARAM,
 };

commit 084b67f6e3f1495732579ca7f9008cf98c3f38fe
Author:     James Almer <jamr...@gmail.com>
AuthorDate: Mon Aug 11 19:01:03 2025 -0300
Commit:     James Almer <jamr...@gmail.com>
CommitDate: Tue Aug 12 19:59:21 2025 +0000

    avcodec/apv: port to the receive_frame() API
    
    You can technically feed the decoder a single packet with more than one AU 
in
    it, even if a demuxer is unlikely to ever export such a thing.
    Given the parser does no packetization to ensure we get a single AU, in 
order
    to not discard any frame beyond the first, the decoupled input/output API
    should be used.
    
    Signed-off-by: James Almer <jamr...@gmail.com>

diff --git a/libavcodec/apv_decode.c b/libavcodec/apv_decode.c
index dd8a07e24f..f477cd37f3 100644
--- a/libavcodec/apv_decode.c
+++ b/libavcodec/apv_decode.c
@@ -52,9 +52,12 @@ typedef struct APVDecodeContext {
     CodedBitstreamFragment au;
     APVDerivedTileInfo tile_info;
 
+    AVPacket *pkt;
     AVFrame *output_frame;
     atomic_int tile_errors;
 
+    int nb_unit;
+
     uint8_t warned_additional_frames;
     uint8_t warned_unknown_pbu_types;
 } APVDecodeContext;
@@ -145,6 +148,7 @@ static av_cold int apv_decode_init(AVCodecContext *avctx)
 
     // Extradata could be set here, but is ignored by the decoder.
 
+    apv->pkt = avctx->internal->in_pkt;
     ff_apv_dsp_init(&apv->dsp);
 
     atomic_init(&apv->tile_errors, 0);
@@ -152,6 +156,16 @@ static av_cold int apv_decode_init(AVCodecContext *avctx)
     return 0;
 }
 
+static void apv_decode_flush(AVCodecContext *avctx)
+{
+    APVDecodeContext *apv = avctx->priv_data;
+
+    apv->nb_unit = 0;
+    av_packet_unref(apv->pkt);
+    ff_cbs_fragment_reset(&apv->au);
+    ff_cbs_flush(apv->cbc);
+}
+
 static av_cold int apv_decode_close(AVCodecContext *avctx)
 {
     APVDecodeContext *apv = avctx->priv_data;
@@ -446,29 +460,20 @@ static int apv_decode_metadata(AVCodecContext *avctx, 
AVFrame *frame,
     return 0;
 }
 
-static int apv_decode_frame(AVCodecContext *avctx, AVFrame *frame,
-                            int *got_frame, AVPacket *packet)
+static int apv_receive_frame_internal(AVCodecContext *avctx, AVFrame *frame)
 {
     APVDecodeContext      *apv = avctx->priv_data;
     CodedBitstreamFragment *au = &apv->au;
-    int err;
+    int i, err;
 
-    err = ff_cbs_read_packet(apv->cbc, au, packet);
-    if (err < 0) {
-        av_log(avctx, AV_LOG_ERROR, "Failed to read packet.\n");
-        goto fail;
-    }
-
-    for (int i = 0; i < au->nb_units; i++) {
+    for (i = apv->nb_unit; i < au->nb_units; i++) {
         CodedBitstreamUnit *pbu = &au->units[i];
 
         switch (pbu->type) {
         case APV_PBU_PRIMARY_FRAME:
             err = apv_decode(avctx, frame, pbu->content);
-            if (err < 0)
-                goto fail;
-            *got_frame = 1;
-            break;
+            i++;
+            goto end;
         case APV_PBU_METADATA:
             apv_decode_metadata(avctx, frame, pbu->content);
             break;
@@ -500,9 +505,49 @@ static int apv_decode_frame(AVCodecContext *avctx, AVFrame 
*frame,
         }
     }
 
-    err = packet->size;
-fail:
-    ff_cbs_fragment_reset(au);
+    err = AVERROR(EAGAIN);
+end:
+    av_assert0(i <= apv->au.nb_units);
+    apv->nb_unit = i;
+
+    if ((err < 0 && err != AVERROR(EAGAIN)) || apv->au.nb_units == i) {
+        av_packet_unref(apv->pkt);
+        ff_cbs_fragment_reset(&apv->au);
+        apv->nb_unit = 0;
+    }
+    if (!err && !frame->buf[0])
+        err = AVERROR(EAGAIN);
+
+    return err;
+}
+
+static int apv_receive_frame(AVCodecContext *avctx, AVFrame *frame)
+{
+    APVDecodeContext *apv = avctx->priv_data;
+    int err;
+
+    do {
+        if (!apv->au.nb_units) {
+            err = ff_decode_get_packet(avctx, apv->pkt);
+            if (err < 0)
+                return err;
+
+            err = ff_cbs_read_packet(apv->cbc, &apv->au, apv->pkt);
+            if (err < 0) {
+                ff_cbs_fragment_reset(&apv->au);
+                av_packet_unref(apv->pkt);
+                av_log(avctx, AV_LOG_ERROR, "Failed to read packet.\n");
+                return err;
+            }
+
+            apv->nb_unit = 0;
+            av_log(avctx, AV_LOG_DEBUG, "Total PBUs on this packet: %d.\n",
+                   apv->au.nb_units);
+        }
+
+        err = apv_receive_frame_internal(avctx, frame);
+    } while (err == AVERROR(EAGAIN));
+
     return err;
 }
 
@@ -513,8 +558,9 @@ const FFCodec ff_apv_decoder = {
     .p.id                  = AV_CODEC_ID_APV,
     .priv_data_size        = sizeof(APVDecodeContext),
     .init                  = apv_decode_init,
+    .flush                 = apv_decode_flush,
     .close                 = apv_decode_close,
-    FF_CODEC_DECODE_CB(apv_decode_frame),
+    FF_CODEC_RECEIVE_FRAME_CB(apv_receive_frame),
     .p.capabilities        = AV_CODEC_CAP_DR1 |
                              AV_CODEC_CAP_SLICE_THREADS |
                              AV_CODEC_CAP_FRAME_THREADS,

commit 4b39d776c39f3a049932c8be0d46f48a4a3a0a7c
Author:     James Almer <jamr...@gmail.com>
AuthorDate: Sun Aug 10 13:44:31 2025 -0300
Commit:     James Almer <jamr...@gmail.com>
CommitDate: Tue Aug 12 19:59:21 2025 +0000

    avcodec/cbs_apv: store derived tile information in a per frame basis
    
    If a single fragment contains more than one frame unit, the tile 
information stored
    in the private context will only correspond to one of them.
    
    Fixes: crash (out of array access)
    Fixes: 
435489659/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_APV_fuzzer-6194885205229568
    
    Found-by: continuous fuzzing process 
https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg
    Signed-off-by: James Almer <jamr...@gmail.com>

diff --git a/libavcodec/apv_decode.c b/libavcodec/apv_decode.c
index 330d4980c0..dd8a07e24f 100644
--- a/libavcodec/apv_decode.c
+++ b/libavcodec/apv_decode.c
@@ -35,6 +35,16 @@
 #include "thread.h"
 
 
+typedef struct APVDerivedTileInfo {
+    uint8_t  tile_cols;
+    uint8_t  tile_rows;
+    uint16_t num_tiles;
+    // The spec uses an extra element on the end of these arrays
+    // not corresponding to any tile.
+    uint16_t col_starts[APV_MAX_TILE_COLS + 1];
+    uint16_t row_starts[APV_MAX_TILE_ROWS + 1];
+} APVDerivedTileInfo;
+
 typedef struct APVDecodeContext {
     CodedBitstreamContext *cbc;
     APVDSPContext dsp;
@@ -184,7 +194,7 @@ static int apv_decode_tile_component(AVCodecContext *avctx, 
void *data,
     APVRawFrame                      *input = data;
     APVDecodeContext                   *apv = avctx->priv_data;
     const CodedBitstreamAPVContext *apv_cbc = apv->cbc->priv_data;
-    const APVDerivedTileInfo     *tile_info = &apv_cbc->tile_info;
+    const APVDerivedTileInfo     *tile_info = &apv->tile_info;
 
     int tile_index = job / apv_cbc->num_comp;
     int comp_index = job % apv_cbc->num_comp;
@@ -297,12 +307,38 @@ fail:
     return err;
 }
 
+static void apv_derive_tile_info(APVDerivedTileInfo *ti,
+                                 const APVRawFrameHeader *fh)
+{
+    int frame_width_in_mbs  = (fh->frame_info.frame_width  + (APV_MB_WIDTH  - 
1)) >> 4;
+    int frame_height_in_mbs = (fh->frame_info.frame_height + (APV_MB_HEIGHT - 
1)) >> 4;
+    int start_mb, i;
+
+    start_mb = 0;
+    for (i = 0; start_mb < frame_width_in_mbs; i++) {
+        ti->col_starts[i] = start_mb * APV_MB_WIDTH;
+        start_mb += fh->tile_info.tile_width_in_mbs;
+    }
+    ti->col_starts[i] = frame_width_in_mbs * APV_MB_WIDTH;
+    ti->tile_cols = i;
+
+    start_mb = 0;
+    for (i = 0; start_mb < frame_height_in_mbs; i++) {
+        ti->row_starts[i] = start_mb * APV_MB_HEIGHT;
+        start_mb += fh->tile_info.tile_height_in_mbs;
+    }
+    ti->row_starts[i] = frame_height_in_mbs * APV_MB_HEIGHT;
+    ti->tile_rows = i;
+
+    ti->num_tiles = ti->tile_cols * ti->tile_rows;
+}
+
 static int apv_decode(AVCodecContext *avctx, AVFrame *output,
                       APVRawFrame *input)
 {
     APVDecodeContext                   *apv = avctx->priv_data;
-    const CodedBitstreamAPVContext *apv_cbc = apv->cbc->priv_data;
-    const APVDerivedTileInfo     *tile_info = &apv_cbc->tile_info;
+    const AVPixFmtDescriptor          *desc = NULL;
+    APVDerivedTileInfo           *tile_info = &apv->tile_info;
     int err, job_count;
 
     err = apv_decode_check_format(avctx, &input->frame_header);
@@ -311,6 +347,9 @@ static int apv_decode(AVCodecContext *avctx, AVFrame 
*output,
         return err;
     }
 
+    desc = av_pix_fmt_desc_get(avctx->pix_fmt);
+    av_assert0(desc);
+
     err = ff_thread_get_buffer(avctx, output, 0);
     if (err < 0)
         return err;
@@ -318,9 +357,11 @@ static int apv_decode(AVCodecContext *avctx, AVFrame 
*output,
     apv->output_frame = output;
     atomic_store_explicit(&apv->tile_errors, 0, memory_order_relaxed);
 
+    apv_derive_tile_info(tile_info, &input->frame_header);
+
     // Each component within a tile is independent of every other,
     // so we can decode all in parallel.
-    job_count = tile_info->num_tiles * apv_cbc->num_comp;
+    job_count = tile_info->num_tiles * desc->nb_components;
 
     avctx->execute2(avctx, apv_decode_tile_component,
                     input, NULL, job_count);
diff --git a/libavcodec/cbs_apv.c b/libavcodec/cbs_apv.c
index 5239cd1269..fdc9042939 100644
--- a/libavcodec/cbs_apv.c
+++ b/libavcodec/cbs_apv.c
@@ -37,33 +37,18 @@ static int cbs_apv_get_num_comp(const APVRawFrameHeader *fh)
     }
 }
 
-static void cbs_apv_derive_tile_info(APVDerivedTileInfo *ti,
+static void cbs_apv_derive_tile_info(CodedBitstreamContext *ctx,
                                      const APVRawFrameHeader *fh)
 {
+    CodedBitstreamAPVContext *priv = ctx->priv_data;
     int frame_width_in_mbs   = (fh->frame_info.frame_width  + 15) / 16;
     int frame_height_in_mbs  = (fh->frame_info.frame_height + 15) / 16;
-    int start_mb, i;
+    int tile_cols = (frame_width_in_mbs  + fh->tile_info.tile_width_in_mbs - 
1)  / fh->tile_info.tile_width_in_mbs;
+    int tile_rows = (frame_height_in_mbs + fh->tile_info.tile_height_in_mbs - 
1) / fh->tile_info.tile_height_in_mbs;
 
-    start_mb = 0;
-    for (i = 0; start_mb < frame_width_in_mbs; i++) {
-        ti->col_starts[i] = start_mb * APV_MB_WIDTH;
-        start_mb += fh->tile_info.tile_width_in_mbs;
-    }
-    av_assert0(i <= APV_MAX_TILE_COLS);
-    ti->col_starts[i] = frame_width_in_mbs * APV_MB_WIDTH;
-    ti->tile_cols = i;
-
-    start_mb = 0;
-    for (i = 0; start_mb < frame_height_in_mbs; i++) {
-        av_assert0(i < APV_MAX_TILE_ROWS);
-        ti->row_starts[i] = start_mb * APV_MB_HEIGHT;
-        start_mb += fh->tile_info.tile_height_in_mbs;
-    }
-    av_assert0(i <= APV_MAX_TILE_ROWS);
-    ti->row_starts[i] = frame_height_in_mbs * APV_MB_HEIGHT;
-    ti->tile_rows = i;
+    av_assert0(tile_cols <= APV_MAX_TILE_COLS && tile_rows <= 
APV_MAX_TILE_ROWS);
 
-    ti->num_tiles = ti->tile_cols * ti->tile_rows;
+    priv->num_tiles = tile_cols * tile_rows;
 }
 
 
diff --git a/libavcodec/cbs_apv.h b/libavcodec/cbs_apv.h
index cbaeb45acb..d91372e644 100644
--- a/libavcodec/cbs_apv.h
+++ b/libavcodec/cbs_apv.h
@@ -187,21 +187,11 @@ typedef struct APVRawMetadata {
 } APVRawMetadata;
 
 
-typedef struct APVDerivedTileInfo {
-    uint8_t  tile_cols;
-    uint8_t  tile_rows;
-    uint16_t num_tiles;
-    // The spec uses an extra element on the end of these arrays
-    // not corresponding to any tile.
-    uint16_t col_starts[APV_MAX_TILE_COLS + 1];
-    uint16_t row_starts[APV_MAX_TILE_ROWS + 1];
-} APVDerivedTileInfo;
-
 typedef struct CodedBitstreamAPVContext {
     int bit_depth;
     int num_comp;
 
-    APVDerivedTileInfo tile_info;
+    uint16_t num_tiles;
 } CodedBitstreamAPVContext;
 
 #endif /* AVCODEC_CBS_APV_H */
diff --git a/libavcodec/cbs_apv_syntax_template.c 
b/libavcodec/cbs_apv_syntax_template.c
index b84565b107..621595ffbf 100644
--- a/libavcodec/cbs_apv_syntax_template.c
+++ b/libavcodec/cbs_apv_syntax_template.c
@@ -128,10 +128,10 @@ static int FUNC(tile_info)(CodedBitstreamContext *ctx, 
RWContext *rw,
 
     ub(1, tile_size_present_in_fh_flag);
 
-    cbs_apv_derive_tile_info(&priv->tile_info, fh);
+    cbs_apv_derive_tile_info(ctx, fh);
 
     if (current->tile_size_present_in_fh_flag) {
-        for (int t = 0; t < priv->tile_info.num_tiles; t++) {
+        for (int t = 0; t < priv->num_tiles; t++) {
             us(32, tile_size_in_fh[t], 10, MAX_UINT_BITS(32), 1, t);
         }
     }
@@ -262,7 +262,7 @@ static int FUNC(frame)(CodedBitstreamContext *ctx, 
RWContext *rw,
 
     CHECK(FUNC(frame_header)(ctx, rw, &current->frame_header));
 
-    for (int t = 0; t < priv->tile_info.num_tiles; t++) {
+    for (int t = 0; t < priv->num_tiles; t++) {
         us(32, tile_size[t], 10, MAX_UINT_BITS(32), 1, t);
 
         CHECK(FUNC(tile)(ctx, rw, &current->tile[t],

-----------------------------------------------------------------------

Summary of changes:
 libavcodec/apv_decode.c              | 135 +++++++++++++++++++++++++++++------
 libavcodec/cbs_apv.c                 |  27 ++-----
 libavcodec/cbs_apv.h                 |  12 +---
 libavcodec/cbs_apv_syntax_template.c |   6 +-
 4 files changed, 123 insertions(+), 57 deletions(-)


hooks/post-receive
-- 

_______________________________________________
ffmpeg-cvslog mailing list
ffmpeg-cvslog@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-cvslog

To unsubscribe, visit link above, or email
ffmpeg-cvslog-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to