mirror of https://git.ffmpeg.org/ffmpeg.git
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:
parent
6b3246488d
commit
0ae969faed
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue