mirror of
https://git.ffmpeg.org/ffmpeg.git
synced 2025-04-27 05:38:07 +00:00
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
This commit is contained in:
parent
ac6b423b0c
commit
12d96de3ac
@ -3339,6 +3339,7 @@ static void flush_dpb(AVCodecContext *avctx){
|
|||||||
idr(h);
|
idr(h);
|
||||||
if(h->s.current_picture_ptr)
|
if(h->s.current_picture_ptr)
|
||||||
h->s.current_picture_ptr->reference= 0;
|
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.current_picture = src->s.current_picture;
|
||||||
dst->s.linesize = src->s.linesize;
|
dst->s.linesize = src->s.linesize;
|
||||||
dst->s.uvlinesize = src->s.uvlinesize;
|
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_msb = src->prev_poc_msb;
|
||||||
dst->prev_poc_lsb = src->prev_poc_lsb;
|
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){
|
static int decode_slice_header(H264Context *h, H264Context *h0){
|
||||||
MpegEncContext * const s = &h->s;
|
MpegEncContext * const s = &h->s;
|
||||||
|
MpegEncContext * const s0 = &h0->s;
|
||||||
unsigned int first_mb_in_slice;
|
unsigned int first_mb_in_slice;
|
||||||
unsigned int pps_id;
|
unsigned int pps_id;
|
||||||
int num_ref_idx_active_override_flag;
|
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};
|
static const uint8_t slice_type_map[5]= {P_TYPE, B_TYPE, I_TYPE, SP_TYPE, SI_TYPE};
|
||||||
unsigned int slice_type, tmp, i;
|
unsigned int slice_type, tmp, i;
|
||||||
int default_ref_list_done = 0;
|
int default_ref_list_done = 0;
|
||||||
|
int last_pic_structure;
|
||||||
|
|
||||||
s->dropable= h->nal_ref_idc == 0;
|
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){
|
if((s->flags2 & CODEC_FLAG2_CHUNKS) && first_mb_in_slice == 0){
|
||||||
h0->current_slice = 0;
|
h0->current_slice = 0;
|
||||||
|
if (!s0->first_field)
|
||||||
s->current_picture_ptr= NULL;
|
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
|
return -1; // we cant (re-)initialize context during parallel decoding
|
||||||
if (MPV_common_init(s) < 0)
|
if (MPV_common_init(s) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
s->first_field = 0;
|
||||||
|
|
||||||
init_scan_tables(h);
|
init_scan_tables(h);
|
||||||
alloc_tables(h);
|
alloc_tables(h);
|
||||||
@ -3977,6 +3983,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
|
|||||||
|
|
||||||
h->mb_mbaff = 0;
|
h->mb_mbaff = 0;
|
||||||
h->mb_aff_frame = 0;
|
h->mb_aff_frame = 0;
|
||||||
|
last_pic_structure = s0->picture_structure;
|
||||||
if(h->sps.frame_mbs_only_flag){
|
if(h->sps.frame_mbs_only_flag){
|
||||||
s->picture_structure= PICT_FRAME;
|
s->picture_structure= PICT_FRAME;
|
||||||
}else{
|
}else{
|
||||||
@ -3990,9 +3997,51 @@ static int decode_slice_header(H264Context *h, H264Context *h0){
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(h0->current_slice == 0){
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(h != h0)
|
if(h != h0)
|
||||||
clone_slice(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];
|
hx = h->thread_context[context_count - 1];
|
||||||
s->mb_x = hx->s.mb_x;
|
s->mb_x = hx->s.mb_x;
|
||||||
s->mb_y = hx->s.mb_y;
|
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++)
|
for(i = 1; i < context_count; i++)
|
||||||
h->s.error_count += h->thread_context[i]->s.error_count;
|
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
|
#endif
|
||||||
if(!(s->flags2 & CODEC_FLAG2_CHUNKS)){
|
if(!(s->flags2 & CODEC_FLAG2_CHUNKS)){
|
||||||
h->current_slice = 0;
|
h->current_slice = 0;
|
||||||
|
if (!s->first_field)
|
||||||
s->current_picture_ptr= NULL;
|
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_offset= h->frame_num_offset;
|
||||||
h->prev_frame_num= h->frame_num;
|
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_msb= h->poc_msb;
|
||||||
h->prev_poc_lsb= h->poc_lsb;
|
h->prev_poc_lsb= h->poc_lsb;
|
||||||
execute_ref_pic_marking(h, h->mmco, h->mmco_index);
|
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);
|
ff_er_frame_end(s);
|
||||||
|
|
||||||
MPV_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
|
//FIXME do something with unavailable reference frames
|
||||||
|
|
||||||
#if 0 //decode order
|
#if 0 //decode order
|
||||||
@ -7763,6 +7833,7 @@ static int decode_frame(AVCodecContext *avctx,
|
|||||||
else
|
else
|
||||||
av_log(avctx, AV_LOG_DEBUG, "no picture\n");
|
av_log(avctx, AV_LOG_DEBUG, "no picture\n");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
assert(pict->data[0] || !*data_size);
|
assert(pict->data[0] || !*data_size);
|
||||||
ff_print_debug_info(s, pict);
|
ff_print_debug_info(s, pict);
|
||||||
|
@ -954,7 +954,7 @@ alloc:
|
|||||||
|
|
||||||
assert(s->pict_type == I_TYPE || (s->last_picture_ptr && s->last_picture_ptr->data[0]));
|
assert(s->pict_type == I_TYPE || (s->last_picture_ptr && s->last_picture_ptr->data[0]));
|
||||||
|
|
||||||
if(s->picture_structure!=PICT_FRAME){
|
if(s->picture_structure!=PICT_FRAME && s->out_format != FMT_H264){
|
||||||
int i;
|
int i;
|
||||||
for(i=0; i<4; i++){
|
for(i=0; i<4; i++){
|
||||||
if(s->picture_structure == PICT_BOTTOM_FIELD){
|
if(s->picture_structure == PICT_BOTTOM_FIELD){
|
||||||
|
Loading…
Reference in New Issue
Block a user