They are stored in the slice header, so technically they are per-slice (though they must be the same in every slice). This will simplify the following commits.tags/n3.2
| @@ -439,6 +439,9 @@ typedef struct H264SliceContext { | |||||
| CABACContext cabac; | CABACContext cabac; | ||||
| uint8_t cabac_state[1024]; | uint8_t cabac_state[1024]; | ||||
| int cabac_init_idc; | int cabac_init_idc; | ||||
| MMCO mmco[MAX_MMCO_COUNT]; | |||||
| int nb_mmco; | |||||
| } H264SliceContext; | } H264SliceContext; | ||||
| /** | /** | ||||
| @@ -671,10 +674,10 @@ void ff_h264_remove_all_refs(H264Context *h); | |||||
| */ | */ | ||||
| int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count); | int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count); | ||||
| int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb, | |||||
| int first_slice); | |||||
| int ff_h264_decode_ref_pic_marking(const H264Context *h, H264SliceContext *sl, | |||||
| GetBitContext *gb); | |||||
| int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice); | |||||
| int ff_generate_sliding_window_mmcos(const H264Context *h, H264SliceContext *sl); | |||||
| void ff_h264_hl_decode_mb(const H264Context *h, H264SliceContext *sl); | void ff_h264_hl_decode_mb(const H264Context *h, H264SliceContext *sl); | ||||
| int ff_h264_decode_init(AVCodecContext *avctx); | int ff_h264_decode_init(AVCodecContext *avctx); | ||||
| @@ -536,9 +536,10 @@ static int check_opcodes(MMCO *mmco1, MMCO *mmco2, int n_mmcos) | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice) | |||||
| int ff_generate_sliding_window_mmcos(const H264Context *h, | |||||
| H264SliceContext *sl) | |||||
| { | { | ||||
| MMCO mmco_temp[MAX_MMCO_COUNT], *mmco = first_slice ? h->mmco : mmco_temp; | |||||
| MMCO *mmco = sl->mmco; | |||||
| int nb_mmco = 0, i = 0; | int nb_mmco = 0, i = 0; | ||||
| assert(h->long_ref_count + h->short_ref_count <= h->ps.sps->ref_frame_count); | assert(h->long_ref_count + h->short_ref_count <= h->ps.sps->ref_frame_count); | ||||
| @@ -557,16 +558,8 @@ int ff_generate_sliding_window_mmcos(H264Context *h, int first_slice) | |||||
| } | } | ||||
| } | } | ||||
| if (first_slice) { | |||||
| h->nb_mmco = nb_mmco; | |||||
| } else if (!first_slice && nb_mmco >= 0 && | |||||
| (nb_mmco != h->nb_mmco || | |||||
| (i = check_opcodes(h->mmco, mmco_temp, nb_mmco)))) { | |||||
| av_log(h->avctx, AV_LOG_ERROR, | |||||
| "Inconsistent MMCO state between slices [%d, %d, %d]\n", | |||||
| nb_mmco, h->nb_mmco, i); | |||||
| return AVERROR_INVALIDDATA; | |||||
| } | |||||
| sl->nb_mmco = nb_mmco; | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -743,11 +736,11 @@ int ff_h264_execute_ref_pic_marking(H264Context *h, MMCO *mmco, int mmco_count) | |||||
| return (h->avctx->err_recognition & AV_EF_EXPLODE) ? err : 0; | return (h->avctx->err_recognition & AV_EF_EXPLODE) ? err : 0; | ||||
| } | } | ||||
| int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb, | |||||
| int first_slice) | |||||
| int ff_h264_decode_ref_pic_marking(const H264Context *h, H264SliceContext *sl, | |||||
| GetBitContext *gb) | |||||
| { | { | ||||
| int i, ret; | int i, ret; | ||||
| MMCO mmco_temp[MAX_MMCO_COUNT], *mmco = first_slice ? h->mmco : mmco_temp; | |||||
| MMCO *mmco = sl->mmco; | |||||
| int nb_mmco = 0; | int nb_mmco = 0; | ||||
| if (h->nal_unit_type == NAL_IDR_SLICE) { // FIXME fields | if (h->nal_unit_type == NAL_IDR_SLICE) { // FIXME fields | ||||
| @@ -803,25 +796,15 @@ int ff_h264_decode_ref_pic_marking(H264Context *h, GetBitContext *gb, | |||||
| } | } | ||||
| nb_mmco = i; | nb_mmco = i; | ||||
| } else { | } else { | ||||
| if (first_slice) { | |||||
| ret = ff_generate_sliding_window_mmcos(h, first_slice); | |||||
| if (ret < 0 && h->avctx->err_recognition & AV_EF_EXPLODE) | |||||
| return ret; | |||||
| } | |||||
| ret = ff_generate_sliding_window_mmcos(h, sl); | |||||
| if (ret < 0 && h->avctx->err_recognition & AV_EF_EXPLODE) | |||||
| return ret; | |||||
| nb_mmco = -1; | nb_mmco = -1; | ||||
| } | } | ||||
| } | } | ||||
| if (first_slice && nb_mmco != -1) { | |||||
| h->nb_mmco = nb_mmco; | |||||
| } else if (!first_slice && nb_mmco >= 0 && | |||||
| (nb_mmco != h->nb_mmco || | |||||
| check_opcodes(h->mmco, mmco_temp, nb_mmco))) { | |||||
| av_log(h->avctx, AV_LOG_ERROR, | |||||
| "Inconsistent MMCO state between slices [%d, %d]\n", | |||||
| nb_mmco, h->nb_mmco); | |||||
| return AVERROR_INVALIDDATA; | |||||
| } | |||||
| if (nb_mmco != -1) | |||||
| sl->nb_mmco = nb_mmco; | |||||
| return 0; | return 0; | ||||
| } | } | ||||
| @@ -1201,10 +1201,12 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl) | |||||
| h->cur_pic_ptr->frame_num = h->poc.prev_frame_num; | h->cur_pic_ptr->frame_num = h->poc.prev_frame_num; | ||||
| ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0); | ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 0); | ||||
| ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1); | ff_thread_report_progress(&h->cur_pic_ptr->tf, INT_MAX, 1); | ||||
| ret = ff_generate_sliding_window_mmcos(h, 1); | |||||
| ret = ff_generate_sliding_window_mmcos(h, sl); | |||||
| if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) | if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) | ||||
| return ret; | return ret; | ||||
| ret = ff_h264_execute_ref_pic_marking(h, h->mmco, h->nb_mmco); | |||||
| ret = ff_h264_execute_ref_pic_marking(h, sl->mmco, sl->nb_mmco); | |||||
| if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) | if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) | ||||
| return ret; | return ret; | ||||
| /* Error concealment: If a ref is missing, copy the previous ref | /* Error concealment: If a ref is missing, copy the previous ref | ||||
| @@ -1342,15 +1344,8 @@ static int h264_slice_header_parse(H264Context *h, H264SliceContext *sl) | |||||
| ff_h264_pred_weight_table(&sl->gb, sps, sl->ref_count, | ff_h264_pred_weight_table(&sl->gb, sps, sl->ref_count, | ||||
| sl->slice_type_nos, &sl->pwt); | sl->slice_type_nos, &sl->pwt); | ||||
| // If frame-mt is enabled, only update mmco tables for the first slice | |||||
| // in a field. Subsequent slices can temporarily clobber h->nb_mmco | |||||
| // or h->mmco, which will cause ref list mix-ups and decoding errors | |||||
| // further down the line. This may break decoding if the first slice is | |||||
| // corrupt, thus we only do this if frame-mt is enabled. | |||||
| if (h->nal_ref_idc) { | if (h->nal_ref_idc) { | ||||
| ret = ff_h264_decode_ref_pic_marking(h, &sl->gb, | |||||
| !(h->avctx->active_thread_type & FF_THREAD_FRAME) || | |||||
| h->current_slice == 0); | |||||
| ret = ff_h264_decode_ref_pic_marking(h, sl, &sl->gb); | |||||
| if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) | if (ret < 0 && (h->avctx->err_recognition & AV_EF_EXPLODE)) | ||||
| return AVERROR_INVALIDDATA; | return AVERROR_INVALIDDATA; | ||||
| } | } | ||||
| @@ -1441,10 +1436,14 @@ int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl) | |||||
| sl->resync_mb_y = sl->mb_y = sl->mb_y + 1; | sl->resync_mb_y = sl->mb_y = sl->mb_y + 1; | ||||
| assert(sl->mb_y < h->mb_height); | assert(sl->mb_y < h->mb_height); | ||||
| if (!h->setup_finished) | |||||
| if (!h->setup_finished) { | |||||
| ff_h264_init_poc(h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc, | ff_h264_init_poc(h->cur_pic_ptr->field_poc, &h->cur_pic_ptr->poc, | ||||
| h->ps.sps, &h->poc, h->picture_structure, h->nal_ref_idc); | h->ps.sps, &h->poc, h->picture_structure, h->nal_ref_idc); | ||||
| memcpy(h->mmco, sl->mmco, sl->nb_mmco * sizeof(*h->mmco)); | |||||
| h->nb_mmco = sl->nb_mmco; | |||||
| } | |||||
| ret = ff_h264_build_ref_list(h, sl); | ret = ff_h264_build_ref_list(h, sl); | ||||
| if (ret < 0) | if (ret < 0) | ||||
| return ret; | return ret; | ||||