[FFmpeg-devel] [PATCH] Fix leaking of side data.

Reimar Döffinger Reimar.Doeffinger at gmx.de
Thu Jan 12 21:34:09 CET 2012


While we correctly "register" the side data when we split it,
the application (in this case FFmpeg) might not update the
AVPacket pool it uses to finally free the packet, thus
causing a leak.
This patch does not fix an even worse case of this: If we
dup the packet even "data" will not be freed in such a case.

Signed-off-by: Reimar Döffinger <Reimar.Doeffinger at gmx.de>
---
 libavcodec/avpacket.c |   15 ++++++++++-----
 libavcodec/internal.h |    5 +++++
 libavcodec/utils.c    |    4 +++-
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index a4bd442..d9ced96 100644
--- a/libavcodec/avpacket.c
+++ b/libavcodec/avpacket.c
@@ -20,6 +20,7 @@
  */
 
 #include "avcodec.h"
+#include "internal.h"
 #include "libavutil/avassert.h"
 #include "bytestream.h"
 
@@ -30,19 +31,23 @@ void av_destruct_packet_nofree(AVPacket *pkt)
     pkt->side_data_elems = 0;
 }
 
-void av_destruct_packet(AVPacket *pkt)
+void ff_packet_free_side_data(AVPacket *pkt)
 {
     int i;
-
-    av_free(pkt->data);
-    pkt->data = NULL; pkt->size = 0;
-
     for (i = 0; i < pkt->side_data_elems; i++)
         av_free(pkt->side_data[i].data);
     av_freep(&pkt->side_data);
     pkt->side_data_elems = 0;
 }
 
+void av_destruct_packet(AVPacket *pkt)
+{
+    av_free(pkt->data);
+    pkt->data = NULL; pkt->size = 0;
+
+    ff_packet_free_side_data(pkt);
+}
+
 void av_init_packet(AVPacket *pkt)
 {
     pkt->pts   = AV_NOPTS_VALUE;
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 13deb87..fa087b9 100644
--- a/libavcodec/internal.h
+++ b/libavcodec/internal.h
@@ -96,6 +96,11 @@ unsigned int avpriv_toupper4(unsigned int x);
  */
 void ff_init_buffer_info(AVCodecContext *s, AVFrame *pic);
 
+/**
+ * Remove and free all side data from packet.
+ */
+void ff_packet_free_side_data(AVPacket *pkt);
+
 int avpriv_lock_avformat(void);
 int avpriv_unlock_avformat(void);
 
diff --git a/libavcodec/utils.c b/libavcodec/utils.c
index b79e23e..83bab2d 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -988,7 +988,7 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
         return -1;
 
     if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type&FF_THREAD_FRAME)){
-        av_packet_split_side_data(avpkt);
+        int did_split = av_packet_split_side_data(avpkt);
         apply_param_change(avctx, avpkt);
         avctx->pkt = avpkt;
         if (HAVE_THREADS && avctx->active_thread_type&FF_THREAD_FRAME)
@@ -1015,6 +1015,8 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
 
         emms_c(); //needed to avoid an emms_c() call before every return;
 
+        if (did_split)
+            ff_packet_free_side_data(avpkt);
 
         if (*got_picture_ptr){
             avctx->frame_number++;
-- 
1.7.8.3



More information about the ffmpeg-devel mailing list