This works with PAFF and CODEC_FLAG2_CHUNKS, though the second is useless and 
should be removed.
---
 libavcodec/h264.c |  156 ++++++++++++++++++++++++++++------------------------
 libavcodec/h264.h |    1 +
 2 files changed, 85 insertions(+), 72 deletions(-)
diff --git a/libavcodec/h264.c b/libavcodec/h264.c
index 4ae4212..0ab49c3 100644
--- a/libavcodec/h264.c
+++ b/libavcodec/h264.c
@@ -2422,6 +2422,7 @@ static int decode_update_context(AVCodecContext *dst, AVCodecContext *src){
         h->prev_poc_lsb= h->poc_lsb;
         execute_ref_pic_marking(h, h->mmco, h->mmco_index);
     }
+    if(h->next_output_pic) h->outputed_poc = h->next_output_pic->poc;
 
     return 0;
 }
@@ -2477,6 +2478,9 @@ static int frame_start(H264Context *h){
 
     s->current_picture_ptr->field_poc[0]=
     s->current_picture_ptr->field_poc[1]= INT_MAX;
+
+    h->next_output_pic = NULL;
+
     assert(s->current_picture_ptr->long_ref==0);
 
     return 0;
@@ -6801,12 +6805,83 @@ static void filter_mb( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8
 
 /**
   * Run setup operations that must be run after slice header decoding.
-  * This includes setting Picture variables and reordering output frames.
+  * This includes finding the next displayed frame.
   *
   * @param h h264 master context
   */
 static void decode_postinit(H264Context *h){
     MpegEncContext * const s = &h->s;
+    Picture *out = s->current_picture_ptr;
+    Picture *cur = s->current_picture_ptr;
+    int i, pics, cross_idr, out_of_order, out_idx;
+
+    s->current_picture_ptr->qscale_type= FF_QSCALE_TYPE_H264;
+    s->current_picture_ptr->pict_type= s->pict_type;
+
+    // Don't do anything if it's the first field or we've already been called.
+    if (h->next_output_pic || cur->field_poc[0]==INT_MAX || cur->field_poc[1]==INT_MAX) return;
+
+    cur->interlaced_frame = FIELD_OR_MBAFF_PICTURE;
+    /* Derive top_field_first from field pocs. */
+    cur->top_field_first = cur->field_poc[0] < cur->field_poc[1];
+
+    //FIXME do something with unavailable reference frames
+
+    /* Sort B-frames into display order */
+
+    if(h->sps.bitstream_restriction_flag
+       && s->avctx->has_b_frames < h->sps.num_reorder_frames){
+        s->avctx->has_b_frames = h->sps.num_reorder_frames;
+        s->low_delay = 0;
+    }
+
+    if(   s->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT
+       && !h->sps.bitstream_restriction_flag){
+        s->avctx->has_b_frames= MAX_DELAYED_PIC_COUNT;
+        s->low_delay= 0;
+    }
+
+    pics = 0;
+    while(h->delayed_pic[pics]) pics++;
+
+    assert(pics <= MAX_DELAYED_PIC_COUNT);
+
+    h->delayed_pic[pics++] = cur;
+    if(cur->reference == 0)
+        cur->reference = DELAYED_PIC_REF;
+
+    out = h->delayed_pic[0];
+    out_idx = 0;
+    for(i=1; h->delayed_pic[i] && h->delayed_pic[i]->poc; i++)
+        if(h->delayed_pic[i]->poc < out->poc){
+            out = h->delayed_pic[i];
+            out_idx = i;
+        }
+    cross_idr = !h->delayed_pic[0]->poc || !!h->delayed_pic[i];
+
+    out_of_order = !cross_idr && out->poc < h->outputed_poc;
+
+    if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= h->sps.num_reorder_frames)
+        { }
+    else if((out_of_order && pics-1 == s->avctx->has_b_frames && s->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT)
+       || (s->low_delay &&
+        ((!cross_idr && out->poc > h->outputed_poc + 2)
+         || cur->pict_type == FF_B_TYPE)))
+    {
+        s->low_delay = 0;
+        s->avctx->has_b_frames++;
+    }
+
+    if(out_of_order || pics > s->avctx->has_b_frames){
+        out->reference &= ~DELAYED_PIC_REF;
+        for(i=out_idx; h->delayed_pic[i]; i++)
+            h->delayed_pic[i] = h->delayed_pic[i+1];
+    }
+    if(!out_of_order && pics > s->avctx->has_b_frames){
+        h->next_output_pic = out;
+    }else{
+        av_log(s->avctx, AV_LOG_DEBUG, "no picture\n");
+    }
 
     ff_report_predecode_done(s->avctx);
 }
@@ -7487,6 +7562,8 @@ static void execute_decode_slices(H264Context *h, int context_count){
     H264Context *hx;
     int i;
 
+    if(!(s->flags2 & CODEC_FLAG2_CHUNKS)) decode_postinit(h);
+
     if(context_count == 1) {
         decode_slice(avctx, h);
     } else {
@@ -7801,16 +7878,12 @@ static int decode_frame(AVCodecContext *avctx,
     }
 
     if(!(s->flags2 & CODEC_FLAG2_CHUNKS) || (s->mb_y >= s->mb_height && s->mb_height)){
-        Picture *out = s->current_picture_ptr;
-        Picture *cur = s->current_picture_ptr;
-        int i, pics, cross_idr, out_of_order, out_idx;
+
+        if(s->flags2 & CODEC_FLAG2_CHUNKS) decode_postinit(h);
 
         s->mb_y= 0;
         ff_report_decode_progress((AVFrame*)s->current_picture_ptr, (16*s->mb_height >> s->first_field) - 1);
 
-        s->current_picture_ptr->qscale_type= FF_QSCALE_TYPE_H264;
-        s->current_picture_ptr->pict_type= s->pict_type;
-
         if(!USE_FRAME_THREADING(avctx)){
             if(!s->dropable) {
                 execute_ref_pic_marking(h, h->mmco, h->mmco_index);
@@ -7819,6 +7892,7 @@ static int decode_frame(AVCodecContext *avctx,
             }
             h->prev_frame_num_offset= h->frame_num_offset;
             h->prev_frame_num= h->frame_num;
+            if(h->next_output_pic) h->outputed_poc = h->next_output_pic->poc;
         }
 
         /*
@@ -7838,75 +7912,13 @@ static int decode_frame(AVCodecContext *avctx,
 
         MPV_frame_end(s);
 
-        if (cur->field_poc[0]==INT_MAX || cur->field_poc[1]==INT_MAX) {
+        if (!h->next_output_pic) {
             /* Wait for second field. */
             *data_size = 0;
 
         } else {
-            cur->interlaced_frame = FIELD_OR_MBAFF_PICTURE;
-            /* Derive top_field_first from field pocs. */
-            cur->top_field_first = cur->field_poc[0] < cur->field_poc[1];
-
-        //FIXME do something with unavailable reference frames
-
-            /* Sort B-frames into display order */
-
-            if(h->sps.bitstream_restriction_flag
-               && s->avctx->has_b_frames < h->sps.num_reorder_frames){
-                s->avctx->has_b_frames = h->sps.num_reorder_frames;
-                s->low_delay = 0;
-            }
-
-            if(   s->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT
-               && !h->sps.bitstream_restriction_flag){
-                s->avctx->has_b_frames= MAX_DELAYED_PIC_COUNT;
-                s->low_delay= 0;
-            }
-
-            pics = 0;
-            while(h->delayed_pic[pics]) pics++;
-
-            assert(pics <= MAX_DELAYED_PIC_COUNT);
-
-            h->delayed_pic[pics++] = cur;
-            if(cur->reference == 0)
-                cur->reference = DELAYED_PIC_REF;
-
-            out = h->delayed_pic[0];
-            out_idx = 0;
-            for(i=1; h->delayed_pic[i] && h->delayed_pic[i]->poc; i++)
-                if(h->delayed_pic[i]->poc < out->poc){
-                    out = h->delayed_pic[i];
-                    out_idx = i;
-                }
-            cross_idr = !h->delayed_pic[0]->poc || !!h->delayed_pic[i];
-
-            out_of_order = !cross_idr && out->poc < h->outputed_poc;
-
-            if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= h->sps.num_reorder_frames)
-                { }
-            else if((out_of_order && pics-1 == s->avctx->has_b_frames && s->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT)
-               || (s->low_delay &&
-                ((!cross_idr && out->poc > h->outputed_poc + 2)
-                 || cur->pict_type == FF_B_TYPE)))
-            {
-                s->low_delay = 0;
-                s->avctx->has_b_frames++;
-            }
-
-            if(out_of_order || pics > s->avctx->has_b_frames){
-                out->reference &= ~DELAYED_PIC_REF;
-                for(i=out_idx; h->delayed_pic[i]; i++)
-                    h->delayed_pic[i] = h->delayed_pic[i+1];
-            }
-            if(!out_of_order && pics > s->avctx->has_b_frames){
-                *data_size = sizeof(AVFrame);
-
-                h->outputed_poc = out->poc;
-                *pict= *(AVFrame*)out;
-            }else{
-                av_log(avctx, AV_LOG_DEBUG, "no picture\n");
-            }
+            *data_size = sizeof(AVFrame);
+            *pict = *(AVFrame*)h->next_output_pic;
         }
     }
 
diff --git a/libavcodec/h264.h b/libavcodec/h264.h
index 39a0a27..c251da3 100644
--- a/libavcodec/h264.h
+++ b/libavcodec/h264.h
@@ -348,6 +348,7 @@ typedef struct H264Context{
                                           according to picture reordering in slice header */
     int ref2frm[16][2][64];          ///< reference to frame number lists, used in the loop filter, the first 2 are for -2,-1
     Picture *delayed_pic[MAX_DELAYED_PIC_COUNT+2]; //FIXME size?
+    Picture *next_output_pic;
     int outputed_poc;
 
     /**
_______________________________________________
FFmpeg-soc mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/ffmpeg-soc

Reply via email to