---
 libavcodec/h264.c      |   38 +++++++++++++++++++++++++++++++-------
 libavcodec/h264.h      |    1 +
 libavcodec/h264_refs.c |    6 +-----
 3 files changed, 33 insertions(+), 12 deletions(-)

diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index ad1ab69..dcb712f 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -1451,16 +1451,36 @@ static void decode_postinit(H264Context *h, int 
setup_finished){
     if (cur->f.reference == 0)
         cur->f.reference = DELAYED_PIC_REF;
 
+    /* Frame reordering. This code takes pictures from coding order and sorts
+     * them by their incremental POC value into display order. It supports POC
+     * gaps, MMCO reset codes and random resets.
+     * A "display group" can start either with a IDR frame (f.key_frame = 1),
+     * and/or can be closed down with a MMCO reset code. In sequences where
+     * there is no delay, we can't detect that (since the frame was already
+     * output to the user), so we also set h->mmco_reset to detect the MMCO
+     * reset code.
+     * If we detect insufficient delays (as per s->avctx->has_b_frames), we
+     * increase the delay between input and output. All frames affected by
+     * the lag (e.g. those that should have been output before another frame
+     * that we already returned to the user) will be dropped. This is a bug
+     * that I will fix later (Ronald). */
+    if (h->mmco_reset || cur->f.key_frame) {
+        for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
+            h->last_pocs[i] = INT_MIN;
+    }
     out = h->delayed_pic[0];
     out_idx = 0;
-    for (i = 1; h->delayed_pic[i] && !h->delayed_pic[i]->f.key_frame && 
!h->delayed_pic[i]->mmco_reset; i++)
+    for (i = 1; i < MAX_DELAYED_PIC_COUNT && h->delayed_pic[i] &&
+         !h->delayed_pic[i-1]->mmco_reset && !h->delayed_pic[i]->f.key_frame; 
i++)
+    {
         if(h->delayed_pic[i]->poc < out->poc){
             out = h->delayed_pic[i];
             out_idx = i;
         }
-    if (s->avctx->has_b_frames == 0 && (h->delayed_pic[0]->f.key_frame || 
h->delayed_pic[0]->mmco_reset))
-        h->next_outputed_poc= INT_MIN;
-    out_of_order = out->poc < h->next_outputed_poc;
+    }
+    if (s->avctx->has_b_frames == 0 && (h->delayed_pic[0]->f.key_frame || 
h->mmco_reset))
+        h->next_outputed_poc = INT_MIN;
+    out_of_order = !out->f.key_frame && !h->mmco_reset && (out->poc < 
h->next_outputed_poc);
 
     if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= 
h->sps.num_reorder_frames)
         { }
@@ -1474,8 +1494,10 @@ static void decode_postinit(H264Context *h, int 
setup_finished){
         if (invalid + cnt < MAX_DELAYED_PIC_COUNT) {
             s->avctx->has_b_frames = FFMAX(s->avctx->has_b_frames, cnt);
         } else if (cnt) {
+            av_log(s->avctx, AV_LOG_WARNING, "Weird manual poc reset\n");
             for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
                 h->last_pocs[i] = INT_MIN;
+            out_of_order = 0;
         }
         s->low_delay = 0;
     } else if (s->low_delay &&
@@ -1485,7 +1507,7 @@ static void decode_postinit(H264Context *h, int 
setup_finished){
         s->avctx->has_b_frames++;
     }
 
-    if(out_of_order || pics > s->avctx->has_b_frames){
+    if(pics > s->avctx->has_b_frames){
         out->f.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
@@ -1496,10 +1518,12 @@ static void decode_postinit(H264Context *h, int 
setup_finished){
     h->last_pocs[MAX_DELAYED_PIC_COUNT - 1] = out->poc;
     if(!out_of_order && pics > s->avctx->has_b_frames){
         h->next_output_pic = out;
-        if (out_idx == 0 && h->delayed_pic[0] && 
(h->delayed_pic[0]->f.key_frame || h->delayed_pic[0]->mmco_reset)) {
+        if (out->mmco_reset || (h->mmco_reset && !h->delayed_pic[0])) {
             h->next_outputed_poc = INT_MIN;
-        } else
+        } else {
             h->next_outputed_poc = out->poc;
+        }
+        h->mmco_reset = 0;
     }else{
         av_log(s->avctx, AV_LOG_DEBUG, "no picture\n");
     }
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index caea7ba..5280e51 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -498,6 +498,7 @@ typedef struct H264Context{
      */
     MMCO mmco[MAX_MMCO_COUNT];
     int mmco_index;
+    int mmco_reset;
 
     int long_ref_count;  ///< number of actual long term references
     int short_ref_count; ///< number of actual short term references
diff --git a/libavcodec/h264_refs.c b/libavcodec/h264_refs.c
index 370b5c3..273c52b 100644
--- a/libavcodec/h264_refs.c
+++ b/libavcodec/h264_refs.c
@@ -582,13 +582,9 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO 
*mmco, int mmco_count){
             for(j = 0; j < 16; j++) {
                 remove_long(h, j, 0);
             }
-            s->current_picture_ptr->poc=
-            s->current_picture_ptr->field_poc[0]=
-            s->current_picture_ptr->field_poc[1]=
-            h->poc_lsb=
-            h->poc_msb=
             h->frame_num=
             s->current_picture_ptr->frame_num= 0;
+            h->mmco_reset = 1;
             s->current_picture_ptr->mmco_reset=1;
             break;
         default: assert(0);
-- 
1.7.2.1

_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to