[FFmpeg-devel] [PATCH] encode_video2: shrink packet after encoding.

Nicolas George nicolas.george at normalesup.org
Wed Feb 29 14:48:52 CET 2012

The with the encode2 API, encoders allocate huge packets to be
sure they have enough room (a typical case is mpeg4, which allocs
~10M for 1280x768 yuv420p) but only actually use a very small part
of the buffer.

Signed-off-by: Nicolas George <nicolas.george at normalesup.org>
 libavcodec/utils.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

Steps to exhibit an actual problem problem:

- Compile in 32-bits or use "limit addressspace 3072M" (Linux+zsh; don't
  know for other OS/shells).

- Create a test source file with subtitles, using min.ass from my last mail
  ./ffmpeg_g -f lavfi -i testsrc,scale=1280:720 -i /tmp/min.ass \
    -vcodec mpeg4 -t 30 -y /tmp/src.mkv

- Transcode the file:
  ./ffmpeg_g -i /tmp/src.mkv -vcodec mpeg4 -y /tmp/dst.mkv

Result: encode fails after ~13 seconds.

Reason: the huge packets accumulate in the muxing queue, waiting for a
subtitle packet to ensure proper interleaving. As most of the buffer was
never accessed, they do not eat a lot of memory, but they do eat a lot of
address space, ultimately filling 3G in about 12-13 seconds' worth of video.

I did not test the performance impact.


  Nicolas George

diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index 63f7fae..99e36f8 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -1198,6 +1198,7 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx,
     int ret;
     int user_packet = !!avpkt->data;
+    void *new_data;
     *got_packet_ptr = 0;
@@ -1218,6 +1219,12 @@ int attribute_align_arg avcodec_encode_video2(AVCodecContext *avctx,
             avpkt->size = 0;
         else if (!(avctx->codec->capabilities & CODEC_CAP_DELAY))
             avpkt->pts = avpkt->dts = frame->pts;
+        if (avpkt->data) {
+            new_data = av_realloc(avpkt->data,
+                                  avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE);
+            if (new_data)
+                avpkt->data = new_data;
+        }

More information about the ffmpeg-devel mailing list