[FFmpeg-cvslog] mpegvideo: fix invalid picture unreferencing.

Ronald S. Bultje git at videolan.org
Thu Jul 21 16:54:42 CEST 2011


ffmpeg | branch: master | Ronald S. Bultje <rsbultje at gmail.com> | Wed Jul 20 09:24:07 2011 -0700| [80469eafb747018cb9d9a2547f65def715d073b2] | committer: Ronald S. Bultje

mpegvideo: fix invalid picture unreferencing.

Mpegvideo would free frames as soon as they're not the next or prev
picture. This is fine for a single-threading model, but fails miserably
in a system where pictures can be referenced (as e.g. last/prev pic)
in other threads. Keeping track of ownership of pictures keeps image
references (e.g. motion vectors, or the reference of a motion vector)
alive as long as the picture data itself is alive.

This also happens to fix make THREADS=[3-16] fate-vsynth[12]-error.

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=80469eafb747018cb9d9a2547f65def715d073b2
---

 libavcodec/mpegvideo.c |   10 ++++++----
 1 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 27dcd74..d422e12 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -318,7 +318,7 @@ int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared){
     s->prev_pict_types[0]= s->dropable ? AV_PICTURE_TYPE_B : s->pict_type;
     if (pic->f.age < PREV_PICT_TYPES_BUFFER_SIZE && s->prev_pict_types[pic->f.age] == AV_PICTURE_TYPE_B)
         pic->f.age = INT_MAX; // Skipped MBs in B-frames are quite rare in MPEG-1/2 and it is a bit tricky to skip them anyway.
-    pic->owner2 = NULL;
+    pic->owner2 = s;
 
     return 0;
 fail: //for the FF_ALLOCZ_OR_GOTO macro
@@ -1041,14 +1041,16 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     /* mark&release old frames */
     if (s->pict_type != AV_PICTURE_TYPE_B && s->last_picture_ptr && s->last_picture_ptr != s->next_picture_ptr && s->last_picture_ptr->f.data[0]) {
       if(s->out_format != FMT_H264 || s->codec_id == CODEC_ID_SVQ3){
-          free_frame_buffer(s, s->last_picture_ptr);
+          if (s->last_picture_ptr->owner2 == s)
+              free_frame_buffer(s, s->last_picture_ptr);
 
         /* release forgotten pictures */
         /* if(mpeg124/h263) */
         if(!s->encoding){
             for(i=0; i<s->picture_count; i++){
-                if (s->picture[i].f.data[0] && &s->picture[i] != s->next_picture_ptr && s->picture[i].f.reference) {
-                    av_log(avctx, AV_LOG_ERROR, "releasing zombie picture\n");
+                if (s->picture[i].owner2 == s && s->picture[i].f.data[0] && &s->picture[i] != s->next_picture_ptr && s->picture[i].f.reference) {
+                    if (!(avctx->active_thread_type & FF_THREAD_FRAME))
+                        av_log(avctx, AV_LOG_ERROR, "releasing zombie picture\n");
                     free_frame_buffer(s, &s->picture[i]);
                 }
             }



More information about the ffmpeg-cvslog mailing list