From a4dae92b5857dfa3c7d7d55179ddbb4eff760afc Mon Sep 17 00:00:00 2001 From: Loren Merritt Date: Tue, 4 Jan 2005 01:12:48 +0000 Subject: [PATCH] Sort B-frames into display order. Originally committed as revision 3799 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavcodec/h264.c | 48 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 9 deletions(-) diff --git a/libavcodec/h264.c b/libavcodec/h264.c index a4ede6f323..bf29af6053 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -281,6 +281,7 @@ typedef struct H264Context{ Picture default_ref_list[2][32]; Picture ref_list[2][32]; //FIXME size? Picture field_ref_list[2][32]; //FIXME size? + Picture *delayed_pic[16]; //FIXME size? /** * memory management control operations buffer. @@ -2929,20 +2930,30 @@ static int pred_weight_table(H264Context *h){ * instantaneous decoder refresh. */ static void idr(H264Context *h){ - int i; + int i,j; + +#define CHECK_DELAY(pic) \ + for(j = 0; h->delayed_pic[j]; j++) \ + if(pic == h->delayed_pic[j]){ \ + pic->reference=1; \ + break; \ + } for(i=0; ilong_ref_count; i++){ h->long_ref[i]->reference=0; + CHECK_DELAY(h->long_ref[i]); h->long_ref[i]= NULL; } h->long_ref_count=0; for(i=0; ishort_ref_count; i++){ h->short_ref[i]->reference=0; + CHECK_DELAY(h->short_ref[i]); h->short_ref[i]= NULL; } h->short_ref_count=0; } +#undef CHECK_DELAY /** * @@ -6088,19 +6099,38 @@ static int decode_frame(AVCodecContext *avctx, //FIXME do something with unavailable reference frames // if(ret==FRAME_SKIPED) return get_consumed_bytes(s, buf_index, buf_size); -#if 0 - if(s->pict_type==B_TYPE || s->low_delay){ - *pict= *(AVFrame*)&s->current_picture; - } else { - *pict= *(AVFrame*)&s->last_picture; - } -#endif if(!s->current_picture_ptr){ av_log(h->s.avctx, AV_LOG_DEBUG, "error, NO frame\n"); return -1; } - *pict= *(AVFrame*)&s->current_picture; //FIXME + { + /* Sort B-frames into display order + * FIXME doesn't allow for multiple delayed frames */ + Picture *cur = s->current_picture_ptr; + Picture *prev = h->delayed_pic[0]; + Picture *out; + + if(cur->pict_type == B_TYPE + || (!h->sps.gaps_in_frame_num_allowed_flag + && prev && cur->poc - prev->poc > 2)){ + s->low_delay = 0; + s->avctx->has_b_frames = 1; + } + + if(s->low_delay || !prev || cur->pict_type == B_TYPE) + out = cur; + else{ + out = prev; + if(prev->reference == 1) + prev->reference = 0; + } + if(!s->low_delay && (!prev || out == prev)) + h->delayed_pic[0] = cur; + + *pict= *(AVFrame*)out; + } + ff_print_debug_info(s, pict); assert(pict->data[0]); //printf("out %d\n", (int)pict->data[0]);