[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [52718] trunk/blender/source/blender/imbuf /intern: == FFMPEG ==

Peter Schlaile peter at schlaile.de
Sun Dec 2 16:15:44 CET 2012


Revision: 52718
          http://projects.blender.org/scm/viewvc.php?view=rev&root=bf-blender&revision=52718
Author:   schlaile
Date:     2012-12-02 15:15:44 +0000 (Sun, 02 Dec 2012)
Log Message:
-----------
== FFMPEG ==

This fixes a memory leak caused by the last packet on stream EOF not freed.
(Memory leak occurs on ffmpeg heap managed by av_malloc / av_free, so it is
invisible to Blender)

Also: clean up the code a little bit (anim->next_packet was never really used,
so could be moved into a local variable)

Modified Paths:
--------------
    trunk/blender/source/blender/imbuf/intern/IMB_anim.h
    trunk/blender/source/blender/imbuf/intern/anim_movie.c
    trunk/blender/source/blender/imbuf/intern/indexer.c

Modified: trunk/blender/source/blender/imbuf/intern/IMB_anim.h
===================================================================
--- trunk/blender/source/blender/imbuf/intern/IMB_anim.h	2012-12-02 15:15:00 UTC (rev 52717)
+++ trunk/blender/source/blender/imbuf/intern/IMB_anim.h	2012-12-02 15:15:44 UTC (rev 52718)
@@ -178,7 +178,6 @@
 	struct ImBuf *last_frame;
 	int64_t last_pts;
 	int64_t next_pts;
-	AVPacket next_packet;
 #endif
 
 #ifdef WITH_REDCODE

Modified: trunk/blender/source/blender/imbuf/intern/anim_movie.c
===================================================================
--- trunk/blender/source/blender/imbuf/intern/anim_movie.c	2012-12-02 15:15:00 UTC (rev 52717)
+++ trunk/blender/source/blender/imbuf/intern/anim_movie.c	2012-12-02 15:15:44 UTC (rev 52718)
@@ -557,7 +557,6 @@
 	anim->last_frame = 0;
 	anim->last_pts = -1;
 	anim->next_pts = -1;
-	anim->next_packet.stream_index = -1;
 
 	anim->pFormatCtx = pFormatCtx;
 	anim->pCodecCtx = pCodecCtx;
@@ -764,41 +763,39 @@
 	}
 }
 
-/* decode one video frame also considering the packet read into next_packet */
+/* decode one video frame */
 
 static int ffmpeg_decode_video_frame(struct anim *anim)
 {
 	int rval = 0;
+	AVPacket next_packet;
 
+	memset(&next_packet, 0, sizeof(AVPacket));
+
 	av_log(anim->pFormatCtx, AV_LOG_DEBUG, "  DECODE VIDEO FRAME\n");
 
-	if (anim->next_packet.stream_index == anim->videoStream) {
-		av_free_packet(&anim->next_packet);
-		anim->next_packet.stream_index = -1;
-	}
-	
-	while ((rval = av_read_frame(anim->pFormatCtx, &anim->next_packet)) >= 0) {
+	while ((rval = av_read_frame(anim->pFormatCtx, &next_packet)) >= 0) {
 		av_log(anim->pFormatCtx, 
 		       AV_LOG_DEBUG, 
 		       "%sREAD: strID=%d (VID: %d) dts=%lld pts=%lld "
 		       "%s\n",
-		       (anim->next_packet.stream_index == anim->videoStream)
+		       (next_packet.stream_index == anim->videoStream)
 		       ? "->" : "  ",
-		       anim->next_packet.stream_index, 
+		       next_packet.stream_index, 
 		       anim->videoStream,
-		       (anim->next_packet.dts == AV_NOPTS_VALUE) ? -1 :
-		       (long long int)anim->next_packet.dts,
-		       (anim->next_packet.pts == AV_NOPTS_VALUE) ? -1 :
-		       (long long int)anim->next_packet.pts,
-		       (anim->next_packet.flags & AV_PKT_FLAG_KEY) ? 
+		       (next_packet.dts == AV_NOPTS_VALUE) ? -1 :
+		       (long long int)next_packet.dts,
+		       (next_packet.pts == AV_NOPTS_VALUE) ? -1 :
+		       (long long int)next_packet.pts,
+		       (next_packet.flags & AV_PKT_FLAG_KEY) ? 
 		       " KEY" : "");
-		if (anim->next_packet.stream_index == anim->videoStream) {
+		if (next_packet.stream_index == anim->videoStream) {
 			anim->pFrameComplete = 0;
 
 			avcodec_decode_video2(
 			    anim->pCodecCtx,
 			    anim->pFrame, &anim->pFrameComplete,
-			    &anim->next_packet);
+			    &next_packet);
 
 			if (anim->pFrameComplete) {
 				anim->next_pts = av_get_pts_from_frame(
@@ -816,20 +813,24 @@
 				break;
 			}
 		}
-		av_free_packet(&anim->next_packet);
-		anim->next_packet.stream_index = -1;
+		av_free_packet(&next_packet);
 	}
+
+	/* this sets size and data fields to zero,
+	   which is necessary to decode the remaining data
+	   in the decoder engine after EOF. It also prevents a memory
+	   leak, since av_read_frame spills out a full size packet even
+	   on EOF... (and: it's save to call on NULL packets) */
+
+	av_free_packet(&next_packet);
 	
 	if (rval == AVERROR_EOF) {
-		anim->next_packet.size = 0;
-		anim->next_packet.data = 0;
-
 		anim->pFrameComplete = 0;
 
 		avcodec_decode_video2(
 			anim->pCodecCtx,
 			anim->pFrame, &anim->pFrameComplete,
-			&anim->next_packet);
+			&next_packet);
 
 		if (anim->pFrameComplete) {
 			anim->next_pts = av_get_pts_from_frame(
@@ -849,8 +850,6 @@
 	}
 
 	if (rval < 0) {
-		anim->next_packet.stream_index = -1;
-
 		av_log(anim->pFormatCtx,
 		       AV_LOG_ERROR, "  DECODE READ FAILED: av_read_frame() "
 		       "returned error: %d\n",  rval);
@@ -1087,13 +1086,6 @@
 
 		anim->next_pts = -1;
 
-		if (anim->next_packet.stream_index == anim->videoStream) {
-			av_free_packet(&anim->next_packet);
-			anim->next_packet.stream_index = -1;
-		}
-
-		/* memset(anim->pFrame, ...) ?? */
-
 		if (ret >= 0) {
 			ffmpeg_decode_video_frame_scan(anim, pts_to_search);
 		}
@@ -1140,9 +1132,6 @@
 		av_free(anim->pFrameDeinterlaced);
 		sws_freeContext(anim->img_convert_ctx);
 		IMB_freeImBuf(anim->last_frame);
-		if (anim->next_packet.stream_index != -1) {
-			av_free_packet(&anim->next_packet);
-		}
 	}
 	anim->duration = 0;
 }

Modified: trunk/blender/source/blender/imbuf/intern/indexer.c
===================================================================
--- trunk/blender/source/blender/imbuf/intern/indexer.c	2012-12-02 15:15:00 UTC (rev 52717)
+++ trunk/blender/source/blender/imbuf/intern/indexer.c	2012-12-02 15:15:44 UTC (rev 52718)
@@ -912,6 +912,8 @@
 	AVPacket next_packet;
 	uint64_t stream_size;
 
+	memset(&next_packet, 0, sizeof(AVPacket));
+
 	in_frame = avcodec_alloc_frame();
 
 	stream_size = avio_size(context->iFormatCtx->pb);
@@ -959,12 +961,13 @@
 	 * according to ffmpeg docs using 0-size packets.
 	 *
 	 * At least, if we haven't already stopped... */
+
+	/* this creates the 0-size packet and prevents a memory leak. */
+	av_free_packet(&next_packet);
+
 	if (!*stop) {
 		int frame_finished;
 
-		next_packet.size = 0;
-		next_packet.data = 0;
-
 		do {
 			frame_finished = 0;
 




More information about the Bf-blender-cvs mailing list