# HG changeset patch # User cehoyos # Date 1191799962 0 # Node ID 8121e27dd9cc49ab8bf3699761a4188610381caa # Parent 74fa2587b8de39b7953f05f84121b3ed86cd2195 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 diff -r 74fa2587b8de -r 8121e27dd9cc h264.c --- a/h264.c Sat Oct 06 15:50:55 2007 +0000 +++ b/h264.c Sun Oct 07 23:32:42 2007 +0000 @@ -3465,42 +3465,80 @@ av_log(h->s.avctx, AV_LOG_DEBUG, "no mmco here\n"); for(i=0; iavctx->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); - - h->long_ref[ mmco[i].long_arg ]= remove_short(h, mmco[i].short_pic_num); + 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; + + 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 @@ } } + 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 @@ 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);