X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fh264_refs.c;h=273c52b475b0f97071cd394d84d49a0bbdfb19de;hb=c3513477bbbc0898e8fe38c4e37ac67298d76a48;hp=7caa4b0003a44acfd8755208a40b8fc0cae35cc3;hpb=733f5990d0600589782bcfa5c9e22a9391c6c19e;p=ffmpeg diff --git a/libavcodec/h264_refs.c b/libavcodec/h264_refs.c index 7caa4b0003a..273c52b475b 100644 --- a/libavcodec/h264_refs.c +++ b/libavcodec/h264_refs.c @@ -2,20 +2,20 @@ * H.26L/H.264/AVC/JVT/14496-10/... reference picture handling * Copyright (c) 2003 Michael Niedermayer * - * 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 */ @@ -39,16 +39,16 @@ static void pic_as_field(Picture *pic, const int parity){ 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; @@ -67,9 +67,9 @@ static int build_def_list(Picture *def, Picture **in, int len, int is_long, int int index=0; while(i[0]reference & sel))) + while (i[0] < len && !(in[ i[0] ] && (in[ i[0] ]->f.reference & sel))) i[0]++; - while(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; @@ -109,7 +109,7 @@ int ff_h264_fill_default_ref_list(H264Context *h){ 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]; @@ -133,7 +133,7 @@ int ff_h264_fill_default_ref_list(H264Context *h){ } 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] && idefault_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]); } @@ -148,7 +148,7 @@ int ff_h264_fill_default_ref_list(H264Context *h){ for (i=0; iref_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; iref_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]); } @@ -229,11 +229,11 @@ int ff_h264_decode_ref_pic_list_reordering(H264Context *h){ 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; } @@ -250,8 +250,8 @@ int ff_h264_decode_ref_pic_list_reordering(H264Context *h){ 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; @@ -285,9 +285,9 @@ int ff_h264_decode_ref_pic_list_reordering(H264Context *h){ } for(list=0; listlist_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; @@ -306,13 +306,13 @@ void ff_h264_fill_mbaff_ref_list(H264Context *h){ 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]; @@ -338,12 +338,12 @@ void ff_h264_fill_mbaff_ref_list(H264Context *h){ */ 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; @@ -453,7 +453,8 @@ static void print_short_term(H264Context *h) { av_log(h->s.avctx, AV_LOG_DEBUG, "short term list:\n"); for(i=0; ishort_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]); } } } @@ -468,7 +469,8 @@ static void print_long_term(H264Context *h) { 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]); } } } @@ -478,8 +480,9 @@ 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->reference)) { + !(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; @@ -495,7 +498,7 @@ void ff_generate_sliding_window_mmcos(H264Context *h) { 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) @@ -512,8 +515,10 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ 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; } } @@ -560,7 +565,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ 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: @@ -577,13 +582,9 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ 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); @@ -599,16 +600,18 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ */ 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) @@ -616,19 +619,22 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_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) @@ -645,7 +651,7 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ 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){ @@ -675,7 +681,7 @@ 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; }