Commit 453f8eae authored by Mickaël Raulet's avatar Mickaël Raulet Committed by Michael Niedermayer

hevc/rext: add support for Range extension tools

SPS features/flags:
- transform_skip_rotation_enabled_flag
- transform_skip_context_enabled_flag
- implicit_rdpcm_enabled_flag
- explicit_rdpcm_enabled_flag
- intra_smoothing_disabled_flag
- persistent_rice_adaptation_enabled_flag

PPS features/flags:
- log2_max_transform_skip_block_size
- cross_component_prediction_enabled_flag
- chroma_qp_offset_list_enabled_flag
- diff_cu_chroma_qp_offset_depth
- chroma_qp_offset_list_len_minus1
- cb_qp_offset_list
- cr_qp_offset_list
- log2_sao_offset_scale_luma
- log2_sao_offset_scale_chroma
(cherry picked from commit 005294c5b939a23099871c6130c8a7cc331f73ee)
Signed-off-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parent 5a41999d
......@@ -628,6 +628,11 @@ static int hls_slice_header(HEVCContext *s)
sh->slice_cr_qp_offset = 0;
}
if (s->pps->chroma_qp_offset_list_enabled_flag)
sh->cu_chroma_qp_offset_enabled_flag = get_bits1(gb);
else
sh->cu_chroma_qp_offset_enabled_flag = 0;
if (s->pps->deblocking_filter_control_present_flag) {
int deblocking_filter_override_flag = 0;
......@@ -738,6 +743,8 @@ static int hls_slice_header(HEVCContext *s)
s->HEVClc->qp_y = s->sh.slice_qp;
s->slice_initialized = 1;
s->HEVClc->tu.cu_qp_offset_cb = 0;
s->HEVClc->tu.cu_qp_offset_cr = 0;
return 0;
}
......@@ -830,6 +837,22 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry)
#undef SET_SAO
#undef CTB
static int hls_cross_component_pred(HEVCContext *s, int idx) {
HEVCLocalContext *lc = s->HEVClc;
int log2_res_scale_abs_plus1 = ff_hevc_log2_res_scale_abs(s, idx);
if (log2_res_scale_abs_plus1 != 0) {
int res_scale_sign_flag = ff_hevc_res_scale_sign_flag(s, idx);
lc->tu.res_scale_val = (1 << (log2_res_scale_abs_plus1 - 1)) *
(1 - 2 * res_scale_sign_flag);
} else {
lc->tu.res_scale_val = 0;
}
return 0;
}
static int hls_transform_unit(HEVCContext *s, int x0, int y0,
int xBase, int yBase, int cb_xBase, int cb_yBase,
int log2_cb_size, int log2_trafo_size,
......@@ -882,6 +905,25 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
ff_hevc_set_qPy(s, x0, y0, cb_xBase, cb_yBase, log2_cb_size);
}
if (s->sh.cu_chroma_qp_offset_enabled_flag && cbf_chroma &&
!lc->cu.cu_transquant_bypass_flag && !lc->tu.is_cu_chroma_qp_offset_coded) {
int cu_chroma_qp_offset_flag = ff_hevc_cu_chroma_qp_offset_flag(s);
if (cu_chroma_qp_offset_flag) {
int cu_chroma_qp_offset_idx = 0;
if (s->pps->chroma_qp_offset_list_len_minus1 > 0) {
cu_chroma_qp_offset_idx = ff_hevc_cu_chroma_qp_offset_idx(s);
av_log(s->avctx, AV_LOG_ERROR,
"cu_chroma_qp_offset_idx not yet tested.\n");
}
lc->tu.cu_qp_offset_cb = s->pps->cb_qp_offset_list[cu_chroma_qp_offset_idx];
lc->tu.cu_qp_offset_cr = s->pps->cr_qp_offset_list[cu_chroma_qp_offset_idx];
} else {
lc->tu.cu_qp_offset_cb = 0;
lc->tu.cu_qp_offset_cr = 0;
}
lc->tu.is_cu_chroma_qp_offset_coded = 1;
}
if (lc->cu.pred_mode == MODE_INTRA && log2_trafo_size < 4) {
if (lc->tu.intra_pred_mode >= 6 &&
lc->tu.intra_pred_mode <= 14) {
......@@ -900,13 +942,20 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
}
}
lc->tu.cross_pf = 0;
if (cbf_luma)
ff_hevc_hls_residual_coding(s, x0, y0, log2_trafo_size, scan_idx, 0);
if (log2_trafo_size > 2 || s->sps->chroma_format_idc == 3) {
int trafo_size_h = 1 << (log2_trafo_size_c + s->sps->hshift[1]);
int trafo_size_v = 1 << (log2_trafo_size_c + s->sps->vshift[1]);
lc->tu.cross_pf = (s->pps->cross_component_prediction_enabled_flag && cbf_luma &&
(lc->cu.pred_mode == MODE_INTER ||
(lc->tu.chroma_mode_c == 4)));
if (lc->tu.cross_pf) {
hls_cross_component_pred(s, 0);
}
for (i = 0; i < (s->sps->chroma_format_idc == 2 ? 2 : 1); i++) {
if (lc->cu.pred_mode == MODE_INTRA) {
ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v);
......@@ -915,8 +964,27 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
if (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (i << log2_trafo_size_c)))
ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c),
log2_trafo_size_c, scan_idx_c, 1);
else
if (lc->tu.cross_pf) {
ptrdiff_t stride = s->frame->linesize[1];
int hshift = s->sps->hshift[1];
int vshift = s->sps->vshift[1];
int16_t *coeffs_y = lc->tu.coeffs[0];
int16_t *coeffs = lc->tu.coeffs[1];
int size = 1 << log2_trafo_size_c;
uint8_t *dst = &s->frame->data[1][(y0 >> vshift) * stride +
((x0 >> hshift) << s->sps->pixel_shift)];
for (i = 0; i < (size * size); i++) {
coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3);
}
s->hevcdsp.transform_add[log2_trafo_size-2](dst, coeffs, stride);
}
}
if (lc->tu.cross_pf) {
hls_cross_component_pred(s, 1);
}
for (i = 0; i < (s->sps->chroma_format_idc == 2 ? 2 : 1); i++) {
if (lc->cu.pred_mode == MODE_INTRA) {
ff_hevc_set_neighbour_available(s, x0, y0 + (i << log2_trafo_size_c), trafo_size_h, trafo_size_v);
......@@ -925,6 +993,22 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0,
if (SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (i << log2_trafo_size_c)))
ff_hevc_hls_residual_coding(s, x0, y0 + (i << log2_trafo_size_c),
log2_trafo_size_c, scan_idx_c, 2);
else
if (lc->tu.cross_pf) {
ptrdiff_t stride = s->frame->linesize[2];
int hshift = s->sps->hshift[2];
int vshift = s->sps->vshift[2];
int16_t *coeffs_y = lc->tu.coeffs[0];
int16_t *coeffs = lc->tu.coeffs[1];
int size = 1 << log2_trafo_size_c;
uint8_t *dst = &s->frame->data[2][(y0 >> vshift) * stride +
((x0 >> hshift) << s->sps->pixel_shift)];
for (i = 0; i < (size * size); i++) {
coeffs[i] = ((lc->tu.res_scale_val * coeffs_y[i]) >> 3);
}
s->hevcdsp.transform_add[log2_trafo_size-2](dst, coeffs, stride);
}
}
} else if (blk_idx == 3) {
int trafo_size_h = 1 << (log2_trafo_size + 1);
......@@ -2070,6 +2154,11 @@ static int hls_coding_quadtree(HEVCContext *s, int x0, int y0,
lc->tu.cu_qp_delta = 0;
}
if (s->sh.cu_chroma_qp_offset_enabled_flag &&
log2_cb_size >= s->sps->log2_ctb_size - s->pps->diff_cu_chroma_qp_offset_depth) {
lc->tu.is_cu_chroma_qp_offset_coded = 0;
}
if (split_cu_flag) {
const int cb_size_split = cb_size >> 1;
const int x1 = x0 + cb_size_split;
......
......@@ -602,6 +602,8 @@ typedef struct SliceHeader {
int slice_cb_qp_offset;
int slice_cr_qp_offset;
uint8_t cu_chroma_qp_offset_enabled_flag;
int beta_offset; ///< beta_offset_div2 * 2
int tc_offset; ///< tc_offset_div2 * 2
......@@ -692,13 +694,20 @@ typedef struct TransformTree {
} TransformTree;
typedef struct TransformUnit {
DECLARE_ALIGNED(32, int16_t, coeffs[2][MAX_TB_SIZE * MAX_TB_SIZE]);
int cu_qp_delta;
int res_scale_val;
// Inferred parameters;
int intra_pred_mode;
int intra_pred_mode_c;
int chroma_mode_c;
uint8_t is_cu_qp_delta_coded;
uint8_t is_cu_chroma_qp_offset_coded;
int8_t cu_qp_offset_cb;
int8_t cu_qp_offset_cr;
uint8_t cross_pf;
} TransformUnit;
typedef struct DBParams {
......@@ -750,6 +759,8 @@ typedef struct HEVCLocalContext {
DECLARE_ALIGNED(16, int16_t, mc_buffer[(MAX_PB_SIZE + 7) * MAX_PB_SIZE]);
uint8_t cabac_state[HEVC_CONTEXTS];
uint8_t stat_coeff[4];
uint8_t first_qp_group;
GetBitContext gb;
......@@ -988,6 +999,8 @@ int ff_hevc_no_residual_syntax_flag_decode(HEVCContext *s);
int ff_hevc_split_transform_flag_decode(HEVCContext *s, int log2_trafo_size);
int ff_hevc_cbf_cb_cr_decode(HEVCContext *s, int trafo_depth);
int ff_hevc_cbf_luma_decode(HEVCContext *s, int trafo_depth);
int ff_hevc_log2_res_scale_abs(HEVCContext *s, int idx);
int ff_hevc_res_scale_sign_flag(HEVCContext *s, int idx);
/**
* Get the number of candidate references for the current frame.
......@@ -1019,6 +1032,8 @@ void ff_hevc_deblocking_boundary_strengths(HEVCContext *s, int x0, int y0,
int log2_trafo_size);
int ff_hevc_cu_qp_delta_sign_flag(HEVCContext *s);
int ff_hevc_cu_qp_delta_abs(HEVCContext *s);
int ff_hevc_cu_chroma_qp_offset_flag(HEVCContext *s);
int ff_hevc_cu_chroma_qp_offset_idx(HEVCContext *s);
void ff_hevc_hls_filter(HEVCContext *s, int x, int y, int ctb_size);
void ff_hevc_hls_filters(HEVCContext *s, int x_ctb, int y_ctb, int ctb_size);
void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0,
......
This diff is collapsed.
......@@ -200,6 +200,7 @@ void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth)
hevcdsp->transform_add[2] = FUNC(transform_add16x16, depth); \
hevcdsp->transform_add[3] = FUNC(transform_add32x32, depth); \
hevcdsp->transform_skip = FUNC(transform_skip, depth); \
hevcdsp->transform_rdpcm = FUNC(transform_rdpcm, depth); \
hevcdsp->idct_4x4_luma = FUNC(transform_4x4_luma, depth); \
hevcdsp->idct[0] = FUNC(idct_4x4, depth); \
hevcdsp->idct[1] = FUNC(idct_8x8, depth); \
......
......@@ -48,6 +48,8 @@ typedef struct HEVCDSPContext {
void (*transform_skip)(int16_t *coeffs, int16_t log2_size);
void (*transform_rdpcm)(int16_t *coeffs, int16_t log2_size, int mode);
void (*idct_4x4_luma)(int16_t *coeffs);
void (*idct[4])(int16_t *coeffs, int col_limit);
......
......@@ -110,6 +110,29 @@ static void FUNC(transform_add32x32)(uint8_t *_dst, int16_t *coeffs,
}
}
static void FUNC(transform_rdpcm)(int16_t *_coeffs, int16_t log2_size, int mode)
{
int16_t *coeffs = (int16_t *) _coeffs;
int x, y;
int size = 1 << log2_size;
if (mode) {
coeffs += size;
for (y = 0; y < size - 1; y++) {
for (x = 0; x < size; x++)
coeffs[x] += coeffs[x - size];
coeffs += size;
}
} else {
for (y = 0; y < size; y++) {
for (x = 1; x < size; x++)
coeffs[x] += coeffs[x - 1];
coeffs += size;
}
}
}
static void FUNC(transform_skip)(int16_t *_coeffs, int16_t log2_size)
{
int shift = 15 - BIT_DEPTH - log2_size;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment