Skip to content

Commit 12d96de

Browse files
Jeff Downsandoma
authored andcommitted
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
1 parent ac6b423 commit 12d96de

File tree

2 files changed

+74
-3
lines changed

2 files changed

+74
-3
lines changed

libavcodec/h264.c

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3339,6 +3339,7 @@ static void flush_dpb(AVCodecContext *avctx){
33393339
idr(h);
33403340
if(h->s.current_picture_ptr)
33413341
h->s.current_picture_ptr->reference= 0;
3342+
h->s.first_field= 0;
33423343
}
33433344

33443345
/**
@@ -3830,6 +3831,7 @@ static void clone_slice(H264Context *dst, H264Context *src)
38303831
dst->s.current_picture = src->s.current_picture;
38313832
dst->s.linesize = src->s.linesize;
38323833
dst->s.uvlinesize = src->s.uvlinesize;
3834+
dst->s.first_field = src->s.first_field;
38333835

38343836
dst->prev_poc_msb = src->prev_poc_msb;
38353837
dst->prev_poc_lsb = src->prev_poc_lsb;
@@ -3857,19 +3859,22 @@ static void clone_slice(H264Context *dst, H264Context *src)
38573859
*/
38583860
static int decode_slice_header(H264Context *h, H264Context *h0){
38593861
MpegEncContext * const s = &h->s;
3862+
MpegEncContext * const s0 = &h0->s;
38603863
unsigned int first_mb_in_slice;
38613864
unsigned int pps_id;
38623865
int num_ref_idx_active_override_flag;
38633866
static const uint8_t slice_type_map[5]= {P_TYPE, B_TYPE, I_TYPE, SP_TYPE, SI_TYPE};
38643867
unsigned int slice_type, tmp, i;
38653868
int default_ref_list_done = 0;
3869+
int last_pic_structure;
38663870

38673871
s->dropable= h->nal_ref_idc == 0;
38683872

38693873
first_mb_in_slice= get_ue_golomb(&s->gb);
38703874

38713875
if((s->flags2 & CODEC_FLAG2_CHUNKS) && first_mb_in_slice == 0){
38723876
h0->current_slice = 0;
3877+
if (!s0->first_field)
38733878
s->current_picture_ptr= NULL;
38743879
}
38753880

@@ -3939,6 +3944,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
39393944
return -1; // we cant (re-)initialize context during parallel decoding
39403945
if (MPV_common_init(s) < 0)
39413946
return -1;
3947+
s->first_field = 0;
39423948

39433949
init_scan_tables(h);
39443950
alloc_tables(h);
@@ -3977,6 +3983,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
39773983

39783984
h->mb_mbaff = 0;
39793985
h->mb_aff_frame = 0;
3986+
last_pic_structure = s0->picture_structure;
39803987
if(h->sps.frame_mbs_only_flag){
39813988
s->picture_structure= PICT_FRAME;
39823989
}else{
@@ -3990,8 +3997,50 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
39903997
}
39913998

39923999
if(h0->current_slice == 0){
3993-
if(frame_start(h) < 0)
4000+
/* See if we have a decoded first field looking for a pair... */
4001+
if (s0->first_field) {
4002+
assert(s0->current_picture_ptr);
4003+
assert(s0->current_picture_ptr->data[0]);
4004+
assert(s0->current_picture_ptr->reference != DELAYED_PIC_REF);
4005+
4006+
/* figure out if we have a complementary field pair */
4007+
if (!FIELD_PICTURE || s->picture_structure == last_pic_structure) {
4008+
/*
4009+
* Previous field is unmatched. Don't display it, but let it
4010+
* remain for reference if marked as such.
4011+
*/
4012+
s0->current_picture_ptr = NULL;
4013+
s0->first_field = FIELD_PICTURE;
4014+
4015+
} else {
4016+
if (h->nal_ref_idc &&
4017+
s0->current_picture_ptr->reference &&
4018+
s0->current_picture_ptr->frame_num != h->frame_num) {
4019+
/*
4020+
* This and previous field were reference, but had
4021+
* different frame_nums. Consider this field first in
4022+
* pair. Throw away previous field except for reference
4023+
* purposes.
4024+
*/
4025+
s0->first_field = 1;
4026+
s0->current_picture_ptr = NULL;
4027+
4028+
} else {
4029+
/* Second field in complementary pair */
4030+
s0->first_field = 0;
4031+
}
4032+
}
4033+
4034+
} else {
4035+
/* Frame or first field in a potentially complementary pair */
4036+
assert(!s0->current_picture_ptr);
4037+
s0->first_field = FIELD_PICTURE;
4038+
}
4039+
4040+
if((!FIELD_PICTURE || s0->first_field) && frame_start(h) < 0) {
4041+
s0->first_field = 0;
39944042
return -1;
4043+
}
39954044
}
39964045
if(h != h0)
39974046
clone_slice(h, h0);
@@ -7363,6 +7412,8 @@ static void execute_decode_slices(H264Context *h, int context_count){
73637412
hx = h->thread_context[context_count - 1];
73647413
s->mb_x = hx->s.mb_x;
73657414
s->mb_y = hx->s.mb_y;
7415+
s->dropable = hx->s.dropable;
7416+
s->picture_structure = hx->s.picture_structure;
73667417
for(i = 1; i < context_count; i++)
73677418
h->s.error_count += h->thread_context[i]->s.error_count;
73687419
}
@@ -7385,6 +7436,7 @@ static int decode_nal_units(H264Context *h, uint8_t *buf, int buf_size){
73857436
#endif
73867437
if(!(s->flags2 & CODEC_FLAG2_CHUNKS)){
73877438
h->current_slice = 0;
7439+
if (!s->first_field)
73887440
s->current_picture_ptr= NULL;
73897441
}
73907442

@@ -7682,16 +7734,34 @@ static int decode_frame(AVCodecContext *avctx,
76827734

76837735
h->prev_frame_num_offset= h->frame_num_offset;
76847736
h->prev_frame_num= h->frame_num;
7685-
if(s->current_picture_ptr->reference & s->picture_structure){
7737+
if(!s->dropable) {
76867738
h->prev_poc_msb= h->poc_msb;
76877739
h->prev_poc_lsb= h->poc_lsb;
76887740
execute_ref_pic_marking(h, h->mmco, h->mmco_index);
76897741
}
76907742

7743+
/*
7744+
* FIXME: Error handling code does not seem to support interlaced
7745+
* when slices span multiple rows
7746+
* The ff_er_add_slice calls don't work right for bottom
7747+
* fields; they cause massive erroneous error concealing
7748+
* Error marking covers both fields (top and bottom).
7749+
* This causes a mismatched s->error_count
7750+
* and a bad error table. Further, the error count goes to
7751+
* INT_MAX when called for bottom field, because mb_y is
7752+
* past end by one (callers fault) and resync_mb_y != 0
7753+
* causes problems for the first MB line, too.
7754+
*/
7755+
if (!FIELD_PICTURE)
76917756
ff_er_frame_end(s);
76927757

76937758
MPV_frame_end(s);
76947759

7760+
if (s->first_field) {
7761+
/* Wait for second field. */
7762+
*data_size = 0;
7763+
7764+
} else {
76957765
//FIXME do something with unavailable reference frames
76967766

76977767
#if 0 //decode order
@@ -7762,6 +7832,7 @@ static int decode_frame(AVCodecContext *avctx,
77627832
*pict= *(AVFrame*)out;
77637833
else
77647834
av_log(avctx, AV_LOG_DEBUG, "no picture\n");
7835+
}
77657836
}
77667837

77677838
assert(pict->data[0] || !*data_size);

libavcodec/mpegvideo.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -954,7 +954,7 @@ int MPV_frame_start(MpegEncContext *s, AVCodecContext *avctx)
954954

955955
assert(s->pict_type == I_TYPE || (s->last_picture_ptr && s->last_picture_ptr->data[0]));
956956

957-
if(s->picture_structure!=PICT_FRAME){
957+
if(s->picture_structure!=PICT_FRAME && s->out_format != FMT_H264){
958958
int i;
959959
for(i=0; i<4; i++){
960960
if(s->picture_structure == PICT_BOTTOM_FIELD){

0 commit comments

Comments
 (0)