PR #21609 opened by mkver
URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21609
Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/21609.patch


>From d845f9b7475c76da897aad5dfbab5c76e2a4df48 Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Fri, 30 Jan 2026 14:25:00 +0100
Subject: [PATCH 1/2] avformat/cafenc: Simplify writing pakt box

Assemble it already in caf_write_packet(). This has the advantage
of reducing the amount of buffers used; it also allows to avoid
a seek when writing the trailer and avoids function call overhead
(for the avio_w8(); it also reduces codesize).

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavformat/cafenc.c | 98 +++++++++++++++-----------------------------
 1 file changed, 34 insertions(+), 64 deletions(-)

diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c
index 5f2d79e0a7..4542cc7b04 100644
--- a/libavformat/cafenc.c
+++ b/libavformat/cafenc.c
@@ -19,6 +19,8 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <stdint.h>
+
 #include "avformat.h"
 #include "caf.h"
 #include "isom.h"
@@ -36,10 +38,9 @@ typedef struct {
     int64_t packets;
     uint32_t frame_size;
 
-    uint32_t *byte_size_buffer;
-    uint32_t *frame_size_buffer;
-    unsigned byte_size_buffer_sz;
-    unsigned frame_size_buffer_sz;
+    uint8_t *pakt_buf;
+    unsigned pakt_buf_size;
+    unsigned pakt_buf_alloc_size;
 } CAFContext;
 
 static uint32_t codec_flags(enum AVCodecID codec_id) {
@@ -235,39 +236,39 @@ static int caf_write_header(AVFormatContext *s)
     return 0;
 }
 
+static uint8_t *put_variable_length_num(uint8_t *buf, uint32_t num)
+{
+    for (int j = 4; j > 0; j--) {
+        unsigned top = num >> j * 7;
+        if (top)
+            *(buf++) = top | 128;
+    }
+    *(buf++) = num & 127;
+    return buf;
+}
+
 static int caf_write_packet(AVFormatContext *s, AVPacket *pkt)
 {
     CAFContext *caf = s->priv_data;
     AVStream *const st = s->streams[0];
 
     if (!st->codecpar->block_align || !caf->frame_size) {
-        void *pkt_sizes;
-        unsigned alloc_size = caf->packets + 1;
+#if SIZE_MAX - 10 < UINT_MAX
+        if (caf->pakt_buf_size > SIZE_MAX - 10)
+            return AVERROR(ERANGE);
+#endif
+        uint8_t *pakt_buf = av_fast_realloc(caf->pakt_buf, 
&caf->pakt_buf_alloc_size,
+                                            caf->pakt_buf_size + (size_t)10);
+        if (!pakt_buf)
+            return AVERROR(ENOMEM);
+        caf->pakt_buf = pakt_buf;
+        pakt_buf += caf->pakt_buf_size;
 
-        if (!st->codecpar->block_align) {
-            if (UINT_MAX / sizeof(*caf->byte_size_buffer) < alloc_size)
-                return AVERROR(ERANGE);
-
-            pkt_sizes = av_fast_realloc(caf->byte_size_buffer,
-                                        &caf->byte_size_buffer_sz,
-                                        alloc_size * 
sizeof(*caf->byte_size_buffer));
-            if (!pkt_sizes)
-                return AVERROR(ENOMEM);
-            caf->byte_size_buffer = pkt_sizes;
-            caf->byte_size_buffer[caf->packets] = pkt->size;
-        }
-        if (!caf->frame_size) {
-            if (UINT_MAX / sizeof(*caf->frame_size_buffer) < alloc_size)
-                return AVERROR(ERANGE);
-
-            pkt_sizes = av_fast_realloc(caf->frame_size_buffer,
-                                        &caf->frame_size_buffer_sz,
-                                        alloc_size * 
sizeof(*caf->frame_size_buffer));
-            if (!pkt_sizes)
-                return AVERROR(ENOMEM);
-            caf->frame_size_buffer = pkt_sizes;
-            caf->frame_size_buffer[caf->packets] = pkt->duration;
-        }
+        if (!st->codecpar->block_align)
+            pakt_buf = put_variable_length_num(pakt_buf, pkt->size);
+        if (!caf->frame_size)
+            pakt_buf = put_variable_length_num(pakt_buf, pkt->duration);
+        caf->pakt_buf_size = pakt_buf - caf->pakt_buf;
     }
     caf->packets++;
     caf->total_duration += pkt->duration;
@@ -294,47 +295,17 @@ static int caf_write_trailer(AVFormatContext *s)
         avio_wb64(pb, file_size - caf->data - 8);
 
         if (!par->block_align || !caf->frame_size || par->initial_padding || 
remainder_frames) {
-            int64_t size = 24;
-
             valid_frames -= par->initial_padding;
             valid_frames -= remainder_frames;
 
             avio_seek(pb, file_size, SEEK_SET);
             ffio_wfourcc(pb, "pakt");
-            avio_wb64(pb, 0); // size, to be replaced
+            avio_wb64(pb, 24 + caf->pakt_buf_size); // size
             avio_wb64(pb, packets); ///< mNumberPackets
             avio_wb64(pb, valid_frames); ///< mNumberValidFrames
             avio_wb32(pb, par->initial_padding); ///< mPrimingFrames
             avio_wb32(pb, remainder_frames); ///< mRemainderFrames
-            for (int i = 0; i < packets; i++) {
-                if (!par->block_align) {
-                    for (int j = 4; j > 0; j--) {
-                        unsigned top = caf->byte_size_buffer[i] >> j * 7;
-                        if (top) {
-                            avio_w8(pb, 128 | (uint8_t)top);
-                            size++;
-                        }
-                    }
-                    avio_w8(pb, caf->byte_size_buffer[i] & 127);
-                    size++;
-                }
-                if (!caf->frame_size) {
-                    for (int j = 4; j > 0; j--) {
-                        unsigned top = caf->frame_size_buffer[i] >> j * 7;
-                        if (top) {
-                            avio_w8(pb, 128 | (uint8_t)top);
-                            size++;
-                        }
-                    }
-                    avio_w8(pb, caf->frame_size_buffer[i] & 127);
-                    size++;
-                }
-            }
-
-            int64_t end = avio_tell(pb);
-            avio_seek(pb, file_size + 4, SEEK_SET);
-            avio_wb64(pb, size);
-            avio_seek(pb, end, SEEK_SET);
+            avio_write(pb, caf->pakt_buf, caf->pakt_buf_size);
         }
     }
 
@@ -345,8 +316,7 @@ static void caf_write_deinit(AVFormatContext *s)
 {
     CAFContext *caf = s->priv_data;
 
-    av_freep(&caf->byte_size_buffer);
-    av_freep(&caf->frame_size_buffer);
+    av_freep(&caf->pakt_buf);
 }
 
 const FFOutputFormat ff_caf_muxer = {
-- 
2.52.0


>From 2b82ab60fea0327a2fd606976fc677ae255902dc Mon Sep 17 00:00:00 2001
From: Andreas Rheinhardt <[email protected]>
Date: Fri, 30 Jan 2026 15:02:33 +0100
Subject: [PATCH 2/2] avformat/cafenc: don't keep track of nb packets ourselves

Just reuse AVStream.nb_frames.

Signed-off-by: Andreas Rheinhardt <[email protected]>
---
 libavformat/cafenc.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/libavformat/cafenc.c b/libavformat/cafenc.c
index 4542cc7b04..8879d13940 100644
--- a/libavformat/cafenc.c
+++ b/libavformat/cafenc.c
@@ -35,7 +35,6 @@
 typedef struct {
     int64_t data;
     int64_t total_duration;
-    int64_t packets;
     uint32_t frame_size;
 
     uint8_t *pakt_buf;
@@ -270,7 +269,6 @@ static int caf_write_packet(AVFormatContext *s, AVPacket 
*pkt)
             pakt_buf = put_variable_length_num(pakt_buf, pkt->duration);
         caf->pakt_buf_size = pakt_buf - caf->pakt_buf;
     }
-    caf->packets++;
     caf->total_duration += pkt->duration;
 
     avio_write(s->pb, pkt->data, pkt->size);
@@ -286,8 +284,8 @@ static int caf_write_trailer(AVFormatContext *s)
 
     if (pb->seekable & AVIO_SEEKABLE_NORMAL) {
         int64_t file_size = avio_tell(pb);
-        int64_t packets = (!par->block_align || !caf->frame_size) ? 
caf->packets : 0;
-        int64_t valid_frames = caf->frame_size ? caf->packets * 
caf->frame_size : caf->total_duration;
+        int64_t packets = (!par->block_align || !caf->frame_size) ? 
st->nb_frames : 0;
+        int64_t valid_frames = caf->frame_size ? st->nb_frames * 
caf->frame_size : caf->total_duration;
         unsigned remainder_frames = valid_frames > caf->total_duration
                                   ? valid_frames - caf->total_duration : 0;
 
-- 
2.52.0

_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]

Reply via email to