* H.26L/H.264/AVC/JVT/14496-10/... reference picture handling
* Copyright (c) 2003 Michael Niedermayer <michaelni@gmx.at>
*
- * This file is part of FFmpeg.
+ * This file is part of Libav.
*
- * FFmpeg is free software; you can redistribute it and/or
+ * Libav is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
- * FFmpeg is distributed in the hope that it will be useful,
+ * Libav is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
+ * License along with Libav; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
int i;
for (i = 0; i < 4; ++i) {
if (parity == PICT_BOTTOM_FIELD)
- pic->data[i] += pic->linesize[i];
- pic->reference = parity;
- pic->linesize[i] *= 2;
+ pic->f.data[i] += pic->f.linesize[i];
+ pic->f.reference = parity;
+ pic->f.linesize[i] *= 2;
}
pic->poc= pic->field_poc[parity == PICT_BOTTOM_FIELD];
}
static int split_field_copy(Picture *dest, Picture *src,
int parity, int id_add){
- int match = !!(src->reference & parity);
+ int match = !!(src->f.reference & parity);
if (match) {
*dest = *src;
int index=0;
while(i[0]<len || i[1]<len){
- while(i[0]<len && !(in[ i[0] ] && (in[ i[0] ]->reference & sel)))
+ while (i[0] < len && !(in[ i[0] ] && (in[ i[0] ]->f.reference & sel)))
i[0]++;
- while(i[1]<len && !(in[ i[1] ] && (in[ i[1] ]->reference & (sel^3))))
+ while (i[1] < len && !(in[ i[1] ] && (in[ i[1] ]->f.reference & (sel^3))))
i[1]++;
if(i[0] < len){
in[ i[0] ]->pic_id= is_long ? i[0] : in[ i[0] ]->frame_num;
MpegEncContext * const s = &h->s;
int i, len;
- if(h->slice_type_nos==FF_B_TYPE){
+ if(h->slice_type_nos==AV_PICTURE_TYPE_B){
Picture *sorted[32];
int cur_poc, list;
int lens[2];
}
if(lens[0] == lens[1] && lens[1] > 1){
- for(i=0; h->default_ref_list[0][i].data[0] == h->default_ref_list[1][i].data[0] && i<lens[0]; i++);
+ for (i = 0; h->default_ref_list[0][i].f.data[0] == h->default_ref_list[1][i].f.data[0] && i < lens[0]; i++);
if(i == lens[0])
FFSWAP(Picture, h->default_ref_list[1][0], h->default_ref_list[1][1]);
}
for (i=0; i<h->ref_count[0]; i++) {
tprintf(h->s.avctx, "List0: %s fn:%d 0x%p\n", (h->default_ref_list[0][i].long_ref ? "LT" : "ST"), h->default_ref_list[0][i].pic_id, h->default_ref_list[0][i].data[0]);
}
- if(h->slice_type_nos==FF_B_TYPE){
+ if(h->slice_type_nos==AV_PICTURE_TYPE_B){
for (i=0; i<h->ref_count[1]; i++) {
tprintf(h->s.avctx, "List1: %s fn:%d 0x%p\n", (h->default_ref_list[1][i].long_ref ? "LT" : "ST"), h->default_ref_list[1][i].pic_id, h->default_ref_list[1][i].data[0]);
}
for(i= h->short_ref_count-1; i>=0; i--){
ref = h->short_ref[i];
- assert(ref->reference);
+ assert(ref->f.reference);
assert(!ref->long_ref);
if(
ref->frame_num == frame_num &&
- (ref->reference & pic_structure)
+ (ref->f.reference & pic_structure)
)
break;
}
return -1;
}
ref = h->long_ref[long_idx];
- assert(!(ref && !ref->reference));
- if(ref && (ref->reference & pic_structure)){
+ assert(!(ref && !ref->f.reference));
+ if (ref && (ref->f.reference & pic_structure)) {
ref->pic_id= pic_id;
assert(ref->long_ref);
i=0;
}
for(list=0; list<h->list_count; list++){
for(index= 0; index < h->ref_count[list]; index++){
- if(!h->ref_list[list][index].data[0]){
+ if (!h->ref_list[list][index].f.data[0]) {
av_log(h->s.avctx, AV_LOG_ERROR, "Missing reference picture\n");
- if(h->default_ref_list[list][0].data[0])
+ if (h->default_ref_list[list][0].f.data[0])
h->ref_list[list][index]= h->default_ref_list[list][0];
else
return -1;
Picture *field = &h->ref_list[list][16+2*i];
field[0] = *frame;
for(j=0; j<3; j++)
- field[0].linesize[j] <<= 1;
- field[0].reference = PICT_TOP_FIELD;
+ field[0].f.linesize[j] <<= 1;
+ field[0].f.reference = PICT_TOP_FIELD;
field[0].poc= field[0].field_poc[0];
field[1] = field[0];
for(j=0; j<3; j++)
- field[1].data[j] += frame->linesize[j];
- field[1].reference = PICT_BOTTOM_FIELD;
+ field[1].f.data[j] += frame->f.linesize[j];
+ field[1].f.reference = PICT_BOTTOM_FIELD;
field[1].poc= field[1].field_poc[1];
h->luma_weight[16+2*i][list][0] = h->luma_weight[16+2*i+1][list][0] = h->luma_weight[i][list][0];
*/
static inline int unreference_pic(H264Context *h, Picture *pic, int refmask){
int i;
- if (pic->reference &= refmask) {
+ if (pic->f.reference &= refmask) {
return 0;
} else {
for(i = 0; h->delayed_pic[i]; i++)
if(pic == h->delayed_pic[i]){
- pic->reference=DELAYED_PIC_REF;
+ pic->f.reference = DELAYED_PIC_REF;
break;
}
return 1;
av_log(h->s.avctx, AV_LOG_DEBUG, "short term list:\n");
for(i=0; i<h->short_ref_count; i++){
Picture *pic= h->short_ref[i];
- av_log(h->s.avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", i, pic->frame_num, pic->poc, pic->data[0]);
+ av_log(h->s.avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n",
+ i, pic->frame_num, pic->poc, pic->f.data[0]);
}
}
}
for(i = 0; i < 16; i++){
Picture *pic= h->long_ref[i];
if (pic) {
- av_log(h->s.avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n", i, pic->frame_num, pic->poc, pic->data[0]);
+ av_log(h->s.avctx, AV_LOG_DEBUG, "%d fn:%d poc:%d %p\n",
+ i, pic->frame_num, pic->poc, pic->f.data[0]);
}
}
}
}
+void ff_generate_sliding_window_mmcos(H264Context *h) {
+ MpegEncContext * const s = &h->s;
+ assert(h->long_ref_count + h->short_ref_count <= h->sps.ref_frame_count);
+
+ h->mmco_index= 0;
+ if(h->short_ref_count && h->long_ref_count + h->short_ref_count == h->sps.ref_frame_count &&
+ !(FIELD_PICTURE && !s->first_field && s->current_picture_ptr->f.reference)) {
+ h->mmco[0].opcode= MMCO_SHORT2UNUSED;
+ h->mmco[0].short_pic_num= h->short_ref[ h->short_ref_count - 1 ]->frame_num;
+ h->mmco_index= 1;
+ if (FIELD_PICTURE) {
+ h->mmco[0].short_pic_num *= 2;
+ h->mmco[1].opcode= MMCO_SHORT2UNUSED;
+ h->mmco[1].short_pic_num= h->mmco[0].short_pic_num + 1;
+ h->mmco_index= 2;
+ }
+ }
+}
+
int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){
MpegEncContext * const s = &h->s;
int i, av_uninit(j);
- int current_ref_assigned=0;
+ int current_ref_assigned=0, err=0;
Picture *av_uninit(pic);
if((s->avctx->debug&FF_DEBUG_MMCO) && mmco_count==0)
pic = find_short(h, frame_num, &j);
if(!pic){
if(mmco[i].opcode != MMCO_SHORT2LONG || !h->long_ref[mmco[i].long_arg]
- || h->long_ref[mmco[i].long_arg]->frame_num != frame_num)
- av_log(h->s.avctx, AV_LOG_ERROR, "mmco: unref short failure\n");
+ || h->long_ref[mmco[i].long_arg]->frame_num != frame_num) {
+ av_log(h->s.avctx, AV_LOG_ERROR, "mmco: unref short failure\n");
+ err = AVERROR_INVALIDDATA;
+ }
continue;
}
}
h->long_ref_count++;
}
- s->current_picture_ptr->reference |= s->picture_structure;
+ s->current_picture_ptr->f.reference |= s->picture_structure;
current_ref_assigned=1;
break;
case MMCO_SET_MAX_LONG:
for(j = 0; j < 16; j++) {
remove_long(h, j, 0);
}
- s->current_picture_ptr->poc=
- s->current_picture_ptr->field_poc[0]=
- s->current_picture_ptr->field_poc[1]=
- h->poc_lsb=
- h->poc_msb=
h->frame_num=
s->current_picture_ptr->frame_num= 0;
+ h->mmco_reset = 1;
s->current_picture_ptr->mmco_reset=1;
break;
default: assert(0);
*/
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;
+ s->current_picture_ptr->f.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");
+ err = AVERROR_INVALIDDATA;
} else {
pic= remove_short(h, s->current_picture_ptr->frame_num, 0);
if(pic){
av_log(h->s.avctx, AV_LOG_ERROR, "illegal short term buffer state detected\n");
+ err = AVERROR_INVALIDDATA;
}
if(h->short_ref_count)
h->short_ref[0]= s->current_picture_ptr;
h->short_ref_count++;
- s->current_picture_ptr->reference |= s->picture_structure;
+ s->current_picture_ptr->f.reference |= s->picture_structure;
}
}
- if (h->long_ref_count + h->short_ref_count > h->sps.ref_frame_count){
+ if (h->long_ref_count + h->short_ref_count -
+ (h->short_ref[0] == s->current_picture_ptr) > h->sps.ref_frame_count){
/* We have too many reference frames, probably due to corrupted
* stream. Need to discard one frame. Prevents overrun of the
* short_ref and long_ref buffers.
*/
av_log(h->s.avctx, AV_LOG_ERROR,
- "number of reference frames exceeds max (probably "
- "corrupt input), discarding one\n");
+ "number of reference frames (%d+%d) exceeds max (%d; probably "
+ "corrupt input), discarding one\n",
+ h->long_ref_count, h->short_ref_count, h->sps.ref_frame_count);
+ err = AVERROR_INVALIDDATA;
if (h->long_ref_count && !h->short_ref_count) {
for (i = 0; i < 16; ++i)
print_short_term(h);
print_long_term(h);
- return 0;
+ return (h->s.avctx->err_recognition & AV_EF_EXPLODE) ? err : 0;
}
int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb){
}
if(opcode==MMCO_SHORT2LONG || opcode==MMCO_LONG2UNUSED || opcode==MMCO_LONG || opcode==MMCO_SET_MAX_LONG){
unsigned int long_arg= get_ue_golomb_31(gb);
- if(long_arg >= 32 || (long_arg >= 16 && !(opcode == MMCO_LONG2UNUSED && FIELD_PICTURE))){
+ if(long_arg >= 32 || (long_arg >= 16 && !(opcode == MMCO_SET_MAX_LONG && long_arg == 16) && !(opcode == MMCO_LONG2UNUSED && FIELD_PICTURE))){
av_log(h->s.avctx, AV_LOG_ERROR, "illegal long ref in memory management control operation %d\n", opcode);
return -1;
}
}
h->mmco_index= i;
}else{
- assert(h->long_ref_count + h->short_ref_count <= h->sps.ref_frame_count);
-
- if(h->short_ref_count && h->long_ref_count + h->short_ref_count == h->sps.ref_frame_count &&
- !(FIELD_PICTURE && !s->first_field && s->current_picture_ptr->reference)) {
- h->mmco[0].opcode= MMCO_SHORT2UNUSED;
- h->mmco[0].short_pic_num= h->short_ref[ h->short_ref_count - 1 ]->frame_num;
- h->mmco_index= 1;
- if (FIELD_PICTURE) {
- h->mmco[0].short_pic_num *= 2;
- h->mmco[1].opcode= MMCO_SHORT2UNUSED;
- h->mmco[1].short_pic_num= h->mmco[0].short_pic_num + 1;
- h->mmco_index= 2;
- }
- }
+ ff_generate_sliding_window_mmcos(h);
}
}