Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 1/2] avcodec/cbs_av1: also store a pointer to the start of the tile group data
@ 2025-03-20 17:01 James Almer
  2025-03-20 17:01 ` [FFmpeg-devel] [PATCH 2/2] avformat/movenccenc: add support for CENC AV1 encryption James Almer
  0 siblings, 1 reply; 9+ messages in thread
From: James Almer @ 2025-03-20 17:01 UTC (permalink / raw)
  To: ffmpeg-devel

This will be useful a following commit, where the offset of the Tile Group
inside a Frame OBU needs to be known.

Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavcodec/cbs_av1.c                 | 91 ++++++++++++++++++----------
 libavcodec/cbs_av1.h                 |  4 ++
 libavcodec/cbs_av1_syntax_template.c |  2 -
 3 files changed, 62 insertions(+), 35 deletions(-)

diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c
index fea079379b..54589a4065 100644
--- a/libavcodec/cbs_av1.c
+++ b/libavcodec/cbs_av1.c
@@ -782,7 +782,8 @@ fail:
 static int cbs_av1_ref_tile_data(CodedBitstreamContext *ctx,
                                  CodedBitstreamUnit *unit,
                                  GetBitContext *gbc,
-                                 AV1RawTileData *td)
+                                 AVBufferRef **data_ref,
+                                 uint8_t **data, size_t *data_size)
 {
     int pos;
 
@@ -795,12 +796,12 @@ static int cbs_av1_ref_tile_data(CodedBitstreamContext *ctx,
     // Must be byte-aligned at this point.
     av_assert0(pos % 8 == 0);
 
-    td->data_ref = av_buffer_ref(unit->data_ref);
-    if (!td->data_ref)
+    *data_ref = av_buffer_ref(unit->data_ref);
+    if (!*data_ref)
         return AVERROR(ENOMEM);
 
-    td->data      = unit->data      + pos / 8;
-    td->data_size = unit->data_size - pos / 8;
+    *data      = unit->data      + pos / 8;
+    *data_size = unit->data_size - pos / 8;
 
     return 0;
 }
@@ -901,28 +902,31 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
                 return err;
         }
         break;
-    case AV1_OBU_TILE_GROUP:
-        {
-            err = cbs_av1_read_tile_group_obu(ctx, &gbc,
-                                              &obu->obu.tile_group);
+    case AV1_OBU_FRAME:
+            err = cbs_av1_read_frame_obu(ctx, &gbc, &obu->obu.frame,
+                                         unit->data_ref);
             if (err < 0)
                 return err;
-
+    // fall-through
+    case AV1_OBU_TILE_GROUP:
+        {
+            AV1RawTileGroup *tile_group = obu->header.obu_type == AV1_OBU_FRAME ? &obu->obu.frame.tile_group
+                                                                                : &obu->obu.tile_group;
             err = cbs_av1_ref_tile_data(ctx, unit, &gbc,
-                                        &obu->obu.tile_group.tile_data);
+                                        &tile_group->data_ref,
+                                        &tile_group->data,
+                                        &tile_group->data_size);
             if (err < 0)
                 return err;
-        }
-        break;
-    case AV1_OBU_FRAME:
-        {
-            err = cbs_av1_read_frame_obu(ctx, &gbc, &obu->obu.frame,
-                                         unit->data_ref);
+
+            err = cbs_av1_read_tile_group_obu(ctx, &gbc, tile_group);
             if (err < 0)
                 return err;
 
             err = cbs_av1_ref_tile_data(ctx, unit, &gbc,
-                                        &obu->obu.frame.tile_group.tile_data);
+                                        &tile_group->tile_data.data_ref,
+                                        &tile_group->tile_data.data,
+                                        &tile_group->tile_data.data_size);
             if (err < 0)
                 return err;
         }
@@ -935,7 +939,9 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
                 return err;
 
             err = cbs_av1_ref_tile_data(ctx, unit, &gbc,
-                                        &obu->obu.tile_list.tile_data);
+                                        &obu->obu.tile_list.tile_data.data_ref,
+                                        &obu->obu.tile_list.tile_data.data,
+                                        &obu->obu.tile_list.tile_data.data_size);
             if (err < 0)
                 return err;
         }
@@ -1065,23 +1071,20 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx,
                 goto error;
         }
         break;
-    case AV1_OBU_TILE_GROUP:
-        {
-            err = cbs_av1_write_tile_group_obu(ctx, pbc,
-                                               &obu->obu.tile_group);
+    case AV1_OBU_FRAME:
+            err = cbs_av1_write_frame_obu(ctx, pbc, &obu->obu.frame, NULL);
             if (err < 0)
                 goto error;
-
-            td = &obu->obu.tile_group.tile_data;
-        }
-        break;
-    case AV1_OBU_FRAME:
+    // fall-through
+    case AV1_OBU_TILE_GROUP:
         {
-            err = cbs_av1_write_frame_obu(ctx, pbc, &obu->obu.frame, NULL);
+            AV1RawTileGroup *tile_group = obu->header.obu_type == AV1_OBU_FRAME ? &obu->obu.frame.tile_group
+                                                                                : &obu->obu.tile_group;
+            err = cbs_av1_write_tile_group_obu(ctx, pbc, tile_group);
             if (err < 0)
                 goto error;
 
-            td = &obu->obu.frame.tile_group.tile_data;
+            td = &tile_group->tile_data;
         }
         break;
     case AV1_OBU_TILE_LIST:
@@ -1258,11 +1261,33 @@ static const CodedBitstreamUnitTypeDescriptor cbs_av1_unit_types[] = {
     CBS_UNIT_TYPE_POD(AV1_OBU_TEMPORAL_DELIMITER,     AV1RawOBU),
     CBS_UNIT_TYPE_POD(AV1_OBU_FRAME_HEADER,           AV1RawOBU),
     CBS_UNIT_TYPE_POD(AV1_OBU_REDUNDANT_FRAME_HEADER, AV1RawOBU),
-
-    CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_TILE_GROUP, AV1RawOBU,
+    {
+        .nb_unit_types     = 1,
+        .unit_type.list[0] = AV1_OBU_TILE_GROUP,
+        .content_type      = CBS_CONTENT_TYPE_INTERNAL_REFS,
+        .content_size      = sizeof(AV1RawOBU),
+        .type.ref          = {
+            .nb_offsets = 2,
+            .offsets    = { offsetof(AV1RawOBU, obu.tile_group.data),
+                            offsetof(AV1RawOBU, obu.tile_group.tile_data.data) }
+        },
+    },
+
+    {
+        .nb_unit_types     = 1,
+        .unit_type.list[0] = AV1_OBU_FRAME,
+        .content_type      = CBS_CONTENT_TYPE_INTERNAL_REFS,
+        .content_size      = sizeof(AV1RawOBU),
+        .type.ref          = {
+            .nb_offsets = 2,
+            .offsets    = { offsetof(AV1RawOBU, obu.frame.tile_group.data),
+                            offsetof(AV1RawOBU, obu.frame.tile_group.tile_data.data) }
+        },
+    },
+    /*CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_TILE_GROUP, AV1RawOBU,
                                obu.tile_group.tile_data.data),
     CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_FRAME,      AV1RawOBU,
-                               obu.frame.tile_group.tile_data.data),
+                               obu.frame.tile_group.tile_data.data),*/
     CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_TILE_LIST,  AV1RawOBU,
                                obu.tile_list.tile_data.data),
     CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_PADDING,    AV1RawOBU,
diff --git a/libavcodec/cbs_av1.h b/libavcodec/cbs_av1.h
index 8586f2bf4a..62c7720142 100644
--- a/libavcodec/cbs_av1.h
+++ b/libavcodec/cbs_av1.h
@@ -295,6 +295,10 @@ typedef struct AV1RawTileData {
 } AV1RawTileData;
 
 typedef struct AV1RawTileGroup {
+    uint8_t     *data;
+    AVBufferRef *data_ref;
+    size_t       data_size;
+
     uint8_t  tile_start_and_end_present_flag;
     uint16_t tg_start;
     uint16_t tg_end;
diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c
index a4a912482c..62a83945ec 100644
--- a/libavcodec/cbs_av1_syntax_template.c
+++ b/libavcodec/cbs_av1_syntax_template.c
@@ -1865,8 +1865,6 @@ static int FUNC(frame_obu)(CodedBitstreamContext *ctx, RWContext *rw,
 
     CHECK(FUNC(byte_alignment)(ctx, rw));
 
-    CHECK(FUNC(tile_group_obu)(ctx, rw, &current->tile_group));
-
     return 0;
 }
 
-- 
2.48.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".

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [FFmpeg-devel] [PATCH 2/2] avformat/movenccenc: add support for CENC AV1 encryption
  2025-03-20 17:01 [FFmpeg-devel] [PATCH 1/2] avcodec/cbs_av1: also store a pointer to the start of the tile group data James Almer
@ 2025-03-20 17:01 ` James Almer
  2025-03-21  2:55   ` Andreas Rheinhardt
  0 siblings, 1 reply; 9+ messages in thread
From: James Almer @ 2025-03-20 17:01 UTC (permalink / raw)
  To: ffmpeg-devel

Signed-off-by: James Almer <jamrial@gmail.com>
---
 configure                |   2 +-
 libavformat/Makefile     |   1 +
 libavformat/cbs.c        |   1 +
 libavformat/cbs_av1.c    |   1 +
 libavformat/movenc.c     |  13 ++-
 libavformat/movenccenc.c | 223 ++++++++++++++++++++++++++++++++++++++-
 libavformat/movenccenc.h |  20 +++-
 7 files changed, 255 insertions(+), 6 deletions(-)
 create mode 100644 libavformat/cbs.c
 create mode 100644 libavformat/cbs_av1.c

diff --git a/configure b/configure
index 14f7bcde0e..0f6b6c20fb 100755
--- a/configure
+++ b/configure
@@ -3689,7 +3689,7 @@ mlp_demuxer_select="mlp_parser"
 mmf_muxer_select="riffenc"
 mov_demuxer_select="iso_media riffdec"
 mov_demuxer_suggest="iamfdec zlib"
-mov_muxer_select="iso_media iso_writer riffenc rtpenc_chain vp9_superframe_bsf aac_adtstoasc_bsf ac3_parser"
+mov_muxer_select="iso_media iso_writer riffenc rtpenc_chain vp9_superframe_bsf aac_adtstoasc_bsf ac3_parser cbs_av1"
 mov_muxer_suggest="iamfenc"
 mp3_demuxer_select="mpegaudio_parser"
 mp3_muxer_select="mpegaudioheader"
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 7730e7c4e6..1e57ae7d8a 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -740,6 +740,7 @@ SHLIBOBJS-$(CONFIG_JNI)                  += ffjni.o
 SHLIBOBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER)  += jpegxl_parse.o
 SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER)     += mpeg4audio_sample_rates.o
 SHLIBOBJS-$(CONFIG_MOV_DEMUXER)          += ac3_channel_layout_tab.o
+SHLIBOBJS-$(CONFIG_MOV_MUXER)            += cbs.o cbs_av1.o
 SHLIBOBJS-$(CONFIG_MP3_MUXER)            += mpegaudiotabs.o
 SHLIBOBJS-$(CONFIG_MXF_MUXER)            += golomb_tab.o \
                                             rangecoder_dec.o
diff --git a/libavformat/cbs.c b/libavformat/cbs.c
new file mode 100644
index 0000000000..8f1235da8d
--- /dev/null
+++ b/libavformat/cbs.c
@@ -0,0 +1 @@
+#include "libavcodec/cbs.c"
diff --git a/libavformat/cbs_av1.c b/libavformat/cbs_av1.c
new file mode 100644
index 0000000000..32b9e72c57
--- /dev/null
+++ b/libavformat/cbs_av1.c
@@ -0,0 +1 @@
+#include "libavcodec/cbs_av1.c"
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index af013e1fc6..c60c46012f 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -6767,7 +6767,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
         } else {
             size = ff_vvc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
         }
-    } else if (par->codec_id == AV_CODEC_ID_AV1) {
+    } else if (par->codec_id == AV_CODEC_ID_AV1 && !trk->cenc.aes_ctr) {
         if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
             ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
                                          &size, &offset);
@@ -6815,6 +6815,13 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
                 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
             } else if(par->codec_id == AV_CODEC_ID_VVC) {
                 ret = AVERROR_PATCHWELCOME;
+            } else if(par->codec_id == AV_CODEC_ID_AV1) {
+                av_assert0(size == pkt->size);
+				ret = ff_mov_cenc_av1_write_obus(s, &trk->cenc, pb, pkt);
+                if (ret > 0) {
+                    size = ret;
+                    ret = 0;
+                }
             } else {
                 ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
             }
@@ -8135,8 +8142,8 @@ static int mov_init(AVFormatContext *s)
         if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
             ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
                 (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC ||
-                 track->par->codec_id == AV_CODEC_ID_VVC),
-                s->flags & AVFMT_FLAG_BITEXACT);
+                 track->par->codec_id == AV_CODEC_ID_VVC || track->par->codec_id == AV_CODEC_ID_AV1),
+                 track->par->codec_id, s->flags & AVFMT_FLAG_BITEXACT);
             if (ret)
                 return ret;
         }
diff --git a/libavformat/movenccenc.c b/libavformat/movenccenc.c
index f54d3bcbca..af801eb3a0 100644
--- a/libavformat/movenccenc.c
+++ b/libavformat/movenccenc.c
@@ -19,6 +19,9 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include "movenccenc.h"
+#include "libavcodec/av1_parse.h"
+#include "libavcodec/bytestream.h"
+#include "libavcodec/cbs_av1.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
 #include "avio_internal.h"
@@ -280,6 +283,203 @@ int ff_mov_cenc_avc_write_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx,
     return 0;
 }
 
+static int write_tiles(AVFormatContext *s, MOVMuxCencContext *ctx, AVIOContext *pb, AV1_OBU_Type type,
+                       const AV1RawFrameHeader *frame_header, const uint8_t *fh_data, size_t fh_data_size,
+                       const AV1RawTileGroup *tile_group)
+{
+    GetByteContext gb;
+    size_t tgh_data_size = tile_group->data_size;
+    int cur_tile_num = frame_header->tile_cols * frame_header->tile_rows;
+    int total = 0;
+
+    // Get the Frame Header size
+    if (type == AV1_OBU_FRAME)
+        fh_data_size -= tgh_data_size;
+    // Get the Tile Group Header size
+    tgh_data_size -= tile_group->tile_data.data_size;
+
+    if (ctx->tile_num < cur_tile_num) {
+        int ret = av_reallocp_array(&ctx->tile_group_sizes, cur_tile_num,
+                                    sizeof(*ctx->tile_group_sizes));
+        if (ret < 0) {
+            ctx->tile_num = 0;
+            return ret;
+        }
+    }
+    ctx->tile_num = cur_tile_num;
+
+    total = fh_data_size + tgh_data_size;
+    ctx->clear_bytes += total;
+
+    bytestream2_init(&gb, tile_group->tile_data.data, tile_group->tile_data.data_size);
+
+    // Build a table with block sizes for encrypted bytes and clear bytes
+    for (unsigned tile_num = tile_group->tg_start; tile_num <= tile_group->tg_end; tile_num++) {
+        uint32_t encrypted_bytes, tile_size_bytes, tile_size = 0;
+
+        if (tile_num == tile_group->tg_end) {
+            tile_size = bytestream2_get_bytes_left(&gb);
+            encrypted_bytes = tile_size & ~0xFU;
+            ctx->clear_bytes += tile_size & 0xFU;
+
+            ctx->tile_group_sizes[tile_num].encrypted_bytes   = encrypted_bytes;
+            ctx->tile_group_sizes[tile_num].aux_clear_bytes   = encrypted_bytes ? ctx->clear_bytes : 0;
+            ctx->tile_group_sizes[tile_num].write_clear_bytes = tile_size & 0xFU;
+
+            if (encrypted_bytes)
+                ctx->clear_bytes = 0;
+            total += tile_size;
+
+            break;
+        }
+
+        tile_size_bytes = frame_header->tile_size_bytes_minus1 + 1;
+        if (bytestream2_get_bytes_left(&gb) < tile_size_bytes)
+            return AVERROR_INVALIDDATA;
+
+        for (int i = 0; i < tile_size_bytes; i++)
+            tile_size |= bytestream2_get_byteu(&gb) << 8 * i;
+        if (bytestream2_get_bytes_left(&gb) <= tile_size)
+            return AVERROR_INVALIDDATA;
+        tile_size++;
+
+        // The spec requires encrypted bytes to be in blocks multiple of 16
+        encrypted_bytes   =  tile_size & ~0xFU;
+        ctx->clear_bytes += (tile_size &  0xFU) + tile_size_bytes;
+
+        ctx->tile_group_sizes[tile_num].encrypted_bytes   = encrypted_bytes;
+        ctx->tile_group_sizes[tile_num].aux_clear_bytes   = encrypted_bytes ? ctx->clear_bytes : 0;
+        ctx->tile_group_sizes[tile_num].write_clear_bytes = (tile_size & 0xFU) + tile_size_bytes;
+
+        if (encrypted_bytes)
+            ctx->clear_bytes = 0;
+
+        total += tile_size + tile_size_bytes;
+        bytestream2_skipu(&gb, tile_size);
+    }
+
+    bytestream2_init(&gb, tile_group->tile_data.data, tile_group->tile_data.data_size);
+
+    avio_write(pb, fh_data, fh_data_size);
+    avio_write(pb, tile_group->data, tgh_data_size);
+
+    for (unsigned tile_num = tile_group->tg_start; tile_num <= tile_group->tg_end; tile_num++) {
+        const struct MOVMuxCencAV1TGInfo *sizes = &ctx->tile_group_sizes[tile_num];
+
+        avio_write(pb, gb.buffer, sizes->write_clear_bytes);
+        bytestream2_skipu(&gb, sizes->write_clear_bytes);
+        mov_cenc_write_encrypted(ctx, pb, gb.buffer, sizes->encrypted_bytes);
+        bytestream2_skipu(&gb, sizes->encrypted_bytes);
+        if (sizes->encrypted_bytes) {
+            unsigned clear_bytes = sizes->aux_clear_bytes;
+            if (clear_bytes > UINT16_MAX) {
+                auxiliary_info_add_subsample(ctx, UINT16_MAX, 0);
+                clear_bytes -= UINT16_MAX;
+            }
+            auxiliary_info_add_subsample(ctx, clear_bytes, sizes->encrypted_bytes);
+        }
+    }
+
+    return total;
+}
+
+int ff_mov_cenc_av1_write_obus(AVFormatContext *s, MOVMuxCencContext* ctx,
+                               AVIOContext *pb, const AVPacket *pkt)
+{
+    CodedBitstreamFragment *td = &ctx->temporal_unit;
+    const CodedBitstreamAV1Context *av1 = ctx->cbc->priv_data;
+    const AV1RawFrameHeader *frame_header = NULL;
+    const uint8_t *fh_data = NULL;
+    size_t fh_data_size;
+    int out_size = 0, ret;
+
+    ret = mov_cenc_start_packet(ctx);
+    if (ret) {
+        return ret;
+    }
+
+    ret = ff_cbs_read_packet(ctx->cbc, td, pkt);
+    if (ret < 0) {
+        av_log(s, AV_LOG_ERROR, "CENC-AV1: Failed to parse temporal unit.\n");
+        return ret;
+    }
+
+    if (!av1->sequence_header) {
+        av_log(s, AV_LOG_ERROR, "CENC-AV1: No sequence header available\n");
+        ret = AVERROR_INVALIDDATA;
+        goto end;
+    }
+
+    for (int i = 0; i < td->nb_units; i++) {
+        const CodedBitstreamUnit *unit = &td->units[i];
+        const AV1RawOBU *obu = unit->content;
+
+        switch (unit->type) {
+        case AV1_OBU_FRAME_HEADER:
+            if (!obu->obu.frame_header.show_existing_frame) {
+                frame_header = &obu->obu.frame_header;
+                fh_data      = unit->data;
+                fh_data_size = unit->data_size;
+                break;
+            }
+        // fall-through
+        case AV1_OBU_SEQUENCE_HEADER:
+        case AV1_OBU_METADATA:
+            avio_write(pb, unit->data, unit->data_size);
+            ctx->clear_bytes += unit->data_size;
+            out_size += unit->data_size;
+            break;
+        case AV1_OBU_FRAME:
+            frame_header = &obu->obu.frame.header;
+            fh_data      = unit->data;
+            fh_data_size = unit->data_size;
+        // fall-through
+        case AV1_OBU_TILE_GROUP:
+            {
+                const AV1RawTileGroup *tile_group;
+
+                if (!frame_header){
+                    ret = AVERROR_INVALIDDATA;
+                    goto end;
+                }
+
+                if (unit->type == AV1_OBU_FRAME)
+                    tile_group = &obu->obu.frame.tile_group;
+                else
+                    tile_group = &obu->obu.tile_group;
+
+                ret = write_tiles(s, ctx, pb, unit->type,
+                                  frame_header, fh_data, fh_data_size, tile_group);
+                if (ret < 0) {
+                    av_log(s, AV_LOG_ERROR, "CENC-AV1: Failed to write tiles\n");
+                    goto end;
+                }
+                av_assert0(ret == unit->data_size);
+                out_size += unit->data_size;
+                frame_header = NULL;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
+    if (ctx->clear_bytes)
+        auxiliary_info_add_subsample(ctx, ctx->clear_bytes, 0);
+    ctx->clear_bytes = 0;
+
+    ret = mov_cenc_end_packet(ctx);
+    if (ret) {
+        ret = AVERROR_INVALIDDATA;
+        goto end;
+    }
+
+    ret = out_size;
+end:
+    ff_cbs_fragment_reset(td);
+    return ret;
+}
+
 /* TODO: reuse this function from movenc.c */
 static int64_t update_size(AVIOContext *pb, int64_t pos)
 {
@@ -388,8 +588,16 @@ int ff_mov_cenc_write_sinf_tag(MOVTrack* track, AVIOContext *pb, uint8_t* kid)
     return update_size(pb, pos);
 }
 
+static const CodedBitstreamUnitType decompose_unit_types[] = {
+    AV1_OBU_TEMPORAL_DELIMITER,
+    AV1_OBU_SEQUENCE_HEADER,
+    AV1_OBU_FRAME_HEADER,
+    AV1_OBU_TILE_GROUP,
+    AV1_OBU_FRAME,
+};
+
 int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key,
-                     int use_subsamples, int bitexact)
+                     int use_subsamples, enum AVCodecID codec_id, int bitexact)
 {
     int ret;
 
@@ -409,6 +617,15 @@ int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key,
 
     ctx->use_subsamples = use_subsamples;
 
+    if (codec_id == AV_CODEC_ID_AV1) {
+        ret = ff_cbs_init(&ctx->cbc, codec_id, NULL);
+        if (ret < 0)
+            return ret;
+
+        ctx->cbc->decompose_unit_types    = decompose_unit_types;
+        ctx->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types);
+    }
+
     return 0;
 }
 
@@ -417,4 +634,8 @@ void ff_mov_cenc_free(MOVMuxCencContext* ctx)
     av_aes_ctr_free(ctx->aes_ctr);
     av_freep(&ctx->auxiliary_info);
     av_freep(&ctx->auxiliary_info_sizes);
+
+    av_freep(&ctx->tile_group_sizes);
+    ff_cbs_fragment_free(&ctx->temporal_unit);
+    ff_cbs_close(&ctx->cbc);
 }
diff --git a/libavformat/movenccenc.h b/libavformat/movenccenc.h
index 7da5268090..722914dc1c 100644
--- a/libavformat/movenccenc.h
+++ b/libavformat/movenccenc.h
@@ -23,6 +23,7 @@
 #define AVFORMAT_MOVENCCENC_H
 
 #include "libavutil/aes_ctr.h"
+#include "libavcodec/cbs.h"
 #include "avformat.h"
 #include "avio.h"
 
@@ -30,6 +31,12 @@
 
 struct MOVTrack;
 
+struct MOVMuxCencAV1TGInfo {
+    uint32_t encrypted_bytes;
+    uint32_t write_clear_bytes;
+    uint32_t aux_clear_bytes;
+};
+
 typedef struct {
     struct AVAESCTR* aes_ctr;
     uint8_t* auxiliary_info;
@@ -43,6 +50,14 @@ typedef struct {
     size_t auxiliary_info_subsample_start;
     uint8_t* auxiliary_info_sizes;
     size_t  auxiliary_info_sizes_alloc_size;
+
+    /* AV1 */
+    struct MOVMuxCencAV1TGInfo *tile_group_sizes;
+    uint32_t clear_bytes;
+    int tile_num;
+    /* CBS */
+    CodedBitstreamContext *cbc;
+    CodedBitstreamFragment temporal_unit;
 } MOVMuxCencContext;
 
 /**
@@ -50,7 +65,8 @@ typedef struct {
  * @param key encryption key, must have a length of AES_CTR_KEY_SIZE
  * @param use_subsamples when enabled parts of a packet can be encrypted, otherwise the whole packet is encrypted
  */
-int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key, int use_subsamples, int bitexact);
+int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key, int use_subsamples,
+                     enum AVCodecID codec_id, int bitexact);
 
 /**
  * Free a CENC context
@@ -73,6 +89,8 @@ int ff_mov_cenc_avc_parse_nal_units(MOVMuxCencContext* ctx, AVIOContext *pb, con
 int ff_mov_cenc_avc_write_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx, int nal_length_size,
     AVIOContext *pb, const uint8_t *buf_in, int size);
 
+int ff_mov_cenc_av1_write_obus(AVFormatContext *s, MOVMuxCencContext* ctx,
+                               AVIOContext *pb, const AVPacket *pkt);
 /**
  * Write the cenc atoms that should reside inside stbl
  */
-- 
2.48.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".

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/2] avformat/movenccenc: add support for CENC AV1 encryption
  2025-03-20 17:01 ` [FFmpeg-devel] [PATCH 2/2] avformat/movenccenc: add support for CENC AV1 encryption James Almer
@ 2025-03-21  2:55   ` Andreas Rheinhardt
  2025-03-21  3:30     ` James Almer
  0 siblings, 1 reply; 9+ messages in thread
From: Andreas Rheinhardt @ 2025-03-21  2:55 UTC (permalink / raw)
  To: ffmpeg-devel

James Almer:
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  configure                |   2 +-
>  libavformat/Makefile     |   1 +
>  libavformat/cbs.c        |   1 +
>  libavformat/cbs_av1.c    |   1 +
>  libavformat/movenc.c     |  13 ++-
>  libavformat/movenccenc.c | 223 ++++++++++++++++++++++++++++++++++++++-
>  libavformat/movenccenc.h |  20 +++-
>  7 files changed, 255 insertions(+), 6 deletions(-)
>  create mode 100644 libavformat/cbs.c
>  create mode 100644 libavformat/cbs_av1.c
> 
> diff --git a/configure b/configure
> index 14f7bcde0e..0f6b6c20fb 100755
> --- a/configure
> +++ b/configure
> @@ -3689,7 +3689,7 @@ mlp_demuxer_select="mlp_parser"
>  mmf_muxer_select="riffenc"
>  mov_demuxer_select="iso_media riffdec"
>  mov_demuxer_suggest="iamfdec zlib"
> -mov_muxer_select="iso_media iso_writer riffenc rtpenc_chain vp9_superframe_bsf aac_adtstoasc_bsf ac3_parser"
> +mov_muxer_select="iso_media iso_writer riffenc rtpenc_chain vp9_superframe_bsf aac_adtstoasc_bsf ac3_parser cbs_av1"
>  mov_muxer_suggest="iamfenc"
>  mp3_demuxer_select="mpegaudio_parser"
>  mp3_muxer_select="mpegaudioheader"
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index 7730e7c4e6..1e57ae7d8a 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -740,6 +740,7 @@ SHLIBOBJS-$(CONFIG_JNI)                  += ffjni.o
>  SHLIBOBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER)  += jpegxl_parse.o
>  SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER)     += mpeg4audio_sample_rates.o
>  SHLIBOBJS-$(CONFIG_MOV_DEMUXER)          += ac3_channel_layout_tab.o
> +SHLIBOBJS-$(CONFIG_MOV_MUXER)            += cbs.o cbs_av1.o
>  SHLIBOBJS-$(CONFIG_MP3_MUXER)            += mpegaudiotabs.o
>  SHLIBOBJS-$(CONFIG_MXF_MUXER)            += golomb_tab.o \
>                                              rangecoder_dec.o
> diff --git a/libavformat/cbs.c b/libavformat/cbs.c
> new file mode 100644
> index 0000000000..8f1235da8d
> --- /dev/null
> +++ b/libavformat/cbs.c
> @@ -0,0 +1 @@
> +#include "libavcodec/cbs.c"
> diff --git a/libavformat/cbs_av1.c b/libavformat/cbs_av1.c
> new file mode 100644
> index 0000000000..32b9e72c57
> --- /dev/null
> +++ b/libavformat/cbs_av1.c
> @@ -0,0 +1 @@
> +#include "libavcodec/cbs_av1.c"
> diff --git a/libavformat/movenc.c b/libavformat/movenc.c
> index af013e1fc6..c60c46012f 100644
> --- a/libavformat/movenc.c
> +++ b/libavformat/movenc.c
> @@ -6767,7 +6767,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
>          } else {
>              size = ff_vvc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
>          }
> -    } else if (par->codec_id == AV_CODEC_ID_AV1) {
> +    } else if (par->codec_id == AV_CODEC_ID_AV1 && !trk->cenc.aes_ctr) {
>          if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
>              ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
>                                           &size, &offset);
> @@ -6815,6 +6815,13 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
>                  ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
>              } else if(par->codec_id == AV_CODEC_ID_VVC) {
>                  ret = AVERROR_PATCHWELCOME;
> +            } else if(par->codec_id == AV_CODEC_ID_AV1) {
> +                av_assert0(size == pkt->size);
> +				ret = ff_mov_cenc_av1_write_obus(s, &trk->cenc, pb, pkt);
> +                if (ret > 0) {
> +                    size = ret;
> +                    ret = 0;
> +                }
>              } else {
>                  ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
>              }
> @@ -8135,8 +8142,8 @@ static int mov_init(AVFormatContext *s)
>          if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
>              ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
>                  (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC ||
> -                 track->par->codec_id == AV_CODEC_ID_VVC),
> -                s->flags & AVFMT_FLAG_BITEXACT);
> +                 track->par->codec_id == AV_CODEC_ID_VVC || track->par->codec_id == AV_CODEC_ID_AV1),
> +                 track->par->codec_id, s->flags & AVFMT_FLAG_BITEXACT);
>              if (ret)
>                  return ret;
>          }
> diff --git a/libavformat/movenccenc.c b/libavformat/movenccenc.c
> index f54d3bcbca..af801eb3a0 100644
> --- a/libavformat/movenccenc.c
> +++ b/libavformat/movenccenc.c
> @@ -19,6 +19,9 @@
>   * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
>   */
>  #include "movenccenc.h"
> +#include "libavcodec/av1_parse.h"
> +#include "libavcodec/bytestream.h"
> +#include "libavcodec/cbs_av1.h"
>  #include "libavutil/intreadwrite.h"
>  #include "libavutil/mem.h"
>  #include "avio_internal.h"
> @@ -280,6 +283,203 @@ int ff_mov_cenc_avc_write_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx,
>      return 0;
>  }
>  
> +static int write_tiles(AVFormatContext *s, MOVMuxCencContext *ctx, AVIOContext *pb, AV1_OBU_Type type,
> +                       const AV1RawFrameHeader *frame_header, const uint8_t *fh_data, size_t fh_data_size,
> +                       const AV1RawTileGroup *tile_group)
> +{
> +    GetByteContext gb;
> +    size_t tgh_data_size = tile_group->data_size;
> +    int cur_tile_num = frame_header->tile_cols * frame_header->tile_rows;
> +    int total = 0;
> +
> +    // Get the Frame Header size
> +    if (type == AV1_OBU_FRAME)
> +        fh_data_size -= tgh_data_size;
> +    // Get the Tile Group Header size
> +    tgh_data_size -= tile_group->tile_data.data_size;
> +
> +    if (ctx->tile_num < cur_tile_num) {
> +        int ret = av_reallocp_array(&ctx->tile_group_sizes, cur_tile_num,
> +                                    sizeof(*ctx->tile_group_sizes));
> +        if (ret < 0) {
> +            ctx->tile_num = 0;
> +            return ret;
> +        }
> +    }
> +    ctx->tile_num = cur_tile_num;
> +
> +    total = fh_data_size + tgh_data_size;
> +    ctx->clear_bytes += total;
> +
> +    bytestream2_init(&gb, tile_group->tile_data.data, tile_group->tile_data.data_size);
> +
> +    // Build a table with block sizes for encrypted bytes and clear bytes
> +    for (unsigned tile_num = tile_group->tg_start; tile_num <= tile_group->tg_end; tile_num++) {
> +        uint32_t encrypted_bytes, tile_size_bytes, tile_size = 0;
> +
> +        if (tile_num == tile_group->tg_end) {
> +            tile_size = bytestream2_get_bytes_left(&gb);
> +            encrypted_bytes = tile_size & ~0xFU;
> +            ctx->clear_bytes += tile_size & 0xFU;
> +
> +            ctx->tile_group_sizes[tile_num].encrypted_bytes   = encrypted_bytes;
> +            ctx->tile_group_sizes[tile_num].aux_clear_bytes   = encrypted_bytes ? ctx->clear_bytes : 0;
> +            ctx->tile_group_sizes[tile_num].write_clear_bytes = tile_size & 0xFU;
> +
> +            if (encrypted_bytes)
> +                ctx->clear_bytes = 0;
> +            total += tile_size;
> +
> +            break;
> +        }
> +
> +        tile_size_bytes = frame_header->tile_size_bytes_minus1 + 1;
> +        if (bytestream2_get_bytes_left(&gb) < tile_size_bytes)
> +            return AVERROR_INVALIDDATA;
> +
> +        for (int i = 0; i < tile_size_bytes; i++)
> +            tile_size |= bytestream2_get_byteu(&gb) << 8 * i;
> +        if (bytestream2_get_bytes_left(&gb) <= tile_size)
> +            return AVERROR_INVALIDDATA;
> +        tile_size++;
> +
> +        // The spec requires encrypted bytes to be in blocks multiple of 16
> +        encrypted_bytes   =  tile_size & ~0xFU;
> +        ctx->clear_bytes += (tile_size &  0xFU) + tile_size_bytes;
> +
> +        ctx->tile_group_sizes[tile_num].encrypted_bytes   = encrypted_bytes;
> +        ctx->tile_group_sizes[tile_num].aux_clear_bytes   = encrypted_bytes ? ctx->clear_bytes : 0;
> +        ctx->tile_group_sizes[tile_num].write_clear_bytes = (tile_size & 0xFU) + tile_size_bytes;
> +
> +        if (encrypted_bytes)
> +            ctx->clear_bytes = 0;
> +
> +        total += tile_size + tile_size_bytes;
> +        bytestream2_skipu(&gb, tile_size);
> +    }
> +
> +    bytestream2_init(&gb, tile_group->tile_data.data, tile_group->tile_data.data_size);
> +
> +    avio_write(pb, fh_data, fh_data_size);
> +    avio_write(pb, tile_group->data, tgh_data_size);
> +
> +    for (unsigned tile_num = tile_group->tg_start; tile_num <= tile_group->tg_end; tile_num++) {
> +        const struct MOVMuxCencAV1TGInfo *sizes = &ctx->tile_group_sizes[tile_num];
> +
> +        avio_write(pb, gb.buffer, sizes->write_clear_bytes);
> +        bytestream2_skipu(&gb, sizes->write_clear_bytes);
> +        mov_cenc_write_encrypted(ctx, pb, gb.buffer, sizes->encrypted_bytes);
> +        bytestream2_skipu(&gb, sizes->encrypted_bytes);
> +        if (sizes->encrypted_bytes) {
> +            unsigned clear_bytes = sizes->aux_clear_bytes;
> +            if (clear_bytes > UINT16_MAX) {
> +                auxiliary_info_add_subsample(ctx, UINT16_MAX, 0);
> +                clear_bytes -= UINT16_MAX;
> +            }
> +            auxiliary_info_add_subsample(ctx, clear_bytes, sizes->encrypted_bytes);
> +        }
> +    }
> +
> +    return total;
> +}
> +
> +int ff_mov_cenc_av1_write_obus(AVFormatContext *s, MOVMuxCencContext* ctx,
> +                               AVIOContext *pb, const AVPacket *pkt)
> +{
> +    CodedBitstreamFragment *td = &ctx->temporal_unit;
> +    const CodedBitstreamAV1Context *av1 = ctx->cbc->priv_data;
> +    const AV1RawFrameHeader *frame_header = NULL;
> +    const uint8_t *fh_data = NULL;
> +    size_t fh_data_size;
> +    int out_size = 0, ret;
> +
> +    ret = mov_cenc_start_packet(ctx);
> +    if (ret) {
> +        return ret;
> +    }
> +
> +    ret = ff_cbs_read_packet(ctx->cbc, td, pkt);
> +    if (ret < 0) {
> +        av_log(s, AV_LOG_ERROR, "CENC-AV1: Failed to parse temporal unit.\n");
> +        return ret;
> +    }
> +
> +    if (!av1->sequence_header) {
> +        av_log(s, AV_LOG_ERROR, "CENC-AV1: No sequence header available\n");
> +        ret = AVERROR_INVALIDDATA;
> +        goto end;
> +    }
> +
> +    for (int i = 0; i < td->nb_units; i++) {
> +        const CodedBitstreamUnit *unit = &td->units[i];
> +        const AV1RawOBU *obu = unit->content;
> +
> +        switch (unit->type) {
> +        case AV1_OBU_FRAME_HEADER:
> +            if (!obu->obu.frame_header.show_existing_frame) {
> +                frame_header = &obu->obu.frame_header;
> +                fh_data      = unit->data;
> +                fh_data_size = unit->data_size;
> +                break;
> +            }
> +        // fall-through
> +        case AV1_OBU_SEQUENCE_HEADER:
> +        case AV1_OBU_METADATA:
> +            avio_write(pb, unit->data, unit->data_size);
> +            ctx->clear_bytes += unit->data_size;
> +            out_size += unit->data_size;
> +            break;
> +        case AV1_OBU_FRAME:
> +            frame_header = &obu->obu.frame.header;
> +            fh_data      = unit->data;
> +            fh_data_size = unit->data_size;
> +        // fall-through
> +        case AV1_OBU_TILE_GROUP:
> +            {
> +                const AV1RawTileGroup *tile_group;
> +
> +                if (!frame_header){
> +                    ret = AVERROR_INVALIDDATA;
> +                    goto end;
> +                }
> +
> +                if (unit->type == AV1_OBU_FRAME)
> +                    tile_group = &obu->obu.frame.tile_group;
> +                else
> +                    tile_group = &obu->obu.tile_group;
> +
> +                ret = write_tiles(s, ctx, pb, unit->type,
> +                                  frame_header, fh_data, fh_data_size, tile_group);
> +                if (ret < 0) {
> +                    av_log(s, AV_LOG_ERROR, "CENC-AV1: Failed to write tiles\n");
> +                    goto end;
> +                }
> +                av_assert0(ret == unit->data_size);
> +                out_size += unit->data_size;
> +                frame_header = NULL;
> +            }
> +            break;
> +        default:
> +            break;
> +        }
> +    }
> +
> +    if (ctx->clear_bytes)
> +        auxiliary_info_add_subsample(ctx, ctx->clear_bytes, 0);
> +    ctx->clear_bytes = 0;
> +
> +    ret = mov_cenc_end_packet(ctx);
> +    if (ret) {
> +        ret = AVERROR_INVALIDDATA;
> +        goto end;
> +    }
> +
> +    ret = out_size;
> +end:
> +    ff_cbs_fragment_reset(td);
> +    return ret;
> +}
> +
>  /* TODO: reuse this function from movenc.c */
>  static int64_t update_size(AVIOContext *pb, int64_t pos)
>  {
> @@ -388,8 +588,16 @@ int ff_mov_cenc_write_sinf_tag(MOVTrack* track, AVIOContext *pb, uint8_t* kid)
>      return update_size(pb, pos);
>  }
>  
> +static const CodedBitstreamUnitType decompose_unit_types[] = {
> +    AV1_OBU_TEMPORAL_DELIMITER,
> +    AV1_OBU_SEQUENCE_HEADER,
> +    AV1_OBU_FRAME_HEADER,
> +    AV1_OBU_TILE_GROUP,
> +    AV1_OBU_FRAME,
> +};
> +
>  int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key,
> -                     int use_subsamples, int bitexact)
> +                     int use_subsamples, enum AVCodecID codec_id, int bitexact)
>  {
>      int ret;
>  
> @@ -409,6 +617,15 @@ int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key,
>  
>      ctx->use_subsamples = use_subsamples;
>  
> +    if (codec_id == AV_CODEC_ID_AV1) {
> +        ret = ff_cbs_init(&ctx->cbc, codec_id, NULL);
> +        if (ret < 0)
> +            return ret;
> +
> +        ctx->cbc->decompose_unit_types    = decompose_unit_types;
> +        ctx->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types);
> +    }
> +
>      return 0;
>  }
>  
> @@ -417,4 +634,8 @@ void ff_mov_cenc_free(MOVMuxCencContext* ctx)
>      av_aes_ctr_free(ctx->aes_ctr);
>      av_freep(&ctx->auxiliary_info);
>      av_freep(&ctx->auxiliary_info_sizes);
> +
> +    av_freep(&ctx->tile_group_sizes);
> +    ff_cbs_fragment_free(&ctx->temporal_unit);
> +    ff_cbs_close(&ctx->cbc);
>  }
> diff --git a/libavformat/movenccenc.h b/libavformat/movenccenc.h
> index 7da5268090..722914dc1c 100644
> --- a/libavformat/movenccenc.h
> +++ b/libavformat/movenccenc.h
> @@ -23,6 +23,7 @@
>  #define AVFORMAT_MOVENCCENC_H
>  
>  #include "libavutil/aes_ctr.h"
> +#include "libavcodec/cbs.h"
>  #include "avformat.h"
>  #include "avio.h"
>  
> @@ -30,6 +31,12 @@
>  
>  struct MOVTrack;
>  
> +struct MOVMuxCencAV1TGInfo {
> +    uint32_t encrypted_bytes;
> +    uint32_t write_clear_bytes;
> +    uint32_t aux_clear_bytes;
> +};
> +
>  typedef struct {
>      struct AVAESCTR* aes_ctr;
>      uint8_t* auxiliary_info;
> @@ -43,6 +50,14 @@ typedef struct {
>      size_t auxiliary_info_subsample_start;
>      uint8_t* auxiliary_info_sizes;
>      size_t  auxiliary_info_sizes_alloc_size;
> +
> +    /* AV1 */
> +    struct MOVMuxCencAV1TGInfo *tile_group_sizes;
> +    uint32_t clear_bytes;
> +    int tile_num;
> +    /* CBS */
> +    CodedBitstreamContext *cbc;
> +    CodedBitstreamFragment temporal_unit;
>  } MOVMuxCencContext;
>  
>  /**
> @@ -50,7 +65,8 @@ typedef struct {
>   * @param key encryption key, must have a length of AES_CTR_KEY_SIZE
>   * @param use_subsamples when enabled parts of a packet can be encrypted, otherwise the whole packet is encrypted
>   */
> -int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key, int use_subsamples, int bitexact);
> +int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key, int use_subsamples,
> +                     enum AVCodecID codec_id, int bitexact);
>  
>  /**
>   * Free a CENC context
> @@ -73,6 +89,8 @@ int ff_mov_cenc_avc_parse_nal_units(MOVMuxCencContext* ctx, AVIOContext *pb, con
>  int ff_mov_cenc_avc_write_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx, int nal_length_size,
>      AVIOContext *pb, const uint8_t *buf_in, int size);
>  
> +int ff_mov_cenc_av1_write_obus(AVFormatContext *s, MOVMuxCencContext* ctx,
> +                               AVIOContext *pb, const AVPacket *pkt);
>  /**
>   * Write the cenc atoms that should reside inside stbl
>   */

Duplicating .o files is meant for small stuff, not for gigantic things
like cbs_av1.o (whose .text is 86519B here).

- Andreas

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/2] avformat/movenccenc: add support for CENC AV1 encryption
  2025-03-21  2:55   ` Andreas Rheinhardt
@ 2025-03-21  3:30     ` James Almer
  2025-03-21  3:52       ` Andreas Rheinhardt
  0 siblings, 1 reply; 9+ messages in thread
From: James Almer @ 2025-03-21  3:30 UTC (permalink / raw)
  To: ffmpeg-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 418 bytes --]

On 3/20/2025 11:55 PM, Andreas Rheinhardt wrote:
> Duplicating .o files is meant for small stuff, not for gigantic things
> like cbs_av1.o (whose .text is 86519B here).

This feature requires complete frame and tile group parsing, which in 
turn requires complete sequence header parsing. The amount of work to 
get that much parsing code in lavf will be huge for little (if any) gain 
in total object size.


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/2] avformat/movenccenc: add support for CENC AV1 encryption
  2025-03-21  3:30     ` James Almer
@ 2025-03-21  3:52       ` Andreas Rheinhardt
  2025-03-21 12:50         ` James Almer
  2025-03-21 19:42         ` [FFmpeg-devel] [PATCH 2/3] avcodec/cbs: allow fine tunning selection of features James Almer
  0 siblings, 2 replies; 9+ messages in thread
From: Andreas Rheinhardt @ 2025-03-21  3:52 UTC (permalink / raw)
  To: ffmpeg-devel

James Almer:
> On 3/20/2025 11:55 PM, Andreas Rheinhardt wrote:
>> Duplicating .o files is meant for small stuff, not for gigantic things
>> like cbs_av1.o (whose .text is 86519B here).
> 
> This feature requires complete frame and tile group parsing, which in
> turn requires complete sequence header parsing. The amount of work to
> get that much parsing code in lavf will be huge for little (if any) gain
> in total object size.
> 

a) Completely wrong: Approximately half of cbs_av1.o is code for writing
which lavf doesn't use.
b) Even the reading code is littered with CBS's tracing stuff which lavf
won't use.
c) There is also parsing stuff that won't be used.
d) Btw: Your patch shouldn't even compile in shared builds if the other
CBS modules are enabled as your lavf/cbs.o will try to pull in the other
ff_cbs_type_*.

- Andreas

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/2] avformat/movenccenc: add support for CENC AV1 encryption
  2025-03-21  3:52       ` Andreas Rheinhardt
@ 2025-03-21 12:50         ` James Almer
  2025-03-21 19:42         ` [FFmpeg-devel] [PATCH 2/3] avcodec/cbs: allow fine tunning selection of features James Almer
  1 sibling, 0 replies; 9+ messages in thread
From: James Almer @ 2025-03-21 12:50 UTC (permalink / raw)
  To: ffmpeg-devel


[-- Attachment #1.1.1: Type: text/plain, Size: 1005 bytes --]

On 3/21/2025 12:52 AM, Andreas Rheinhardt wrote:
> James Almer:
>> On 3/20/2025 11:55 PM, Andreas Rheinhardt wrote:
>>> Duplicating .o files is meant for small stuff, not for gigantic things
>>> like cbs_av1.o (whose .text is 86519B here).
>>
>> This feature requires complete frame and tile group parsing, which in
>> turn requires complete sequence header parsing. The amount of work to
>> get that much parsing code in lavf will be huge for little (if any) gain
>> in total object size.
>>
> 
> a) Completely wrong: Approximately half of cbs_av1.o is code for writing
> which lavf doesn't use.
> b) Even the reading code is littered with CBS's tracing stuff which lavf
> won't use.
> c) There is also parsing stuff that won't be used.

I could make it so i selectively enable portions of the module.

> d) Btw: Your patch shouldn't even compile in shared builds if the other
> CBS modules are enabled as your lavf/cbs.o will try to pull in the other
> ff_cbs_type_*.

Ditto.


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 495 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [FFmpeg-devel] [PATCH 2/3] avcodec/cbs: allow fine tunning selection of features
  2025-03-21  3:52       ` Andreas Rheinhardt
  2025-03-21 12:50         ` James Almer
@ 2025-03-21 19:42         ` James Almer
  2025-03-21 19:42           ` [FFmpeg-devel] [PATCH v2 3/3] avformat/movenccenc: add support for CENC AV1 encryption James Almer
  2025-03-22 14:25           ` [FFmpeg-devel] [PATCH 2/3] avcodec/cbs: allow fine tunning selection of features Andreas Rheinhardt
  1 sibling, 2 replies; 9+ messages in thread
From: James Almer @ 2025-03-21 19:42 UTC (permalink / raw)
  To: ffmpeg-devel

This will be useful in an upcoming commit, where CBS will be utilized by
a module outside libavcodec.

Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavcodec/cbs.c                     | 100 ++++++++++++++++++++++-----
 libavcodec/cbs_av1.c                 |  64 ++++++++++++++++-
 libavcodec/cbs_av1.h                 |  15 ++++
 libavcodec/cbs_av1_syntax_template.c |   6 ++
 libavcodec/cbs_internal.h            |  48 +++++++++++++
 5 files changed, 212 insertions(+), 21 deletions(-)

diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
index 01dd916d81..94bf174700 100644
--- a/libavcodec/cbs.c
+++ b/libavcodec/cbs.c
@@ -18,8 +18,6 @@
 
 #include <string.h>
 
-#include "config.h"
-
 #include "libavutil/avassert.h"
 #include "libavutil/buffer.h"
 #include "libavutil/common.h"
@@ -33,55 +31,55 @@
 
 
 static const CodedBitstreamType *const cbs_type_table[] = {
-#if CONFIG_CBS_AV1
+#if CBS_AV1
     &ff_cbs_type_av1,
 #endif
-#if CONFIG_CBS_H264
+#if CBS_H264
     &ff_cbs_type_h264,
 #endif
-#if CONFIG_CBS_H265
+#if CBS_H265
     &ff_cbs_type_h265,
 #endif
-#if CONFIG_CBS_H266
+#if CBS_H266
     &ff_cbs_type_h266,
 #endif
-#if CONFIG_CBS_JPEG
+#if CBS_JPEG
     &ff_cbs_type_jpeg,
 #endif
-#if CONFIG_CBS_MPEG2
+#if CBS_MPEG2
     &ff_cbs_type_mpeg2,
 #endif
-#if CONFIG_CBS_VP8
+#if CBS_VP8
     &ff_cbs_type_vp8,
 #endif
-#if CONFIG_CBS_VP9
+#if CBS_VP9
     &ff_cbs_type_vp9,
 #endif
 };
 
 const enum AVCodecID ff_cbs_all_codec_ids[] = {
-#if CONFIG_CBS_AV1
+#if CBS_AV1
     AV_CODEC_ID_AV1,
 #endif
-#if CONFIG_CBS_H264
+#if CBS_H264
     AV_CODEC_ID_H264,
 #endif
-#if CONFIG_CBS_H265
+#if CBS_H265
     AV_CODEC_ID_H265,
 #endif
-#if CONFIG_CBS_H266
+#if CBS_H266
     AV_CODEC_ID_H266,
 #endif
-#if CONFIG_CBS_JPEG
+#if CBS_JPEG
     AV_CODEC_ID_MJPEG,
 #endif
-#if CONFIG_CBS_MPEG2
+#if CBS_MPEG2
     AV_CODEC_ID_MPEG2VIDEO,
 #endif
-#if CONFIG_CBS_VP8
+#if CBS_VP8
     AV_CODEC_ID_VP8,
 #endif
-#if CONFIG_CBS_VP9
+#if CBS_VP9
     AV_CODEC_ID_VP9,
 #endif
     AV_CODEC_ID_NONE
@@ -234,6 +232,7 @@ static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
     return 0;
 }
 
+#if CBS_READ
 static int cbs_fill_fragment_data(CodedBitstreamFragment *frag,
                                   const uint8_t *data, size_t size)
 {
@@ -282,37 +281,51 @@ static int cbs_read_data(CodedBitstreamContext *ctx,
 
     return cbs_read_fragment_content(ctx, frag);
 }
+#endif
 
 int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
                           CodedBitstreamFragment *frag,
                           const AVCodecParameters *par)
 {
+#if CBS_READ
     return cbs_read_data(ctx, frag, NULL,
                          par->extradata,
                          par->extradata_size, 1);
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 int ff_cbs_read_extradata_from_codec(CodedBitstreamContext *ctx,
                                      CodedBitstreamFragment *frag,
                                      const AVCodecContext *avctx)
 {
+#if CBS_READ
     return cbs_read_data(ctx, frag, NULL,
                          avctx->extradata,
                          avctx->extradata_size, 1);
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 int ff_cbs_read_packet(CodedBitstreamContext *ctx,
                        CodedBitstreamFragment *frag,
                        const AVPacket *pkt)
 {
+#if CBS_READ
     return cbs_read_data(ctx, frag, pkt->buf,
                          pkt->data, pkt->size, 0);
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 int ff_cbs_read_packet_side_data(CodedBitstreamContext *ctx,
                                  CodedBitstreamFragment *frag,
                                  const AVPacket *pkt)
 {
+#if CBS_READ
     size_t side_data_size;
     const uint8_t *side_data =
         av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
@@ -320,16 +333,24 @@ int ff_cbs_read_packet_side_data(CodedBitstreamContext *ctx,
 
     return cbs_read_data(ctx, frag, NULL,
                          side_data, side_data_size, 1);
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 int ff_cbs_read(CodedBitstreamContext *ctx,
                 CodedBitstreamFragment *frag,
                 const uint8_t *data, size_t size)
 {
+#if CBS_READ
     return cbs_read_data(ctx, frag, NULL,
                          data, size, 0);
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
+#if CBS_WRITE
 /**
  * Allocate a new internal data buffer of the given size in the unit.
  *
@@ -405,10 +426,12 @@ static int cbs_write_unit_data(CodedBitstreamContext *ctx,
 
     return 0;
 }
+#endif
 
 int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
                                CodedBitstreamFragment *frag)
 {
+#if CBS_WRITE
     int err, i;
 
     for (i = 0; i < frag->nb_units; i++) {
@@ -440,12 +463,16 @@ int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
     av_assert0(frag->data && frag->data_ref);
 
     return 0;
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
                            AVCodecParameters *par,
                            CodedBitstreamFragment *frag)
 {
+#if CBS_WRITE
     int err;
 
     err = ff_cbs_write_fragment_data(ctx, frag);
@@ -469,12 +496,16 @@ int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
     par->extradata_size = frag->data_size;
 
     return 0;
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 int ff_cbs_write_packet(CodedBitstreamContext *ctx,
                         AVPacket *pkt,
                         CodedBitstreamFragment *frag)
 {
+#if CBS_WRITE
     AVBufferRef *buf;
     int err;
 
@@ -493,16 +524,21 @@ int ff_cbs_write_packet(CodedBitstreamContext *ctx,
     pkt->size = frag->data_size;
 
     return 0;
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 
 void ff_cbs_trace_header(CodedBitstreamContext *ctx,
                          const char *name)
 {
+#if CBS_TRACE
     if (!ctx->trace_enable)
         return;
 
     av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name);
+#endif
 }
 
 void ff_cbs_trace_read_log(void *trace_context,
@@ -510,6 +546,7 @@ void ff_cbs_trace_read_log(void *trace_context,
                            const char *str, const int *subscripts,
                            int64_t value)
 {
+#if CBS_TRACE
     CodedBitstreamContext *ctx = trace_context;
     char name[256];
     char bits[256];
@@ -561,6 +598,7 @@ void ff_cbs_trace_read_log(void *trace_context,
 
     av_log(ctx->log_ctx, ctx->trace_level, "%-10d  %s%*s = %"PRId64"\n",
            position, name, pad, bits, value);
+#endif
 }
 
 void ff_cbs_trace_write_log(void *trace_context,
@@ -568,6 +606,7 @@ void ff_cbs_trace_write_log(void *trace_context,
                             const char *str, const int *subscripts,
                             int64_t value)
 {
+#if CBS_TRACE
     CodedBitstreamContext *ctx = trace_context;
 
     // Ensure that the syntax element is written to the output buffer,
@@ -591,6 +630,7 @@ void ff_cbs_trace_write_log(void *trace_context,
     skip_bits_long(&gbc, position - length);
 
     ff_cbs_trace_read_log(ctx, &gbc, length, str, subscripts, value);
+#endif
 }
 
 static av_always_inline int cbs_read_unsigned(CodedBitstreamContext *ctx,
@@ -633,15 +673,23 @@ int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc,
                          const int *subscripts, uint32_t *write_to,
                          uint32_t range_min, uint32_t range_max)
 {
+#if CBS_READ
     return cbs_read_unsigned(ctx, gbc, width, name, subscripts,
                              write_to, range_min, range_max);
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 int ff_cbs_read_simple_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc,
                                 int width, const char *name, uint32_t *write_to)
 {
+#if CBS_READ
     return cbs_read_unsigned(ctx, gbc, width, name, NULL,
                              write_to, 0, UINT32_MAX);
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
@@ -649,6 +697,7 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
                           const int *subscripts, uint32_t value,
                           uint32_t range_min, uint32_t range_max)
 {
+#if CBS_WRITE
     CBS_TRACE_WRITE_START();
 
     av_assert0(width > 0 && width <= 32);
@@ -671,13 +720,20 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
     CBS_TRACE_WRITE_END();
 
     return 0;
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 int ff_cbs_write_simple_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
                                  int width, const char *name, uint32_t value)
 {
+#if CBS_WRITE
     return ff_cbs_write_unsigned(ctx, pbc, width, name, NULL,
                                  value, 0, MAX_UINT_BITS(width));
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 int ff_cbs_read_signed(CodedBitstreamContext *ctx, GetBitContext *gbc,
@@ -685,6 +741,7 @@ int ff_cbs_read_signed(CodedBitstreamContext *ctx, GetBitContext *gbc,
                        const int *subscripts, int32_t *write_to,
                        int32_t range_min, int32_t range_max)
 {
+#if CBS_READ
     int32_t value;
 
     CBS_TRACE_READ_START();
@@ -710,6 +767,9 @@ int ff_cbs_read_signed(CodedBitstreamContext *ctx, GetBitContext *gbc,
 
     *write_to = value;
     return 0;
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
@@ -717,6 +777,7 @@ int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
                         const int *subscripts, int32_t value,
                         int32_t range_min, int32_t range_max)
 {
+#if CBS_WRITE
     CBS_TRACE_WRITE_START();
 
     av_assert0(width > 0 && width <= 32);
@@ -739,6 +800,9 @@ int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
     CBS_TRACE_WRITE_END();
 
     return 0;
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 
diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c
index d7862a2e48..e0a4eba20f 100644
--- a/libavcodec/cbs_av1.c
+++ b/libavcodec/cbs_av1.c
@@ -27,6 +27,7 @@
 #include "libavutil/refstruct.h"
 
 
+#if CBS_READ
 static int cbs_av1_read_uvlc(CodedBitstreamContext *ctx, GetBitContext *gbc,
                              const char *name, uint32_t *write_to,
                              uint32_t range_min, uint32_t range_max)
@@ -84,7 +85,9 @@ static int cbs_av1_read_uvlc(CodedBitstreamContext *ctx, GetBitContext *gbc,
     *write_to = value;
     return 0;
 }
+#endif
 
+#if CBS_WRITE
 static int cbs_av1_write_uvlc(CodedBitstreamContext *ctx, PutBitContext *pbc,
                               const char *name, uint32_t value,
                               uint32_t range_min, uint32_t range_max)
@@ -115,7 +118,9 @@ static int cbs_av1_write_uvlc(CodedBitstreamContext *ctx, PutBitContext *pbc,
 
     return 0;
 }
+#endif
 
+#if CBS_READ
 static int cbs_av1_read_leb128(CodedBitstreamContext *ctx, GetBitContext *gbc,
                                const char *name, uint64_t *write_to)
 {
@@ -146,7 +151,9 @@ static int cbs_av1_read_leb128(CodedBitstreamContext *ctx, GetBitContext *gbc,
     *write_to = value;
     return 0;
 }
+#endif
 
+#if CBS_WRITE
 static int cbs_av1_write_leb128(CodedBitstreamContext *ctx, PutBitContext *pbc,
                                 const char *name, uint64_t value, int fixed_length)
 {
@@ -182,7 +189,9 @@ static int cbs_av1_write_leb128(CodedBitstreamContext *ctx, PutBitContext *pbc,
 
     return 0;
 }
+#endif
 
+#if CBS_READ
 static int cbs_av1_read_ns(CodedBitstreamContext *ctx, GetBitContext *gbc,
                            uint32_t n, const char *name,
                            const int *subscripts, uint32_t *write_to)
@@ -220,7 +229,9 @@ static int cbs_av1_read_ns(CodedBitstreamContext *ctx, GetBitContext *gbc,
     *write_to = value;
     return 0;
 }
+#endif
 
+#if CBS_WRITE
 static int cbs_av1_write_ns(CodedBitstreamContext *ctx, PutBitContext *pbc,
                             uint32_t n, const char *name,
                             const int *subscripts, uint32_t value)
@@ -256,7 +267,9 @@ static int cbs_av1_write_ns(CodedBitstreamContext *ctx, PutBitContext *pbc,
 
     return 0;
 }
+#endif
 
+#if CBS_READ
 static int cbs_av1_read_increment(CodedBitstreamContext *ctx, GetBitContext *gbc,
                                   uint32_t range_min, uint32_t range_max,
                                   const char *name, uint32_t *write_to)
@@ -284,7 +297,9 @@ static int cbs_av1_read_increment(CodedBitstreamContext *ctx, GetBitContext *gbc
     *write_to = value;
     return 0;
 }
+#endif
 
+#if CBS_WRITE
 static int cbs_av1_write_increment(CodedBitstreamContext *ctx, PutBitContext *pbc,
                                    uint32_t range_min, uint32_t range_max,
                                    const char *name, uint32_t value)
@@ -315,7 +330,9 @@ static int cbs_av1_write_increment(CodedBitstreamContext *ctx, PutBitContext *pb
 
     return 0;
 }
+#endif
 
+#if CBS_READ
 static int cbs_av1_read_subexp(CodedBitstreamContext *ctx, GetBitContext *gbc,
                                uint32_t range_max, const char *name,
                                const int *subscripts, uint32_t *write_to)
@@ -360,7 +377,9 @@ static int cbs_av1_read_subexp(CodedBitstreamContext *ctx, GetBitContext *gbc,
     *write_to = value;
     return err;
 }
+#endif
 
+#if CBS_WRITE
 static int cbs_av1_write_subexp(CodedBitstreamContext *ctx, PutBitContext *pbc,
                                 uint32_t range_max, const char *name,
                                 const int *subscripts, uint32_t value)
@@ -420,6 +439,7 @@ static int cbs_av1_write_subexp(CodedBitstreamContext *ctx, PutBitContext *pbc,
 
     return err;
 }
+#endif
 
 
 static int cbs_av1_tile_log2(int blksize, int target)
@@ -441,7 +461,7 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq,
     return diff;
 }
 
-static size_t cbs_av1_get_payload_bytes_left(GetBitContext *gbc)
+static av_unused size_t cbs_av1_get_payload_bytes_left(GetBitContext *gbc)
 {
     GetBitContext tmp = *gbc;
     size_t size = 0;
@@ -469,6 +489,7 @@ static size_t cbs_av1_get_payload_bytes_left(GetBitContext *gbc)
 
 #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
 
+#if CBS_READ
 #define fc(width, name, range_min, range_max) \
         xf(width, name, current->name, range_min, range_max, 0, )
 #define flag(name) fb(1, name)
@@ -584,8 +605,9 @@ static size_t cbs_av1_get_payload_bytes_left(GetBitContext *gbc)
 #undef leb128
 #undef infer
 #undef byte_alignment
+#endif // CBS_READ
 
-
+#if CBS_WRITE
 #define WRITE
 #define READWRITE write
 #define RWContext PutBitContext
@@ -668,12 +690,13 @@ static size_t cbs_av1_get_payload_bytes_left(GetBitContext *gbc)
 #undef leb128
 #undef infer
 #undef byte_alignment
-
+#endif // CBS_WRITE
 
 static int cbs_av1_split_fragment(CodedBitstreamContext *ctx,
                                   CodedBitstreamFragment *frag,
                                   int header)
 {
+#if CBS_READ
     GetBitContext gbc;
     uint8_t *data;
     size_t size;
@@ -777,6 +800,9 @@ success:
 fail:
     ctx->trace_enable = trace;
     return err;
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 static int cbs_av1_ref_tile_data(CodedBitstreamContext *ctx,
@@ -809,6 +835,7 @@ static int cbs_av1_ref_tile_data(CodedBitstreamContext *ctx,
 static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
                              CodedBitstreamUnit *unit)
 {
+#if CBS_READ
     CodedBitstreamAV1Context *priv = ctx->priv_data;
     AV1RawOBU *obu;
     GetBitContext gbc;
@@ -931,6 +958,7 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
                 return err;
         }
         break;
+#if CBS_OBU_TILE_LIST
     case AV1_OBU_TILE_LIST:
         {
             err = cbs_av1_read_tile_list_obu(ctx, &gbc,
@@ -946,6 +974,8 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
                 return err;
         }
         break;
+#endif
+#if CBS_OBU_METADATA
     case AV1_OBU_METADATA:
         {
             err = cbs_av1_read_metadata_obu(ctx, &gbc, &obu->obu.metadata);
@@ -953,6 +983,8 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
                 return err;
         }
         break;
+#endif
+#if CBS_OBU_PADDING
     case AV1_OBU_PADDING:
         {
             err = cbs_av1_read_padding_obu(ctx, &gbc, &obu->obu.padding);
@@ -960,6 +992,7 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
                 return err;
         }
         break;
+#endif
     default:
         return AVERROR(ENOSYS);
     }
@@ -982,12 +1015,16 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
     }
 
     return 0;
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 static int cbs_av1_write_obu(CodedBitstreamContext *ctx,
                              CodedBitstreamUnit *unit,
                              PutBitContext *pbc)
 {
+#if CBS_WRITE
     CodedBitstreamAV1Context *priv = ctx->priv_data;
     AV1RawOBU *obu = unit->content;
     PutBitContext pbc_tmp;
@@ -1087,6 +1124,7 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx,
             td = &tile_group->tile_data;
         }
         break;
+#if CBS_OBU_TILE_LIST
     case AV1_OBU_TILE_LIST:
         {
             err = cbs_av1_write_tile_list_obu(ctx, pbc, &obu->obu.tile_list);
@@ -1096,6 +1134,8 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx,
             td = &obu->obu.tile_list.tile_data;
         }
         break;
+#endif
+#if CBS_OBU_METADATA
     case AV1_OBU_METADATA:
         {
             err = cbs_av1_write_metadata_obu(ctx, pbc, &obu->obu.metadata);
@@ -1103,6 +1143,8 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx,
                 goto error;
         }
         break;
+#endif
+#if CBS_OBU_PADDING
     case AV1_OBU_PADDING:
         {
             err = cbs_av1_write_padding_obu(ctx, pbc, &obu->obu.padding);
@@ -1110,6 +1152,7 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx,
                 goto error;
         }
         break;
+#endif
     default:
         err = AVERROR(ENOSYS);
         goto error;
@@ -1182,11 +1225,15 @@ error:
     av_buffer_unref(&av1ctx.frame_header_ref);
 
     return err;
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 static int cbs_av1_assemble_fragment(CodedBitstreamContext *ctx,
                                      CodedBitstreamFragment *frag)
 {
+#if CBS_WRITE
     size_t size, pos;
     int i;
 
@@ -1210,6 +1257,9 @@ static int cbs_av1_assemble_fragment(CodedBitstreamContext *ctx,
     frag->data_size = size;
 
     return 0;
+#else
+    return AVERROR(ENOSYS);
+#endif
 }
 
 static void cbs_av1_flush(CodedBitstreamContext *ctx)
@@ -1234,6 +1284,7 @@ static void cbs_av1_close(CodedBitstreamContext *ctx)
     av_buffer_unref(&priv->frame_header_ref);
 }
 
+#if CBS_OBU_METADATA
 static void cbs_av1_free_metadata(AVRefStructOpaque unused, void *content)
 {
     AV1RawOBU *obu = content;
@@ -1255,6 +1306,7 @@ static void cbs_av1_free_metadata(AVRefStructOpaque unused, void *content)
         av_buffer_unref(&md->metadata.unknown.payload_ref);
     }
 }
+#endif
 
 static const CodedBitstreamUnitTypeDescriptor cbs_av1_unit_types[] = {
     CBS_UNIT_TYPE_POD(AV1_OBU_SEQUENCE_HEADER,        AV1RawOBU),
@@ -1284,13 +1336,19 @@ static const CodedBitstreamUnitTypeDescriptor cbs_av1_unit_types[] = {
                             offsetof(AV1RawOBU, obu.frame.tile_group.tile_data.data) }
         },
     },
+#if CBS_OBU_TILE_LIST
     CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_TILE_LIST,  AV1RawOBU,
                                obu.tile_list.tile_data.data),
+#endif
+#if CBS_OBU_PADDING
     CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_PADDING,    AV1RawOBU,
                                obu.padding.payload),
+#endif
 
+#if CBS_OBU_METADATA
     CBS_UNIT_TYPE_COMPLEX(AV1_OBU_METADATA, AV1RawOBU,
                           &cbs_av1_free_metadata),
+#endif
 
     CBS_UNIT_TYPE_END_OF_LIST
 };
diff --git a/libavcodec/cbs_av1.h b/libavcodec/cbs_av1.h
index 62c7720142..0c73e12c84 100644
--- a/libavcodec/cbs_av1.h
+++ b/libavcodec/cbs_av1.h
@@ -25,6 +25,15 @@
 #include "av1.h"
 #include "cbs.h"
 
+#ifndef CBS_OBU_METADATA
+#define CBS_OBU_METADATA 1
+#endif
+#ifndef CBS_OBU_TILE_LIST
+#define CBS_OBU_TILE_LIST 1
+#endif
+#ifndef CBS_OBU_PADDING
+#define CBS_OBU_PADDING 1
+#endif
 
 typedef struct AV1RawOBUHeader {
     uint8_t obu_forbidden_bit;
@@ -411,9 +420,15 @@ typedef struct AV1RawOBU {
         AV1RawFrameHeader    frame_header;
         AV1RawFrame          frame;
         AV1RawTileGroup      tile_group;
+#if CBS_OBU_TILE_LIST
         AV1RawTileList       tile_list;
+#endif
+#if CBS_OBU_METADATA
         AV1RawMetadata       metadata;
+#endif
+#if CBS_OBU_PADDING
         AV1RawPadding        padding;
+#endif
     } obu;
 } AV1RawOBU;
 
diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c
index 62a83945ec..b594bfd22b 100644
--- a/libavcodec/cbs_av1_syntax_template.c
+++ b/libavcodec/cbs_av1_syntax_template.c
@@ -1868,6 +1868,7 @@ static int FUNC(frame_obu)(CodedBitstreamContext *ctx, RWContext *rw,
     return 0;
 }
 
+#if CBS_OBU_TILE_LIST
 static int FUNC(tile_list_obu)(CodedBitstreamContext *ctx, RWContext *rw,
                                AV1RawTileList *current)
 {
@@ -1882,7 +1883,9 @@ static int FUNC(tile_list_obu)(CodedBitstreamContext *ctx, RWContext *rw,
 
     return 0;
 }
+#endif
 
+#if CBS_OBU_METADATA
 static int FUNC(metadata_hdr_cll)(CodedBitstreamContext *ctx, RWContext *rw,
                                   AV1RawMetadataHDRCLL *current)
 {
@@ -2101,7 +2104,9 @@ static int FUNC(metadata_obu)(CodedBitstreamContext *ctx, RWContext *rw,
 
     return 0;
 }
+#endif
 
+#if CBS_OBU_PADDING
 static int FUNC(padding_obu)(CodedBitstreamContext *ctx, RWContext *rw,
                              AV1RawPadding *current)
 {
@@ -2125,3 +2130,4 @@ static int FUNC(padding_obu)(CodedBitstreamContext *ctx, RWContext *rw,
 
     return 0;
 }
+#endif
diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h
index 80cad2b162..f15ba1ab90 100644
--- a/libavcodec/cbs_internal.h
+++ b/libavcodec/cbs_internal.h
@@ -22,6 +22,8 @@
 #include <stddef.h>
 #include <stdint.h>
 
+#include "config.h"
+
 #include "libavutil/log.h"
 
 #include "cbs.h"
@@ -30,6 +32,40 @@
 #include "put_bits.h"
 #include "libavutil/refstruct.h"
 
+#ifndef CBS_READ
+#define CBS_READ 1
+#endif
+#ifndef CBS_WRITE
+#define CBS_WRITE 1
+#endif
+#ifndef CBS_TRACE
+#define CBS_TRACE 1
+#endif
+
+#ifndef CBS_AV1
+#define CBS_AV1 CONFIG_CBS_AV1
+#endif
+#ifndef CBS_H264
+#define CBS_H264 CONFIG_CBS_H264
+#endif
+#ifndef CBS_H265
+#define CBS_H265 CONFIG_CBS_H265
+#endif
+#ifndef CBS_H266
+#define CBS_H266 CONFIG_CBS_H266
+#endif
+#ifndef CBS_JPEG
+#define CBS_JPEG CONFIG_CBS_JPEG
+#endif
+#ifndef CBS_MPEG2
+#define CBS_MPEG2 CONFIG_CBS_MPEG2
+#endif
+#ifndef CBS_VP8
+#define CBS_VP8 CONFIG_CBS_VP8
+#endif
+#ifndef CBS_VP9
+#define CBS_VP9 CONFIG_CBS_VP9
+#endif
 
 enum CBSContentType {
     // Unit content may contain some references to other structures, but all
@@ -204,6 +240,7 @@ int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
 #define MIN_INT_BITS(length) (-(INT64_C(1) << ((length) - 1)))
 
 
+#if CBS_TRACE
 // Start of a syntax element during read tracing.
 #define CBS_TRACE_READ_START() \
     GetBitContext trace_start; \
@@ -284,6 +321,17 @@ int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
         } \
     } while (0)
 
+#else // CBS_TRACE
+#define CBS_TRACE_READ_START() do { } while (0)
+#define CBS_TRACE_READ_END() do { } while (0)
+#define CBS_TRACE_READ_END_NO_SUBSCRIPTS() do { } while (0)
+#define CBS_TRACE_READ_END_VALUE_ONLY() do { } while (0)
+#define CBS_TRACE_WRITE_START() do { } while (0)
+#define CBS_TRACE_WRITE_END() do { } while (0)
+#define CBS_TRACE_WRITE_END_NO_SUBSCRIPTS() do { } while (0)
+#define CBS_TRACE_WRITE_END_VALUE_ONLY() do { } while (0)
+#endif // CBS_TRACE
+
 #define TYPE_LIST(...) { __VA_ARGS__ }
 #define CBS_UNIT_TYPE_POD(type_, structure) { \
         .nb_unit_types  = 1, \
-- 
2.48.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".

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [FFmpeg-devel] [PATCH v2 3/3] avformat/movenccenc: add support for CENC AV1 encryption
  2025-03-21 19:42         ` [FFmpeg-devel] [PATCH 2/3] avcodec/cbs: allow fine tunning selection of features James Almer
@ 2025-03-21 19:42           ` James Almer
  2025-03-22 14:25           ` [FFmpeg-devel] [PATCH 2/3] avcodec/cbs: allow fine tunning selection of features Andreas Rheinhardt
  1 sibling, 0 replies; 9+ messages in thread
From: James Almer @ 2025-03-21 19:42 UTC (permalink / raw)
  To: ffmpeg-devel

Signed-off-by: James Almer <jamrial@gmail.com>
---
 configure                |   2 +-
 libavformat/Makefile     |   1 +
 libavformat/cbs.c        |  10 ++
 libavformat/cbs_av1.c    |   6 ++
 libavformat/movenc.c     |  13 ++-
 libavformat/movenccenc.c | 223 ++++++++++++++++++++++++++++++++++++++-
 libavformat/movenccenc.h |  20 +++-
 7 files changed, 269 insertions(+), 6 deletions(-)
 create mode 100644 libavformat/cbs.c
 create mode 100644 libavformat/cbs_av1.c

diff --git a/configure b/configure
index 14f7bcde0e..0f6b6c20fb 100755
--- a/configure
+++ b/configure
@@ -3689,7 +3689,7 @@ mlp_demuxer_select="mlp_parser"
 mmf_muxer_select="riffenc"
 mov_demuxer_select="iso_media riffdec"
 mov_demuxer_suggest="iamfdec zlib"
-mov_muxer_select="iso_media iso_writer riffenc rtpenc_chain vp9_superframe_bsf aac_adtstoasc_bsf ac3_parser"
+mov_muxer_select="iso_media iso_writer riffenc rtpenc_chain vp9_superframe_bsf aac_adtstoasc_bsf ac3_parser cbs_av1"
 mov_muxer_suggest="iamfenc"
 mp3_demuxer_select="mpegaudio_parser"
 mp3_muxer_select="mpegaudioheader"
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 7730e7c4e6..1e57ae7d8a 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -740,6 +740,7 @@ SHLIBOBJS-$(CONFIG_JNI)                  += ffjni.o
 SHLIBOBJS-$(CONFIG_JPEGXL_ANIM_DEMUXER)  += jpegxl_parse.o
 SHLIBOBJS-$(CONFIG_MATROSKA_DEMUXER)     += mpeg4audio_sample_rates.o
 SHLIBOBJS-$(CONFIG_MOV_DEMUXER)          += ac3_channel_layout_tab.o
+SHLIBOBJS-$(CONFIG_MOV_MUXER)            += cbs.o cbs_av1.o
 SHLIBOBJS-$(CONFIG_MP3_MUXER)            += mpegaudiotabs.o
 SHLIBOBJS-$(CONFIG_MXF_MUXER)            += golomb_tab.o \
                                             rangecoder_dec.o
diff --git a/libavformat/cbs.c b/libavformat/cbs.c
new file mode 100644
index 0000000000..9e970004ba
--- /dev/null
+++ b/libavformat/cbs.c
@@ -0,0 +1,10 @@
+#define CBS_WRITE 0
+#define CBS_TRACE 0
+#define CBS_H264 0
+#define CBS_H265 0
+#define CBS_H266 0
+#define CBS_JPEG 0
+#define CBS_MPEG2 0
+#define CBS_VP8 0
+#define CBS_VP9 0
+#include "libavcodec/cbs.c"
diff --git a/libavformat/cbs_av1.c b/libavformat/cbs_av1.c
new file mode 100644
index 0000000000..47a4d0c3a1
--- /dev/null
+++ b/libavformat/cbs_av1.c
@@ -0,0 +1,6 @@
+#define CBS_WRITE 0
+#define CBS_TRACE 0
+#define CBS_OBU_TILE_LIST 0
+#define CBS_OBU_METADATA 0
+#define CBS_OBU_PADDING 0
+#include "libavcodec/cbs_av1.c"
diff --git a/libavformat/movenc.c b/libavformat/movenc.c
index af013e1fc6..c60c46012f 100644
--- a/libavformat/movenc.c
+++ b/libavformat/movenc.c
@@ -6767,7 +6767,7 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
         } else {
             size = ff_vvc_annexb2mp4(pb, pkt->data, pkt->size, 0, NULL);
         }
-    } else if (par->codec_id == AV_CODEC_ID_AV1) {
+    } else if (par->codec_id == AV_CODEC_ID_AV1 && !trk->cenc.aes_ctr) {
         if (trk->hint_track >= 0 && trk->hint_track < mov->nb_tracks) {
             ret = ff_av1_filter_obus_buf(pkt->data, &reformatted_data,
                                          &size, &offset);
@@ -6815,6 +6815,13 @@ int ff_mov_write_packet(AVFormatContext *s, AVPacket *pkt)
                 ret = ff_mov_cenc_avc_write_nal_units(s, &trk->cenc, nal_size_length, pb, pkt->data, size);
             } else if(par->codec_id == AV_CODEC_ID_VVC) {
                 ret = AVERROR_PATCHWELCOME;
+            } else if(par->codec_id == AV_CODEC_ID_AV1) {
+                av_assert0(size == pkt->size);
+				ret = ff_mov_cenc_av1_write_obus(s, &trk->cenc, pb, pkt);
+                if (ret > 0) {
+                    size = ret;
+                    ret = 0;
+                }
             } else {
                 ret = ff_mov_cenc_write_packet(&trk->cenc, pb, pkt->data, size);
             }
@@ -8135,8 +8142,8 @@ static int mov_init(AVFormatContext *s)
         if (mov->encryption_scheme == MOV_ENC_CENC_AES_CTR) {
             ret = ff_mov_cenc_init(&track->cenc, mov->encryption_key,
                 (track->par->codec_id == AV_CODEC_ID_H264 || track->par->codec_id == AV_CODEC_ID_HEVC ||
-                 track->par->codec_id == AV_CODEC_ID_VVC),
-                s->flags & AVFMT_FLAG_BITEXACT);
+                 track->par->codec_id == AV_CODEC_ID_VVC || track->par->codec_id == AV_CODEC_ID_AV1),
+                 track->par->codec_id, s->flags & AVFMT_FLAG_BITEXACT);
             if (ret)
                 return ret;
         }
diff --git a/libavformat/movenccenc.c b/libavformat/movenccenc.c
index f54d3bcbca..af801eb3a0 100644
--- a/libavformat/movenccenc.c
+++ b/libavformat/movenccenc.c
@@ -19,6 +19,9 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 #include "movenccenc.h"
+#include "libavcodec/av1_parse.h"
+#include "libavcodec/bytestream.h"
+#include "libavcodec/cbs_av1.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
 #include "avio_internal.h"
@@ -280,6 +283,203 @@ int ff_mov_cenc_avc_write_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx,
     return 0;
 }
 
+static int write_tiles(AVFormatContext *s, MOVMuxCencContext *ctx, AVIOContext *pb, AV1_OBU_Type type,
+                       const AV1RawFrameHeader *frame_header, const uint8_t *fh_data, size_t fh_data_size,
+                       const AV1RawTileGroup *tile_group)
+{
+    GetByteContext gb;
+    size_t tgh_data_size = tile_group->data_size;
+    int cur_tile_num = frame_header->tile_cols * frame_header->tile_rows;
+    int total = 0;
+
+    // Get the Frame Header size
+    if (type == AV1_OBU_FRAME)
+        fh_data_size -= tgh_data_size;
+    // Get the Tile Group Header size
+    tgh_data_size -= tile_group->tile_data.data_size;
+
+    if (ctx->tile_num < cur_tile_num) {
+        int ret = av_reallocp_array(&ctx->tile_group_sizes, cur_tile_num,
+                                    sizeof(*ctx->tile_group_sizes));
+        if (ret < 0) {
+            ctx->tile_num = 0;
+            return ret;
+        }
+    }
+    ctx->tile_num = cur_tile_num;
+
+    total = fh_data_size + tgh_data_size;
+    ctx->clear_bytes += total;
+
+    bytestream2_init(&gb, tile_group->tile_data.data, tile_group->tile_data.data_size);
+
+    // Build a table with block sizes for encrypted bytes and clear bytes
+    for (unsigned tile_num = tile_group->tg_start; tile_num <= tile_group->tg_end; tile_num++) {
+        uint32_t encrypted_bytes, tile_size_bytes, tile_size = 0;
+
+        if (tile_num == tile_group->tg_end) {
+            tile_size = bytestream2_get_bytes_left(&gb);
+            encrypted_bytes = tile_size & ~0xFU;
+            ctx->clear_bytes += tile_size & 0xFU;
+
+            ctx->tile_group_sizes[tile_num].encrypted_bytes   = encrypted_bytes;
+            ctx->tile_group_sizes[tile_num].aux_clear_bytes   = encrypted_bytes ? ctx->clear_bytes : 0;
+            ctx->tile_group_sizes[tile_num].write_clear_bytes = tile_size & 0xFU;
+
+            if (encrypted_bytes)
+                ctx->clear_bytes = 0;
+            total += tile_size;
+
+            break;
+        }
+
+        tile_size_bytes = frame_header->tile_size_bytes_minus1 + 1;
+        if (bytestream2_get_bytes_left(&gb) < tile_size_bytes)
+            return AVERROR_INVALIDDATA;
+
+        for (int i = 0; i < tile_size_bytes; i++)
+            tile_size |= bytestream2_get_byteu(&gb) << 8 * i;
+        if (bytestream2_get_bytes_left(&gb) <= tile_size)
+            return AVERROR_INVALIDDATA;
+        tile_size++;
+
+        // The spec requires encrypted bytes to be in blocks multiple of 16
+        encrypted_bytes   =  tile_size & ~0xFU;
+        ctx->clear_bytes += (tile_size &  0xFU) + tile_size_bytes;
+
+        ctx->tile_group_sizes[tile_num].encrypted_bytes   = encrypted_bytes;
+        ctx->tile_group_sizes[tile_num].aux_clear_bytes   = encrypted_bytes ? ctx->clear_bytes : 0;
+        ctx->tile_group_sizes[tile_num].write_clear_bytes = (tile_size & 0xFU) + tile_size_bytes;
+
+        if (encrypted_bytes)
+            ctx->clear_bytes = 0;
+
+        total += tile_size + tile_size_bytes;
+        bytestream2_skipu(&gb, tile_size);
+    }
+
+    bytestream2_init(&gb, tile_group->tile_data.data, tile_group->tile_data.data_size);
+
+    avio_write(pb, fh_data, fh_data_size);
+    avio_write(pb, tile_group->data, tgh_data_size);
+
+    for (unsigned tile_num = tile_group->tg_start; tile_num <= tile_group->tg_end; tile_num++) {
+        const struct MOVMuxCencAV1TGInfo *sizes = &ctx->tile_group_sizes[tile_num];
+
+        avio_write(pb, gb.buffer, sizes->write_clear_bytes);
+        bytestream2_skipu(&gb, sizes->write_clear_bytes);
+        mov_cenc_write_encrypted(ctx, pb, gb.buffer, sizes->encrypted_bytes);
+        bytestream2_skipu(&gb, sizes->encrypted_bytes);
+        if (sizes->encrypted_bytes) {
+            unsigned clear_bytes = sizes->aux_clear_bytes;
+            if (clear_bytes > UINT16_MAX) {
+                auxiliary_info_add_subsample(ctx, UINT16_MAX, 0);
+                clear_bytes -= UINT16_MAX;
+            }
+            auxiliary_info_add_subsample(ctx, clear_bytes, sizes->encrypted_bytes);
+        }
+    }
+
+    return total;
+}
+
+int ff_mov_cenc_av1_write_obus(AVFormatContext *s, MOVMuxCencContext* ctx,
+                               AVIOContext *pb, const AVPacket *pkt)
+{
+    CodedBitstreamFragment *td = &ctx->temporal_unit;
+    const CodedBitstreamAV1Context *av1 = ctx->cbc->priv_data;
+    const AV1RawFrameHeader *frame_header = NULL;
+    const uint8_t *fh_data = NULL;
+    size_t fh_data_size;
+    int out_size = 0, ret;
+
+    ret = mov_cenc_start_packet(ctx);
+    if (ret) {
+        return ret;
+    }
+
+    ret = ff_cbs_read_packet(ctx->cbc, td, pkt);
+    if (ret < 0) {
+        av_log(s, AV_LOG_ERROR, "CENC-AV1: Failed to parse temporal unit.\n");
+        return ret;
+    }
+
+    if (!av1->sequence_header) {
+        av_log(s, AV_LOG_ERROR, "CENC-AV1: No sequence header available\n");
+        ret = AVERROR_INVALIDDATA;
+        goto end;
+    }
+
+    for (int i = 0; i < td->nb_units; i++) {
+        const CodedBitstreamUnit *unit = &td->units[i];
+        const AV1RawOBU *obu = unit->content;
+
+        switch (unit->type) {
+        case AV1_OBU_FRAME_HEADER:
+            if (!obu->obu.frame_header.show_existing_frame) {
+                frame_header = &obu->obu.frame_header;
+                fh_data      = unit->data;
+                fh_data_size = unit->data_size;
+                break;
+            }
+        // fall-through
+        case AV1_OBU_SEQUENCE_HEADER:
+        case AV1_OBU_METADATA:
+            avio_write(pb, unit->data, unit->data_size);
+            ctx->clear_bytes += unit->data_size;
+            out_size += unit->data_size;
+            break;
+        case AV1_OBU_FRAME:
+            frame_header = &obu->obu.frame.header;
+            fh_data      = unit->data;
+            fh_data_size = unit->data_size;
+        // fall-through
+        case AV1_OBU_TILE_GROUP:
+            {
+                const AV1RawTileGroup *tile_group;
+
+                if (!frame_header){
+                    ret = AVERROR_INVALIDDATA;
+                    goto end;
+                }
+
+                if (unit->type == AV1_OBU_FRAME)
+                    tile_group = &obu->obu.frame.tile_group;
+                else
+                    tile_group = &obu->obu.tile_group;
+
+                ret = write_tiles(s, ctx, pb, unit->type,
+                                  frame_header, fh_data, fh_data_size, tile_group);
+                if (ret < 0) {
+                    av_log(s, AV_LOG_ERROR, "CENC-AV1: Failed to write tiles\n");
+                    goto end;
+                }
+                av_assert0(ret == unit->data_size);
+                out_size += unit->data_size;
+                frame_header = NULL;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
+    if (ctx->clear_bytes)
+        auxiliary_info_add_subsample(ctx, ctx->clear_bytes, 0);
+    ctx->clear_bytes = 0;
+
+    ret = mov_cenc_end_packet(ctx);
+    if (ret) {
+        ret = AVERROR_INVALIDDATA;
+        goto end;
+    }
+
+    ret = out_size;
+end:
+    ff_cbs_fragment_reset(td);
+    return ret;
+}
+
 /* TODO: reuse this function from movenc.c */
 static int64_t update_size(AVIOContext *pb, int64_t pos)
 {
@@ -388,8 +588,16 @@ int ff_mov_cenc_write_sinf_tag(MOVTrack* track, AVIOContext *pb, uint8_t* kid)
     return update_size(pb, pos);
 }
 
+static const CodedBitstreamUnitType decompose_unit_types[] = {
+    AV1_OBU_TEMPORAL_DELIMITER,
+    AV1_OBU_SEQUENCE_HEADER,
+    AV1_OBU_FRAME_HEADER,
+    AV1_OBU_TILE_GROUP,
+    AV1_OBU_FRAME,
+};
+
 int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key,
-                     int use_subsamples, int bitexact)
+                     int use_subsamples, enum AVCodecID codec_id, int bitexact)
 {
     int ret;
 
@@ -409,6 +617,15 @@ int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key,
 
     ctx->use_subsamples = use_subsamples;
 
+    if (codec_id == AV_CODEC_ID_AV1) {
+        ret = ff_cbs_init(&ctx->cbc, codec_id, NULL);
+        if (ret < 0)
+            return ret;
+
+        ctx->cbc->decompose_unit_types    = decompose_unit_types;
+        ctx->cbc->nb_decompose_unit_types = FF_ARRAY_ELEMS(decompose_unit_types);
+    }
+
     return 0;
 }
 
@@ -417,4 +634,8 @@ void ff_mov_cenc_free(MOVMuxCencContext* ctx)
     av_aes_ctr_free(ctx->aes_ctr);
     av_freep(&ctx->auxiliary_info);
     av_freep(&ctx->auxiliary_info_sizes);
+
+    av_freep(&ctx->tile_group_sizes);
+    ff_cbs_fragment_free(&ctx->temporal_unit);
+    ff_cbs_close(&ctx->cbc);
 }
diff --git a/libavformat/movenccenc.h b/libavformat/movenccenc.h
index 7da5268090..722914dc1c 100644
--- a/libavformat/movenccenc.h
+++ b/libavformat/movenccenc.h
@@ -23,6 +23,7 @@
 #define AVFORMAT_MOVENCCENC_H
 
 #include "libavutil/aes_ctr.h"
+#include "libavcodec/cbs.h"
 #include "avformat.h"
 #include "avio.h"
 
@@ -30,6 +31,12 @@
 
 struct MOVTrack;
 
+struct MOVMuxCencAV1TGInfo {
+    uint32_t encrypted_bytes;
+    uint32_t write_clear_bytes;
+    uint32_t aux_clear_bytes;
+};
+
 typedef struct {
     struct AVAESCTR* aes_ctr;
     uint8_t* auxiliary_info;
@@ -43,6 +50,14 @@ typedef struct {
     size_t auxiliary_info_subsample_start;
     uint8_t* auxiliary_info_sizes;
     size_t  auxiliary_info_sizes_alloc_size;
+
+    /* AV1 */
+    struct MOVMuxCencAV1TGInfo *tile_group_sizes;
+    uint32_t clear_bytes;
+    int tile_num;
+    /* CBS */
+    CodedBitstreamContext *cbc;
+    CodedBitstreamFragment temporal_unit;
 } MOVMuxCencContext;
 
 /**
@@ -50,7 +65,8 @@ typedef struct {
  * @param key encryption key, must have a length of AES_CTR_KEY_SIZE
  * @param use_subsamples when enabled parts of a packet can be encrypted, otherwise the whole packet is encrypted
  */
-int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key, int use_subsamples, int bitexact);
+int ff_mov_cenc_init(MOVMuxCencContext* ctx, uint8_t* encryption_key, int use_subsamples,
+                     enum AVCodecID codec_id, int bitexact);
 
 /**
  * Free a CENC context
@@ -73,6 +89,8 @@ int ff_mov_cenc_avc_parse_nal_units(MOVMuxCencContext* ctx, AVIOContext *pb, con
 int ff_mov_cenc_avc_write_nal_units(AVFormatContext *s, MOVMuxCencContext* ctx, int nal_length_size,
     AVIOContext *pb, const uint8_t *buf_in, int size);
 
+int ff_mov_cenc_av1_write_obus(AVFormatContext *s, MOVMuxCencContext* ctx,
+                               AVIOContext *pb, const AVPacket *pkt);
 /**
  * Write the cenc atoms that should reside inside stbl
  */
-- 
2.48.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".

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [FFmpeg-devel] [PATCH 2/3] avcodec/cbs: allow fine tunning selection of features
  2025-03-21 19:42         ` [FFmpeg-devel] [PATCH 2/3] avcodec/cbs: allow fine tunning selection of features James Almer
  2025-03-21 19:42           ` [FFmpeg-devel] [PATCH v2 3/3] avformat/movenccenc: add support for CENC AV1 encryption James Almer
@ 2025-03-22 14:25           ` Andreas Rheinhardt
  1 sibling, 0 replies; 9+ messages in thread
From: Andreas Rheinhardt @ 2025-03-22 14:25 UTC (permalink / raw)
  To: ffmpeg-devel

James Almer:
> This will be useful in an upcoming commit, where CBS will be utilized by
> a module outside libavcodec.
> 
> Signed-off-by: James Almer <jamrial@gmail.com>
> ---
>  libavcodec/cbs.c                     | 100 ++++++++++++++++++++++-----
>  libavcodec/cbs_av1.c                 |  64 ++++++++++++++++-
>  libavcodec/cbs_av1.h                 |  15 ++++
>  libavcodec/cbs_av1_syntax_template.c |   6 ++
>  libavcodec/cbs_internal.h            |  48 +++++++++++++
>  5 files changed, 212 insertions(+), 21 deletions(-)
> 
> diff --git a/libavcodec/cbs.c b/libavcodec/cbs.c
> index 01dd916d81..94bf174700 100644
> --- a/libavcodec/cbs.c
> +++ b/libavcodec/cbs.c
> @@ -18,8 +18,6 @@
>  
>  #include <string.h>
>  
> -#include "config.h"
> -
>  #include "libavutil/avassert.h"
>  #include "libavutil/buffer.h"
>  #include "libavutil/common.h"
> @@ -33,55 +31,55 @@
>  
>  
>  static const CodedBitstreamType *const cbs_type_table[] = {
> -#if CONFIG_CBS_AV1
> +#if CBS_AV1
>      &ff_cbs_type_av1,
>  #endif
> -#if CONFIG_CBS_H264
> +#if CBS_H264
>      &ff_cbs_type_h264,
>  #endif
> -#if CONFIG_CBS_H265
> +#if CBS_H265
>      &ff_cbs_type_h265,
>  #endif
> -#if CONFIG_CBS_H266
> +#if CBS_H266
>      &ff_cbs_type_h266,
>  #endif
> -#if CONFIG_CBS_JPEG
> +#if CBS_JPEG
>      &ff_cbs_type_jpeg,
>  #endif
> -#if CONFIG_CBS_MPEG2
> +#if CBS_MPEG2
>      &ff_cbs_type_mpeg2,
>  #endif
> -#if CONFIG_CBS_VP8
> +#if CBS_VP8
>      &ff_cbs_type_vp8,
>  #endif
> -#if CONFIG_CBS_VP9
> +#if CBS_VP9
>      &ff_cbs_type_vp9,
>  #endif
>  };
>  
>  const enum AVCodecID ff_cbs_all_codec_ids[] = {
> -#if CONFIG_CBS_AV1
> +#if CBS_AV1
>      AV_CODEC_ID_AV1,
>  #endif
> -#if CONFIG_CBS_H264
> +#if CBS_H264
>      AV_CODEC_ID_H264,
>  #endif
> -#if CONFIG_CBS_H265
> +#if CBS_H265
>      AV_CODEC_ID_H265,
>  #endif
> -#if CONFIG_CBS_H266
> +#if CBS_H266
>      AV_CODEC_ID_H266,
>  #endif
> -#if CONFIG_CBS_JPEG
> +#if CBS_JPEG
>      AV_CODEC_ID_MJPEG,
>  #endif
> -#if CONFIG_CBS_MPEG2
> +#if CBS_MPEG2
>      AV_CODEC_ID_MPEG2VIDEO,
>  #endif
> -#if CONFIG_CBS_VP8
> +#if CBS_VP8
>      AV_CODEC_ID_VP8,
>  #endif
> -#if CONFIG_CBS_VP9
> +#if CBS_VP9
>      AV_CODEC_ID_VP9,
>  #endif
>      AV_CODEC_ID_NONE
> @@ -234,6 +232,7 @@ static int cbs_read_fragment_content(CodedBitstreamContext *ctx,
>      return 0;
>  }
>  
> +#if CBS_READ
>  static int cbs_fill_fragment_data(CodedBitstreamFragment *frag,
>                                    const uint8_t *data, size_t size)
>  {
> @@ -282,37 +281,51 @@ static int cbs_read_data(CodedBitstreamContext *ctx,
>  
>      return cbs_read_fragment_content(ctx, frag);
>  }
> +#endif
>  
>  int ff_cbs_read_extradata(CodedBitstreamContext *ctx,
>                            CodedBitstreamFragment *frag,
>                            const AVCodecParameters *par)
>  {
> +#if CBS_READ
>      return cbs_read_data(ctx, frag, NULL,
>                           par->extradata,
>                           par->extradata_size, 1);
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  int ff_cbs_read_extradata_from_codec(CodedBitstreamContext *ctx,
>                                       CodedBitstreamFragment *frag,
>                                       const AVCodecContext *avctx)
>  {
> +#if CBS_READ
>      return cbs_read_data(ctx, frag, NULL,
>                           avctx->extradata,
>                           avctx->extradata_size, 1);
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  int ff_cbs_read_packet(CodedBitstreamContext *ctx,
>                         CodedBitstreamFragment *frag,
>                         const AVPacket *pkt)
>  {
> +#if CBS_READ
>      return cbs_read_data(ctx, frag, pkt->buf,
>                           pkt->data, pkt->size, 0);
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  int ff_cbs_read_packet_side_data(CodedBitstreamContext *ctx,
>                                   CodedBitstreamFragment *frag,
>                                   const AVPacket *pkt)
>  {
> +#if CBS_READ
>      size_t side_data_size;
>      const uint8_t *side_data =
>          av_packet_get_side_data(pkt, AV_PKT_DATA_NEW_EXTRADATA,
> @@ -320,16 +333,24 @@ int ff_cbs_read_packet_side_data(CodedBitstreamContext *ctx,
>  
>      return cbs_read_data(ctx, frag, NULL,
>                           side_data, side_data_size, 1);
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  int ff_cbs_read(CodedBitstreamContext *ctx,
>                  CodedBitstreamFragment *frag,
>                  const uint8_t *data, size_t size)
>  {
> +#if CBS_READ
>      return cbs_read_data(ctx, frag, NULL,
>                           data, size, 0);
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
> +#if CBS_WRITE
>  /**
>   * Allocate a new internal data buffer of the given size in the unit.
>   *
> @@ -405,10 +426,12 @@ static int cbs_write_unit_data(CodedBitstreamContext *ctx,
>  
>      return 0;
>  }
> +#endif
>  
>  int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
>                                 CodedBitstreamFragment *frag)
>  {
> +#if CBS_WRITE
>      int err, i;
>  
>      for (i = 0; i < frag->nb_units; i++) {
> @@ -440,12 +463,16 @@ int ff_cbs_write_fragment_data(CodedBitstreamContext *ctx,
>      av_assert0(frag->data && frag->data_ref);
>  
>      return 0;
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
>                             AVCodecParameters *par,
>                             CodedBitstreamFragment *frag)
>  {
> +#if CBS_WRITE
>      int err;
>  
>      err = ff_cbs_write_fragment_data(ctx, frag);
> @@ -469,12 +496,16 @@ int ff_cbs_write_extradata(CodedBitstreamContext *ctx,
>      par->extradata_size = frag->data_size;
>  
>      return 0;
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  int ff_cbs_write_packet(CodedBitstreamContext *ctx,
>                          AVPacket *pkt,
>                          CodedBitstreamFragment *frag)
>  {
> +#if CBS_WRITE
>      AVBufferRef *buf;
>      int err;
>  
> @@ -493,16 +524,21 @@ int ff_cbs_write_packet(CodedBitstreamContext *ctx,
>      pkt->size = frag->data_size;
>  
>      return 0;
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  
>  void ff_cbs_trace_header(CodedBitstreamContext *ctx,
>                           const char *name)
>  {
> +#if CBS_TRACE
>      if (!ctx->trace_enable)
>          return;
>  
>      av_log(ctx->log_ctx, ctx->trace_level, "%s\n", name);
> +#endif
>  }
>  
>  void ff_cbs_trace_read_log(void *trace_context,
> @@ -510,6 +546,7 @@ void ff_cbs_trace_read_log(void *trace_context,
>                             const char *str, const int *subscripts,
>                             int64_t value)
>  {
> +#if CBS_TRACE
>      CodedBitstreamContext *ctx = trace_context;
>      char name[256];
>      char bits[256];
> @@ -561,6 +598,7 @@ void ff_cbs_trace_read_log(void *trace_context,
>  
>      av_log(ctx->log_ctx, ctx->trace_level, "%-10d  %s%*s = %"PRId64"\n",
>             position, name, pad, bits, value);
> +#endif
>  }
>  
>  void ff_cbs_trace_write_log(void *trace_context,
> @@ -568,6 +606,7 @@ void ff_cbs_trace_write_log(void *trace_context,
>                              const char *str, const int *subscripts,
>                              int64_t value)
>  {
> +#if CBS_TRACE
>      CodedBitstreamContext *ctx = trace_context;
>  
>      // Ensure that the syntax element is written to the output buffer,
> @@ -591,6 +630,7 @@ void ff_cbs_trace_write_log(void *trace_context,
>      skip_bits_long(&gbc, position - length);
>  
>      ff_cbs_trace_read_log(ctx, &gbc, length, str, subscripts, value);
> +#endif
>  }
>  
>  static av_always_inline int cbs_read_unsigned(CodedBitstreamContext *ctx,
> @@ -633,15 +673,23 @@ int ff_cbs_read_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc,
>                           const int *subscripts, uint32_t *write_to,
>                           uint32_t range_min, uint32_t range_max)
>  {
> +#if CBS_READ
>      return cbs_read_unsigned(ctx, gbc, width, name, subscripts,
>                               write_to, range_min, range_max);
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  int ff_cbs_read_simple_unsigned(CodedBitstreamContext *ctx, GetBitContext *gbc,
>                                  int width, const char *name, uint32_t *write_to)
>  {
> +#if CBS_READ
>      return cbs_read_unsigned(ctx, gbc, width, name, NULL,
>                               write_to, 0, UINT32_MAX);
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
> @@ -649,6 +697,7 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
>                            const int *subscripts, uint32_t value,
>                            uint32_t range_min, uint32_t range_max)
>  {
> +#if CBS_WRITE
>      CBS_TRACE_WRITE_START();
>  
>      av_assert0(width > 0 && width <= 32);
> @@ -671,13 +720,20 @@ int ff_cbs_write_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
>      CBS_TRACE_WRITE_END();
>  
>      return 0;
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  int ff_cbs_write_simple_unsigned(CodedBitstreamContext *ctx, PutBitContext *pbc,
>                                   int width, const char *name, uint32_t value)
>  {
> +#if CBS_WRITE
>      return ff_cbs_write_unsigned(ctx, pbc, width, name, NULL,
>                                   value, 0, MAX_UINT_BITS(width));
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  int ff_cbs_read_signed(CodedBitstreamContext *ctx, GetBitContext *gbc,
> @@ -685,6 +741,7 @@ int ff_cbs_read_signed(CodedBitstreamContext *ctx, GetBitContext *gbc,
>                         const int *subscripts, int32_t *write_to,
>                         int32_t range_min, int32_t range_max)
>  {
> +#if CBS_READ
>      int32_t value;
>  
>      CBS_TRACE_READ_START();
> @@ -710,6 +767,9 @@ int ff_cbs_read_signed(CodedBitstreamContext *ctx, GetBitContext *gbc,
>  
>      *write_to = value;
>      return 0;
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
> @@ -717,6 +777,7 @@ int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
>                          const int *subscripts, int32_t value,
>                          int32_t range_min, int32_t range_max)
>  {
> +#if CBS_WRITE
>      CBS_TRACE_WRITE_START();
>  
>      av_assert0(width > 0 && width <= 32);
> @@ -739,6 +800,9 @@ int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
>      CBS_TRACE_WRITE_END();
>  
>      return 0;
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  
> diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c
> index d7862a2e48..e0a4eba20f 100644
> --- a/libavcodec/cbs_av1.c
> +++ b/libavcodec/cbs_av1.c
> @@ -27,6 +27,7 @@
>  #include "libavutil/refstruct.h"
>  
>  
> +#if CBS_READ
>  static int cbs_av1_read_uvlc(CodedBitstreamContext *ctx, GetBitContext *gbc,
>                               const char *name, uint32_t *write_to,
>                               uint32_t range_min, uint32_t range_max)
> @@ -84,7 +85,9 @@ static int cbs_av1_read_uvlc(CodedBitstreamContext *ctx, GetBitContext *gbc,
>      *write_to = value;
>      return 0;
>  }
> +#endif
>  
> +#if CBS_WRITE
>  static int cbs_av1_write_uvlc(CodedBitstreamContext *ctx, PutBitContext *pbc,
>                                const char *name, uint32_t value,
>                                uint32_t range_min, uint32_t range_max)
> @@ -115,7 +118,9 @@ static int cbs_av1_write_uvlc(CodedBitstreamContext *ctx, PutBitContext *pbc,
>  
>      return 0;
>  }
> +#endif
>  
> +#if CBS_READ
>  static int cbs_av1_read_leb128(CodedBitstreamContext *ctx, GetBitContext *gbc,
>                                 const char *name, uint64_t *write_to)
>  {
> @@ -146,7 +151,9 @@ static int cbs_av1_read_leb128(CodedBitstreamContext *ctx, GetBitContext *gbc,
>      *write_to = value;
>      return 0;
>  }
> +#endif
>  
> +#if CBS_WRITE
>  static int cbs_av1_write_leb128(CodedBitstreamContext *ctx, PutBitContext *pbc,
>                                  const char *name, uint64_t value, int fixed_length)
>  {
> @@ -182,7 +189,9 @@ static int cbs_av1_write_leb128(CodedBitstreamContext *ctx, PutBitContext *pbc,
>  
>      return 0;
>  }
> +#endif
>  
> +#if CBS_READ
>  static int cbs_av1_read_ns(CodedBitstreamContext *ctx, GetBitContext *gbc,
>                             uint32_t n, const char *name,
>                             const int *subscripts, uint32_t *write_to)
> @@ -220,7 +229,9 @@ static int cbs_av1_read_ns(CodedBitstreamContext *ctx, GetBitContext *gbc,
>      *write_to = value;
>      return 0;
>  }
> +#endif
>  
> +#if CBS_WRITE
>  static int cbs_av1_write_ns(CodedBitstreamContext *ctx, PutBitContext *pbc,
>                              uint32_t n, const char *name,
>                              const int *subscripts, uint32_t value)
> @@ -256,7 +267,9 @@ static int cbs_av1_write_ns(CodedBitstreamContext *ctx, PutBitContext *pbc,
>  
>      return 0;
>  }
> +#endif
>  
> +#if CBS_READ
>  static int cbs_av1_read_increment(CodedBitstreamContext *ctx, GetBitContext *gbc,
>                                    uint32_t range_min, uint32_t range_max,
>                                    const char *name, uint32_t *write_to)
> @@ -284,7 +297,9 @@ static int cbs_av1_read_increment(CodedBitstreamContext *ctx, GetBitContext *gbc
>      *write_to = value;
>      return 0;
>  }
> +#endif
>  
> +#if CBS_WRITE
>  static int cbs_av1_write_increment(CodedBitstreamContext *ctx, PutBitContext *pbc,
>                                     uint32_t range_min, uint32_t range_max,
>                                     const char *name, uint32_t value)
> @@ -315,7 +330,9 @@ static int cbs_av1_write_increment(CodedBitstreamContext *ctx, PutBitContext *pb
>  
>      return 0;
>  }
> +#endif
>  
> +#if CBS_READ
>  static int cbs_av1_read_subexp(CodedBitstreamContext *ctx, GetBitContext *gbc,
>                                 uint32_t range_max, const char *name,
>                                 const int *subscripts, uint32_t *write_to)
> @@ -360,7 +377,9 @@ static int cbs_av1_read_subexp(CodedBitstreamContext *ctx, GetBitContext *gbc,
>      *write_to = value;
>      return err;
>  }
> +#endif
>  
> +#if CBS_WRITE
>  static int cbs_av1_write_subexp(CodedBitstreamContext *ctx, PutBitContext *pbc,
>                                  uint32_t range_max, const char *name,
>                                  const int *subscripts, uint32_t value)
> @@ -420,6 +439,7 @@ static int cbs_av1_write_subexp(CodedBitstreamContext *ctx, PutBitContext *pbc,
>  
>      return err;
>  }
> +#endif
>  
>  
>  static int cbs_av1_tile_log2(int blksize, int target)
> @@ -441,7 +461,7 @@ static int cbs_av1_get_relative_dist(const AV1RawSequenceHeader *seq,
>      return diff;
>  }
>  
> -static size_t cbs_av1_get_payload_bytes_left(GetBitContext *gbc)
> +static av_unused size_t cbs_av1_get_payload_bytes_left(GetBitContext *gbc)
>  {
>      GetBitContext tmp = *gbc;
>      size_t size = 0;
> @@ -469,6 +489,7 @@ static size_t cbs_av1_get_payload_bytes_left(GetBitContext *gbc)
>  
>  #define SUBSCRIPTS(subs, ...) (subs > 0 ? ((int[subs + 1]){ subs, __VA_ARGS__ }) : NULL)
>  
> +#if CBS_READ
>  #define fc(width, name, range_min, range_max) \
>          xf(width, name, current->name, range_min, range_max, 0, )
>  #define flag(name) fb(1, name)
> @@ -584,8 +605,9 @@ static size_t cbs_av1_get_payload_bytes_left(GetBitContext *gbc)
>  #undef leb128
>  #undef infer
>  #undef byte_alignment
> +#endif // CBS_READ
>  
> -
> +#if CBS_WRITE
>  #define WRITE
>  #define READWRITE write
>  #define RWContext PutBitContext
> @@ -668,12 +690,13 @@ static size_t cbs_av1_get_payload_bytes_left(GetBitContext *gbc)
>  #undef leb128
>  #undef infer
>  #undef byte_alignment
> -
> +#endif // CBS_WRITE
>  
>  static int cbs_av1_split_fragment(CodedBitstreamContext *ctx,
>                                    CodedBitstreamFragment *frag,
>                                    int header)
>  {
> +#if CBS_READ
>      GetBitContext gbc;
>      uint8_t *data;
>      size_t size;
> @@ -777,6 +800,9 @@ success:
>  fail:
>      ctx->trace_enable = trace;
>      return err;
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  static int cbs_av1_ref_tile_data(CodedBitstreamContext *ctx,
> @@ -809,6 +835,7 @@ static int cbs_av1_ref_tile_data(CodedBitstreamContext *ctx,
>  static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
>                               CodedBitstreamUnit *unit)
>  {
> +#if CBS_READ
>      CodedBitstreamAV1Context *priv = ctx->priv_data;
>      AV1RawOBU *obu;
>      GetBitContext gbc;
> @@ -931,6 +958,7 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
>                  return err;
>          }
>          break;
> +#if CBS_OBU_TILE_LIST
>      case AV1_OBU_TILE_LIST:
>          {
>              err = cbs_av1_read_tile_list_obu(ctx, &gbc,
> @@ -946,6 +974,8 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
>                  return err;
>          }
>          break;
> +#endif
> +#if CBS_OBU_METADATA
>      case AV1_OBU_METADATA:
>          {
>              err = cbs_av1_read_metadata_obu(ctx, &gbc, &obu->obu.metadata);
> @@ -953,6 +983,8 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
>                  return err;
>          }
>          break;
> +#endif
> +#if CBS_OBU_PADDING
>      case AV1_OBU_PADDING:
>          {
>              err = cbs_av1_read_padding_obu(ctx, &gbc, &obu->obu.padding);
> @@ -960,6 +992,7 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
>                  return err;
>          }
>          break;
> +#endif
>      default:
>          return AVERROR(ENOSYS);
>      }
> @@ -982,12 +1015,16 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx,
>      }
>  
>      return 0;
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  static int cbs_av1_write_obu(CodedBitstreamContext *ctx,
>                               CodedBitstreamUnit *unit,
>                               PutBitContext *pbc)
>  {
> +#if CBS_WRITE
>      CodedBitstreamAV1Context *priv = ctx->priv_data;
>      AV1RawOBU *obu = unit->content;
>      PutBitContext pbc_tmp;
> @@ -1087,6 +1124,7 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx,
>              td = &tile_group->tile_data;
>          }
>          break;
> +#if CBS_OBU_TILE_LIST
>      case AV1_OBU_TILE_LIST:
>          {
>              err = cbs_av1_write_tile_list_obu(ctx, pbc, &obu->obu.tile_list);
> @@ -1096,6 +1134,8 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx,
>              td = &obu->obu.tile_list.tile_data;
>          }
>          break;
> +#endif
> +#if CBS_OBU_METADATA
>      case AV1_OBU_METADATA:
>          {
>              err = cbs_av1_write_metadata_obu(ctx, pbc, &obu->obu.metadata);
> @@ -1103,6 +1143,8 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx,
>                  goto error;
>          }
>          break;
> +#endif
> +#if CBS_OBU_PADDING
>      case AV1_OBU_PADDING:
>          {
>              err = cbs_av1_write_padding_obu(ctx, pbc, &obu->obu.padding);
> @@ -1110,6 +1152,7 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx,
>                  goto error;
>          }
>          break;
> +#endif
>      default:
>          err = AVERROR(ENOSYS);
>          goto error;
> @@ -1182,11 +1225,15 @@ error:
>      av_buffer_unref(&av1ctx.frame_header_ref);
>  
>      return err;
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  static int cbs_av1_assemble_fragment(CodedBitstreamContext *ctx,
>                                       CodedBitstreamFragment *frag)
>  {
> +#if CBS_WRITE
>      size_t size, pos;
>      int i;
>  
> @@ -1210,6 +1257,9 @@ static int cbs_av1_assemble_fragment(CodedBitstreamContext *ctx,
>      frag->data_size = size;
>  
>      return 0;
> +#else
> +    return AVERROR(ENOSYS);
> +#endif
>  }
>  
>  static void cbs_av1_flush(CodedBitstreamContext *ctx)
> @@ -1234,6 +1284,7 @@ static void cbs_av1_close(CodedBitstreamContext *ctx)
>      av_buffer_unref(&priv->frame_header_ref);
>  }
>  
> +#if CBS_OBU_METADATA
>  static void cbs_av1_free_metadata(AVRefStructOpaque unused, void *content)
>  {
>      AV1RawOBU *obu = content;
> @@ -1255,6 +1306,7 @@ static void cbs_av1_free_metadata(AVRefStructOpaque unused, void *content)
>          av_buffer_unref(&md->metadata.unknown.payload_ref);
>      }
>  }
> +#endif
>  
>  static const CodedBitstreamUnitTypeDescriptor cbs_av1_unit_types[] = {
>      CBS_UNIT_TYPE_POD(AV1_OBU_SEQUENCE_HEADER,        AV1RawOBU),
> @@ -1284,13 +1336,19 @@ static const CodedBitstreamUnitTypeDescriptor cbs_av1_unit_types[] = {
>                              offsetof(AV1RawOBU, obu.frame.tile_group.tile_data.data) }
>          },
>      },
> +#if CBS_OBU_TILE_LIST
>      CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_TILE_LIST,  AV1RawOBU,
>                                 obu.tile_list.tile_data.data),
> +#endif
> +#if CBS_OBU_PADDING
>      CBS_UNIT_TYPE_INTERNAL_REF(AV1_OBU_PADDING,    AV1RawOBU,
>                                 obu.padding.payload),
> +#endif
>  
> +#if CBS_OBU_METADATA
>      CBS_UNIT_TYPE_COMPLEX(AV1_OBU_METADATA, AV1RawOBU,
>                            &cbs_av1_free_metadata),
> +#endif
>  
>      CBS_UNIT_TYPE_END_OF_LIST
>  };
> diff --git a/libavcodec/cbs_av1.h b/libavcodec/cbs_av1.h
> index 62c7720142..0c73e12c84 100644
> --- a/libavcodec/cbs_av1.h
> +++ b/libavcodec/cbs_av1.h
> @@ -25,6 +25,15 @@
>  #include "av1.h"
>  #include "cbs.h"
>  
> +#ifndef CBS_OBU_METADATA
> +#define CBS_OBU_METADATA 1
> +#endif
> +#ifndef CBS_OBU_TILE_LIST
> +#define CBS_OBU_TILE_LIST 1
> +#endif
> +#ifndef CBS_OBU_PADDING
> +#define CBS_OBU_PADDING 1
> +#endif
>  
>  typedef struct AV1RawOBUHeader {
>      uint8_t obu_forbidden_bit;
> @@ -411,9 +420,15 @@ typedef struct AV1RawOBU {
>          AV1RawFrameHeader    frame_header;
>          AV1RawFrame          frame;
>          AV1RawTileGroup      tile_group;
> +#if CBS_OBU_TILE_LIST
>          AV1RawTileList       tile_list;
> +#endif
> +#if CBS_OBU_METADATA
>          AV1RawMetadata       metadata;
> +#endif
> +#if CBS_OBU_PADDING
>          AV1RawPadding        padding;
> +#endif
>      } obu;
>  } AV1RawOBU;
>  
> diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c
> index 62a83945ec..b594bfd22b 100644
> --- a/libavcodec/cbs_av1_syntax_template.c
> +++ b/libavcodec/cbs_av1_syntax_template.c
> @@ -1868,6 +1868,7 @@ static int FUNC(frame_obu)(CodedBitstreamContext *ctx, RWContext *rw,
>      return 0;
>  }
>  
> +#if CBS_OBU_TILE_LIST
>  static int FUNC(tile_list_obu)(CodedBitstreamContext *ctx, RWContext *rw,
>                                 AV1RawTileList *current)
>  {
> @@ -1882,7 +1883,9 @@ static int FUNC(tile_list_obu)(CodedBitstreamContext *ctx, RWContext *rw,
>  
>      return 0;
>  }
> +#endif
>  
> +#if CBS_OBU_METADATA
>  static int FUNC(metadata_hdr_cll)(CodedBitstreamContext *ctx, RWContext *rw,
>                                    AV1RawMetadataHDRCLL *current)
>  {
> @@ -2101,7 +2104,9 @@ static int FUNC(metadata_obu)(CodedBitstreamContext *ctx, RWContext *rw,
>  
>      return 0;
>  }
> +#endif
>  
> +#if CBS_OBU_PADDING
>  static int FUNC(padding_obu)(CodedBitstreamContext *ctx, RWContext *rw,
>                               AV1RawPadding *current)
>  {
> @@ -2125,3 +2130,4 @@ static int FUNC(padding_obu)(CodedBitstreamContext *ctx, RWContext *rw,
>  
>      return 0;
>  }
> +#endif
> diff --git a/libavcodec/cbs_internal.h b/libavcodec/cbs_internal.h
> index 80cad2b162..f15ba1ab90 100644
> --- a/libavcodec/cbs_internal.h
> +++ b/libavcodec/cbs_internal.h
> @@ -22,6 +22,8 @@
>  #include <stddef.h>
>  #include <stdint.h>
>  
> +#include "config.h"
> +
>  #include "libavutil/log.h"
>  
>  #include "cbs.h"
> @@ -30,6 +32,40 @@
>  #include "put_bits.h"
>  #include "libavutil/refstruct.h"
>  
> +#ifndef CBS_READ
> +#define CBS_READ 1
> +#endif
> +#ifndef CBS_WRITE
> +#define CBS_WRITE 1
> +#endif
> +#ifndef CBS_TRACE
> +#define CBS_TRACE 1
> +#endif
> +
> +#ifndef CBS_AV1
> +#define CBS_AV1 CONFIG_CBS_AV1
> +#endif
> +#ifndef CBS_H264
> +#define CBS_H264 CONFIG_CBS_H264
> +#endif
> +#ifndef CBS_H265
> +#define CBS_H265 CONFIG_CBS_H265
> +#endif
> +#ifndef CBS_H266
> +#define CBS_H266 CONFIG_CBS_H266
> +#endif
> +#ifndef CBS_JPEG
> +#define CBS_JPEG CONFIG_CBS_JPEG
> +#endif
> +#ifndef CBS_MPEG2
> +#define CBS_MPEG2 CONFIG_CBS_MPEG2
> +#endif
> +#ifndef CBS_VP8
> +#define CBS_VP8 CONFIG_CBS_VP8
> +#endif
> +#ifndef CBS_VP9
> +#define CBS_VP9 CONFIG_CBS_VP9
> +#endif
>  
>  enum CBSContentType {
>      // Unit content may contain some references to other structures, but all
> @@ -204,6 +240,7 @@ int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
>  #define MIN_INT_BITS(length) (-(INT64_C(1) << ((length) - 1)))
>  
>  
> +#if CBS_TRACE
>  // Start of a syntax element during read tracing.
>  #define CBS_TRACE_READ_START() \
>      GetBitContext trace_start; \
> @@ -284,6 +321,17 @@ int ff_cbs_write_signed(CodedBitstreamContext *ctx, PutBitContext *pbc,
>          } \
>      } while (0)
>  
> +#else // CBS_TRACE
> +#define CBS_TRACE_READ_START() do { } while (0)
> +#define CBS_TRACE_READ_END() do { } while (0)
> +#define CBS_TRACE_READ_END_NO_SUBSCRIPTS() do { } while (0)
> +#define CBS_TRACE_READ_END_VALUE_ONLY() do { } while (0)
> +#define CBS_TRACE_WRITE_START() do { } while (0)
> +#define CBS_TRACE_WRITE_END() do { } while (0)
> +#define CBS_TRACE_WRITE_END_NO_SUBSCRIPTS() do { } while (0)
> +#define CBS_TRACE_WRITE_END_VALUE_ONLY() do { } while (0)
> +#endif // CBS_TRACE
> +
>  #define TYPE_LIST(...) { __VA_ARGS__ }
>  #define CBS_UNIT_TYPE_POD(type_, structure) { \
>          .nb_unit_types  = 1, \

This patch (or rather the next) breaks the fundamental rule of
duplicating object files: The object files really need to be interchangable.
(Rationale: It is possible to --enable-static and --enable-shared at the
same time and users are allowed to link a subset of libraries statically
and another subset in a dynamic manner. In such a scenario the archives
need to contain everything as if used for a dynamic build (because lavc
may be linked dynamically, so that its internal symbols aren't
available), but if linking is performed statically, then the duplicated
object files (here: lavf/cbs.o) are used everywhere. And this will cause
mayhem because your lavf versions are only stripped down.)

- Andreas

_______________________________________________
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".

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2025-03-22 14:25 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-03-20 17:01 [FFmpeg-devel] [PATCH 1/2] avcodec/cbs_av1: also store a pointer to the start of the tile group data James Almer
2025-03-20 17:01 ` [FFmpeg-devel] [PATCH 2/2] avformat/movenccenc: add support for CENC AV1 encryption James Almer
2025-03-21  2:55   ` Andreas Rheinhardt
2025-03-21  3:30     ` James Almer
2025-03-21  3:52       ` Andreas Rheinhardt
2025-03-21 12:50         ` James Almer
2025-03-21 19:42         ` [FFmpeg-devel] [PATCH 2/3] avcodec/cbs: allow fine tunning selection of features James Almer
2025-03-21 19:42           ` [FFmpeg-devel] [PATCH v2 3/3] avformat/movenccenc: add support for CENC AV1 encryption James Almer
2025-03-22 14:25           ` [FFmpeg-devel] [PATCH 2/3] avcodec/cbs: allow fine tunning selection of features Andreas Rheinhardt

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