aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReimar Döffinger <Reimar.Doeffinger@gmx.de>2012-01-12 21:31:11 +0100
committerReimar Döffinger <Reimar.Doeffinger@gmx.de>2012-01-14 17:23:57 +0100
commitc4ba5198ea48f8f648d85a853ea46e29001c12c8 (patch)
treeb2cada03e1941b6241bcffdf24a6296c1450da7f
parent45c39e566fe6d263e6ce0268b4629e5de3aa4d0c (diff)
downloadffmpeg-c4ba5198ea48f8f648d85a853ea46e29001c12c8.tar.gz
Fix leaking of side data.
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 also makes the av_dup_packet unnecessary which could cause an even worse leak in this situation. Also change the code to not modify the user-provide AVPacket at all. Signed-off-by: Reimar Döffinger <Reimar.Doeffinger@gmx.de>
-rw-r--r--libavcodec/avcodec.h2
-rw-r--r--libavcodec/avpacket.c17
-rw-r--r--libavcodec/internal.h5
-rw-r--r--libavcodec/utils.c17
4 files changed, 27 insertions, 14 deletions
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 69e541a8f0..9a8ca81db9 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -4297,7 +4297,7 @@ int avcodec_decode_audio4(AVCodecContext *avctx, AVFrame *frame,
*/
int avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
int *got_picture_ptr,
- AVPacket *avpkt);
+ const AVPacket *avpkt);
/**
* Decode a subtitle message.
diff --git a/libavcodec/avpacket.c b/libavcodec/avpacket.c
index a4bd442176..5a51900ebf 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;
@@ -239,8 +244,6 @@ int av_packet_split_side_data(AVPacket *pkt){
unsigned int size;
uint8_t *p;
- av_dup_packet(pkt);
-
p = pkt->data + pkt->size - 8 - 5;
for (i=1; ; i++){
size = AV_RB32(p);
diff --git a/libavcodec/internal.h b/libavcodec/internal.h
index 068b34bbaa..e6270f81bf 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 219be6b7fb..e25f1dfb41 100644
--- a/libavcodec/utils.c
+++ b/libavcodec/utils.c
@@ -994,24 +994,26 @@ static void apply_param_change(AVCodecContext *avctx, AVPacket *avpkt)
int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *picture,
int *got_picture_ptr,
- AVPacket *avpkt)
+ const AVPacket *avpkt)
{
int ret;
+ // copy to ensure we do not change avpkt
+ AVPacket tmp = *avpkt;
*got_picture_ptr= 0;
if((avctx->coded_width||avctx->coded_height) && av_image_check_size(avctx->coded_width, avctx->coded_height, 0, avctx))
return -1;
if((avctx->codec->capabilities & CODEC_CAP_DELAY) || avpkt->size || (avctx->active_thread_type&FF_THREAD_FRAME)){
- av_packet_split_side_data(avpkt);
- apply_param_change(avctx, avpkt);
- avctx->pkt = avpkt;
+ int did_split = av_packet_split_side_data(&tmp);
+ apply_param_change(avctx, &tmp);
+ avctx->pkt = &tmp;
if (HAVE_THREADS && avctx->active_thread_type&FF_THREAD_FRAME)
ret = ff_thread_decode_frame(avctx, picture, got_picture_ptr,
- avpkt);
+ &tmp);
else {
ret = avctx->codec->decode(avctx, picture, got_picture_ptr,
- avpkt);
+ &tmp);
picture->pkt_dts= avpkt->dts;
if(!avctx->has_b_frames){
@@ -1030,6 +1032,9 @@ int attribute_align_arg avcodec_decode_video2(AVCodecContext *avctx, AVFrame *pi
emms_c(); //needed to avoid an emms_c() call before every return;
+ avctx->pkt = NULL;
+ if (did_split)
+ ff_packet_free_side_data(&tmp);
if (*got_picture_ptr){
avctx->frame_number++;