diff options
author | Mickaƫl Raulet <mraulet@insa-rennes.fr> | 2014-07-15 00:20:22 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2014-07-15 14:08:20 +0200 |
commit | 453f8eaee213a1940c5d5dda7cb1bcd148e2c183 (patch) | |
tree | 81a50e2209a60e5d5e5cad9016a5fd20e5079fb6 /libavcodec/hevc.c | |
parent | 5a41999d81459297183c4e27618e38f8ba719853 (diff) |
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: Michael Niedermayer <michaelni@gmx.at>
Diffstat (limited to 'libavcodec/hevc.c')
-rw-r--r-- | libavcodec/hevc.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index 75bdb80650..17f72524e2 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -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; |