---
 libavcodec/h264.c |   46 +++++++++++++++++++++++++++-------------------
 1 files changed, 27 insertions(+), 19 deletions(-)
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 95a5aed..e0ab15d 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -1640,29 +1640,17 @@ static inline int quantize_c(DCTELEM *block, uint8_t *scantable, int qscale, int
 
 static inline int mc_dir_part_y(H264Context *h, Picture *pic, int n, int height,
                                  int y_offset, int list){
-    MpegEncContext * const s = &h->s;
     int my= h->mv_cache[list][ scan8[n] ][1] + 4*y_offset;
     int filter_height= 6;
     int extra_height= h->emu_edge_height;
     const int full_my= my>>2;
 
     if(!pic->data[0]) return -1;
-    if((pic->reference&3) != PICT_FRAME) return 16*s->mb_height-1;
 
     if(full_my < (extra_height + filter_height)){
         my = abs(my) + extra_height*4;
     }
 
-    /*
-    if(!ENABLE_GRAY && !(s->flags&CODEC_FLAG_GRAY)){
-        if(MB_FIELD){
-            const int pic_height = 16*s->mb_height >> MB_FIELD;
-            // chroma offset when predicting from a field of opposite parity
-            my += 2 * ((s->mb_y & 1) - (pic->reference - 1));
-            emu |= (my>>3) < 0 || (my>>3) + 8 >= (pic_height>>1);
-        }
-    }*/
-
     return (my + height * 4 + filter_height * 4 + 1) >> 2;
 }
 
@@ -1671,12 +1659,17 @@ static inline void mc_part_y(H264Context *h, int refs[2][48], int n, int height,
     MpegEncContext * const s = &h->s;
     int my;
 
-    y_offset += 16*(s->mb_y >> MB_FIELD);
+    y_offset += 16*(s->mb_y >> FIELD_PICTURE);
 
     if(list0){
         int ref_n = h->ref_cache[0][ scan8[n] ], my;
         Picture *ref= &h->ref_list[0][ref_n];
-        if(ref->thread_opaque != s->current_picture_ptr->thread_opaque){
+
+        // Error resilience puts the current picture in the ref list.
+        // Don't try to wait on these as it will cause a deadlock.
+        // Fields can wait on each other, though.
+        if(ref->thread_opaque != s->current_picture.thread_opaque ||
+           (ref->reference&3) != s->picture_structure) {
             my = mc_dir_part_y(h, ref, n, height, y_offset, 0);
             refs[0][ref_n] = FFMAX(refs[0][ref_n], my);
         }
@@ -1685,7 +1678,9 @@ static inline void mc_part_y(H264Context *h, int refs[2][48], int n, int height,
     if(list1){
         int ref_n = h->ref_cache[1][ scan8[n] ];
         Picture *ref= &h->ref_list[1][ref_n];
-        if(ref->thread_opaque != s->current_picture_ptr->thread_opaque){
+
+        if(ref->thread_opaque != s->current_picture.thread_opaque ||
+           (ref->reference&3) != s->picture_structure) {
             my = mc_dir_part_y(h, ref, n, height, y_offset, 1);
             refs[1][ref_n] = FFMAX(refs[1][ref_n], my);
         }
@@ -1703,7 +1698,6 @@ static void avail_motion(H264Context *h){
     const int mb_type= s->current_picture.mb_type[mb_xy];
     int refs[2][48];
     int ref, list;
-    int pic_height = 16*s->mb_height;
 
     memset(refs, -1, sizeof(refs));
 
@@ -1755,11 +1749,25 @@ static void avail_motion(H264Context *h){
         }
     }
 
-    //L1 refs are closer than L0, so wait for them first
     for(list=1; list>=0; list--){
         for(ref=0; ref<48; ref++){
-            if(refs[list][ref] >= 0)
-                ff_await_frame_progress((AVFrame*)&h->ref_list[list][ref], FFMIN(refs[list][ref], pic_height-1));
+            int row = refs[list][ref];
+            if(row >= 0){
+                Picture *ref_pic = &h->ref_list[list][ref];
+                int pic_height = 16*s->mb_height >> ref_pic->field_picture;
+                int ref_field = ref_pic->reference - 1;
+
+                if(!FIELD_PICTURE && ref_pic->field_picture){ // frame referencing two fields
+                    ff_await_field_progress((AVFrame*)ref_pic, FFMIN((row >> 1) - !(row&1), pic_height-1), 1);
+                    ff_await_field_progress((AVFrame*)ref_pic, FFMIN((row >> 1)           , pic_height-1), 0);
+                }else if(FIELD_PICTURE && !ref_pic->field_picture){ // field referencing one field of a frame
+                    ff_await_field_progress((AVFrame*)ref_pic, FFMIN(row*2 + ref_field    , pic_height-1), 0);
+                }else if(FIELD_PICTURE){
+                    ff_await_field_progress((AVFrame*)ref_pic, FFMIN(row, pic_height-1), ref_field);
+                }else{
+                    ff_await_field_progress((AVFrame*)ref_pic, FFMIN(row, pic_height-1), 0);
+                }
+            }
         }
     }
 }
_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc

Reply via email to