Augment MMCO execution to work with both fields and frames. 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 10678 to svn://svn.ffmpeg.org/ffmpeg/trunk
This commit is contained in:
Jeff Downs 2007-10-07 23:32:42 +00:00 committed by Carl Eugen Hoyos
parent 6b3246488d
commit 0ae969faed
1 changed files with 80 additions and 13 deletions

View File

@ -3465,42 +3465,80 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
av_log(h->s.avctx, AV_LOG_DEBUG, "no mmco here\n");
for(i=0; i<mmco_count; i++){
int structure, frame_num, unref_pic;
if(s->avctx->debug&FF_DEBUG_MMCO)
av_log(h->s.avctx, AV_LOG_DEBUG, "mmco:%d %d %d\n", h->mmco[i].opcode, h->mmco[i].short_pic_num, h->mmco[i].long_arg);
switch(mmco[i].opcode){
case MMCO_SHORT2UNUSED:
pic= remove_short(h, mmco[i].short_pic_num);
if(pic)
unreference_pic(h, pic, 0);
else if(s->avctx->debug&FF_DEBUG_MMCO)
av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: remove_short() failure\n");
if(s->avctx->debug&FF_DEBUG_MMCO)
av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: unref short %d count %d\n", h->mmco[i].short_pic_num, h->short_ref_count);
frame_num = pic_num_extract(h, mmco[i].short_pic_num, &structure);
pic = find_short(h, frame_num, &j);
if (pic) {
if (unreference_pic(h, pic, structure ^ PICT_FRAME))
remove_short_at_index(h, j);
} else if(s->avctx->debug&FF_DEBUG_MMCO)
av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: unref short failure\n");
break;
case MMCO_SHORT2LONG:
pic= remove_long(h, mmco[i].long_arg);
if(pic) unreference_pic(h, pic, 0);
if (FIELD_PICTURE && mmco[i].long_arg < h->long_ref_count &&
h->long_ref[mmco[i].long_arg]->frame_num ==
mmco[i].short_pic_num / 2) {
/* do nothing, we've already moved this field pair. */
} else {
int frame_num = mmco[i].short_pic_num >> FIELD_PICTURE;
h->long_ref[ mmco[i].long_arg ]= remove_short(h, mmco[i].short_pic_num);
pic= remove_long(h, mmco[i].long_arg);
if(pic) unreference_pic(h, pic, 0);
h->long_ref[ mmco[i].long_arg ]= remove_short(h, frame_num);
if (h->long_ref[ mmco[i].long_arg ]){
h->long_ref[ mmco[i].long_arg ]->long_ref=1;
h->long_ref_count++;
}
}
break;
case MMCO_LONG2UNUSED:
pic= remove_long(h, mmco[i].long_arg);
if(pic)
unreference_pic(h, pic, 0);
else if(s->avctx->debug&FF_DEBUG_MMCO)
av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: remove_long() failure\n");
j = pic_num_extract(h, mmco[i].long_arg, &structure);
pic = h->long_ref[j];
if (pic) {
if (unreference_pic(h, pic, structure ^ PICT_FRAME))
remove_long_at_index(h, j);
} else if(s->avctx->debug&FF_DEBUG_MMCO)
av_log(h->s.avctx, AV_LOG_DEBUG, "mmco: unref long failure\n");
break;
case MMCO_LONG:
unref_pic = 1;
if (FIELD_PICTURE && !s->first_field) {
if (h->long_ref[mmco[i].long_arg] == s->current_picture_ptr) {
/* Just mark second field as referenced */
unref_pic = 0;
} else if (s->current_picture_ptr->reference) {
/* First field in pair is in short term list or
* at a different long term index.
* This is not allowed; see 7.4.3, notes 2 and 3.
* Report the problem and keep the pair where it is,
* and mark this field valid.
*/
av_log(h->s.avctx, AV_LOG_ERROR,
"illegal long term reference assignment for second "
"field in complementary field pair (first field is "
"short term or has non-matching long index)\n");
unref_pic = 0;
}
}
if (unref_pic) {
pic= remove_long(h, mmco[i].long_arg);
if(pic) unreference_pic(h, pic, 0);
h->long_ref[ mmco[i].long_arg ]= s->current_picture_ptr;
h->long_ref[ mmco[i].long_arg ]->long_ref=1;
h->long_ref_count++;
}
s->current_picture_ptr->reference |= s->picture_structure;
current_ref_assigned=1;
break;
case MMCO_SET_MAX_LONG:
@ -3525,6 +3563,34 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
}
}
if (!current_ref_assigned && FIELD_PICTURE &&
!s->first_field && s->current_picture_ptr->reference) {
/* Second field of complementary field pair; the first field of
* which is already referenced. If short referenced, it
* should be first entry in short_ref. If not, it must exist
* in long_ref; trying to put it on the short list here is an
* error in the encoded bit stream (ref: 7.4.3, NOTE 2 and 3).
*/
if (h->short_ref_count && h->short_ref[0] == s->current_picture_ptr) {
/* Just mark the second field valid */
s->current_picture_ptr->reference = PICT_FRAME;
} else if (s->current_picture_ptr->long_ref) {
av_log(h->s.avctx, AV_LOG_ERROR, "illegal short term reference "
"assignment for second field "
"in complementary field pair "
"(first field is long term)\n");
} else {
/*
* First field in reference, but not in any sensible place on our
* reference lists. This shouldn't happen unless reference
* handling somewhere else is wrong.
*/
assert(0);
}
current_ref_assigned = 1;
}
if(!current_ref_assigned){
pic= remove_short(h, s->current_picture_ptr->frame_num);
if(pic){
@ -3538,6 +3604,7 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
h->short_ref[0]= s->current_picture_ptr;
h->short_ref[0]->long_ref=0;
h->short_ref_count++;
s->current_picture_ptr->reference |= s->picture_structure;
}
print_short_term(h);