[FFmpeg-devel] [PATCH 7/7] avcodec/movtextenc: Don't copy data around unnecessarily

Andreas Rheinhardt andreas.rheinhardt at outlook.com
Sun Feb 18 03:43:08 EET 2024


Using av_bprint_init_for_buffer() avoids copying data
into the internal AVBPrint buffer (or worse: to allocate
a temporary buffer in case the internal buffer does not
suffice).

Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt at outlook.com>
---
 libavcodec/movtextenc.c | 33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/libavcodec/movtextenc.c b/libavcodec/movtextenc.c
index 7aa74d7c9d..fd8c7dc9f7 100644
--- a/libavcodec/movtextenc.c
+++ b/libavcodec/movtextenc.c
@@ -22,7 +22,6 @@
 #include <stdarg.h>
 #include "avcodec.h"
 #include "libavutil/opt.h"
-#include "libavutil/avstring.h"
 #include "libavutil/intreadwrite.h"
 #include "libavutil/mem.h"
 #include "libavutil/common.h"
@@ -170,7 +169,6 @@ static int mov_text_encode_close(AVCodecContext *avctx)
     ff_ass_split_free(s->ass_ctx);
     av_freep(&s->style_attributes);
     av_freep(&s->fonts);
-    av_bprint_finalize(&s->buffer, NULL);
     return 0;
 }
 
@@ -183,6 +181,9 @@ static int encode_sample_description(AVCodecContext *avctx)
     int font_names_total_len = 0;
     MovTextContext *s = avctx->priv_data;
     uint8_t buf[30], *p = buf;
+    int ret;
+
+    av_bprint_init(&s->buffer, 0, INT_MAX - AV_INPUT_BUFFER_PADDING_SIZE + 1);
 
     //  0x00, 0x00, 0x00, 0x00, // uint32_t displayFlags
     //  0x01,                   // int8_t horizontal-justification
@@ -306,19 +307,23 @@ static int encode_sample_description(AVCodecContext *avctx)
     //     };
 
     if (!av_bprint_is_complete(&s->buffer)) {
-        return AVERROR(ENOMEM);
+        ret = AVERROR(ENOMEM);
+        goto fail;
     }
 
     avctx->extradata_size = s->buffer.len;
     avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
     if (!avctx->extradata) {
-        return AVERROR(ENOMEM);
+        ret = AVERROR(ENOMEM);
+        goto fail;
     }
 
     memcpy(avctx->extradata, s->buffer.str, avctx->extradata_size);
-    av_bprint_clear(&s->buffer);
+    ret = 0;
+fail:
+    av_bprint_finalize(&s->buffer, NULL);
 
-    return 0;
+    return ret;
 }
 
 static av_cold int mov_text_encode_init(AVCodecContext *avctx)
@@ -327,8 +332,6 @@ static av_cold int mov_text_encode_init(AVCodecContext *avctx)
     MovTextContext *s = avctx->priv_data;
     s->avctx = avctx;
 
-    av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED);
-
     s->ass_ctx = ff_ass_split(avctx->subtitle_header);
     if (!s->ass_ctx)
         return AVERROR_INVALIDDATA;
@@ -640,10 +643,14 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
     ASSDialog *dialog;
     int i, length;
 
+    if (bufsize < 3)
+        goto too_small;
+
     s->text_pos = 0;
     s->count = 0;
     s->box_flags = 0;
-    av_bprint_clear(&s->buffer);
+
+    av_bprint_init_for_buffer(&s->buffer, buf + 2, bufsize - 2);
     for (i = 0; i < sub->num_rects; i++) {
         const char *ass = sub->rects[i]->ass;
 
@@ -663,23 +670,19 @@ static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
     if (s->buffer.len > UINT16_MAX)
         return AVERROR(ERANGE);
     AV_WB16(buf, s->buffer.len);
-    buf += 2;
 
     for (size_t j = 0; j < box_count; j++)
         box_types[j].encode(s);
 
-    if (!av_bprint_is_complete(&s->buffer))
-        return AVERROR(ENOMEM);
-
     if (!s->buffer.len)
         return 0;
 
-    if (s->buffer.len > bufsize - 3) {
+    if (!av_bprint_is_complete(&s->buffer)) {
+too_small:
         av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n");
         return AVERROR_BUFFER_TOO_SMALL;
     }
 
-    memcpy(buf, s->buffer.str, s->buffer.len);
     length = s->buffer.len + 2;
 
     return length;
-- 
2.34.1



More information about the ffmpeg-devel mailing list