From 5a41999d81459297183c4e27618e38f8ba719853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Raulet?= Date: Tue, 15 Jul 2014 00:16:53 +0200 Subject: [PATCH] hevc/rext: basic infrastructure for supporting range extension - support for 4:2:2 and 4:4:4 up to 12 bits - add a new profile for range extension (cherry picked from commit d3c067fa65bbc871758d28aa07f54123430ca346) Signed-off-by: Michael Niedermayer --- libavcodec/avcodec.h | 1 + libavcodec/hevc.c | 287 ++++++++++++++++++++++++--------- libavcodec/hevc.h | 25 ++- libavcodec/hevc_cabac.c | 8 +- libavcodec/hevc_filter.c | 70 ++++---- libavcodec/hevc_ps.c | 133 +++++++++++++-- libavcodec/hevcdsp.c | 7 + libavcodec/hevcdsp.h | 4 +- libavcodec/hevcdsp_template.c | 6 +- libavcodec/hevcpred.c | 7 + libavcodec/hevcpred_template.c | 9 +- 11 files changed, 422 insertions(+), 135 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 178349a542..93ba4d087c 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -2866,6 +2866,7 @@ typedef struct AVCodecContext { #define FF_PROFILE_HEVC_MAIN 1 #define FF_PROFILE_HEVC_MAIN_10 2 #define FF_PROFILE_HEVC_MAIN_STILL_PICTURE 3 +#define FF_PROFILE_HEVC_REXT 4 /** * level diff --git a/libavcodec/hevc.c b/libavcodec/hevc.c index d30e1fb3a4..75bdb80650 100644 --- a/libavcodec/hevc.c +++ b/libavcodec/hevc.c @@ -157,7 +157,7 @@ static void pred_weight_table(HEVCContext *s, GetBitContext *gb) s->sh.luma_offset_l0[i] = 0; } } - if (s->sps->chroma_format_idc != 0) { // FIXME: invert "if" and "for" + if (s->sps->chroma_format_idc != 0) { for (i = 0; i < s->sh.nb_refs[L0]; i++) chroma_weight_l0_flag[i] = get_bits1(gb); } else { @@ -761,7 +761,6 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry) HEVCLocalContext *lc = s->HEVClc; int sao_merge_left_flag = 0; int sao_merge_up_flag = 0; - int shift = s->sps->bit_depth - FFMIN(s->sps->bit_depth, 10); SAOParams *sao = &CTB(s->sao, rx, ry); int c_idx, i; @@ -778,6 +777,9 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry) } for (c_idx = 0; c_idx < 3; c_idx++) { + int log2_sao_offset_scale = c_idx == 0 ? s->pps->log2_sao_offset_scale_luma : + s->pps->log2_sao_offset_scale_chroma; + if (!s->sh.slice_sample_adaptive_offset_flag[c_idx]) { sao->type_idx[c_idx] = SAO_NOT_APPLIED; continue; @@ -813,13 +815,14 @@ static void hls_sao_param(HEVCContext *s, int rx, int ry) // Inferred parameters sao->offset_val[c_idx][0] = 0; for (i = 0; i < 4; i++) { - sao->offset_val[c_idx][i + 1] = sao->offset_abs[c_idx][i] << shift; + sao->offset_val[c_idx][i + 1] = sao->offset_abs[c_idx][i]; if (sao->type_idx[c_idx] == SAO_EDGE) { if (i > 1) sao->offset_val[c_idx][i + 1] = -sao->offset_val[c_idx][i + 1]; } else if (sao->offset_sign[c_idx][i]) { sao->offset_val[c_idx][i + 1] = -sao->offset_val[c_idx][i + 1]; } + sao->offset_val[c_idx][i + 1] <<= log2_sao_offset_scale; } } } @@ -833,31 +836,30 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, int trafo_depth, int blk_idx) { HEVCLocalContext *lc = s->HEVClc; + const int log2_trafo_size_c = log2_trafo_size - s->sps->hshift[1]; + int i; if (lc->cu.pred_mode == MODE_INTRA) { int trafo_size = 1 << log2_trafo_size; ff_hevc_set_neighbour_available(s, x0, y0, trafo_size, trafo_size); s->hpc.intra_pred[log2_trafo_size - 2](s, x0, y0, 0); - if (log2_trafo_size > 2) { - trafo_size = trafo_size << (s->sps->hshift[1] - 1); - ff_hevc_set_neighbour_available(s, x0, y0, trafo_size, trafo_size); - s->hpc.intra_pred[log2_trafo_size - 3](s, x0, y0, 1); - s->hpc.intra_pred[log2_trafo_size - 3](s, x0, y0, 2); - } else if (blk_idx == 3) { - trafo_size = trafo_size << s->sps->hshift[1]; - ff_hevc_set_neighbour_available(s, xBase, yBase, - trafo_size, trafo_size); - s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 1); - s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 2); - } } if (lc->tt.cbf_luma || SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0) || - SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0)) { + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) || + (s->sps->chroma_format_idc == 2 && + (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << log2_trafo_size_c)) || + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << log2_trafo_size_c))))) { int scan_idx = SCAN_DIAG; int scan_idx_c = SCAN_DIAG; + int cbf_luma = lc->tt.cbf_luma; + int cbf_chroma = SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0) || + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) || + (s->sps->chroma_format_idc == 2 && + (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << log2_trafo_size_c)) || + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << log2_trafo_size_c)))); if (s->pps->cu_qp_delta_enabled_flag && !lc->tu.is_cu_qp_delta_coded) { lc->tu.cu_qp_delta = ff_hevc_cu_qp_delta_abs(s); @@ -881,37 +883,102 @@ static int hls_transform_unit(HEVCContext *s, int x0, int y0, } if (lc->cu.pred_mode == MODE_INTRA && log2_trafo_size < 4) { - if (lc->tu.cur_intra_pred_mode >= 6 && - lc->tu.cur_intra_pred_mode <= 14) { + if (lc->tu.intra_pred_mode >= 6 && + lc->tu.intra_pred_mode <= 14) { scan_idx = SCAN_VERT; - } else if (lc->tu.cur_intra_pred_mode >= 22 && - lc->tu.cur_intra_pred_mode <= 30) { + } else if (lc->tu.intra_pred_mode >= 22 && + lc->tu.intra_pred_mode <= 30) { scan_idx = SCAN_HORIZ; } - if (lc->pu.intra_pred_mode_c >= 6 && - lc->pu.intra_pred_mode_c <= 14) { + if (lc->tu.intra_pred_mode_c >= 6 && + lc->tu.intra_pred_mode_c <= 14) { scan_idx_c = SCAN_VERT; - } else if (lc->pu.intra_pred_mode_c >= 22 && - lc->pu.intra_pred_mode_c <= 30) { + } else if (lc->tu.intra_pred_mode_c >= 22 && + lc->tu.intra_pred_mode_c <= 30) { scan_idx_c = SCAN_HORIZ; } } - if (lc->tt.cbf_luma) + + if (cbf_luma) ff_hevc_hls_residual_coding(s, x0, y0, log2_trafo_size, scan_idx, 0); - if (log2_trafo_size > 2) { - if (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0)) - ff_hevc_hls_residual_coding(s, x0, y0, log2_trafo_size - 1, scan_idx_c, 1); - if (SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0)) - ff_hevc_hls_residual_coding(s, x0, y0, log2_trafo_size - 1, scan_idx_c, 2); + 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]); + + 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); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 1); + } + 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); + } + + 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); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (i << log2_trafo_size_c), 2); + } + 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 (blk_idx == 3) { - if (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], xBase, yBase)) - ff_hevc_hls_residual_coding(s, xBase, yBase, log2_trafo_size, scan_idx_c, 1); - if (SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], xBase, yBase)) - ff_hevc_hls_residual_coding(s, xBase, yBase, log2_trafo_size, scan_idx_c, 2); + int trafo_size_h = 1 << (log2_trafo_size + 1); + int trafo_size_v = 1 << (log2_trafo_size + s->sps->vshift[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, xBase, yBase + (i << log2_trafo_size), + trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 1); + } + if (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], xBase, yBase + (i << log2_trafo_size_c))) + ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size), + log2_trafo_size, scan_idx_c, 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, xBase, yBase + (i << log2_trafo_size), + trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (i << log2_trafo_size), 2); + } + if (SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], xBase, yBase + (i << log2_trafo_size_c))) + ff_hevc_hls_residual_coding(s, xBase, yBase + (i << log2_trafo_size), + log2_trafo_size, scan_idx_c, 2); + } + } + } else if (lc->cu.pred_mode == MODE_INTRA) { + 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]); + ff_hevc_set_neighbour_available(s, x0, y0, trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 1); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0, 2); + if (s->sps->chroma_format_idc == 2) { + ff_hevc_set_neighbour_available(s, x0, y0 + (1 << log2_trafo_size_c), + trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 1); + s->hpc.intra_pred[log2_trafo_size_c - 2](s, x0, y0 + (1 << log2_trafo_size_c), 2); + } + } else if (blk_idx == 3) { + int trafo_size_h = 1 << (log2_trafo_size + 1); + int trafo_size_v = 1 << (log2_trafo_size + s->sps->vshift[1]); + ff_hevc_set_neighbour_available(s, xBase, yBase, + trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 1); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase, 2); + if (s->sps->chroma_format_idc == 2) { + ff_hevc_set_neighbour_available(s, xBase, yBase + (1 << (log2_trafo_size)), + trafo_size_h, trafo_size_v); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 1); + s->hpc.intra_pred[log2_trafo_size - 2](s, xBase, yBase + (1 << (log2_trafo_size)), 2); + } } } + return 0; } @@ -944,16 +1011,38 @@ static int hls_transform_tree(HEVCContext *s, int x0, int y0, SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth - 1], xBase, yBase); SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) = SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth - 1], xBase, yBase); + if (s->sps->chroma_format_idc == 2) { + int xBase_cb = xBase & ((1 << log2_trafo_size) - 1); + int yBase_cb = yBase & ((1 << log2_trafo_size) - 1); + SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = + SAMPLE_CBF2(lc->tt.cbf_cb[trafo_depth - 1], xBase_cb, yBase_cb + (1 << (log2_trafo_size))); + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = + SAMPLE_CBF2(lc->tt.cbf_cr[trafo_depth - 1], xBase_cb, yBase_cb + (1 << (log2_trafo_size))); + } } else { SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0) = SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) = 0; + if (s->sps->chroma_format_idc == 2) { + SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = 0; + } } if (lc->cu.intra_split_flag) { - if (trafo_depth == 1) - lc->tu.cur_intra_pred_mode = lc->pu.intra_pred_mode[blk_idx]; + if (trafo_depth == 1) { + lc->tu.intra_pred_mode = lc->pu.intra_pred_mode[blk_idx]; + if (s->sps->chroma_format_idc == 3) { + lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[blk_idx]; + lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[blk_idx]; + } else { + lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[0]; + lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[0]; + } + } } else { - lc->tu.cur_intra_pred_mode = lc->pu.intra_pred_mode[0]; + lc->tu.intra_pred_mode = lc->pu.intra_pred_mode[0]; + lc->tu.intra_pred_mode_c = lc->pu.intra_pred_mode_c[0]; + lc->tu.chroma_mode_c = lc->pu.chroma_mode_c[0]; } lc->tt.cbf_luma = 1; @@ -974,17 +1063,25 @@ static int hls_transform_tree(HEVCContext *s, int x0, int y0, lc->tt.inter_split_flag; } - if (log2_trafo_size > 2) { + if (log2_trafo_size > 2 || s->sps->chroma_format_idc == 3) { if (trafo_depth == 0 || SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth - 1], xBase, yBase)) { SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0) = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); + if (s->sps->chroma_format_idc == 2 && (!split_transform_flag || log2_trafo_size == 3)) { + SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = + ff_hevc_cbf_cb_cr_decode(s, trafo_depth); + } } if (trafo_depth == 0 || SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth - 1], xBase, yBase)) { SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) = ff_hevc_cbf_cb_cr_decode(s, trafo_depth); + if (s->sps->chroma_format_idc == 2 && (!split_transform_flag || log2_trafo_size == 3)) { + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) = + ff_hevc_cbf_cb_cr_decode(s, trafo_depth); + } } } @@ -1019,7 +1116,10 @@ static int hls_transform_tree(HEVCContext *s, int x0, int y0, if (lc->cu.pred_mode == MODE_INTRA || trafo_depth != 0 || SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0) || - SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0)) { + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0) || + (s->sps->chroma_format_idc == 2 && + (SAMPLE_CBF(lc->tt.cbf_cb[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1))) || + SAMPLE_CBF(lc->tt.cbf_cr[trafo_depth], x0, y0 + (1 << (log2_trafo_size - 1)))))) { lc->tt.cbf_luma = ff_hevc_cbf_luma_decode(s, trafo_depth); } @@ -1061,7 +1161,10 @@ static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size) int stride2 = s->frame->linesize[2]; uint8_t *dst2 = &s->frame->data[2][(y0 >> s->sps->vshift[2]) * stride2 + ((x0 >> s->sps->hshift[2]) << s->sps->pixel_shift)]; - int length = cb_size * cb_size * s->sps->pcm.bit_depth + ((cb_size * cb_size) >> 1) * s->sps->pcm.bit_depth_chroma; + int length = cb_size * cb_size * s->sps->pcm.bit_depth + + (((cb_size >> s->sps->hshift[1]) * (cb_size >> s->sps->vshift[1])) + + ((cb_size >> s->sps->hshift[2]) * (cb_size >> s->sps->vshift[2]))) * + s->sps->pcm.bit_depth_chroma; const uint8_t *pcm = skip_bytes(&lc->cc, (length + 7) >> 3); int ret; @@ -1072,9 +1175,15 @@ static int hls_pcm_sample(HEVCContext *s, int x0, int y0, int log2_cb_size) if (ret < 0) return ret; - s->hevcdsp.put_pcm(dst0, stride0, cb_size, &gb, s->sps->pcm.bit_depth); - s->hevcdsp.put_pcm(dst1, stride1, cb_size / 2, &gb, s->sps->pcm.bit_depth_chroma); - s->hevcdsp.put_pcm(dst2, stride2, cb_size / 2, &gb, s->sps->pcm.bit_depth_chroma); + s->hevcdsp.put_pcm(dst0, stride0, cb_size, cb_size, &gb, s->sps->pcm.bit_depth); + s->hevcdsp.put_pcm(dst1, stride1, + cb_size >> s->sps->hshift[1], + cb_size >> s->sps->vshift[1], + &gb, s->sps->pcm.bit_depth_chroma); + s->hevcdsp.put_pcm(dst2, stride2, + cb_size >> s->sps->hshift[2], + cb_size >> s->sps->vshift[2], + &gb, s->sps->pcm.bit_depth_chroma); return 0; } @@ -1415,7 +1524,7 @@ static void hevc_await_progress(HEVCContext *s, HEVCFrame *ref, static void hls_prediction_unit(HEVCContext *s, int x0, int y0, int nPbW, int nPbH, - int log2_cb_size, int partIdx) + int log2_cb_size, int partIdx, int idx) { #define POS(c_idx, x, y) \ &s->frame->data[c_idx][((y) >> s->sps->vshift[c_idx]) * s->frame->linesize[c_idx] + \ @@ -1521,7 +1630,7 @@ static void hls_prediction_unit(HEVCContext *s, int x0, int y0, x_pu = x0 >> s->sps->log2_min_pu_size; y_pu = y0 >> s->sps->log2_min_pu_size; - for(j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++) + for (j = 0; j < nPbH >> s->sps->log2_min_pu_size; j++) for (i = 0; i < nPbW >> s->sps->log2_min_pu_size; i++) tab_mvf[(y_pu + j) * min_pu_width + x_pu + i] = current_mv; } @@ -1689,6 +1798,10 @@ static av_always_inline void set_ct_depth(HEVCContext *s, int x0, int y0, ct_depth, length); } +static const uint8_t tab_mode_idx[] = { + 0, 1, 2, 2, 2, 2, 3, 5, 7, 8, 10, 12, 13, 15, 17, 18, 19, 20, + 21, 22, 23, 23, 24, 24, 25, 25, 26, 27, 27, 28, 28, 29, 29, 30, 31}; + static void intra_prediction_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) { @@ -1718,14 +1831,42 @@ static void intra_prediction_unit(HEVCContext *s, int x0, int y0, } } - chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s); - if (chroma_mode != 4) { - if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode]) - lc->pu.intra_pred_mode_c = 34; - else - lc->pu.intra_pred_mode_c = intra_chroma_table[chroma_mode]; - } else { - lc->pu.intra_pred_mode_c = lc->pu.intra_pred_mode[0]; + if (s->sps->chroma_format_idc == 3) { + for (i = 0; i < side; i++) { + for (j = 0; j < side; j++) { + lc->pu.chroma_mode_c[2 * i + j] = chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s); + if (chroma_mode != 4) { + if (lc->pu.intra_pred_mode[2 * i + j] == intra_chroma_table[chroma_mode]) + lc->pu.intra_pred_mode_c[2 * i + j] = 34; + else + lc->pu.intra_pred_mode_c[2 * i + j] = intra_chroma_table[chroma_mode]; + } else { + lc->pu.intra_pred_mode_c[2 * i + j] = lc->pu.intra_pred_mode[2 * i + j]; + } + } + } + } else if (s->sps->chroma_format_idc == 2) { + int mode_idx; + lc->pu.chroma_mode_c[0] = chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s); + if (chroma_mode != 4) { + if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode]) + mode_idx = 34; + else + mode_idx = intra_chroma_table[chroma_mode]; + } else { + mode_idx = lc->pu.intra_pred_mode[0]; + } + lc->pu.intra_pred_mode_c[0] = tab_mode_idx[mode_idx]; + } else if (s->sps->chroma_format_idc != 0) { + chroma_mode = ff_hevc_intra_chroma_pred_mode_decode(s); + if (chroma_mode != 4) { + if (lc->pu.intra_pred_mode[0] == intra_chroma_table[chroma_mode]) + lc->pu.intra_pred_mode_c[0] = 34; + else + lc->pu.intra_pred_mode_c[0] = intra_chroma_table[chroma_mode]; + } else { + lc->pu.intra_pred_mode_c[0] = lc->pu.intra_pred_mode[0]; + } } } @@ -1761,8 +1902,9 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) int min_cb_width = s->sps->min_cb_width; int x_cb = x0 >> log2_min_cb_size; int y_cb = y0 >> log2_min_cb_size; + int idx = log2_cb_size - 2; + int qp_block_mask = (1<<(s->sps->log2_ctb_size - s->pps->diff_cu_qp_delta_depth)) - 1; int x, y, ret; - int qp_block_mask = (1<<(s->sps->log2_ctb_size - s->pps->diff_cu_qp_delta_depth)) - 1; lc->cu.x = x0; lc->cu.y = y0; @@ -1794,7 +1936,7 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) } if (SAMPLE_CTB(s->skip_flag, x_cb, y_cb)) { - hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0); + hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx); intra_prediction_unit_default_value(s, x0, y0, log2_cb_size); if (!s->sh.disable_deblocking_filter_flag) @@ -1830,37 +1972,37 @@ static int hls_coding_unit(HEVCContext *s, int x0, int y0, int log2_cb_size) intra_prediction_unit_default_value(s, x0, y0, log2_cb_size); switch (lc->cu.part_mode) { case PART_2Nx2N: - hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0); + hls_prediction_unit(s, x0, y0, cb_size, cb_size, log2_cb_size, 0, idx); break; case PART_2NxN: - hls_prediction_unit(s, x0, y0, cb_size, cb_size / 2, log2_cb_size, 0); - hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size, cb_size / 2, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size, cb_size / 2, log2_cb_size, 0, idx); + hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size, cb_size / 2, log2_cb_size, 1, idx); break; case PART_Nx2N: - hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size, log2_cb_size, 0); - hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size, log2_cb_size, 0, idx - 1); + hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size, log2_cb_size, 1, idx - 1); break; case PART_2NxnU: - hls_prediction_unit(s, x0, y0, cb_size, cb_size / 4, log2_cb_size, 0); - hls_prediction_unit(s, x0, y0 + cb_size / 4, cb_size, cb_size * 3 / 4, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size, cb_size / 4, log2_cb_size, 0, idx); + hls_prediction_unit(s, x0, y0 + cb_size / 4, cb_size, cb_size * 3 / 4, log2_cb_size, 1, idx); break; case PART_2NxnD: - hls_prediction_unit(s, x0, y0, cb_size, cb_size * 3 / 4, log2_cb_size, 0); - hls_prediction_unit(s, x0, y0 + cb_size * 3 / 4, cb_size, cb_size / 4, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size, cb_size * 3 / 4, log2_cb_size, 0, idx); + hls_prediction_unit(s, x0, y0 + cb_size * 3 / 4, cb_size, cb_size / 4, log2_cb_size, 1, idx); break; case PART_nLx2N: - hls_prediction_unit(s, x0, y0, cb_size / 4, cb_size, log2_cb_size, 0); - hls_prediction_unit(s, x0 + cb_size / 4, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size / 4, cb_size, log2_cb_size, 0, idx - 2); + hls_prediction_unit(s, x0 + cb_size / 4, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 1, idx - 2); break; case PART_nRx2N: - hls_prediction_unit(s, x0, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 0); - hls_prediction_unit(s, x0 + cb_size * 3 / 4, y0, cb_size / 4, cb_size, log2_cb_size, 1); + hls_prediction_unit(s, x0, y0, cb_size * 3 / 4, cb_size, log2_cb_size, 0, idx - 2); + hls_prediction_unit(s, x0 + cb_size * 3 / 4, y0, cb_size / 4, cb_size, log2_cb_size, 1, idx - 2); break; case PART_NxN: - hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size / 2, log2_cb_size, 0); - hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size / 2, log2_cb_size, 1); - hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 2); - hls_prediction_unit(s, x0 + cb_size / 2, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 3); + hls_prediction_unit(s, x0, y0, cb_size / 2, cb_size / 2, log2_cb_size, 0, idx - 1); + hls_prediction_unit(s, x0 + cb_size / 2, y0, cb_size / 2, cb_size / 2, log2_cb_size, 1, idx - 1); + hls_prediction_unit(s, x0, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 2, idx - 1); + hls_prediction_unit(s, x0 + cb_size / 2, y0 + cb_size / 2, cb_size / 2, cb_size / 2, log2_cb_size, 3, idx - 1); break; } } @@ -3216,6 +3358,7 @@ static const AVProfile profiles[] = { { FF_PROFILE_HEVC_MAIN, "Main" }, { FF_PROFILE_HEVC_MAIN_10, "Main 10" }, { FF_PROFILE_HEVC_MAIN_STILL_PICTURE, "Main Still Picture" }, + { FF_PROFILE_HEVC_REXT, "Rext" }, { FF_PROFILE_UNKNOWN }, }; diff --git a/libavcodec/hevc.h b/libavcodec/hevc.h index 81753e2d25..8272502bff 100644 --- a/libavcodec/hevc.h +++ b/libavcodec/hevc.h @@ -83,6 +83,7 @@ #define SAMPLE(tab, x, y) ((tab)[(y) * s->sps->width + (x)]) #define SAMPLE_CTB(tab, x, y) ((tab)[(y) * min_cb_width + (x)]) #define SAMPLE_CBF(tab, x, y) ((tab)[((y) & ((1<nal_unit_type == NAL_IDR_W_RADL || (s)->nal_unit_type == NAL_IDR_N_LP) #define IS_BLA(s) ((s)->nal_unit_type == NAL_BLA_W_RADL || (s)->nal_unit_type == NAL_BLA_W_LP || \ @@ -457,6 +458,13 @@ typedef struct HEVCSPS { int max_transform_hierarchy_depth_inter; int max_transform_hierarchy_depth_intra; + int transform_skip_rotation_enabled_flag; + int transform_skip_context_enabled_flag; + int implicit_rdpcm_enabled_flag; + int explicit_rdpcm_enabled_flag; + int intra_smoothing_disabled_flag; + int persistent_rice_adaptation_enabled_flag; + ///< coded frame dimension in various units int width; int height; @@ -526,6 +534,15 @@ typedef struct HEVCPPS { int log2_parallel_merge_level; ///< log2_parallel_merge_level_minus2 + 2 int num_extra_slice_header_bits; uint8_t slice_header_extension_present_flag; + uint8_t log2_max_transform_skip_block_size; + uint8_t cross_component_prediction_enabled_flag; + uint8_t chroma_qp_offset_list_enabled_flag; + uint8_t diff_cu_chroma_qp_offset_depth; + uint8_t chroma_qp_offset_list_len_minus1; + int8_t cb_qp_offset_list[5]; + int8_t cr_qp_offset_list[5]; + uint8_t log2_sao_offset_scale_luma; + uint8_t log2_sao_offset_scale_chroma; // Inferred parameters unsigned int *column_width; ///< ColumnWidth @@ -661,7 +678,8 @@ typedef struct PredictionUnit { uint8_t intra_pred_mode[4]; Mv mvd; uint8_t merge_flag; - uint8_t intra_pred_mode_c; + uint8_t intra_pred_mode_c[4]; + uint8_t chroma_mode_c[4]; } PredictionUnit; typedef struct TransformTree { @@ -677,7 +695,9 @@ typedef struct TransformUnit { int cu_qp_delta; // Inferred parameters; - int cur_intra_pred_mode; + int intra_pred_mode; + int intra_pred_mode_c; + int chroma_mode_c; uint8_t is_cu_qp_delta_coded; } TransformUnit; @@ -968,7 +988,6 @@ 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_transform_skip_flag_decode(HEVCContext *s, int c_idx); /** * Get the number of candidate references for the current frame. diff --git a/libavcodec/hevc_cabac.c b/libavcodec/hevc_cabac.c index 3da2bf0617..d2b4f29b83 100644 --- a/libavcodec/hevc_cabac.c +++ b/libavcodec/hevc_cabac.c @@ -894,7 +894,7 @@ int ff_hevc_cbf_luma_decode(HEVCContext *s, int trafo_depth) return GET_CABAC(elem_offset[CBF_LUMA] + !trafo_depth); } -int ff_hevc_transform_skip_flag_decode(HEVCContext *s, int c_idx) +static int ff_hevc_transform_skip_flag_decode(HEVCContext *s, int c_idx) { return GET_CABAC(elem_offset[TRANSFORM_SKIP_FLAG] + !!c_idx); } @@ -1093,16 +1093,18 @@ void ff_hevc_hls_residual_coding(HEVCContext *s, int x0, int y0, // Derive QP for dequant if (!lc->cu.cu_transquant_bypass_flag) { static const int qp_c[] = { 29, 30, 31, 32, 33, 33, 34, 34, 35, 35, 36, 36, 37, 37 }; - static const uint8_t rem6[51 + 2 * 6 + 1] = { + static const uint8_t rem6[51 + 4 * 6 + 1] = { 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, + 4, 5, 0, 1, 2, 3, 4, 5, 0, 1 }; - static const uint8_t div6[51 + 2 * 6 + 1] = { + static const uint8_t div6[51 + 4 * 6 + 1] = { 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, + 10, 10, 11, 11, 11, 11, 11, 11, 12, 12 }; int qp_y = lc->qp_y; diff --git a/libavcodec/hevc_filter.c b/libavcodec/hevc_filter.c index d18e04f90c..0d3e238d69 100644 --- a/libavcodec/hevc_filter.c +++ b/libavcodec/hevc_filter.c @@ -61,12 +61,16 @@ static int chroma_tc(HEVCContext *s, int qp_y, int c_idx, int tc_offset) offset = s->pps->cr_qp_offset; qp_i = av_clip(qp_y + offset, 0, 57); - if (qp_i < 30) - qp = qp_i; - else if (qp_i > 43) - qp = qp_i - 6; - else - qp = qp_c[qp_i - 30]; + if (s->sps->chroma_format_idc == 1) { + if (qp_i < 30) + qp = qp_i; + else if (qp_i > 43) + qp = qp_i - 6; + else + qp = qp_c[qp_i - 30]; + } else { + qp = av_clip(qp_i, 0, 51); + } idxt = av_clip(qp + DEFAULT_INTRA_TC_OFFSET + tc_offset, 0, 53); return tctable[idxt]; @@ -327,6 +331,9 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) if (x0) { left_tc_offset = s->deblock[ctb - 1].tc_offset; left_beta_offset = s->deblock[ctb - 1].beta_offset; + } else { + left_tc_offset = 0; + left_beta_offset = 0; } x_end = x0 + ctb_size; @@ -371,22 +378,25 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) // vertical filtering chroma for (chroma = 1; chroma <= 2; chroma++) { - for (y = y0; y < y_end; y += 16) { - for (x = x0 ? x0 : 16; x < x_end; x += 16) { - const int bs0 = s->vertical_bs[(x >> 3) + (y >> 2) * s->bs_width]; - const int bs1 = s->vertical_bs[(x >> 3) + ((y + 8) >> 2) * s->bs_width]; + int h = 1 << s->sps->hshift[chroma]; + int v = 1 << s->sps->vshift[chroma]; + for (y = y0; y < y_end; y += (8 * v)) { + for (x = x0 ? x0 : 8 * h; x < x_end; x += (8 * h)) { + const int bs0 = s->vertical_bs[(x >> 3) + (y >> 2) * s->bs_width]; + const int bs1 = s->vertical_bs[(x >> 3) + ((y + (4 * v)) >> 2) * s->bs_width]; + if ((bs0 == 2) || (bs1 == 2)) { - const int qp0 = (get_qPy(s, x - 1, y) + get_qPy(s, x, y) + 1) >> 1; - const int qp1 = (get_qPy(s, x - 1, y + 8) + get_qPy(s, x, y + 8) + 1) >> 1; + const int qp0 = (get_qPy(s, x - 1, y) + get_qPy(s, x, y) + 1) >> 1; + const int qp1 = (get_qPy(s, x - 1, y + (4 * v)) + get_qPy(s, x, y + (4 * v)) + 1) >> 1; c_tc[0] = (bs0 == 2) ? chroma_tc(s, qp0, chroma, tc_offset) : 0; c_tc[1] = (bs1 == 2) ? chroma_tc(s, qp1, chroma, tc_offset) : 0; - src = &s->frame->data[chroma][y / 2 * s->frame->linesize[chroma] + ((x / 2) << s->sps->pixel_shift)]; + src = &s->frame->data[chroma][(y >> s->sps->vshift[chroma]) * s->frame->linesize[chroma] + ((x >> s->sps->hshift[chroma]) << s->sps->pixel_shift)]; if (pcmf) { no_p[0] = get_pcm(s, x - 1, y); - no_p[1] = get_pcm(s, x - 1, y + 8); + no_p[1] = get_pcm(s, x - 1, y + (4 * v)); no_q[0] = get_pcm(s, x, y); - no_q[1] = get_pcm(s, x, y + 8); + no_q[1] = get_pcm(s, x, y + (4 * v)); s->hevcdsp.hevc_v_loop_filter_chroma_c(src, s->frame->linesize[chroma], c_tc, no_p, no_q); @@ -436,35 +446,37 @@ static void deblocking_filter_CTB(HEVCContext *s, int x0, int y0) // horizontal filtering chroma for (chroma = 1; chroma <= 2; chroma++) { - for (y = y0 ? y0 : 16; y < y_end; y += 16) { - for (x = x0 - 8; x < x_end; x += 16) { + int h = 1 << s->sps->hshift[chroma]; + int v = 1 << s->sps->vshift[chroma]; + for (y = y0 ? y0 : 8 * v; y < y_end; y += (8 * v)) { + for (x = x0 - 8; x < x_end; x += (8 * h)) { int bs0, bs1; // to make sure no memory access over boundary when x = -8 // TODO: simplify with row based deblocking if (x < 0) { bs0 = 0; - bs1 = s->horizontal_bs[(x + 8 + y * s->bs_width) >> 2]; - } else if (x >= x_end - 8) { - bs0 = s->horizontal_bs[(x + y * s->bs_width) >> 2]; + bs1 = s->horizontal_bs[(x + (4 * h) + y * s->bs_width) >> 2]; + } else if (x >= x_end - 4 * h) { + bs0 = s->horizontal_bs[(x + y * s->bs_width) >> 2]; bs1 = 0; } else { - bs0 = s->horizontal_bs[(x + y * s->bs_width) >> 2]; - bs1 = s->horizontal_bs[(x + 8 + y * s->bs_width) >> 2]; + bs0 = s->horizontal_bs[(x + y * s->bs_width) >> 2]; + bs1 = s->horizontal_bs[(x + (4 * h) + y * s->bs_width) >> 2]; } if ((bs0 == 2) || (bs1 == 2)) { - const int qp0 = bs0 == 2 ? (get_qPy(s, x, y - 1) + get_qPy(s, x, y) + 1) >> 1 : 0; - const int qp1 = bs1 == 2 ? (get_qPy(s, x + 8, y - 1) + get_qPy(s, x + 8, y) + 1) >> 1 : 0; + const int qp0 = bs0 == 2 ? (get_qPy(s, x, y - 1) + get_qPy(s, x, y) + 1) >> 1 : 0; + const int qp1 = bs1 == 2 ? (get_qPy(s, x + (4 * h), y - 1) + get_qPy(s, x + (4 * h), y) + 1) >> 1 : 0; tc_offset = x >= x0 ? cur_tc_offset : left_tc_offset; c_tc[0] = bs0 == 2 ? chroma_tc(s, qp0, chroma, tc_offset) : 0; c_tc[1] = bs1 == 2 ? chroma_tc(s, qp1, chroma, cur_tc_offset) : 0; - src = &s->frame->data[chroma][y / 2 * s->frame->linesize[chroma] + ((x / 2) << s->sps->pixel_shift)]; + src = &s->frame->data[chroma][(y >> s->sps->vshift[1]) * s->frame->linesize[chroma] + ((x >> s->sps->hshift[1]) << s->sps->pixel_shift)]; if (pcmf) { - no_p[0] = get_pcm(s, x, y - 1); - no_p[1] = get_pcm(s, x + 8, y - 1); - no_q[0] = get_pcm(s, x, y); - no_q[1] = get_pcm(s, x + 8, y); + no_p[0] = get_pcm(s, x, y - 1); + no_p[1] = get_pcm(s, x + (4 * h), y - 1); + no_q[0] = get_pcm(s, x, y); + no_q[1] = get_pcm(s, x + (4 * h), y); s->hevcdsp.hevc_h_loop_filter_chroma_c(src, s->frame->linesize[chroma], c_tc, no_p, no_q); diff --git a/libavcodec/hevc_ps.c b/libavcodec/hevc_ps.c index dc843e89e0..ba166cb16d 100644 --- a/libavcodec/hevc_ps.c +++ b/libavcodec/hevc_ps.c @@ -207,6 +207,8 @@ static void decode_profile_tier_level(HEVCContext *s, PTLCommon *ptl) av_log(s->avctx, AV_LOG_DEBUG, "Main 10 profile bitstream\n"); else if (ptl->profile_idc == FF_PROFILE_HEVC_MAIN_STILL_PICTURE) av_log(s->avctx, AV_LOG_DEBUG, "Main Still Picture profile bitstream\n"); + else if (ptl->profile_idc == FF_PROFILE_HEVC_REXT) + av_log(s->avctx, AV_LOG_DEBUG, "Range Extension profile bitstream\n"); else av_log(s->avctx, AV_LOG_WARNING, "Unknown HEVC profile: %d\n", ptl->profile_idc); @@ -668,8 +670,8 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) } sps->chroma_format_idc = get_ue_golomb_long(gb); - if (sps->chroma_format_idc != 1) { - avpriv_report_missing_feature(s->avctx, "chroma_format_idc != 1\n"); + if (!(sps->chroma_format_idc == 1 || sps->chroma_format_idc == 2 || sps->chroma_format_idc == 3)) { + avpriv_report_missing_feature(s->avctx, "chroma_format_idc != {1, 2, 3}\n"); ret = AVERROR_PATCHWELCOME; goto err; } @@ -677,6 +679,9 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) if (sps->chroma_format_idc == 3) sps->separate_colour_plane_flag = get_bits1(gb); + if (sps->separate_colour_plane_flag) + sps->chroma_format_idc = 0; + sps->width = get_ue_golomb_long(gb); sps->height = get_ue_golomb_long(gb); if ((ret = av_image_check_size(sps->width, @@ -718,20 +723,30 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) goto err; } - if (sps->chroma_format_idc == 1) { - switch (sps->bit_depth) { - case 8: sps->pix_fmt = AV_PIX_FMT_YUV420P; break; - case 9: sps->pix_fmt = AV_PIX_FMT_YUV420P9; break; - case 10: sps->pix_fmt = AV_PIX_FMT_YUV420P10; break; - default: - av_log(s->avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", - sps->bit_depth); - ret = AVERROR_PATCHWELCOME; - goto err; - } - } else { + switch (sps->bit_depth) { + case 8: + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P; + break; + case 9: + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P9; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P9; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P9; + break; + case 10: + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P10; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P10; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P10; + break; + case 12: + if (sps->chroma_format_idc == 1) sps->pix_fmt = AV_PIX_FMT_YUV420P12; + if (sps->chroma_format_idc == 2) sps->pix_fmt = AV_PIX_FMT_YUV422P12; + if (sps->chroma_format_idc == 3) sps->pix_fmt = AV_PIX_FMT_YUV444P12; + break; + default: av_log(s->avctx, AV_LOG_ERROR, - "non-4:2:0 support is currently unspecified.\n"); + "4:2:0, 4:2:2, 4:4:4 supports are currently specified for 8, 10 and 12 bits.\n"); return AVERROR_PATCHWELCOME; } @@ -862,8 +877,42 @@ int ff_hevc_decode_nal_sps(HEVCContext *s) vui_present = get_bits1(gb); if (vui_present) decode_vui(s, sps); - skip_bits1(gb); // sps_extension_flag + if (get_bits1(gb)) { // sps_extension_flag + int sps_extension_flag[1]; + for (i = 0; i < 1; i++) + sps_extension_flag[i] = get_bits1(gb); + skip_bits(gb, 7); //sps_extension_7bits = get_bits(gb, 7); + if (sps_extension_flag[0]) { + int extended_precision_processing_flag; + int high_precision_offsets_enabled_flag; + int cabac_bypass_alignment_enabled_flag; + + sps->transform_skip_rotation_enabled_flag = get_bits1(gb); + sps->transform_skip_context_enabled_flag = get_bits1(gb); + sps->implicit_rdpcm_enabled_flag = get_bits1(gb); + + sps->explicit_rdpcm_enabled_flag = get_bits1(gb); + + extended_precision_processing_flag = get_bits1(gb); + if (extended_precision_processing_flag) + av_log(s->avctx, AV_LOG_WARNING, + "extended_precision_processing_flag not yet implemented\n"); + + sps->intra_smoothing_disabled_flag = get_bits1(gb); + high_precision_offsets_enabled_flag = get_bits1(gb); + if (high_precision_offsets_enabled_flag) + av_log(s->avctx, AV_LOG_WARNING, + "high_precision_offsets_enabled_flag not yet implemented\n"); + + sps->persistent_rice_adaptation_enabled_flag = get_bits1(gb); + + cabac_bypass_alignment_enabled_flag = get_bits1(gb); + if (cabac_bypass_alignment_enabled_flag) + av_log(s->avctx, AV_LOG_WARNING, + "cabac_bypass_alignment_enabled_flag not yet implemented\n"); + } + } if (s->apply_defdispwin) { sps->output_window.left_offset += sps->vui.def_disp_win.left_offset; sps->output_window.right_offset += sps->vui.def_disp_win.right_offset; @@ -997,6 +1046,46 @@ static void hevc_pps_free(void *opaque, uint8_t *data) av_freep(&pps); } +static int pps_range_extensions(HEVCContext *s, HEVCPPS *pps, HEVCSPS *sps) { + GetBitContext *gb = &s->HEVClc->gb; + int i; + + if (pps->transform_skip_enabled_flag) { + pps->log2_max_transform_skip_block_size = get_ue_golomb_long(gb) + 2; + } + pps->cross_component_prediction_enabled_flag = get_bits1(gb); + if (pps->cross_component_prediction_enabled_flag) { + av_log(s->avctx, AV_LOG_WARNING, + "cross_component_prediction_enabled_flag is not yet implemented.\n"); + } + pps->chroma_qp_offset_list_enabled_flag = get_bits1(gb); + if (pps->chroma_qp_offset_list_enabled_flag) { + pps->diff_cu_chroma_qp_offset_depth = get_ue_golomb_long(gb); + pps->chroma_qp_offset_list_len_minus1 = get_ue_golomb_long(gb); + if (pps->chroma_qp_offset_list_len_minus1 && pps->chroma_qp_offset_list_len_minus1 >= 5) { + av_log(s->avctx, AV_LOG_ERROR, + "chroma_qp_offset_list_len_minus1 shall be in the range [0, 5].\n"); + return AVERROR_INVALIDDATA; + } + for (i = 0; i <= pps->chroma_qp_offset_list_len_minus1; i++) { + pps->cb_qp_offset_list[i] = get_se_golomb_long(gb); + if (pps->cb_qp_offset_list[i]) { + av_log(s->avctx, AV_LOG_WARNING, + "cb_qp_offset_list not tested yet.\n"); + } + pps->cr_qp_offset_list[i] = get_se_golomb_long(gb); + if (pps->cr_qp_offset_list[i]) { + av_log(s->avctx, AV_LOG_WARNING, + "cb_qp_offset_list not tested yet.\n"); + } + } + } + pps->log2_sao_offset_scale_luma = get_ue_golomb_long(gb); + pps->log2_sao_offset_scale_chroma = get_ue_golomb_long(gb); + + return(0); +} + int ff_hevc_decode_nal_pps(HEVCContext *s) { GetBitContext *gb = &s->HEVClc->gb; @@ -1030,6 +1119,7 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) pps->disable_dbf = 0; pps->beta_offset = 0; pps->tc_offset = 0; + pps->log2_max_transform_skip_block_size = 2; // Coded parameters pps_id = get_ue_golomb_long(gb); @@ -1190,7 +1280,16 @@ int ff_hevc_decode_nal_pps(HEVCContext *s) } pps->slice_header_extension_present_flag = get_bits1(gb); - skip_bits1(gb); // pps_extension_flag + + if (get_bits1(gb)) { // pps_extension_present_flag + int pps_range_extensions_flag = get_bits1(gb); + /* int pps_extension_7bits = */ get_bits(gb, 7); + if (sps->ptl.general_ptl.profile_idc == FF_PROFILE_HEVC_REXT && pps_range_extensions_flag) { + av_log(s->avctx, AV_LOG_ERROR, + "PPS extension flag is partially implemented.\n"); + pps_range_extensions(s, pps, sps); + } + } // Inferred parameters pps->col_bd = av_malloc_array(pps->num_tile_columns + 1, sizeof(*pps->col_bd)); diff --git a/libavcodec/hevcdsp.c b/libavcodec/hevcdsp.c index eeea542691..a22a3a5cfa 100644 --- a/libavcodec/hevcdsp.c +++ b/libavcodec/hevcdsp.c @@ -119,6 +119,10 @@ DECLARE_ALIGNED(16, const int8_t, ff_hevc_qpel_filters[3][16]) = { #include "hevcdsp_template.c" #undef BIT_DEPTH +#define BIT_DEPTH 12 +#include "hevcdsp_template.c" +#undef BIT_DEPTH + void ff_hevc_dsp_init(HEVCDSPContext *hevcdsp, int bit_depth) { #undef FUNC @@ -235,6 +239,9 @@ int i = 0; case 10: HEVC_DSP(10); break; + case 12: + HEVC_DSP(12); + break; default: HEVC_DSP(8); break; diff --git a/libavcodec/hevcdsp.h b/libavcodec/hevcdsp.h index e17ee7b4ce..25480646ad 100644 --- a/libavcodec/hevcdsp.h +++ b/libavcodec/hevcdsp.h @@ -41,8 +41,8 @@ typedef struct SAOParams { } SAOParams; typedef struct HEVCDSPContext { - void (*put_pcm)(uint8_t *dst, ptrdiff_t stride, int size, - GetBitContext *gb, int pcm_bit_depth); + void (*put_pcm)(uint8_t *_dst, ptrdiff_t _stride, int width, int height, + struct GetBitContext *gb, int pcm_bit_depth); void (*transform_add[4])(uint8_t *_dst, int16_t *coeffs, ptrdiff_t _stride); diff --git a/libavcodec/hevcdsp_template.c b/libavcodec/hevcdsp_template.c index b08050b67a..cceba2453d 100644 --- a/libavcodec/hevcdsp_template.c +++ b/libavcodec/hevcdsp_template.c @@ -27,7 +27,7 @@ #include "hevcdsp.h" -static void FUNC(put_pcm)(uint8_t *_dst, ptrdiff_t stride, int size, +static void FUNC(put_pcm)(uint8_t *_dst, ptrdiff_t stride, int width, int height, GetBitContext *gb, int pcm_bit_depth) { int x, y; @@ -35,8 +35,8 @@ static void FUNC(put_pcm)(uint8_t *_dst, ptrdiff_t stride, int size, stride /= sizeof(pixel); - for (y = 0; y < size; y++) { - for (x = 0; x < size; x++) + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) dst[x] = get_bits(gb, pcm_bit_depth) << (BIT_DEPTH - pcm_bit_depth); dst += stride; } diff --git a/libavcodec/hevcpred.c b/libavcodec/hevcpred.c index 4dfbfbfed0..4598229b36 100644 --- a/libavcodec/hevcpred.c +++ b/libavcodec/hevcpred.c @@ -36,6 +36,10 @@ #include "hevcpred_template.c" #undef BIT_DEPTH +#define BIT_DEPTH 12 +#include "hevcpred_template.c" +#undef BIT_DEPTH + void ff_hevc_pred_init(HEVCPredContext *hpc, int bit_depth) { #undef FUNC @@ -63,6 +67,9 @@ void ff_hevc_pred_init(HEVCPredContext *hpc, int bit_depth) case 10: HEVC_PRED(10); break; + case 12: + HEVC_PRED(12); + break; default: HEVC_PRED(8); break; diff --git a/libavcodec/hevcpred_template.c b/libavcodec/hevcpred_template.c index 75cff8675b..81242304dd 100644 --- a/libavcodec/hevcpred_template.c +++ b/libavcodec/hevcpred_template.c @@ -91,8 +91,8 @@ do { \ int min_pu_width = s->sps->min_pu_width; - enum IntraPredMode mode = c_idx ? lc->pu.intra_pred_mode_c : - lc->tu.cur_intra_pred_mode; + enum IntraPredMode mode = c_idx ? lc->tu.intra_pred_mode_c : + lc->tu.intra_pred_mode; pixel4 a; pixel left_array[2 * MAX_TB_SIZE + 1]; pixel filtered_left_array[2 * MAX_TB_SIZE + 1]; @@ -207,7 +207,6 @@ do { \ j++; EXTEND_LEFT_CIP(top, j, j + 1); left[-1] = top[-1]; - j = 0; } } else { j = 0; @@ -221,7 +220,6 @@ do { \ top[-1] = top[0]; } left[-1] = top[-1]; - j = 0; } left[-1] = top[-1]; if (cand_bottom_left || cand_left) { @@ -238,7 +236,6 @@ do { \ if (!IS_INTRA(-1, - 1)) left[-1] = left[0]; } else if (x0 == 0) { - a = PIXEL_SPLAT_X4(left[size_max_y - 1]); EXTEND(left, 0, size_max_y); } else { a = PIXEL_SPLAT_X4(left[size_max_y - 1]); @@ -290,7 +287,7 @@ do { \ top[-1] = left[-1]; // Filtering process - if (c_idx == 0) { + if (!s->sps->intra_smoothing_disabled_flag && (c_idx == 0 || s->sps->chroma_format_idc == 3)) { if (mode != INTRA_DC && size != 4){ int intra_hor_ver_dist_thresh[] = { 7, 1, 0 }; int min_dist_vert_hor = FFMIN(FFABS((int)(mode - 26U)),