int mb_x, int mb_y, int mb_intra, int mb_skipped)
{
H264Context *h = opaque;
+ H264SliceContext *sl = &h->slice_ctx[0];
h->mb_x = mb_x;
h->mb_y = mb_y;
h->mb_xy = mb_x + mb_y * h->mb_stride;
- memset(h->non_zero_count_cache, 0, sizeof(h->non_zero_count_cache));
+ memset(sl->non_zero_count_cache, 0, sizeof(sl->non_zero_count_cache));
assert(ref >= 0);
/* FIXME: It is possible albeit uncommon that slice references
* differ between slices. We take the easy approach and ignore
ref = 0;
fill_rectangle(&h->cur_pic.ref_index[0][4 * h->mb_xy],
2, 2, 2, ref, 1);
- fill_rectangle(&h->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
- fill_rectangle(h->mv_cache[0][scan8[0]], 4, 4, 8,
+ fill_rectangle(&sl->ref_cache[0][scan8[0]], 4, 4, 8, ref, 1);
+ fill_rectangle(sl->mv_cache[0][scan8[0]], 4, 4, 8,
pack16to32((*mv)[0][0][0], (*mv)[0][0][1]), 4);
assert(!FRAME_MBAFF(h));
- ff_h264_hl_decode_mb(h);
+ ff_h264_hl_decode_mb(h, &h->slice_ctx[0]);
}
void ff_h264_draw_horiz_band(H264Context *h, int y, int height)
* Check if the top & left blocks are available if needed and
* change the dc mode so it only uses the available blocks.
*/
-int ff_h264_check_intra4x4_pred_mode(H264Context *h)
+int ff_h264_check_intra4x4_pred_mode(H264Context *h, H264SliceContext *sl)
{
static const int8_t top[12] = {
-1, 0, LEFT_DC_PRED, -1, -1, -1, -1, -1, 0
};
int i;
- if (!(h->top_samples_available & 0x8000)) {
+ if (!(sl->top_samples_available & 0x8000)) {
for (i = 0; i < 4; i++) {
- int status = top[h->intra4x4_pred_mode_cache[scan8[0] + i]];
+ int status = top[sl->intra4x4_pred_mode_cache[scan8[0] + i]];
if (status < 0) {
av_log(h->avctx, AV_LOG_ERROR,
"top block unavailable for requested intra4x4 mode %d at %d %d\n",
status, h->mb_x, h->mb_y);
return AVERROR_INVALIDDATA;
} else if (status) {
- h->intra4x4_pred_mode_cache[scan8[0] + i] = status;
+ sl->intra4x4_pred_mode_cache[scan8[0] + i] = status;
}
}
}
- if ((h->left_samples_available & 0x8888) != 0x8888) {
+ if ((sl->left_samples_available & 0x8888) != 0x8888) {
static const int mask[4] = { 0x8000, 0x2000, 0x80, 0x20 };
for (i = 0; i < 4; i++)
- if (!(h->left_samples_available & mask[i])) {
- int status = left[h->intra4x4_pred_mode_cache[scan8[0] + 8 * i]];
+ if (!(sl->left_samples_available & mask[i])) {
+ int status = left[sl->intra4x4_pred_mode_cache[scan8[0] + 8 * i]];
if (status < 0) {
av_log(h->avctx, AV_LOG_ERROR,
"left block unavailable for requested intra4x4 mode %d at %d %d\n",
status, h->mb_x, h->mb_y);
return AVERROR_INVALIDDATA;
} else if (status) {
- h->intra4x4_pred_mode_cache[scan8[0] + 8 * i] = status;
+ sl->intra4x4_pred_mode_cache[scan8[0] + 8 * i] = status;
}
}
}
* Check if the top & left blocks are available if needed and
* change the dc mode so it only uses the available blocks.
*/
-int ff_h264_check_intra_pred_mode(H264Context *h, int mode, int is_chroma)
+int ff_h264_check_intra_pred_mode(H264Context *h, H264SliceContext *sl,
+ int mode, int is_chroma)
{
static const int8_t top[4] = { LEFT_DC_PRED8x8, 1, -1, -1 };
static const int8_t left[5] = { TOP_DC_PRED8x8, -1, 2, -1, DC_128_PRED8x8 };
return AVERROR_INVALIDDATA;
}
- if (!(h->top_samples_available & 0x8000)) {
+ if (!(sl->top_samples_available & 0x8000)) {
mode = top[mode];
if (mode < 0) {
av_log(h->avctx, AV_LOG_ERROR,
}
}
- if ((h->left_samples_available & 0x8080) != 0x8080) {
+ if ((sl->left_samples_available & 0x8080) != 0x8080) {
mode = left[mode];
- if (is_chroma && (h->left_samples_available & 0x8080)) {
+ if (is_chroma && (sl->left_samples_available & 0x8080)) {
// mad cow disease mode, aka MBAFF + constrained_intra_pred
mode = ALZHEIMER_DC_L0T_PRED8x8 +
- (!(h->left_samples_available & 0x8000)) +
+ (!(sl->left_samples_available & 0x8000)) +
2 * (mode == DC_128_PRED8x8);
}
if (mode < 0) {
FF_ALLOCZ_OR_GOTO(h->avctx, h->intra4x4_pred_mode,
row_mb_num * 8 * sizeof(uint8_t), fail)
+ h->slice_ctx[0].intra4x4_pred_mode = h->intra4x4_pred_mode;
+
FF_ALLOCZ_OR_GOTO(h->avctx, h->non_zero_count,
big_mb_num * 48 * sizeof(uint8_t), fail)
FF_ALLOCZ_OR_GOTO(h->avctx, h->slice_table_base,
FF_ALLOCZ_OR_GOTO(h->avctx, h->top_borders[1],
h->mb_width * 16 * 3 * sizeof(uint8_t) * 2, fail)
- h->ref_cache[0][scan8[5] + 1] =
- h->ref_cache[0][scan8[7] + 1] =
- h->ref_cache[0][scan8[13] + 1] =
- h->ref_cache[1][scan8[5] + 1] =
- h->ref_cache[1][scan8[7] + 1] =
- h->ref_cache[1][scan8[13] + 1] = PART_NOT_AVAILABLE;
+ for (i = 0; i < h->nb_slice_ctx; i++) {
+ h->slice_ctx[i].ref_cache[0][scan8[5] + 1] =
+ h->slice_ctx[i].ref_cache[0][scan8[7] + 1] =
+ h->slice_ctx[i].ref_cache[0][scan8[13] + 1] =
+ h->slice_ctx[i].ref_cache[1][scan8[5] + 1] =
+ h->slice_ctx[i].ref_cache[1][scan8[7] + 1] =
+ h->slice_ctx[i].ref_cache[1][scan8[13] + 1] = PART_NOT_AVAILABLE;
+ }
if (CONFIG_ERROR_RESILIENCE) {
/* init ER */
er->avctx = h->avctx;
- er->mecc = &h->mecc;
er->decode_mb = h264_er_decode_mb;
er->opaque = h;
er->quarter_sample = 1;
h->dequant_coeff_pps = -1;
/* needed so that IDCT permutation is known early */
- if (CONFIG_ERROR_RESILIENCE)
- ff_me_cmp_init(&h->mecc, h->avctx);
ff_videodsp_init(&h->vdsp, 8);
memset(h->pps.scaling_matrix4, 16, 6 * 16 * sizeof(uint8_t));
h->pixel_shift = 0;
h->sps.bit_depth_luma = avctx->bits_per_raw_sample = 8;
+ h->nb_slice_ctx = (avctx->active_thread_type & FF_THREAD_SLICE) ? H264_MAX_THREADS : 1;
+ h->slice_ctx = av_mallocz_array(h->nb_slice_ctx, sizeof(*h->slice_ctx));
+ if (!h->slice_ctx) {
+ h->nb_slice_ctx = 0;
+ return AVERROR(ENOMEM);
+ }
+
h->thread_context[0] = h;
+ for (i = 0; i < h->nb_slice_ctx; i++)
+ h->slice_ctx[i].h264 = h->thread_context[0];
+
h->outputed_poc = h->next_outputed_poc = INT_MIN;
for (i = 0; i < MAX_DELAYED_PIC_COUNT; i++)
h->last_pocs[i] = INT_MIN;
static int decode_init_thread_copy(AVCodecContext *avctx)
{
H264Context *h = avctx->priv_data;
+ int i;
if (!avctx->internal->is_copy)
return 0;
memset(h->sps_buffers, 0, sizeof(h->sps_buffers));
memset(h->pps_buffers, 0, sizeof(h->pps_buffers));
+ h->nb_slice_ctx = (avctx->active_thread_type & FF_THREAD_SLICE) ? H264_MAX_THREADS : 1;
+ h->slice_ctx = av_mallocz_array(h->nb_slice_ctx, sizeof(*h->slice_ctx));
+ if (!h->slice_ctx) {
+ h->nb_slice_ctx = 0;
+ return AVERROR(ENOMEM);
+ }
+
+ for (i = 0; i < h->nb_slice_ctx; i++)
+ h->slice_ctx[i].h264 = h;
+
+ h->avctx = avctx;
+ h->rbsp_buffer[0] = NULL;
+ h->rbsp_buffer[1] = NULL;
+ h->rbsp_buffer_size[0] = 0;
+ h->rbsp_buffer_size[1] = 0;
h->context_initialized = 0;
return 0;
ff_thread_finish_setup(h->avctx);
}
-int ff_pred_weight_table(H264Context *h)
+int ff_pred_weight_table(H264Context *h, H264SliceContext *sl)
{
int list, i;
int luma_def, chroma_def;
- h->use_weight = 0;
- h->use_weight_chroma = 0;
- h->luma_log2_weight_denom = get_ue_golomb(&h->gb);
+ sl->use_weight = 0;
+ sl->use_weight_chroma = 0;
+ sl->luma_log2_weight_denom = get_ue_golomb(&h->gb);
if (h->sps.chroma_format_idc)
- h->chroma_log2_weight_denom = get_ue_golomb(&h->gb);
- luma_def = 1 << h->luma_log2_weight_denom;
- chroma_def = 1 << h->chroma_log2_weight_denom;
+ sl->chroma_log2_weight_denom = get_ue_golomb(&h->gb);
+ luma_def = 1 << sl->luma_log2_weight_denom;
+ chroma_def = 1 << sl->chroma_log2_weight_denom;
for (list = 0; list < 2; list++) {
- h->luma_weight_flag[list] = 0;
- h->chroma_weight_flag[list] = 0;
+ sl->luma_weight_flag[list] = 0;
+ sl->chroma_weight_flag[list] = 0;
for (i = 0; i < h->ref_count[list]; i++) {
int luma_weight_flag, chroma_weight_flag;
luma_weight_flag = get_bits1(&h->gb);
if (luma_weight_flag) {
- h->luma_weight[i][list][0] = get_se_golomb(&h->gb);
- h->luma_weight[i][list][1] = get_se_golomb(&h->gb);
- if (h->luma_weight[i][list][0] != luma_def ||
- h->luma_weight[i][list][1] != 0) {
- h->use_weight = 1;
- h->luma_weight_flag[list] = 1;
+ sl->luma_weight[i][list][0] = get_se_golomb(&h->gb);
+ sl->luma_weight[i][list][1] = get_se_golomb(&h->gb);
+ if (sl->luma_weight[i][list][0] != luma_def ||
+ sl->luma_weight[i][list][1] != 0) {
+ sl->use_weight = 1;
+ sl->luma_weight_flag[list] = 1;
}
} else {
- h->luma_weight[i][list][0] = luma_def;
- h->luma_weight[i][list][1] = 0;
+ sl->luma_weight[i][list][0] = luma_def;
+ sl->luma_weight[i][list][1] = 0;
}
if (h->sps.chroma_format_idc) {
if (chroma_weight_flag) {
int j;
for (j = 0; j < 2; j++) {
- h->chroma_weight[i][list][j][0] = get_se_golomb(&h->gb);
- h->chroma_weight[i][list][j][1] = get_se_golomb(&h->gb);
- if (h->chroma_weight[i][list][j][0] != chroma_def ||
- h->chroma_weight[i][list][j][1] != 0) {
- h->use_weight_chroma = 1;
- h->chroma_weight_flag[list] = 1;
+ sl->chroma_weight[i][list][j][0] = get_se_golomb(&h->gb);
+ sl->chroma_weight[i][list][j][1] = get_se_golomb(&h->gb);
+ if (sl->chroma_weight[i][list][j][0] != chroma_def ||
+ sl->chroma_weight[i][list][j][1] != 0) {
+ sl->use_weight_chroma = 1;
+ sl->chroma_weight_flag[list] = 1;
}
}
} else {
int j;
for (j = 0; j < 2; j++) {
- h->chroma_weight[i][list][j][0] = chroma_def;
- h->chroma_weight[i][list][j][1] = 0;
+ sl->chroma_weight[i][list][j][0] = chroma_def;
+ sl->chroma_weight[i][list][j][1] = 0;
}
}
}
if (h->slice_type_nos != AV_PICTURE_TYPE_B)
break;
}
- h->use_weight = h->use_weight || h->use_weight_chroma;
+ sl->use_weight = sl->use_weight || sl->use_weight_chroma;
return 0;
}
if (h->cur_pic_ptr)
h->cur_pic_ptr->reference = 0;
h->first_field = 0;
- memset(h->ref_list[0], 0, sizeof(h->ref_list[0]));
- memset(h->ref_list[1], 0, sizeof(h->ref_list[1]));
- memset(h->default_ref_list[0], 0, sizeof(h->default_ref_list[0]));
- memset(h->default_ref_list[1], 0, sizeof(h->default_ref_list[1]));
ff_h264_reset_sei(h);
h->recovery_frame = -1;
h->frame_recovered = 0;
h->mb_x = h->mb_y = 0;
- h->parse_context.state = -1;
- h->parse_context.frame_start_found = 0;
- h->parse_context.overread = 0;
- h->parse_context.overread_index = 0;
- h->parse_context.index = 0;
- h->parse_context.last_index = 0;
-
ff_h264_free_tables(h, 1);
h->context_initialized = 0;
}
ff_h264qpel_init(&h->h264qpel, h->sps.bit_depth_luma);
ff_h264_pred_init(&h->hpc, h->avctx->codec_id, h->sps.bit_depth_luma,
h->sps.chroma_format_idc);
- if (CONFIG_ERROR_RESILIENCE)
- ff_me_cmp_init(&h->mecc, h->avctx);
ff_videodsp_init(&h->vdsp, h->sps.bit_depth_luma);
} else {
av_log(h->avctx, AV_LOG_ERROR, "Unsupported bit depth %d\n",
{
AVCodecContext *const avctx = h->avctx;
H264Context *hx; ///< thread context
+ H264SliceContext *sl;
int buf_index;
unsigned context_count;
int next_avc;
}
hx = h->thread_context[context_count];
+ sl = &h->slice_ctx[context_count];
ptr = ff_h264_decode_nal(hx, buf + buf_index, &dst_length,
&consumed, next_avc - buf_index);
init_get_bits(&hx->gb, ptr, bit_length);
hx->intra_gb_ptr =
hx->inter_gb_ptr = &hx->gb;
- hx->data_partitioning = 0;
- if ((err = ff_h264_decode_slice_header(hx, h)))
+ if ((err = ff_h264_decode_slice_header(hx, sl, h)))
break;
if (h->sei_recovery_frame_cnt >= 0 && h->recovery_frame < 0) {
}
break;
case NAL_DPA:
- if (h->avctx->flags & CODEC_FLAG2_CHUNKS) {
- av_log(h->avctx, AV_LOG_ERROR,
- "Decoding in chunks is not supported for "
- "partitioned slices.\n");
- return AVERROR(ENOSYS);
- }
-
- init_get_bits(&hx->gb, ptr, bit_length);
- hx->intra_gb_ptr =
- hx->inter_gb_ptr = NULL;
-
- if ((err = ff_h264_decode_slice_header(hx, h)) < 0) {
- /* make sure data_partitioning is cleared if it was set
- * before, so we don't try decoding a slice without a valid
- * slice header later */
- h->data_partitioning = 0;
- break;
- }
-
- hx->data_partitioning = 1;
- break;
case NAL_DPB:
- init_get_bits(&hx->intra_gb, ptr, bit_length);
- hx->intra_gb_ptr = &hx->intra_gb;
- break;
case NAL_DPC:
- init_get_bits(&hx->inter_gb, ptr, bit_length);
- hx->inter_gb_ptr = &hx->inter_gb;
-
- if (hx->redundant_pic_count == 0 &&
- hx->intra_gb_ptr &&
- hx->data_partitioning &&
- h->cur_pic_ptr && h->context_initialized &&
- (avctx->skip_frame < AVDISCARD_NONREF || hx->nal_ref_idc) &&
- (avctx->skip_frame < AVDISCARD_BIDIR ||
- hx->slice_type_nos != AV_PICTURE_TYPE_B) &&
- (avctx->skip_frame < AVDISCARD_NONKEY ||
- hx->slice_type_nos == AV_PICTURE_TYPE_I) &&
- avctx->skip_frame < AVDISCARD_ALL)
- context_count++;
+ avpriv_request_sample(avctx, "data partitioning");
+ ret = AVERROR(ENOSYS);
+ goto end;
break;
case NAL_SEI:
init_get_bits(&h->gb, ptr, bit_length);
h->nal_unit_type = hx->nal_unit_type;
h->nal_ref_idc = hx->nal_ref_idc;
hx = h;
+ sl = &h->slice_ctx[0];
goto again;
}
}
int ret;
h->flags = avctx->flags;
- /* reset data partitioning here, to ensure GetBitContexts from previous
- * packets do not get used. */
- h->data_partitioning = 0;
/* end of stream, output what is still in the buffers */
out:
ff_h264_free_tables(h, 1); // FIXME cleanup init stuff perhaps
+ av_freep(&h->slice_ctx);
+ h->nb_slice_ctx = 0;
+
for (i = 0; i < MAX_SPS_COUNT; i++)
av_freep(h->sps_buffers + i);