/**
* Mimic alloc_tables(), but for every context thread.
*/
-static void clone_tables(H264Context *dst, H264Context *src, int i)
+static void clone_tables(H264Context *dst, H264SliceContext *sl,
+ H264Context *src, int i)
{
- dst->intra4x4_pred_mode = src->intra4x4_pred_mode + i * 8 * 2 * src->mb_stride;
+ sl->intra4x4_pred_mode = src->intra4x4_pred_mode + i * 8 * 2 * src->mb_stride;
+
dst->non_zero_count = src->non_zero_count;
dst->slice_table = src->slice_table;
dst->cbp_table = src->cbp_table;
memcpy(h->block_offset, h1->block_offset, sizeof(h->block_offset));
if (!inited) {
+ H264SliceContext *orig_slice_ctx = h->slice_ctx;
+
for (i = 0; i < MAX_SPS_COUNT; i++)
av_freep(h->sps_buffers + i);
memset(&h->cur_pic, 0, sizeof(h->cur_pic));
memset(&h->last_pic_for_ec, 0, sizeof(h->last_pic_for_ec));
+ h->slice_ctx = orig_slice_ctx;
+
h->avctx = dst;
h->DPB = NULL;
h->qscale_table_pool = NULL;
h->coded_picture_number = h1->coded_picture_number;
h->first_field = h1->first_field;
h->picture_structure = h1->picture_structure;
- h->qscale = h1->qscale;
h->droppable = h1->droppable;
h->low_delay = h1->low_delay;
* @param field 0/1 initialize the weight for interlaced MBAFF
* -1 initializes the rest
*/
-static void implicit_weight_table(H264Context *h, int field)
+static void implicit_weight_table(H264Context *h, H264SliceContext *sl, int field)
{
int ref0, ref1, i, cur_poc, ref_start, ref_count0, ref_count1;
for (i = 0; i < 2; i++) {
- h->luma_weight_flag[i] = 0;
- h->chroma_weight_flag[i] = 0;
+ sl->luma_weight_flag[i] = 0;
+ sl->chroma_weight_flag[i] = 0;
}
if (field < 0) {
}
if (h->ref_count[0] == 1 && h->ref_count[1] == 1 && !FRAME_MBAFF(h) &&
h->ref_list[0][0].poc + h->ref_list[1][0].poc == 2 * cur_poc) {
- h->use_weight = 0;
- h->use_weight_chroma = 0;
+ sl->use_weight = 0;
+ sl->use_weight_chroma = 0;
return;
}
ref_start = 0;
ref_count1 = 16 + 2 * h->ref_count[1];
}
- h->use_weight = 2;
- h->use_weight_chroma = 2;
- h->luma_log2_weight_denom = 5;
- h->chroma_log2_weight_denom = 5;
+ sl->use_weight = 2;
+ sl->use_weight_chroma = 2;
+ sl->luma_log2_weight_denom = 5;
+ sl->chroma_log2_weight_denom = 5;
for (ref0 = ref_start; ref0 < ref_count0; ref0++) {
int poc0 = h->ref_list[0][ref0].poc;
}
}
if (field < 0) {
- h->implicit_weight[ref0][ref1][0] =
- h->implicit_weight[ref0][ref1][1] = w;
+ sl->implicit_weight[ref0][ref1][0] =
+ sl->implicit_weight[ref0][ref1][1] = w;
} else {
- h->implicit_weight[ref0][ref1][field] = w;
+ sl->implicit_weight[ref0][ref1][field] = w;
}
}
}
c->uvlinesize = h->uvlinesize;
c->chroma_x_shift = h->chroma_x_shift;
c->chroma_y_shift = h->chroma_y_shift;
- c->qscale = h->qscale;
c->droppable = h->droppable;
c->low_delay = h->low_delay;
c->mb_width = h->mb_width;
c->workaround_bugs = h->workaround_bugs;
c->pict_type = h->pict_type;
+ h->slice_ctx[i].h264 = c;
+
init_scan_tables(c);
- clone_tables(c, h, i);
+ clone_tables(c, &h->slice_ctx[i], h, i);
c->context_initialized = 1;
}
*
* @return 0 if okay, <0 if an error occurred, 1 if decoding must not be multithreaded
*/
-int ff_h264_decode_slice_header(H264Context *h, H264Context *h0)
+int ff_h264_decode_slice_header(H264Context *h, H264SliceContext *sl, H264Context *h0)
{
unsigned int first_mb_in_slice;
unsigned int pps_id;
if ((h->pps.weighted_pred && h->slice_type_nos == AV_PICTURE_TYPE_P) ||
(h->pps.weighted_bipred_idc == 1 &&
h->slice_type_nos == AV_PICTURE_TYPE_B))
- ff_pred_weight_table(h);
+ ff_pred_weight_table(h, sl);
else if (h->pps.weighted_bipred_idc == 2 &&
h->slice_type_nos == AV_PICTURE_TYPE_B) {
- implicit_weight_table(h, -1);
+ implicit_weight_table(h, sl, -1);
} else {
- h->use_weight = 0;
+ sl->use_weight = 0;
for (i = 0; i < 2; i++) {
- h->luma_weight_flag[i] = 0;
- h->chroma_weight_flag[i] = 0;
+ sl->luma_weight_flag[i] = 0;
+ sl->chroma_weight_flag[i] = 0;
}
}
}
if (FRAME_MBAFF(h)) {
- ff_h264_fill_mbaff_ref_list(h);
+ ff_h264_fill_mbaff_ref_list(h, sl);
if (h->pps.weighted_bipred_idc == 2 && h->slice_type_nos == AV_PICTURE_TYPE_B) {
- implicit_weight_table(h, 0);
- implicit_weight_table(h, 1);
+ implicit_weight_table(h, sl, 0);
+ implicit_weight_table(h, sl, 1);
}
}
av_log(h->avctx, AV_LOG_ERROR, "QP %u out of range\n", tmp);
return AVERROR_INVALIDDATA;
}
- h->qscale = tmp;
- h->chroma_qp[0] = get_chroma_qp(h, 0, h->qscale);
- h->chroma_qp[1] = get_chroma_qp(h, 1, h->qscale);
+ sl->qscale = tmp;
+ sl->chroma_qp[0] = get_chroma_qp(h, 0, sl->qscale);
+ sl->chroma_qp[1] = get_chroma_qp(h, 1, sl->qscale);
// FIXME qscale / qp ... stuff
if (h->slice_type == AV_PICTURE_TYPE_SP)
get_bits1(&h->gb); /* sp_for_switch_flag */
}
}
}
- h->qp_thresh = 15 -
+ sl->qp_thresh = 15 -
FFMIN(h->slice_alpha_c0_offset, h->slice_beta_offset) -
FFMAX3(0,
h->pps.chroma_qp_index_offset[0],
h->cur_pic_ptr->field_poc[0],
h->cur_pic_ptr->field_poc[1],
h->ref_count[0], h->ref_count[1],
- h->qscale,
+ sl->qscale,
h->deblocking_filter,
h->slice_alpha_c0_offset, h->slice_beta_offset,
- h->use_weight,
- h->use_weight == 1 && h->use_weight_chroma ? "c" : "",
+ sl->use_weight,
+ sl->use_weight == 1 && sl->use_weight_chroma ? "c" : "",
h->slice_type == AV_PICTURE_TYPE_B ? (h->direct_spatial_mv_pred ? "SPAT" : "TEMP") : "");
}
*
* @return non zero if the loop filter can be skipped
*/
-static int fill_filter_caches(H264Context *h, int mb_type)
+static int fill_filter_caches(H264Context *h, H264SliceContext *sl, int mb_type)
{
const int mb_xy = h->mb_xy;
int top_xy, left_xy[LEFT_MBS];
}
}
- h->top_mb_xy = top_xy;
- h->left_mb_xy[LTOP] = left_xy[LTOP];
- h->left_mb_xy[LBOT] = left_xy[LBOT];
+ sl->top_mb_xy = top_xy;
+ sl->left_mb_xy[LTOP] = left_xy[LTOP];
+ sl->left_mb_xy[LBOT] = left_xy[LBOT];
{
/* For sufficiently low qp, filtering wouldn't do anything.
* This is a conservative estimate: could also check beta_offset
* and more accurate chroma_qp. */
- int qp_thresh = h->qp_thresh; // FIXME strictly we should store qp_thresh for each mb of a slice
+ int qp_thresh = sl->qp_thresh; // FIXME strictly we should store qp_thresh for each mb of a slice
int qp = h->cur_pic.qscale_table[mb_xy];
if (qp <= qp_thresh &&
(left_xy[LTOP] < 0 ||
if (h->slice_table[left_xy[LBOT]] == 0xFFFF)
left_type[LTOP] = left_type[LBOT] = 0;
}
- h->top_type = top_type;
- h->left_type[LTOP] = left_type[LTOP];
- h->left_type[LBOT] = left_type[LBOT];
+ sl->top_type = top_type;
+ sl->left_type[LTOP] = left_type[LTOP];
+ sl->left_type[LBOT] = left_type[LBOT];
if (IS_INTRA(mb_type))
return 0;
return 0;
}
-static void loop_filter(H264Context *h, int start_x, int end_x)
+static void loop_filter(H264Context *h, H264SliceContext *sl, int start_x, int end_x)
{
uint8_t *dest_y, *dest_cb, *dest_cr;
int linesize, uvlinesize, mb_x, mb_y;
}
backup_mb_border(h, dest_y, dest_cb, dest_cr, linesize,
uvlinesize, 0);
- if (fill_filter_caches(h, mb_type))
+ if (fill_filter_caches(h, sl, mb_type))
continue;
- h->chroma_qp[0] = get_chroma_qp(h, 0, h->cur_pic.qscale_table[mb_xy]);
- h->chroma_qp[1] = get_chroma_qp(h, 1, h->cur_pic.qscale_table[mb_xy]);
+ sl->chroma_qp[0] = get_chroma_qp(h, 0, h->cur_pic.qscale_table[mb_xy]);
+ sl->chroma_qp[1] = get_chroma_qp(h, 1, h->cur_pic.qscale_table[mb_xy]);
if (FRAME_MBAFF(h)) {
- ff_h264_filter_mb(h, mb_x, mb_y, dest_y, dest_cb, dest_cr,
+ ff_h264_filter_mb(h, sl, mb_x, mb_y, dest_y, dest_cb, dest_cr,
linesize, uvlinesize);
} else {
- ff_h264_filter_mb_fast(h, mb_x, mb_y, dest_y, dest_cb,
+ ff_h264_filter_mb_fast(h, sl, mb_x, mb_y, dest_y, dest_cb,
dest_cr, linesize, uvlinesize);
}
}
h->slice_type = old_slice_type;
h->mb_x = end_x;
h->mb_y = end_mb_y - FRAME_MBAFF(h);
- h->chroma_qp[0] = get_chroma_qp(h, 0, h->qscale);
- h->chroma_qp[1] = get_chroma_qp(h, 1, h->qscale);
+ sl->chroma_qp[0] = get_chroma_qp(h, 0, sl->qscale);
+ sl->chroma_qp[1] = get_chroma_qp(h, 1, sl->qscale);
}
static void predict_field_decoding_flag(H264Context *h)
static int decode_slice(struct AVCodecContext *avctx, void *arg)
{
- H264Context *h = *(void **)arg;
+ H264SliceContext *sl = arg;
+ H264Context *h = sl->h264;
int lf_x_start = h->mb_x;
h->mb_skip_run = -1;
h->gb.buffer + get_bits_count(&h->gb) / 8,
(get_bits_left(&h->gb) + 7) / 8);
- ff_h264_init_cabac_states(h);
+ ff_h264_init_cabac_states(h, sl);
for (;;) {
// START_TIMER
- int ret = ff_h264_decode_mb_cabac(h);
+ int ret = ff_h264_decode_mb_cabac(h, sl);
int eos;
// STOP_TIMER("decode_mb_cabac")
if (ret >= 0)
- ff_h264_hl_decode_mb(h);
+ ff_h264_hl_decode_mb(h, sl);
// FIXME optimal? or let mb_decode decode 16x32 ?
if (ret >= 0 && FRAME_MBAFF(h)) {
h->mb_y++;
- ret = ff_h264_decode_mb_cabac(h);
+ ret = ff_h264_decode_mb_cabac(h, sl);
if (ret >= 0)
- ff_h264_hl_decode_mb(h);
+ ff_h264_hl_decode_mb(h, sl);
h->mb_y--;
}
eos = get_cabac_terminate(&h->cabac);
er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x - 1,
h->mb_y, ER_MB_END);
if (h->mb_x >= lf_x_start)
- loop_filter(h, lf_x_start, h->mb_x + 1);
+ loop_filter(h, sl, lf_x_start, h->mb_x + 1);
return 0;
}
if (h->cabac.bytestream > h->cabac.bytestream_end + 2 )
}
if (++h->mb_x >= h->mb_width) {
- loop_filter(h, lf_x_start, h->mb_x);
+ loop_filter(h, sl, lf_x_start, h->mb_x);
h->mb_x = lf_x_start = 0;
decode_finish_row(h);
++h->mb_y;
er_add_slice(h, h->resync_mb_x, h->resync_mb_y, h->mb_x - 1,
h->mb_y, ER_MB_END);
if (h->mb_x > lf_x_start)
- loop_filter(h, lf_x_start, h->mb_x);
+ loop_filter(h, sl, lf_x_start, h->mb_x);
return 0;
}
}
} else {
for (;;) {
- int ret = ff_h264_decode_mb_cavlc(h);
+ int ret = ff_h264_decode_mb_cavlc(h, sl);
if (ret >= 0)
- ff_h264_hl_decode_mb(h);
+ ff_h264_hl_decode_mb(h, sl);
// FIXME optimal? or let mb_decode decode 16x32 ?
if (ret >= 0 && FRAME_MBAFF(h)) {
h->mb_y++;
- ret = ff_h264_decode_mb_cavlc(h);
+ ret = ff_h264_decode_mb_cavlc(h, sl);
if (ret >= 0)
- ff_h264_hl_decode_mb(h);
+ ff_h264_hl_decode_mb(h, sl);
h->mb_y--;
}
}
if (++h->mb_x >= h->mb_width) {
- loop_filter(h, lf_x_start, h->mb_x);
+ loop_filter(h, sl, lf_x_start, h->mb_x);
h->mb_x = lf_x_start = 0;
decode_finish_row(h);
++h->mb_y;
er_add_slice(h, h->resync_mb_x, h->resync_mb_y,
h->mb_x - 1, h->mb_y, ER_MB_END);
if (h->mb_x > lf_x_start)
- loop_filter(h, lf_x_start, h->mb_x);
+ loop_filter(h, sl, lf_x_start, h->mb_x);
return 0;
} else {
h->avctx->codec->capabilities & CODEC_CAP_HWACCEL_VDPAU)
return 0;
if (context_count == 1) {
- return decode_slice(avctx, &h);
+ return decode_slice(avctx, &h->slice_ctx[0]);
} else {
av_assert0(context_count > 0);
for (i = 1; i < context_count; i++) {
hx->x264_build = h->x264_build;
}
- avctx->execute(avctx, decode_slice, h->thread_context,
- NULL, context_count, sizeof(void *));
+ avctx->execute(avctx, decode_slice, h->slice_ctx,
+ NULL, context_count, sizeof(h->slice_ctx[0]));
/* pull back stuff from slices to master context */
hx = h->thread_context[context_count - 1];