diff options
author | Jeff Downs <heydowns@borg.com> | 2007-10-08 17:44:38 +0000 |
---|---|---|
committer | Andreas Ă–man <andreas@lonelycoder.com> | 2007-10-08 17:44:38 +0000 |
commit | 12d96de3acf660d53d6931e2045ec21fd8ae718f (patch) | |
tree | a3bee9fe82e500e22b96d2876287ed61bdcf7dab /libavcodec/h264.c | |
parent | ac6b423b0c070f34de2b6a8df7913c6fe7aaa0de (diff) | |
download | ffmpeg-12d96de3acf660d53d6931e2045ec21fd8ae718f.tar.gz |
Manage Picture buffers for fields as well as frames. Pair complementary fields into one MPV Picture.
Part of PAFF implementation.
patch by Jeff Downs, heydowns a borg d com
original thread:
Subject: [FFmpeg-devel] [PATCH] Implement PAFF in H.264
Date: 18/09/07 20:30
Originally committed as revision 10691 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/h264.c')
-rw-r--r-- | libavcodec/h264.c | 75 |
1 files changed, 73 insertions, 2 deletions
diff --git a/libavcodec/h264.c b/libavcodec/h264.c index cfc8de7771..752f2d236f 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -3339,6 +3339,7 @@ static void flush_dpb(AVCodecContext *avctx){ idr(h); if(h->s.current_picture_ptr) h->s.current_picture_ptr->reference= 0; + h->s.first_field= 0; } /** @@ -3830,6 +3831,7 @@ static void clone_slice(H264Context *dst, H264Context *src) dst->s.current_picture = src->s.current_picture; dst->s.linesize = src->s.linesize; dst->s.uvlinesize = src->s.uvlinesize; + dst->s.first_field = src->s.first_field; dst->prev_poc_msb = src->prev_poc_msb; dst->prev_poc_lsb = src->prev_poc_lsb; @@ -3857,12 +3859,14 @@ static void clone_slice(H264Context *dst, H264Context *src) */ static int decode_slice_header(H264Context *h, H264Context *h0){ MpegEncContext * const s = &h->s; + MpegEncContext * const s0 = &h0->s; unsigned int first_mb_in_slice; unsigned int pps_id; int num_ref_idx_active_override_flag; static const uint8_t slice_type_map[5]= {P_TYPE, B_TYPE, I_TYPE, SP_TYPE, SI_TYPE}; unsigned int slice_type, tmp, i; int default_ref_list_done = 0; + int last_pic_structure; s->dropable= h->nal_ref_idc == 0; @@ -3870,6 +3874,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ if((s->flags2 & CODEC_FLAG2_CHUNKS) && first_mb_in_slice == 0){ h0->current_slice = 0; + if (!s0->first_field) s->current_picture_ptr= NULL; } @@ -3939,6 +3944,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ return -1; // we cant (re-)initialize context during parallel decoding if (MPV_common_init(s) < 0) return -1; + s->first_field = 0; init_scan_tables(h); alloc_tables(h); @@ -3977,6 +3983,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ h->mb_mbaff = 0; h->mb_aff_frame = 0; + last_pic_structure = s0->picture_structure; if(h->sps.frame_mbs_only_flag){ s->picture_structure= PICT_FRAME; }else{ @@ -3990,8 +3997,50 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ } if(h0->current_slice == 0){ - if(frame_start(h) < 0) + /* See if we have a decoded first field looking for a pair... */ + if (s0->first_field) { + assert(s0->current_picture_ptr); + assert(s0->current_picture_ptr->data[0]); + assert(s0->current_picture_ptr->reference != DELAYED_PIC_REF); + + /* figure out if we have a complementary field pair */ + if (!FIELD_PICTURE || s->picture_structure == last_pic_structure) { + /* + * Previous field is unmatched. Don't display it, but let it + * remain for reference if marked as such. + */ + s0->current_picture_ptr = NULL; + s0->first_field = FIELD_PICTURE; + + } else { + if (h->nal_ref_idc && + s0->current_picture_ptr->reference && + s0->current_picture_ptr->frame_num != h->frame_num) { + /* + * This and previous field were reference, but had + * different frame_nums. Consider this field first in + * pair. Throw away previous field except for reference + * purposes. + */ + s0->first_field = 1; + s0->current_picture_ptr = NULL; + + } else { + /* Second field in complementary pair */ + s0->first_field = 0; + } + } + + } else { + /* Frame or first field in a potentially complementary pair */ + assert(!s0->current_picture_ptr); + s0->first_field = FIELD_PICTURE; + } + + if((!FIELD_PICTURE || s0->first_field) && frame_start(h) < 0) { + s0->first_field = 0; return -1; + } } if(h != h0) clone_slice(h, h0); @@ -7363,6 +7412,8 @@ static void execute_decode_slices(H264Context *h, int context_count){ hx = h->thread_context[context_count - 1]; s->mb_x = hx->s.mb_x; s->mb_y = hx->s.mb_y; + s->dropable = hx->s.dropable; + s->picture_structure = hx->s.picture_structure; for(i = 1; i < context_count; i++) h->s.error_count += h->thread_context[i]->s.error_count; } @@ -7385,6 +7436,7 @@ static int decode_nal_units(H264Context *h, uint8_t *buf, int buf_size){ #endif if(!(s->flags2 & CODEC_FLAG2_CHUNKS)){ h->current_slice = 0; + if (!s->first_field) s->current_picture_ptr= NULL; } @@ -7682,16 +7734,34 @@ static int decode_frame(AVCodecContext *avctx, h->prev_frame_num_offset= h->frame_num_offset; h->prev_frame_num= h->frame_num; - if(s->current_picture_ptr->reference & s->picture_structure){ + if(!s->dropable) { h->prev_poc_msb= h->poc_msb; h->prev_poc_lsb= h->poc_lsb; execute_ref_pic_marking(h, h->mmco, h->mmco_index); } + /* + * FIXME: Error handling code does not seem to support interlaced + * when slices span multiple rows + * The ff_er_add_slice calls don't work right for bottom + * fields; they cause massive erroneous error concealing + * Error marking covers both fields (top and bottom). + * This causes a mismatched s->error_count + * and a bad error table. Further, the error count goes to + * INT_MAX when called for bottom field, because mb_y is + * past end by one (callers fault) and resync_mb_y != 0 + * causes problems for the first MB line, too. + */ + if (!FIELD_PICTURE) ff_er_frame_end(s); MPV_frame_end(s); + if (s->first_field) { + /* Wait for second field. */ + *data_size = 0; + + } else { //FIXME do something with unavailable reference frames #if 0 //decode order @@ -7762,6 +7832,7 @@ static int decode_frame(AVCodecContext *avctx, *pict= *(AVFrame*)out; else av_log(avctx, AV_LOG_DEBUG, "no picture\n"); + } } assert(pict->data[0] || !*data_size); |