[FFmpeg-cvslog] Merge remote-tracking branch 'ffmpeg-mt/master'

Alexander Strange git at videolan.org
Mon Apr 18 01:00:41 CEST 2011


ffmpeg | branch: master | Alexander Strange <astrange at ithinksw.com> | Mon Apr 18 00:47:35 2011 +0200| [7e2eb4bacd70541702bd086ab2a39cb7653d314e] | committer: Michael Niedermayer

    Merge remote-tracking branch 'ffmpeg-mt/master'

    * ffmpeg-mt/master:
      Release unused pictures even when not calling ff_h264_frame_start()
      h264: Fix decoding race condition with PAFF
      h264: cosmetic whitespace change
    Duplicate  Fix REBASE_PICTURE with h.264
    Not pulled  Update test scripts to use ffmpeg instead of ffmpeg_g
    Duplicate  Fix ffmpeg-mt fixme in h264

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

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

 libavcodec/h264.c      |   14 ++++++++++----
 libavcodec/mpegvideo.c |   23 +++++++++++++++++------
 libavcodec/mpegvideo.h |    6 ++++--
 3 files changed, 31 insertions(+), 12 deletions(-)

diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 48a2455..c64e6fb 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -715,7 +715,7 @@ static int decode_update_thread_context(AVCodecContext *dst, const AVCodecContex
     copy_fields(h, h1, short_ref, cabac_init_idc);
 
     copy_picture_range(h->short_ref,   h1->short_ref,   32, s, s1);
-    copy_picture_range(h->long_ref,    h1->long_ref,    32,  s, s1);
+    copy_picture_range(h->long_ref,    h1->long_ref,    32, s, s1);
     copy_picture_range(h->delayed_pic, h1->delayed_pic, MAX_DELAYED_PIC_COUNT+2, s, s1);
 
     h->last_slice_type = h1->last_slice_type;
@@ -930,6 +930,8 @@ static void decode_postinit(H264Context *h){
 
     if(out_of_order || pics > s->avctx->has_b_frames){
         out->reference &= ~DELAYED_PIC_REF;
+        out->owner2 = s; // for frame threading, the owner must be the second field's thread
+                         // or else the first thread can release the picture and reuse it unsafely
         for(i=out_idx; h->delayed_pic[i]; i++)
             h->delayed_pic[i] = h->delayed_pic[i+1];
     }
@@ -2049,9 +2051,13 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
             s0->first_field = FIELD_PICTURE;
         }
 
-        if((!FIELD_PICTURE || s0->first_field) && ff_h264_frame_start(h) < 0) {
-            s0->first_field = 0;
-            return -1;
+        if(!FIELD_PICTURE || s0->first_field) {
+            if (ff_h264_frame_start(h) < 0) {
+                s0->first_field = 0;
+                return -1;
+            }
+        } else {
+            ff_release_unused_pictures(s, 0);
         }
     }
     if(h != h0)
diff --git a/libavcodec/mpegvideo.c b/libavcodec/mpegvideo.c
index 676c3eb..819f58d 100644
--- a/libavcodec/mpegvideo.c
+++ b/libavcodec/mpegvideo.c
@@ -316,6 +316,7 @@ int ff_alloc_picture(MpegEncContext *s, Picture *pic, int shared){
     s->prev_pict_types[0]= s->dropable ? FF_B_TYPE : s->pict_type;
     if(pic->age < PREV_PICT_TYPES_BUFFER_SIZE && s->prev_pict_types[pic->age] == FF_B_TYPE)
         pic->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 = s;
 
     return 0;
 fail: //for the FF_ALLOCZ_OR_GOTO macro
@@ -946,6 +947,21 @@ void init_vlc_rl(RLTable *rl)
     }
 }
 
+void ff_release_unused_pictures(MpegEncContext *s, int remove_current)
+{
+    int i;
+
+    /* release non reference frames */
+    for(i=0; i<s->picture_count; i++){
+        if(s->picture[i].data[0] && !s->picture[i].reference
+           && s->picture[i].owner2 == s
+           && (remove_current || &s->picture[i] != s->current_picture_ptr)
+           /*&& s->picture[i].type!=FF_BUFFER_TYPE_SHARED*/){
+            free_frame_buffer(s, &s->picture[i]);
+        }
+    }
+}
+
 int ff_find_unused_picture(MpegEncContext *s, int shared){
     int i;
 
@@ -1025,12 +1041,7 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
     }
 
     if(!s->encoding){
-        /* release non reference frames */
-        for(i=0; i<s->picture_count; i++){
-            if(s->picture[i].data[0] && !s->picture[i].reference /*&& s->picture[i].type!=FF_BUFFER_TYPE_SHARED*/){
-                free_frame_buffer(s, &s->picture[i]);
-            }
-        }
+        ff_release_unused_pictures(s, 1);
 
         if(s->current_picture_ptr && s->current_picture_ptr->data[0]==NULL)
             pic= s->current_picture_ptr; //we already have a unused image (maybe it was set before reading the header)
diff --git a/libavcodec/mpegvideo.h b/libavcodec/mpegvideo.h
index fee75b2..3836a6e 100644
--- a/libavcodec/mpegvideo.h
+++ b/libavcodec/mpegvideo.h
@@ -76,6 +76,8 @@ enum OutputFormat {
 #define EXT_START_CODE          0x000001b5
 #define USER_START_CODE         0x000001b2
 
+struct MpegEncContext;
+
 /**
  * Picture.
  */
@@ -132,10 +134,9 @@ typedef struct Picture{
     uint8_t *mb_mean;           ///< Table for MB luminance
     int32_t *mb_cmp_score;      ///< Table for MB cmp scores, for mb decision FIXME remove
     int b_frame_score;          /* */
+    struct MpegEncContext *owner2; ///< pointer to the MpegEncContext that allocated this picture
 } Picture;
 
-struct MpegEncContext;
-
 /**
  * Motion estimation context.
  */
@@ -712,6 +713,7 @@ void ff_draw_horiz_band(MpegEncContext *s, int y, int h);
 void ff_mpeg_flush(AVCodecContext *avctx);
 void ff_print_debug_info(MpegEncContext *s, AVFrame *pict);
 void ff_write_quant_matrix(PutBitContext *pb, uint16_t *matrix);
+void ff_release_unused_pictures(MpegEncContext *s, int remove_current);
 int ff_find_unused_picture(MpegEncContext *s, int shared);
 void ff_denoise_dct(MpegEncContext *s, DCTELEM *block);
 void ff_update_duplicate_context(MpegEncContext *dst, MpegEncContext *src);



More information about the ffmpeg-cvslog mailing list