From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <ffmpeg-devel-bounces@ffmpeg.org>
Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100])
	by master.gitmailbox.com (Postfix) with ESMTPS id 6A58544B0E
	for <ffmpegdev@gitmailbox.com>; Sun, 23 Mar 2025 13:43:23 +0000 (UTC)
Received: from [127.0.1.1] (localhost [127.0.0.1])
	by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1208B687C71;
	Sun, 23 Mar 2025 15:43:07 +0200 (EET)
Received: from mail-pl1-f179.google.com (mail-pl1-f179.google.com
 [209.85.214.179])
 by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 60D06687BA6
 for <ffmpeg-devel@ffmpeg.org>; Sun, 23 Mar 2025 15:43:00 +0200 (EET)
Received: by mail-pl1-f179.google.com with SMTP id
 d9443c01a7336-22438c356c8so65855705ad.1
 for <ffmpeg-devel@ffmpeg.org>; Sun, 23 Mar 2025 06:43:00 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=gmail.com; s=20230601; t=1742737378; x=1743342178; darn=ffmpeg.org;
 h=content-transfer-encoding:mime-version:references:in-reply-to
 :message-id:date:subject:to:from:from:to:cc:subject:date:message-id
 :reply-to; bh=VDQOqSvsa1DZco3uONP5I2zJb+hDnihWgi0FSS1zJ6w=;
 b=J7t9X5h5eRJa9De0qXU5yAgQLQCl5dwsDf7tu+LETEKOcEO1d1ywr8DP+/M8HXRkfB
 sPfMj4Doh8YWO3Tm5vNox8P2IePjd0u8c3aJGbSS1jLpuSK2owI5N2PKpvQzwxj3yf0V
 dRpj3cP2xVqiHRnD9nyEyJg31l2kZow1TEp21slId0hOKG6CkMD2RgZ+0pUf9NJX/lh2
 cPPHcazWFkRLe2JgNQ188t9HeKKrG8quW4a7bI4Bv0UgKEaL2LFOOKdSmilx0cmKtZ2L
 Km0q2PLXb2lE/kgyBQ5ZTpLD9EbmLURJngrOktASg+8l7Kur09UQUQdBayJfQC/elVYk
 Y9MQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20230601; t=1742737378; x=1743342178;
 h=content-transfer-encoding:mime-version:references:in-reply-to
 :message-id:date:subject:to:from:x-gm-message-state:from:to:cc
 :subject:date:message-id:reply-to;
 bh=VDQOqSvsa1DZco3uONP5I2zJb+hDnihWgi0FSS1zJ6w=;
 b=c7wtdln9UbzzcnUfE/NHcdQksK3hwqpMfivK8cR1odwe28q7vkV9VEOZLBQU4NdVeZ
 UtFOsEaeSHnsNfqNlBBFmwE26yo/VtxY9ktVbXZiikQU6quP/5zwCKRV7O6t6m+jjLq+
 tlgHmmiwIHVmXd22YZnLFMUX+m1UihgfabtFILz6joyzKKqRpVuRC4oDTkbSRYGPxmhj
 4mXl5vbdYevDn/kFDJtuEamYjYKoh+iWkUlIemoT+1cFvL9ryeMWybarbYinozcra3i+
 O7v9vF2gdWFDDsVCqxvA6we0QbJ7kSqr9w0vkaoKdiOC/sg4Z8dTduLvJh6nWqDdSlfg
 1c9Q==
X-Gm-Message-State: AOJu0Yw2TjPX3rMu3GMNroZU0HQJ5XPY4nDLhOt7A4pDFXZ0HGptirXp
 Cey6gQ+my623nfVqb/D6GuMm1COd5GxvCMHRJoXjcv6n6jNOTCEu0qeoMg==
X-Gm-Gg: ASbGncuqYR7DfQrgPRfZ9WUkOAWktftdGoQHR4ohsvQ+YwUussYf6INY62ud4w3d6iP
 b6gLAz0blmVRUFROIXcj1AfU8GoSsWZyIiC/HbznJpHHaN5kyzQn85Z3AlD1YbXWC9tfR9pvLxd
 PFGxhV+F++BQO29Hm7da5YW66NWJL8tbF3CO1CXzpdH8iKr238gZScYlnnq4OVIguPENUNhZJL/
 nfEXVsVq4+HtpaIJAPMIhP9W8TiL8z1uFJktfvyOkicWEhwwx9/bdheYMt6tBXLIAgj6OW/ndjn
 yLnkmyW31791XHYRCaNqXnN8ouS3M2lwv59aY1QlmKsA0BIn1V4xIDYmLl8uTEc=
X-Google-Smtp-Source: AGHT+IFCmAu08GnD9TbUyDCw/dincUZyBBbtJ4EaxFvPtFxf0uBkaRdg1jZo7V/iwZFcBu7fZhHRIA==
X-Received: by 2002:a17:903:46c5:b0:220:d79f:60f1 with SMTP id
 d9443c01a7336-22780e122dcmr141962715ad.42.1742737377413; 
 Sun, 23 Mar 2025 06:42:57 -0700 (PDT)
Received: from localhost.localdomain ([2800:2121:b000:82e:5907:af58:35a0:9462])
 by smtp.gmail.com with ESMTPSA id
 d9443c01a7336-227811da9dbsm51629935ad.179.2025.03.23.06.42.55
 for <ffmpeg-devel@ffmpeg.org>
 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
 Sun, 23 Mar 2025 06:42:56 -0700 (PDT)
From: James Almer <jamrial@gmail.com>
To: ffmpeg-devel@ffmpeg.org
Date: Sun, 23 Mar 2025 10:42:32 -0300
Message-ID: <20250323134232.1397-2-jamrial@gmail.com>
X-Mailer: git-send-email 2.48.1
In-Reply-To: <GV1SPRMB00367FABE3D06BEE02D86F938FDA2@GV1SPRMB0036.EURP250.PROD.OUTLOOK.COM>
References: <GV1SPRMB00367FABE3D06BEE02D86F938FDA2@GV1SPRMB0036.EURP250.PROD.OUTLOOK.COM>
MIME-Version: 1.0
Subject: [FFmpeg-devel] [PATCH v3 2/2] avformat/movenccenc: add support for
 CENC AV1 encryption
X-BeenThere: ffmpeg-devel@ffmpeg.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: FFmpeg development discussions and patches <ffmpeg-devel.ffmpeg.org>
List-Unsubscribe: <https://ffmpeg.org/mailman/options/ffmpeg-devel>,
 <mailto:ffmpeg-devel-request@ffmpeg.org?subject=unsubscribe>
List-Archive: <https://ffmpeg.org/pipermail/ffmpeg-devel>
List-Post: <mailto:ffmpeg-devel@ffmpeg.org>
List-Help: <mailto:ffmpeg-devel-request@ffmpeg.org?subject=help>
List-Subscribe: <https://ffmpeg.org/mailman/listinfo/ffmpeg-devel>,
 <mailto:ffmpeg-devel-request@ffmpeg.org?subject=subscribe>
Reply-To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: 7bit
Errors-To: ffmpeg-devel-bounces@ffmpeg.org
Sender: "ffmpeg-devel" <ffmpeg-devel-bounces@ffmpeg.org>
Archived-At: <https://master.gitmailbox.com/ffmpegdev/20250323134232.1397-2-jamrial@gmail.com/>
List-Archive: <https://master.gitmailbox.com/ffmpegdev/>
List-Post: <mailto:ffmpegdev@gitmailbox.com>

Signed-off-by: James Almer <jamrial@gmail.com>
---
 libavformat/Makefile     |   2 +-
 libavformat/cbs.c        |   2 +
 libavformat/cbs.h        |  35 ++++++
 libavformat/cbs_av1.c    |   5 +
 libavformat/movenc.c     |  13 ++-
 libavformat/movenccenc.c | 223 ++++++++++++++++++++++++++++++++++++++-
 libavformat/movenccenc.h |  20 +++-
 tests/ref/fate/source    |   2 +
 8 files changed, 296 insertions(+), 6 deletions(-)
 create mode 100644 libavformat/cbs.c
 create mode 100644 libavformat/cbs.h
 create mode 100644 libavformat/cbs_av1.c

diff --git a/libavformat/Makefile b/libavformat/Makefile
index 7730e7c4e6..a94ac66e7e 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -377,7 +377,7 @@ OBJS-$(CONFIG_MOV_DEMUXER)               += mov.o mov_chan.o mov_esds.o \
 OBJS-$(CONFIG_MOV_MUXER)                 += movenc.o \
                                             movenchint.o mov_chan.o rtp.o \
                                             movenccenc.o movenc_ttml.o rawutils.o \
-                                            dovi_isom.o evc.o
+                                            dovi_isom.o evc.o cbs.o cbs_av1.o
 OBJS-$(CONFIG_MP2_MUXER)                 += rawenc.o
 OBJS-$(CONFIG_MP3_DEMUXER)               += mp3dec.o replaygain.o
 OBJS-$(CONFIG_MP3_MUXER)                 += mp3enc.o rawenc.o id3v2enc.o
diff --git a/libavformat/cbs.c b/libavformat/cbs.c
new file mode 100644
index 0000000000..748d298a40
--- /dev/null
+++ b/libavformat/cbs.c
@@ -0,0 +1,2 @@
+#include "cbs.h"
+#include "libavcodec/cbs.c"
diff --git a/libavformat/cbs.h b/libavformat/cbs.h
new file mode 100644
index 0000000000..e4dc231001
--- /dev/null
+++ b/libavformat/cbs.h
@@ -0,0 +1,35 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef AVFORMAT_CBS_H
+#define AVFORMAT_CBS_H
+
+#define CBS_PREFIX lavf_cbs
+#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.h"
+
+#endif /* AVFORMAT_CBS_H */
diff --git a/libavformat/cbs_av1.c b/libavformat/cbs_av1.c
new file mode 100644
index 0000000000..a0c5617d18
--- /dev/null
+++ b/libavformat/cbs_av1.c
@@ -0,0 +1,5 @@
+#define CBS_OBU_TILE_LIST 0
+#define CBS_OBU_METADATA 0
+#define CBS_OBU_PADDING 0
+#include "cbs.h"
+#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..32094ebd7b 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_lavf_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_lavf_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_lavf_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_lavf_cbs_fragment_free(&ctx->temporal_unit);
+    ff_lavf_cbs_close(&ctx->cbc);
 }
diff --git a/libavformat/movenccenc.h b/libavformat/movenccenc.h
index 7da5268090..77a0716c81 100644
--- a/libavformat/movenccenc.h
+++ b/libavformat/movenccenc.h
@@ -25,11 +25,18 @@
 #include "libavutil/aes_ctr.h"
 #include "avformat.h"
 #include "avio.h"
+#include "cbs.h"
 
 #define CENC_KID_SIZE (16)
 
 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
  */
diff --git a/tests/ref/fate/source b/tests/ref/fate/source
index 78d3a2e0fa..d4b9bcee4c 100644
--- a/tests/ref/fate/source
+++ b/tests/ref/fate/source
@@ -10,6 +10,8 @@ libavdevice/riscv/cpu_common.c
 libavfilter/file_open.c
 libavfilter/log2_tab.c
 libavfilter/riscv/cpu_common.c
+libavformat/cbs.c
+libavformat/cbs_av1.c
 libavformat/file_open.c
 libavformat/golomb_tab.c
 libavformat/log2_tab.c
-- 
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".