On Wed, Nov 30, 2011 at 1:22 AM, Ronald S. Bultje <rsbul...@gmail.com> wrote: > Fixes fate-h264-conformance-{mr2_tandberg_e,mr3_tandberg_b} without > requiring -strict 1. > --- > libavcodec/h264.c | 69 +++++++++++++++++++++++++++++++++++------------ > libavcodec/h264.h | 1 + > libavcodec/h264_refs.c | 6 +--- > 3 files changed, 53 insertions(+), 23 deletions(-) > > diff --git a/libavcodec/h264.c b/libavcodec/h264.c > index ad1ab69..acd7179 100644 > --- a/libavcodec/h264.c > +++ b/libavcodec/h264.c > @@ -1348,6 +1348,7 @@ static void decode_postinit(H264Context *h, int > setup_finished){ > Picture *out = s->current_picture_ptr; > Picture *cur = s->current_picture_ptr; > int i, pics, out_of_order, out_idx; > + int invalid = 0, cnt = 0; > > s->current_picture_ptr->f.qscale_type = FF_QSCALE_TYPE_H264; > s->current_picture_ptr->f.pict_type = s->pict_type; > @@ -1438,7 +1439,7 @@ static void decode_postinit(H264Context *h, int > setup_finished){ > > if( s->avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT > && !h->sps.bitstream_restriction_flag){ > - s->avctx->has_b_frames= MAX_DELAYED_PIC_COUNT; > + s->avctx->has_b_frames = MAX_DELAYED_PIC_COUNT - 1; > s->low_delay= 0; > } >
This part looks OK. > @@ -1451,31 +1452,54 @@ 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. > + * FIXME: 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 we will fix later. */ > + for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) { > + cnt += out->poc < h->last_pocs[i]; > + invalid += out->poc == INT_MIN; > + } > + if (!h->mmco_reset && !cur->f.key_frame && cnt + invalid == > MAX_DELAYED_PIC_COUNT && cnt > 0) { > + h->mmco_reset = 2; You set mmco_reset to 1 and 2 but I only see comparisons of it against 0. What samples does this fix? > + if (pics > 1) > + h->delayed_pic[pics - 2]->mmco_reset = 2; > + } > + if (h->mmco_reset || cur->f.key_frame) { > + for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) > + h->last_pocs[i] = INT_MIN; > + cnt = 0; > + invalid = MAX_DELAYED_PIC_COUNT; > + } > 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) > { } > else if (out_of_order && pics-1 == s->avctx->has_b_frames && > s->avctx->has_b_frames < MAX_DELAYED_PIC_COUNT) { > - int cnt = 0, invalid = 0; > - for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) { > - cnt += out->poc < h->last_pocs[i]; > - invalid += h->last_pocs[i] == INT_MIN; > - } > if (invalid + cnt < MAX_DELAYED_PIC_COUNT) { > s->avctx->has_b_frames = FFMAX(s->avctx->has_b_frames, cnt); > - } else if (cnt) { > - for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) > - h->last_pocs[i] = INT_MIN; > } > s->low_delay = 0; > } else if (s->low_delay && > @@ -1485,7 +1509,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 > @@ -1493,13 +1517,20 @@ static void decode_postinit(H264Context *h, int > setup_finished){ > h->delayed_pic[i] = h->delayed_pic[i+1]; > } > memmove(h->last_pocs, &h->last_pocs[1], sizeof(*h->last_pocs) * > (MAX_DELAYED_PIC_COUNT - 1)); > - h->last_pocs[MAX_DELAYED_PIC_COUNT - 1] = out->poc; > + h->last_pocs[MAX_DELAYED_PIC_COUNT - 1] = cur->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)) { > - h->next_outputed_poc = INT_MIN; > - } else > + if (out->mmco_reset) { > + if (out_idx > 0) { > + h->next_outputed_poc = out->poc; > + h->delayed_pic[out_idx - 1]->mmco_reset = out->mmco_reset; > + } else { > + h->next_outputed_poc = INT_MIN; > + } > + } else { > h->next_outputed_poc = out->poc; > + } > + h->mmco_reset = 0; > }else{ > av_log(s->avctx, AV_LOG_DEBUG, "no picture\n"); > } > @@ -2353,6 +2384,8 @@ static void flush_dpb(AVCodecContext *avctx){ > h->delayed_pic[i]->f.reference = 0; > h->delayed_pic[i]= NULL; > } > + for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++) > + h->last_pocs[i] = INT_MIN; > h->outputed_poc=h->next_outputed_poc= INT_MIN; > h->prev_interlaced_frame = 1; > idr(h); > 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 > libav-devel@libav.org > https://lists.libav.org/mailman/listinfo/libav-devel > _______________________________________________ libav-devel mailing list libav-devel@libav.org https://lists.libav.org/mailman/listinfo/libav-devel