mirror of
https://git.videolan.org/git/ffmpeg.git
synced 2024-09-07 00:20:09 +02:00
h264: decode the MMCOs into per-slice contexts
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.
This commit is contained in:
parent
39ab2ea531
commit
2d410ebbaa
@ -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 ff_h264_decode_ref_pic_marking(const H264Context *h, H264SliceContext *sl,
|
||||||
int first_slice);
|
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) {
|
sl->nb_mmco = nb_mmco;
|
||||||
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;
|
|
||||||
}
|
|
||||||
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 ff_h264_decode_ref_pic_marking(const H264Context *h, H264SliceContext *sl,
|
||||||
int first_slice)
|
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, sl);
|
||||||
ret = ff_generate_sliding_window_mmcos(h, first_slice);
|
|
||||||
if (ret < 0 && h->avctx->err_recognition & AV_EF_EXPLODE)
|
if (ret < 0 && h->avctx->err_recognition & AV_EF_EXPLODE)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
|
||||||
nb_mmco = -1;
|
nb_mmco = -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (first_slice && nb_mmco != -1) {
|
if (nb_mmco != -1)
|
||||||
h->nb_mmco = nb_mmco;
|
sl->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;
|
|
||||||
}
|
|
||||||
|
|
||||||
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,
|
ret = ff_h264_decode_ref_pic_marking(h, sl, &sl->gb);
|
||||||
!(h->avctx->active_thread_type & FF_THREAD_FRAME) ||
|
|
||||||
h->current_slice == 0);
|
|
||||||
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;
|
||||||
|
Loading…
Reference in New Issue
Block a user