X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fh264.c;h=ffcb2b268c7e215aca7e5c000c4c821098de7931;hb=f8a80fd69df1735730f1b3c7f37506ffe0570d0d;hp=b1e5bb11f65201b308a7bf8ed77034d15fb6b149;hpb=fa178ed2a4f7a42eaad8236dd73f28c6d426df6d;p=ffmpeg diff --git a/libavcodec/h264.c b/libavcodec/h264.c index b1e5bb11f65..ffcb2b268c7 100644 --- a/libavcodec/h264.c +++ b/libavcodec/h264.c @@ -1703,7 +1703,7 @@ static inline void mc_dir_part(H264Context *h, Picture *pic, int n, int square, const int full_mx= mx>>2; const int full_my= my>>2; const int pic_width = 16*s->mb_width; - const int pic_height = 16*s->mb_height >> (MB_MBAFF || FIELD_PICTURE); + const int pic_height = 16*s->mb_height >> MB_FIELD; if(!pic->data[0]) //FIXME this is unacceptable, some senseable error concealment must be done for missing reference frames return; @@ -1727,9 +1727,9 @@ static inline void mc_dir_part(H264Context *h, Picture *pic, int n, int square, if(ENABLE_GRAY && s->flags&CODEC_FLAG_GRAY) return; - if(MB_MBAFF || FIELD_PICTURE){ + if(MB_FIELD){ // chroma offset when predicting from a field of opposite parity - my += 2 * ((s->mb_y & 1) - (h->ref_cache[list][scan8[n]] & 1)); + my += 2 * ((s->mb_y & 1) - (pic->reference - 1)); emu |= (my>>3) < 0 || (my>>3) + 8 >= (pic_height>>1); } src_cb= pic->data[1] + (mx>>3) + (my>>3)*h->mb_uvlinesize; @@ -1762,7 +1762,7 @@ static inline void mc_part_std(H264Context *h, int n, int square, int chroma_hei dest_cb += x_offset + y_offset*h->mb_uvlinesize; dest_cr += x_offset + y_offset*h->mb_uvlinesize; x_offset += 8*s->mb_x; - y_offset += 8*(s->mb_y >> (MB_MBAFF || FIELD_PICTURE)); + y_offset += 8*(s->mb_y >> MB_FIELD); if(list0){ Picture *ref= &h->ref_list[0][ h->ref_cache[0][ scan8[n] ] ]; @@ -1795,7 +1795,7 @@ static inline void mc_part_weighted(H264Context *h, int n, int square, int chrom dest_cb += x_offset + y_offset*h->mb_uvlinesize; dest_cr += x_offset + y_offset*h->mb_uvlinesize; x_offset += 8*s->mb_x; - y_offset += 8*(s->mb_y >> (MB_MBAFF || FIELD_PICTURE)); + y_offset += 8*(s->mb_y >> MB_FIELD); if(list0 && list1){ /* don't optimize for luma-only case, since B-frames usually @@ -2764,11 +2764,12 @@ static void hl_decode_mb(H264Context *h){ else hl_decode_mb_simple(h); } -static void pic_as_field(Picture *pic, const int bottom){ +static void pic_as_field(Picture *pic, const int parity){ int i; for (i = 0; i < 4; ++i) { - if (bottom) + if (parity == PICT_BOTTOM_FIELD) pic->data[i] += pic->linesize[i]; + pic->reference = parity; pic->linesize[i] *= 2; } } @@ -2779,7 +2780,7 @@ static int split_field_copy(Picture *dest, Picture *src, if (match) { *dest = *src; - pic_as_field(dest, parity == PICT_BOTTOM_FIELD); + pic_as_field(dest, parity); dest->pic_id *= 2; dest->pic_id += id_add; } @@ -3076,7 +3077,7 @@ static int decode_ref_pic_list_reordering(H264Context *h){ const unsigned int abs_diff_pic_num= get_ue_golomb(&s->gb) + 1; int frame_num; - if(abs_diff_pic_num >= h->max_pic_num){ + if(abs_diff_pic_num > h->max_pic_num){ av_log(h->s.avctx, AV_LOG_ERROR, "abs_diff_pic_num overflow\n"); return -1; } @@ -3133,8 +3134,7 @@ static int decode_ref_pic_list_reordering(H264Context *h){ } h->ref_list[list][index]= *ref; if (FIELD_PICTURE){ - int bot = pic_structure == PICT_BOTTOM_FIELD; - pic_as_field(&h->ref_list[list][index], bot); + pic_as_field(&h->ref_list[list][index], pic_structure); } } }else{ @@ -3166,9 +3166,11 @@ static void fill_mbaff_ref_list(H264Context *h){ field[0] = *frame; for(j=0; j<3; j++) field[0].linesize[j] <<= 1; + field[0].reference = PICT_TOP_FIELD; field[1] = field[0]; for(j=0; j<3; j++) field[1].data[j] += frame->linesize[j]; + field[1].reference = PICT_BOTTOM_FIELD; h->luma_weight[list][16+2*i] = h->luma_weight[list][16+2*i+1] = h->luma_weight[list][i]; h->luma_offset[list][16+2*i] = h->luma_offset[list][16+2*i+1] = h->luma_offset[list][i]; @@ -3339,6 +3341,8 @@ static void flush_dpb(AVCodecContext *avctx){ idr(h); if(h->s.current_picture_ptr) h->s.current_picture_ptr->reference= 0; + h->s.first_field= 0; + ff_mpeg_flush(avctx); } /** @@ -3458,50 +3462,88 @@ static void print_long_term(H264Context *h) { static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ MpegEncContext * const s = &h->s; int i, j; - int current_is_long=0; + int current_ref_assigned=0; Picture *pic; if((s->avctx->debug&FF_DEBUG_MMCO) && mmco_count==0) 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); + 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); - if (h->long_ref[ mmco[i].long_arg ]){ - h->long_ref[ mmco[i].long_arg ]->long_ref=1; - h->long_ref_count++; + 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: - pic= remove_long(h, mmco[i].long_arg); - if(pic) unreference_pic(h, pic, 0); + 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++; + 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++; + } - current_is_long=1; + s->current_picture_ptr->reference |= s->picture_structure; + current_ref_assigned=1; break; case MMCO_SET_MAX_LONG: assert(mmco[i].long_arg <= 16); @@ -3525,7 +3567,35 @@ static int execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count){ } } - if(!current_is_long){ + 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){ unreference_pic(h, pic, 0); @@ -3538,6 +3608,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); @@ -3565,7 +3636,7 @@ static int decode_ref_pic_marking(H264Context *h, GetBitContext *gb){ h->mmco[i].opcode= opcode; if(opcode==MMCO_SHORT2UNUSED || opcode==MMCO_SHORT2LONG){ - h->mmco[i].short_pic_num= (h->frame_num - get_ue_golomb(gb) - 1) & ((1<sps.log2_max_frame_num)-1); //FIXME fields + h->mmco[i].short_pic_num= (h->curr_pic_num - get_ue_golomb(gb) - 1) & (h->max_pic_num - 1); /* if(h->mmco[i].short_pic_num >= h->short_ref_count || h->short_ref[ h->mmco[i].short_pic_num ] == NULL){ av_log(s->avctx, AV_LOG_ERROR, "illegal short ref in memory management control operation %d\n", mmco); return -1; @@ -3573,7 +3644,7 @@ static int 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(gb); - if(/*h->mmco[i].long_arg >= h->long_ref_count || h->long_ref[ h->mmco[i].long_arg ] == NULL*/ long_arg >= 16){ + if(long_arg >= 32 || (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; } @@ -3591,10 +3662,17 @@ static int decode_ref_pic_marking(H264Context *h, GetBitContext *gb){ }else{ assert(h->long_ref_count + h->short_ref_count <= h->sps.ref_frame_count); - if(h->long_ref_count + h->short_ref_count == h->sps.ref_frame_count){ //FIXME fields + if(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; + } }else h->mmco_index= 0; } @@ -3690,8 +3768,10 @@ static int init_poc(H264Context *h){ s->current_picture_ptr->field_poc[1]= field_poc[1]; s->current_picture_ptr->poc = field_poc[1]; } - if(!FIELD_PICTURE || !s->first_field) - s->current_picture_ptr->poc= FFMIN(field_poc[0], field_poc[1]); + if(!FIELD_PICTURE || !s->first_field) { + Picture *cur = s->current_picture_ptr; + cur->poc= FFMIN(cur->field_poc[0], cur->field_poc[1]); + } return 0; } @@ -3756,6 +3836,7 @@ static void clone_slice(H264Context *dst, H264Context *src) dst->s.current_picture = src->s.current_picture; dst->s.linesize = src->s.linesize; dst->s.uvlinesize = src->s.uvlinesize; + dst->s.first_field = src->s.first_field; dst->prev_poc_msb = src->prev_poc_msb; dst->prev_poc_lsb = src->prev_poc_lsb; @@ -3783,12 +3864,14 @@ static void clone_slice(H264Context *dst, H264Context *src) */ static int decode_slice_header(H264Context *h, H264Context *h0){ MpegEncContext * const s = &h->s; + MpegEncContext * const s0 = &h0->s; unsigned int first_mb_in_slice; unsigned int pps_id; int num_ref_idx_active_override_flag; static const uint8_t slice_type_map[5]= {P_TYPE, B_TYPE, I_TYPE, SP_TYPE, SI_TYPE}; unsigned int slice_type, tmp, i; int default_ref_list_done = 0; + int last_pic_structure; s->dropable= h->nal_ref_idc == 0; @@ -3796,7 +3879,8 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ if((s->flags2 & CODEC_FLAG2_CHUNKS) && first_mb_in_slice == 0){ h0->current_slice = 0; - s->current_picture_ptr= NULL; + if (!s0->first_field) + s->current_picture_ptr= NULL; } slice_type= get_ue_golomb(&s->gb); @@ -3865,6 +3949,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ return -1; // we cant (re-)initialize context during parallel decoding if (MPV_common_init(s) < 0) return -1; + s->first_field = 0; init_scan_tables(h); alloc_tables(h); @@ -3903,12 +3988,12 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ h->mb_mbaff = 0; h->mb_aff_frame = 0; + last_pic_structure = s0->picture_structure; if(h->sps.frame_mbs_only_flag){ s->picture_structure= PICT_FRAME; }else{ if(get_bits1(&s->gb)) { //field_pic_flag s->picture_structure= PICT_TOP_FIELD + get_bits1(&s->gb); //bottom_field_flag - av_log(h->s.avctx, AV_LOG_ERROR, "PAFF interlacing is not implemented\n"); } else { s->picture_structure= PICT_FRAME; h->mb_aff_frame = h->sps.mb_aff; @@ -3916,8 +4001,50 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ } if(h0->current_slice == 0){ - if(frame_start(h) < 0) + /* See if we have a decoded first field looking for a pair... */ + if (s0->first_field) { + assert(s0->current_picture_ptr); + assert(s0->current_picture_ptr->data[0]); + assert(s0->current_picture_ptr->reference != DELAYED_PIC_REF); + + /* figure out if we have a complementary field pair */ + if (!FIELD_PICTURE || s->picture_structure == last_pic_structure) { + /* + * Previous field is unmatched. Don't display it, but let it + * remain for reference if marked as such. + */ + s0->current_picture_ptr = NULL; + s0->first_field = FIELD_PICTURE; + + } else { + if (h->nal_ref_idc && + s0->current_picture_ptr->reference && + s0->current_picture_ptr->frame_num != h->frame_num) { + /* + * This and previous field were reference, but had + * different frame_nums. Consider this field first in + * pair. Throw away previous field except for reference + * purposes. + */ + s0->first_field = 1; + s0->current_picture_ptr = NULL; + + } else { + /* Second field in complementary pair */ + s0->first_field = 0; + } + } + + } else { + /* Frame or first field in a potentially complementary pair */ + assert(!s0->current_picture_ptr); + s0->first_field = FIELD_PICTURE; + } + + if((!FIELD_PICTURE || s0->first_field) && frame_start(h) < 0) { + s0->first_field = 0; return -1; + } } if(h != h0) clone_slice(h, h0); @@ -3976,8 +4103,8 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ if(h->slice_type == P_TYPE || h->slice_type == SP_TYPE || h->slice_type == B_TYPE){ if(h->slice_type == B_TYPE){ h->direct_spatial_mv_pred= get_bits1(&s->gb); - if(h->sps.mb_aff && h->direct_spatial_mv_pred) - av_log(h->s.avctx, AV_LOG_ERROR, "MBAFF + spatial direct mode is not implemented\n"); + if(FIELD_OR_MBAFF_PICTURE && h->direct_spatial_mv_pred) + av_log(h->s.avctx, AV_LOG_ERROR, "Interlaced pictures + spatial direct mode is not implemented\n"); } num_ref_idx_active_override_flag= get_bits1(&s->gb); @@ -4096,7 +4223,7 @@ static int decode_slice_header(H264Context *h, H264Context *h0){ h->slice_num = ++h0->current_slice; h->emu_edge_width= (s->flags&CODEC_FLAG_EMU_EDGE) ? 0 : 16; - h->emu_edge_height= FRAME_MBAFF ? 0 : h->emu_edge_width; + h->emu_edge_height= (FRAME_MBAFF || FIELD_PICTURE) ? 0 : h->emu_edge_width; if(s->avctx->debug&FF_DEBUG_PICT_INFO){ av_log(h->s.avctx, AV_LOG_DEBUG, "slice:%d %s mb:%d %c pps:%u frame:%d poc:%d/%d ref:%d/%d qp:%d loop:%d:%d:%d weight:%d%s\n", @@ -6245,12 +6372,13 @@ static void filter_mb_edgech( H264Context *h, uint8_t *pix, int stride, int16_t static void filter_mb_fast( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, uint8_t *img_cb, uint8_t *img_cr, unsigned int linesize, unsigned int uvlinesize) { MpegEncContext * const s = &h->s; + int mb_y_firstrow = s->picture_structure == PICT_BOTTOM_FIELD; int mb_xy, mb_type; int qp, qp0, qp1, qpc, qpc0, qpc1, qp_thresh; mb_xy = mb_x + mb_y*s->mb_stride; - if(mb_x==0 || mb_y==0 || !s->dsp.h264_loop_filter_strength || h->pps.chroma_qp_diff || + if(mb_x==0 || mb_y==mb_y_firstrow || !s->dsp.h264_loop_filter_strength || h->pps.chroma_qp_diff || (h->deblocking_filter == 2 && (h->slice_table[mb_xy] != h->slice_table[h->top_mb_xy] || h->slice_table[mb_xy] != h->slice_table[mb_xy - 1]))) { filter_mb(h, mb_x, mb_y, img_y, img_cb, img_cr, linesize, uvlinesize); @@ -6277,17 +6405,18 @@ static void filter_mb_fast( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, if( IS_INTRA(mb_type) ) { int16_t bS4[4] = {4,4,4,4}; int16_t bS3[4] = {3,3,3,3}; + int16_t *bSH = FIELD_PICTURE ? bS3 : bS4; if( IS_8x8DCT(mb_type) ) { filter_mb_edgev( h, &img_y[4*0], linesize, bS4, qp0 ); filter_mb_edgev( h, &img_y[4*2], linesize, bS3, qp ); - filter_mb_edgeh( h, &img_y[4*0*linesize], linesize, bS4, qp1 ); + filter_mb_edgeh( h, &img_y[4*0*linesize], linesize, bSH, qp1 ); filter_mb_edgeh( h, &img_y[4*2*linesize], linesize, bS3, qp ); } else { filter_mb_edgev( h, &img_y[4*0], linesize, bS4, qp0 ); filter_mb_edgev( h, &img_y[4*1], linesize, bS3, qp ); filter_mb_edgev( h, &img_y[4*2], linesize, bS3, qp ); filter_mb_edgev( h, &img_y[4*3], linesize, bS3, qp ); - filter_mb_edgeh( h, &img_y[4*0*linesize], linesize, bS4, qp1 ); + filter_mb_edgeh( h, &img_y[4*0*linesize], linesize, bSH, qp1 ); filter_mb_edgeh( h, &img_y[4*1*linesize], linesize, bS3, qp ); filter_mb_edgeh( h, &img_y[4*2*linesize], linesize, bS3, qp ); filter_mb_edgeh( h, &img_y[4*3*linesize], linesize, bS3, qp ); @@ -6296,9 +6425,9 @@ static void filter_mb_fast( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, filter_mb_edgecv( h, &img_cb[2*2], uvlinesize, bS3, qpc ); filter_mb_edgecv( h, &img_cr[2*0], uvlinesize, bS4, qpc0 ); filter_mb_edgecv( h, &img_cr[2*2], uvlinesize, bS3, qpc ); - filter_mb_edgech( h, &img_cb[2*0*uvlinesize], uvlinesize, bS4, qpc1 ); + filter_mb_edgech( h, &img_cb[2*0*uvlinesize], uvlinesize, bSH, qpc1 ); filter_mb_edgech( h, &img_cb[2*2*uvlinesize], uvlinesize, bS3, qpc ); - filter_mb_edgech( h, &img_cr[2*0*uvlinesize], uvlinesize, bS4, qpc1 ); + filter_mb_edgech( h, &img_cr[2*0*uvlinesize], uvlinesize, bSH, qpc1 ); filter_mb_edgech( h, &img_cr[2*2*uvlinesize], uvlinesize, bS3, qpc ); return; } else { @@ -6322,7 +6451,7 @@ static void filter_mb_fast( H264Context *h, int mb_x, int mb_y, uint8_t *img_y, if( IS_INTRA(s->current_picture.mb_type[mb_xy-1]) ) bSv[0][0] = 0x0004000400040004ULL; if( IS_INTRA(s->current_picture.mb_type[h->top_mb_xy]) ) - bSv[1][0] = 0x0004000400040004ULL; + bSv[1][0] = FIELD_PICTURE ? 0x0003000300030003ULL : 0x0004000400040004ULL; #define FILTER(hv,dir,edge)\ if(bSv[dir][edge]) {\ @@ -7288,6 +7417,8 @@ static void execute_decode_slices(H264Context *h, int context_count){ hx = h->thread_context[context_count - 1]; s->mb_x = hx->s.mb_x; s->mb_y = hx->s.mb_y; + s->dropable = hx->s.dropable; + s->picture_structure = hx->s.picture_structure; for(i = 1; i < context_count; i++) h->s.error_count += h->thread_context[i]->s.error_count; } @@ -7310,7 +7441,8 @@ static int decode_nal_units(H264Context *h, uint8_t *buf, int buf_size){ #endif if(!(s->flags2 & CODEC_FLAG2_CHUNKS)){ h->current_slice = 0; - s->current_picture_ptr= NULL; + if (!s->first_field) + s->current_picture_ptr= NULL; } for(;;){ @@ -7607,86 +7739,109 @@ static int decode_frame(AVCodecContext *avctx, h->prev_frame_num_offset= h->frame_num_offset; h->prev_frame_num= h->frame_num; - if(s->current_picture_ptr->reference & s->picture_structure){ + if(!s->dropable) { h->prev_poc_msb= h->poc_msb; h->prev_poc_lsb= h->poc_lsb; execute_ref_pic_marking(h, h->mmco, h->mmco_index); } - ff_er_frame_end(s); + /* + * FIXME: Error handling code does not seem to support interlaced + * when slices span multiple rows + * The ff_er_add_slice calls don't work right for bottom + * fields; they cause massive erroneous error concealing + * Error marking covers both fields (top and bottom). + * This causes a mismatched s->error_count + * and a bad error table. Further, the error count goes to + * INT_MAX when called for bottom field, because mb_y is + * past end by one (callers fault) and resync_mb_y != 0 + * causes problems for the first MB line, too. + */ + if (!FIELD_PICTURE) + ff_er_frame_end(s); MPV_frame_end(s); - //FIXME do something with unavailable reference frames + if (s->first_field) { + /* Wait for second field. */ + *data_size = 0; -#if 0 //decode order - *data_size = sizeof(AVFrame); -#else - /* Sort B-frames into display order */ + } else { + cur->interlaced_frame = FIELD_OR_MBAFF_PICTURE; + /* Derive top_field_first from field pocs. */ + cur->top_field_first = cur->field_poc[0] < cur->field_poc[1]; - if(h->sps.bitstream_restriction_flag - && s->avctx->has_b_frames < h->sps.num_reorder_frames){ - s->avctx->has_b_frames = h->sps.num_reorder_frames; - s->low_delay = 0; - } + //FIXME do something with unavailable reference frames - pics = 0; - while(h->delayed_pic[pics]) pics++; +#if 0 //decode order + *data_size = sizeof(AVFrame); +#else + /* Sort B-frames into display order */ - assert(pics+1 < sizeof(h->delayed_pic) / sizeof(h->delayed_pic[0])); + if(h->sps.bitstream_restriction_flag + && s->avctx->has_b_frames < h->sps.num_reorder_frames){ + s->avctx->has_b_frames = h->sps.num_reorder_frames; + s->low_delay = 0; + } - h->delayed_pic[pics++] = cur; - if(cur->reference == 0) - cur->reference = DELAYED_PIC_REF; + pics = 0; + while(h->delayed_pic[pics]) pics++; - cross_idr = 0; - for(i=0; h->delayed_pic[i]; i++) - if(h->delayed_pic[i]->key_frame || h->delayed_pic[i]->poc==0) - cross_idr = 1; + assert(pics+1 < sizeof(h->delayed_pic) / sizeof(h->delayed_pic[0])); - out = h->delayed_pic[0]; - out_idx = 0; - for(i=1; h->delayed_pic[i] && !h->delayed_pic[i]->key_frame; i++) - if(h->delayed_pic[i]->poc < out->poc){ - out = h->delayed_pic[i]; - out_idx = i; - } + h->delayed_pic[pics++] = cur; + if(cur->reference == 0) + cur->reference = DELAYED_PIC_REF; - out_of_order = !cross_idr && prev && out->poc < prev->poc; - if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= h->sps.num_reorder_frames) - { } - else if(prev && pics <= s->avctx->has_b_frames) - out = prev; - else if((out_of_order && pics-1 == s->avctx->has_b_frames && pics < 15) - || (s->low_delay && - ((!cross_idr && prev && out->poc > prev->poc + 2) - || cur->pict_type == B_TYPE))) - { - s->low_delay = 0; - s->avctx->has_b_frames++; - out = prev; - } - else if(out_of_order) - out = prev; + cross_idr = 0; + for(i=0; h->delayed_pic[i]; i++) + if(h->delayed_pic[i]->key_frame || h->delayed_pic[i]->poc==0) + cross_idr = 1; - if(out_of_order || pics > s->avctx->has_b_frames){ - for(i=out_idx; h->delayed_pic[i]; i++) - h->delayed_pic[i] = h->delayed_pic[i+1]; - } + out = h->delayed_pic[0]; + out_idx = 0; + for(i=1; h->delayed_pic[i] && !h->delayed_pic[i]->key_frame; i++) + if(h->delayed_pic[i]->poc < out->poc){ + out = h->delayed_pic[i]; + out_idx = i; + } - if(prev == out) - *data_size = 0; - else - *data_size = sizeof(AVFrame); - if(prev && prev != out && prev->reference == DELAYED_PIC_REF) - prev->reference = 0; - h->delayed_output_pic = out; + out_of_order = !cross_idr && prev && out->poc < prev->poc; + if(h->sps.bitstream_restriction_flag && s->avctx->has_b_frames >= h->sps.num_reorder_frames) + { } + else if(prev && pics <= s->avctx->has_b_frames) + out = prev; + else if((out_of_order && pics-1 == s->avctx->has_b_frames && pics < 15) + || (s->low_delay && + ((!cross_idr && prev && out->poc > prev->poc + 2) + || cur->pict_type == B_TYPE))) + { + s->low_delay = 0; + s->avctx->has_b_frames++; + out = prev; + } + else if(out_of_order) + out = prev; + + if(out_of_order || pics > s->avctx->has_b_frames){ + for(i=out_idx; h->delayed_pic[i]; i++) + h->delayed_pic[i] = h->delayed_pic[i+1]; + } + + if(prev == out) + *data_size = 0; + else + *data_size = sizeof(AVFrame); + if(prev && prev != out && prev->reference == DELAYED_PIC_REF) + prev->reference = 0; + h->delayed_output_pic = out; #endif - if(out) - *pict= *(AVFrame*)out; - else - av_log(avctx, AV_LOG_DEBUG, "no picture\n"); + if(out) + *pict= *(AVFrame*)out; + else + av_log(avctx, AV_LOG_DEBUG, "no picture\n"); + } } assert(pict->data[0] || !*data_size); @@ -7724,7 +7879,7 @@ static inline void fill_mb_avail(H264Context *h){ #undef random #define COUNT 8000 #define SIZE (COUNT*40) -int main(){ +int main(void){ int i; uint8_t temp[SIZE]; PutBitContext pb;