From aabf6ca3ee92c8d3ec3cc5199fdc32f49e8fca6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Tue, 9 Aug 2016 22:01:51 +0900 Subject: [PATCH 1/3] Extract encoding code from encoderstate.c Moves functions kvz_encode_coding_tree and kvz_encode_coeff_nxn from encoderstate.c to encode_coding_tree.c. --- build/kvazaar_lib/kvazaar_lib.vcxproj | 4 +- build/kvazaar_lib/kvazaar_lib.vcxproj.filters | 8 +- src/Makefile.am | 2 + src/encode_coding_tree.c | 1082 +++++++++++++++++ src/encode_coding_tree.h | 44 + src/encoderstate.c | 1045 +--------------- src/encoderstate.h | 14 - src/rdo.c | 1 + 8 files changed, 1140 insertions(+), 1060 deletions(-) create mode 100644 src/encode_coding_tree.c create mode 100644 src/encode_coding_tree.h diff --git a/build/kvazaar_lib/kvazaar_lib.vcxproj b/build/kvazaar_lib/kvazaar_lib.vcxproj index 408d93eb..d8976a00 100644 --- a/build/kvazaar_lib/kvazaar_lib.vcxproj +++ b/build/kvazaar_lib/kvazaar_lib.vcxproj @@ -139,6 +139,7 @@ + @@ -217,6 +218,7 @@ + @@ -294,4 +296,4 @@ - \ No newline at end of file + diff --git a/build/kvazaar_lib/kvazaar_lib.vcxproj.filters b/build/kvazaar_lib/kvazaar_lib.vcxproj.filters index 496e9f3d..08fce24d 100644 --- a/build/kvazaar_lib/kvazaar_lib.vcxproj.filters +++ b/build/kvazaar_lib/kvazaar_lib.vcxproj.filters @@ -207,6 +207,9 @@ Bitstream + + Bitstream + Optimization\strategies @@ -393,6 +396,9 @@ Bitstream + + Bitstream + Optimization\strategies @@ -417,4 +423,4 @@ Optimization\strategies\x86_asm - \ No newline at end of file + diff --git a/src/Makefile.am b/src/Makefile.am index b4ae85df..3e4f9aa9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -56,6 +56,8 @@ libkvazaar_la_SOURCES = \ encoder_state-ctors_dtors.h \ encoder_state-geometry.c \ encoder_state-geometry.h \ + encode_coding_tree.c \ + encode_coding_tree.h \ filter.c \ filter.h \ global.h \ diff --git a/src/encode_coding_tree.c b/src/encode_coding_tree.c new file mode 100644 index 00000000..9167a5a6 --- /dev/null +++ b/src/encode_coding_tree.c @@ -0,0 +1,1082 @@ +/***************************************************************************** + * This file is part of Kvazaar HEVC encoder. + * + * Copyright (C) 2013-2015 Tampere University of Technology and others (see + * COPYING file). + * + * Kvazaar is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * Kvazaar is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with Kvazaar. If not, see . + ****************************************************************************/ + +#include "encode_coding_tree.h" + +#include "cabac.h" +#include "context.h" +#include "cu.h" +#include "encoder.h" +#include "extras/crypto.h" +#include "imagelist.h" +#include "inter.h" +#include "intra.h" +#include "kvazaar.h" +#include "kvz_math.h" +#include "tables.h" +#include "videoframe.h" + +/** + * \brief Encode (X,Y) position of the last significant coefficient + * + * \param lastpos_x X component of last coefficient + * \param lastpos_y Y component of last coefficient + * \param width Block width + * \param height Block height + * \param type plane type / luminance or chrominance + * \param scan scan type (diag, hor, ver) + * + * This method encodes the X and Y component within a block of the last + * significant coefficient. + */ +static void encode_last_significant_xy(encoder_state_t * const state, + uint8_t lastpos_x, uint8_t lastpos_y, + uint8_t width, uint8_t height, + uint8_t type, uint8_t scan) +{ + cabac_data_t * const cabac = &state->cabac; + + const int index = kvz_math_floor_log2(width) - 2; + uint8_t ctx_offset = type ? 0 : (index * 3 + (index + 1) / 4); + uint8_t shift = type ? index : (index + 3) / 4; + + cabac_ctx_t *base_ctx_x = (type ? cabac->ctx.cu_ctx_last_x_chroma : cabac->ctx.cu_ctx_last_x_luma); + cabac_ctx_t *base_ctx_y = (type ? cabac->ctx.cu_ctx_last_y_chroma : cabac->ctx.cu_ctx_last_y_luma); + + if (scan == SCAN_VER) { + SWAP(lastpos_x, lastpos_y, uint8_t); + } + + const int group_idx_x = g_group_idx[lastpos_x]; + const int group_idx_y = g_group_idx[lastpos_y]; + + // x prefix + for (int last_x = 0; last_x < group_idx_x; last_x++) { + cabac->cur_ctx = &base_ctx_x[ctx_offset + (last_x >> shift)]; + CABAC_BIN(cabac, 1, "last_sig_coeff_x_prefix"); + } + if (group_idx_x < g_group_idx[width - 1]) { + cabac->cur_ctx = &base_ctx_x[ctx_offset + (group_idx_x >> shift)]; + CABAC_BIN(cabac, 0, "last_sig_coeff_x_prefix"); + } + + // y prefix + for (int last_y = 0; last_y < group_idx_y; last_y++) { + cabac->cur_ctx = &base_ctx_y[ctx_offset + (last_y >> shift)]; + CABAC_BIN(cabac, 1, "last_sig_coeff_y_prefix"); + } + if (group_idx_y < g_group_idx[height - 1]) { + cabac->cur_ctx = &base_ctx_y[ctx_offset + (group_idx_y >> shift)]; + CABAC_BIN(cabac, 0, "last_sig_coeff_y_prefix"); + } + + // last_sig_coeff_x_suffix + if (group_idx_x > 3) { + const int suffix = lastpos_x - g_min_in_group[group_idx_x]; + const int bits = (group_idx_x - 2) / 2; + CABAC_BINS_EP(cabac, suffix, bits, "last_sig_coeff_x_suffix"); + } + + // last_sig_coeff_y_suffix + if (group_idx_y > 3) { + const int suffix = lastpos_y - g_min_in_group[group_idx_y]; + const int bits = (group_idx_y - 2) / 2; + CABAC_BINS_EP(cabac, suffix, bits, "last_sig_coeff_y_suffix"); + } +} + +void kvz_encode_coeff_nxn(encoder_state_t * const state, + coeff_t *coeff, + uint8_t width, + uint8_t type, + int8_t scan_mode, + int8_t tr_skip) +{ + const encoder_control_t * const encoder = state->encoder_control; + cabac_data_t * const cabac = &state->cabac; + int c1 = 1; + uint8_t last_coeff_x = 0; + uint8_t last_coeff_y = 0; + int32_t i; + uint32_t sig_coeffgroup_flag[8 * 8] = { 0 }; + + int8_t be_valid = encoder->sign_hiding; + int32_t scan_pos_sig; + uint32_t go_rice_param = 0; + uint32_t blk_pos, pos_y, pos_x, sig, ctx_sig; + + // CONSTANTS + const uint32_t num_blk_side = width >> TR_MIN_LOG2_SIZE; + const uint32_t log2_block_size = kvz_g_convert_to_bit[width] + 2; + const uint32_t *scan = + kvz_g_sig_last_scan[scan_mode][log2_block_size - 1]; + const uint32_t *scan_cg = g_sig_last_scan_cg[log2_block_size - 2][scan_mode]; + + // Init base contexts according to block type + cabac_ctx_t *base_coeff_group_ctx = &(cabac->ctx.cu_sig_coeff_group_model[type]); + cabac_ctx_t *baseCtx = (type == 0) ? &(cabac->ctx.cu_sig_model_luma[0]) : + &(cabac->ctx.cu_sig_model_chroma[0]); + + // Scan all coeff groups to find out which of them have coeffs. + // Populate sig_coeffgroup_flag with that info. + + unsigned sig_cg_cnt = 0; + for (int cg_y = 0; cg_y < width / 4; ++cg_y) { + for (int cg_x = 0; cg_x < width / 4; ++cg_x) { + unsigned cg_pos = cg_y * width * 4 + cg_x * 4; + for (int coeff_row = 0; coeff_row < 4; ++coeff_row) { + // Load four 16-bit coeffs and see if any of them are non-zero. + unsigned coeff_pos = cg_pos + coeff_row * width; + uint64_t four_coeffs = *(uint64_t*)(&coeff[coeff_pos]); + if (four_coeffs) { + ++sig_cg_cnt; + unsigned cg_pos_y = (cg_pos >> log2_block_size) >> TR_MIN_LOG2_SIZE; + unsigned cg_pos_x = (cg_pos & (width - 1)) >> TR_MIN_LOG2_SIZE; + sig_coeffgroup_flag[cg_pos_x + cg_pos_y * num_blk_side] = 1; + break; + } + } + } + } + + // Rest of the code assumes at least one non-zero coeff. + assert(sig_cg_cnt > 0); + + // Find the last coeff group by going backwards in scan order. + unsigned scan_cg_last = num_blk_side * num_blk_side - 1; + while (!sig_coeffgroup_flag[scan_cg[scan_cg_last]]) { + --scan_cg_last; + } + + // Find the last coeff by going backwards in scan order. + unsigned scan_pos_last = scan_cg_last * 16 + 15; + while (!coeff[scan[scan_pos_last]]) { + --scan_pos_last; + } + + int pos_last = scan[scan_pos_last]; + + // transform skip flag + if(width == 4 && encoder->trskip_enable) { + cabac->cur_ctx = (type == 0) ? &(cabac->ctx.transform_skip_model_luma) : &(cabac->ctx.transform_skip_model_chroma); + CABAC_BIN(cabac, tr_skip, "transform_skip_flag"); + } + + last_coeff_x = pos_last & (width - 1); + last_coeff_y = (uint8_t)(pos_last >> log2_block_size); + + // Code last_coeff_x and last_coeff_y + encode_last_significant_xy(state, last_coeff_x, last_coeff_y, width, width, + type, scan_mode); + + scan_pos_sig = scan_pos_last; + + // significant_coeff_flag + for (i = scan_cg_last; i >= 0; i--) { + int32_t sub_pos = i << 4; // LOG2_SCAN_SET_SIZE; + int32_t abs_coeff[16]; + int32_t cg_blk_pos = scan_cg[i]; + int32_t cg_pos_y = cg_blk_pos / num_blk_side; + int32_t cg_pos_x = cg_blk_pos - (cg_pos_y * num_blk_side); + + uint32_t coeff_signs = 0; + int32_t last_nz_pos_in_cg = -1; + int32_t first_nz_pos_in_cg = 16; + int32_t num_non_zero = 0; + go_rice_param = 0; + + if (scan_pos_sig == scan_pos_last) { + abs_coeff[0] = abs(coeff[pos_last]); + coeff_signs = (coeff[pos_last] < 0); + num_non_zero = 1; + last_nz_pos_in_cg = scan_pos_sig; + first_nz_pos_in_cg = scan_pos_sig; + scan_pos_sig--; + } + + if (i == scan_cg_last || i == 0) { + sig_coeffgroup_flag[cg_blk_pos] = 1; + } else { + uint32_t sig_coeff_group = (sig_coeffgroup_flag[cg_blk_pos] != 0); + uint32_t ctx_sig = kvz_context_get_sig_coeff_group(sig_coeffgroup_flag, cg_pos_x, + cg_pos_y, width); + cabac->cur_ctx = &base_coeff_group_ctx[ctx_sig]; + CABAC_BIN(cabac, sig_coeff_group, "coded_sub_block_flag"); + } + + if (sig_coeffgroup_flag[cg_blk_pos]) { + int32_t pattern_sig_ctx = kvz_context_calc_pattern_sig_ctx(sig_coeffgroup_flag, + cg_pos_x, cg_pos_y, width); + + for (; scan_pos_sig >= sub_pos; scan_pos_sig--) { + blk_pos = scan[scan_pos_sig]; + pos_y = blk_pos >> log2_block_size; + pos_x = blk_pos - (pos_y << log2_block_size); + sig = (coeff[blk_pos] != 0) ? 1 : 0; + + if (scan_pos_sig > sub_pos || i == 0 || num_non_zero) { + ctx_sig = kvz_context_get_sig_ctx_inc(pattern_sig_ctx, scan_mode, pos_x, pos_y, + log2_block_size, type); + cabac->cur_ctx = &baseCtx[ctx_sig]; + CABAC_BIN(cabac, sig, "sig_coeff_flag"); + } + + if (sig) { + abs_coeff[num_non_zero] = abs(coeff[blk_pos]); + coeff_signs = 2 * coeff_signs + (coeff[blk_pos] < 0); + num_non_zero++; + + if (last_nz_pos_in_cg == -1) { + last_nz_pos_in_cg = scan_pos_sig; + } + + first_nz_pos_in_cg = scan_pos_sig; + } + } + } else { + scan_pos_sig = sub_pos - 1; + } + + if (num_non_zero > 0) { + bool sign_hidden = last_nz_pos_in_cg - first_nz_pos_in_cg >= 4 /* SBH_THRESHOLD */ + && !encoder->cfg->lossless; + uint32_t ctx_set = (i > 0 && type == 0) ? 2 : 0; + cabac_ctx_t *base_ctx_mod; + int32_t num_c1_flag, first_c2_flag_idx, idx, first_coeff2; + + if (c1 == 0) { + ctx_set++; + } + + c1 = 1; + + base_ctx_mod = (type == 0) ? &(cabac->ctx.cu_one_model_luma[4 * ctx_set]) : + &(cabac->ctx.cu_one_model_chroma[4 * ctx_set]); + num_c1_flag = MIN(num_non_zero, C1FLAG_NUMBER); + first_c2_flag_idx = -1; + + for (idx = 0; idx < num_c1_flag; idx++) { + uint32_t symbol = (abs_coeff[idx] > 1) ? 1 : 0; + cabac->cur_ctx = &base_ctx_mod[c1]; + CABAC_BIN(cabac, symbol, "coeff_abs_level_greater1_flag"); + + if (symbol) { + c1 = 0; + + if (first_c2_flag_idx == -1) { + first_c2_flag_idx = idx; + } + } else if ((c1 < 3) && (c1 > 0)) { + c1++; + } + } + + if (c1 == 0) { + base_ctx_mod = (type == 0) ? &(cabac->ctx.cu_abs_model_luma[ctx_set]) : + &(cabac->ctx.cu_abs_model_chroma[ctx_set]); + + if (first_c2_flag_idx != -1) { + uint8_t symbol = (abs_coeff[first_c2_flag_idx] > 2) ? 1 : 0; + cabac->cur_ctx = &base_ctx_mod[0]; + CABAC_BIN(cabac, symbol, "coeff_abs_level_greater2_flag"); + } + } + if (be_valid && sign_hidden) { + coeff_signs = coeff_signs >> 1; + if(!state->cabac.only_count) + if (state->encoder_control->cfg->crypto_features & KVZ_CRYPTO_TRANSF_COEFF_SIGNS) { + coeff_signs = coeff_signs ^ ff_get_key(&state->tile->dbs_g, num_non_zero-1); + } + CABAC_BINS_EP(cabac, coeff_signs , (num_non_zero - 1), "coeff_sign_flag"); + } else { + if(!state->cabac.only_count) + if (state->encoder_control->cfg->crypto_features & KVZ_CRYPTO_TRANSF_COEFF_SIGNS) + coeff_signs = coeff_signs ^ ff_get_key(&state->tile->dbs_g, num_non_zero); + CABAC_BINS_EP(cabac, coeff_signs, num_non_zero, "coeff_sign_flag"); + } + + if (c1 == 0 || num_non_zero > C1FLAG_NUMBER) { + first_coeff2 = 1; + + for (idx = 0; idx < num_non_zero; idx++) { + int32_t base_level = (idx < C1FLAG_NUMBER) ? (2 + first_coeff2) : 1; + + if (abs_coeff[idx] >= base_level) { + if(!state->cabac.only_count) { + if (state->encoder_control->cfg->crypto_features & KVZ_CRYPTO_TRANSF_COEFFS) + kvz_cabac_write_coeff_remain_encry(state, cabac, abs_coeff[idx] - base_level, go_rice_param, base_level); + else + kvz_cabac_write_coeff_remain(cabac, abs_coeff[idx] - base_level, go_rice_param); + } else + kvz_cabac_write_coeff_remain(cabac, abs_coeff[idx] - base_level, go_rice_param); + + if (abs_coeff[idx] > 3 * (1 << go_rice_param)) { + go_rice_param = MIN(go_rice_param + 1, 4); + } + } + + if (abs_coeff[idx] >= 2) { + first_coeff2 = 0; + } + } + } + } + } +} + +static void encode_transform_unit(encoder_state_t * const state, + int x_pu, int y_pu, int depth) +{ + assert(depth >= 1 && depth <= MAX_PU_DEPTH); + + const videoframe_t * const frame = state->tile->frame; + const uint8_t width = LCU_WIDTH >> depth; + const uint8_t width_c = (depth == MAX_PU_DEPTH ? width : width / 2); + + const cu_info_t *cur_pu = kvz_cu_array_at_const(frame->cu_array, x_pu << 2, y_pu << 2); + + const int x_cu = x_pu / 2; + const int y_cu = y_pu / 2; + const cu_info_t *cur_cu = kvz_videoframe_get_cu_const(frame, x_cu, y_cu); + + coeff_t coeff_y[LCU_WIDTH*LCU_WIDTH+1]; + coeff_t coeff_u[LCU_WIDTH*LCU_WIDTH>>2]; + coeff_t coeff_v[LCU_WIDTH*LCU_WIDTH>>2]; + int32_t coeff_stride = frame->width; + + int8_t scan_idx = kvz_get_scan_order(cur_pu->type, cur_pu->intra.mode, depth); + + int cbf_y = cbf_is_set(cur_pu->cbf, depth, COLOR_Y); + + if (cbf_y) { + int x = x_pu * (LCU_WIDTH >> MAX_PU_DEPTH); + int y = y_pu * (LCU_WIDTH >> MAX_PU_DEPTH); + coeff_t *orig_pos = &frame->coeff_y[x + y * frame->width]; + for (y = 0; y < width; y++) { + for (x = 0; x < width; x++) { + coeff_y[x+y*width] = orig_pos[x]; + } + orig_pos += coeff_stride; + } + } + + // CoeffNxN + // Residual Coding + if (cbf_y) { + kvz_encode_coeff_nxn(state, coeff_y, width, 0, scan_idx, cur_pu->intra.tr_skip); + } + + if (depth == MAX_DEPTH + 1 && !(x_pu % 2 && y_pu % 2)) { + // For size 4x4 luma transform the corresponding chroma transforms are + // also of size 4x4 covering 8x8 luma pixels. The residual is coded + // in the last transform unit so for the other ones, don't do anything. + return; + } + + bool chroma_cbf_set = cbf_is_set(cur_cu->cbf, depth, COLOR_U) || + cbf_is_set(cur_cu->cbf, depth, COLOR_V); + if (chroma_cbf_set) { + int x, y; + coeff_t *orig_pos_u, *orig_pos_v; + + if (depth <= MAX_DEPTH) { + x = x_pu * (LCU_WIDTH >> (MAX_PU_DEPTH + 1)); + y = y_pu * (LCU_WIDTH >> (MAX_PU_DEPTH + 1)); + } else { + // for 4x4 select top left pixel of the CU. + x = x_cu * (LCU_WIDTH >> (MAX_DEPTH + 1)); + y = y_cu * (LCU_WIDTH >> (MAX_DEPTH + 1)); + } + orig_pos_u = &frame->coeff_u[x + y * (frame->width >> 1)]; + orig_pos_v = &frame->coeff_v[x + y * (frame->width >> 1)]; + for (y = 0; y < (width_c); y++) { + for (x = 0; x < (width_c); x++) { + coeff_u[x+y*(width_c)] = orig_pos_u[x]; + coeff_v[x+y*(width_c)] = orig_pos_v[x]; + } + orig_pos_u += coeff_stride>>1; + orig_pos_v += coeff_stride>>1; + } + + scan_idx = kvz_get_scan_order(cur_cu->type, cur_cu->intra.mode_chroma, depth); + + if (cbf_is_set(cur_cu->cbf, depth, COLOR_U)) { + kvz_encode_coeff_nxn(state, coeff_u, width_c, 2, scan_idx, 0); + } + + if (cbf_is_set(cur_cu->cbf, depth, COLOR_V)) { + kvz_encode_coeff_nxn(state, coeff_v, width_c, 2, scan_idx, 0); + } + } +} + +/** + * \param encoder + * \param x_pu Prediction units' x coordinate. + * \param y_pu Prediction units' y coordinate. + * \param depth Depth from LCU. + * \param tr_depth Depth from last CU. + * \param parent_coeff_u What was signaled at previous level for cbf_cb. + * \param parent_coeff_v What was signlaed at previous level for cbf_cr. + */ +static void encode_transform_coeff(encoder_state_t * const state, + int32_t x_pu, + int32_t y_pu, + int8_t depth, + int8_t tr_depth, + uint8_t parent_coeff_u, + uint8_t parent_coeff_v) +{ + cabac_data_t * const cabac = &state->cabac; + const videoframe_t * const frame = state->tile->frame; + + const cu_info_t *cur_pu = kvz_cu_array_at_const(frame->cu_array, x_pu << 2, y_pu << 2); + + const int32_t x_cu = x_pu / 2; + const int32_t y_cu = y_pu / 2; + const cu_info_t *cur_cu = kvz_videoframe_get_cu_const(frame, x_cu, y_cu); + + // NxN signifies implicit transform split at the first transform level. + // There is a similar implicit split for inter, but it is only used when + // transform hierarchy is not in use. + int intra_split_flag = (cur_cu->type == CU_INTRA && cur_cu->part_size == SIZE_NxN); + + // The implicit split by intra NxN is not counted towards max_tr_depth. + int tr_depth_intra = state->encoder_control->tr_depth_intra; + int max_tr_depth = (cur_cu->type == CU_INTRA ? tr_depth_intra + intra_split_flag : TR_DEPTH_INTER); + + int8_t split = (cur_cu->tr_depth > depth); + + const int cb_flag_y = cbf_is_set(cur_pu->cbf, depth, COLOR_Y); + const int cb_flag_u = cbf_is_set(cur_cu->cbf, depth, COLOR_U); + const int cb_flag_v = cbf_is_set(cur_cu->cbf, depth, COLOR_V); + + // The split_transform_flag is not signaled when: + // - transform size is greater than 32 (depth == 0) + // - transform size is 4 (depth == MAX_PU_DEPTH) + // - transform depth is max + // - cu is intra NxN and it's the first split + if (depth > 0 && + depth < MAX_PU_DEPTH && + tr_depth < max_tr_depth && + !(intra_split_flag && tr_depth == 0)) + { + cabac->cur_ctx = &(cabac->ctx.trans_subdiv_model[5 - ((kvz_g_convert_to_bit[LCU_WIDTH] + 2) - depth)]); + CABAC_BIN(cabac, split, "split_transform_flag"); + } + + // Chroma cb flags are not signaled when one of the following: + // - transform size is 4 (2x2 chroma transform doesn't exist) + // - they have already been signaled to 0 previously + // When they are not present they are inferred to be 0, except for size 4 + // when the flags from previous level are used. + if (depth < MAX_PU_DEPTH) { + cabac->cur_ctx = &(cabac->ctx.qt_cbf_model_chroma[tr_depth]); + if (tr_depth == 0 || parent_coeff_u) { + CABAC_BIN(cabac, cb_flag_u, "cbf_cb"); + } + if (tr_depth == 0 || parent_coeff_v) { + CABAC_BIN(cabac, cb_flag_v, "cbf_cr"); + } + } + + if (split) { + uint8_t pu_offset = 1 << (MAX_PU_DEPTH - (depth + 1)); + encode_transform_coeff(state, x_pu, y_pu, depth + 1, tr_depth + 1, cb_flag_u, cb_flag_v); + encode_transform_coeff(state, x_pu + pu_offset, y_pu, depth + 1, tr_depth + 1, cb_flag_u, cb_flag_v); + encode_transform_coeff(state, x_pu, y_pu + pu_offset, depth + 1, tr_depth + 1, cb_flag_u, cb_flag_v); + encode_transform_coeff(state, x_pu + pu_offset, y_pu + pu_offset, depth + 1, tr_depth + 1, cb_flag_u, cb_flag_v); + return; + } + + // Luma coded block flag is signaled when one of the following: + // - prediction mode is intra + // - transform depth > 0 + // - we have chroma coefficients at this level + // When it is not present, it is inferred to be 1. + if(cur_cu->type == CU_INTRA || tr_depth > 0 || cb_flag_u || cb_flag_v) { + cabac->cur_ctx = &(cabac->ctx.qt_cbf_model_luma[!tr_depth]); + CABAC_BIN(cabac, cb_flag_y, "cbf_luma"); + } + + if (cb_flag_y | cb_flag_u | cb_flag_v) { + encode_transform_unit(state, x_pu, y_pu, depth); + } +} + +static void encode_inter_prediction_unit(encoder_state_t * const state, + cabac_data_t * const cabac, + const cu_info_t * const cur_cu, + int x, int y, int width, int height, + int depth) +{ + // Mergeflag + int16_t num_cand = 0; + cabac->cur_ctx = &(cabac->ctx.cu_merge_flag_ext_model); + CABAC_BIN(cabac, cur_cu->merged, "MergeFlag"); + num_cand = MRG_MAX_NUM_CANDS; + if (cur_cu->merged) { //merge + if (num_cand > 1) { + int32_t ui; + for (ui = 0; ui < num_cand - 1; ui++) { + int32_t symbol = (ui != cur_cu->merge_idx); + if (ui == 0) { + cabac->cur_ctx = &(cabac->ctx.cu_merge_idx_ext_model); + CABAC_BIN(cabac, symbol, "MergeIndex"); + } else { + CABAC_BIN_EP(cabac,symbol,"MergeIndex"); + } + if (symbol == 0) break; + } + } + } else { + uint32_t ref_list_idx; + uint32_t j; + int ref_list[2] = { 0, 0 }; + for (j = 0; j < state->global->ref->used_size; j++) { + if (state->global->ref->pocs[j] < state->global->poc) { + ref_list[0]++; + } else { + ref_list[1]++; + } + } + + // Void TEncSbac::codeInterDir( TComDataCU* pcCU, UInt uiAbsPartIdx ) + if (state->global->slicetype == KVZ_SLICE_B) + { + // Code Inter Dir + uint8_t inter_dir = cur_cu->inter.mv_dir-1; + uint8_t ctx = depth; + + + if (cur_cu->part_size == SIZE_2Nx2N || (LCU_WIDTH >> depth) != 8) + { + cabac->cur_ctx = &(cabac->ctx.inter_dir[ctx]); + CABAC_BIN(cabac, (inter_dir == 2), "inter_pred_idc"); + } + if (inter_dir < 2) + { + cabac->cur_ctx = &(cabac->ctx.inter_dir[4]); + CABAC_BIN(cabac, inter_dir, "inter_pred_idc"); + } + } + + for (ref_list_idx = 0; ref_list_idx < 2; ref_list_idx++) { + if (cur_cu->inter.mv_dir & (1 << ref_list_idx)) { + if (ref_list[ref_list_idx] > 1) { + // parseRefFrmIdx + int32_t ref_frame = state->global->refmap[cur_cu->inter.mv_ref[ref_list_idx]].idx; + + cabac->cur_ctx = &(cabac->ctx.cu_ref_pic_model[0]); + CABAC_BIN(cabac, (ref_frame != 0), "ref_idx_lX"); + + if (ref_frame > 0) { + int32_t i; + int32_t ref_num = ref_list[ref_list_idx] - 2; + + cabac->cur_ctx = &(cabac->ctx.cu_ref_pic_model[1]); + ref_frame--; + + for (i = 0; i < ref_num; ++i) { + const uint32_t symbol = (i == ref_frame) ? 0 : 1; + + if (i == 0) { + CABAC_BIN(cabac, symbol, "ref_idx_lX"); + } else { + CABAC_BIN_EP(cabac, symbol, "ref_idx_lX"); + } + if (symbol == 0) break; + } + } + } + + if (!(/*pcCU->getSlice()->getMvdL1ZeroFlag() &&*/ state->global->ref_list == REF_PIC_LIST_1 && cur_cu->inter.mv_dir == 3)) { + + int16_t mv_cand[2][2]; + kvz_inter_get_mv_cand_cua( + state, + x, y, width, height, + mv_cand, cur_cu, ref_list_idx); + + uint8_t cu_mv_cand = CU_GET_MV_CAND(cur_cu, ref_list_idx); + + const int32_t mvd_hor = cur_cu->inter.mv[ref_list_idx][0] - mv_cand[cu_mv_cand][0]; + const int32_t mvd_ver = cur_cu->inter.mv[ref_list_idx][1] - mv_cand[cu_mv_cand][1]; + const int8_t hor_abs_gr0 = mvd_hor != 0; + const int8_t ver_abs_gr0 = mvd_ver != 0; + const uint32_t mvd_hor_abs = abs(mvd_hor); + const uint32_t mvd_ver_abs = abs(mvd_ver); + + + cabac->cur_ctx = &(cabac->ctx.cu_mvd_model[0]); + CABAC_BIN(cabac, (mvd_hor != 0), "abs_mvd_greater0_flag_hor"); + CABAC_BIN(cabac, (mvd_ver != 0), "abs_mvd_greater0_flag_ver"); + + cabac->cur_ctx = &(cabac->ctx.cu_mvd_model[1]); + + if (hor_abs_gr0) { + CABAC_BIN(cabac, (mvd_hor_abs>1), "abs_mvd_greater1_flag_hor"); + } + + if (ver_abs_gr0) { + CABAC_BIN(cabac, (mvd_ver_abs>1), "abs_mvd_greater1_flag_ver"); + } + + if (hor_abs_gr0) { + if (mvd_hor_abs > 1) { + kvz_cabac_write_ep_ex_golomb(state, cabac, mvd_hor_abs-2, 1); + } + uint32_t mvd_hor_sign = (mvd_hor>0)?0:1; + if(!state->cabac.only_count) + if (state->encoder_control->cfg->crypto_features & KVZ_CRYPTO_MV_SIGNS) + mvd_hor_sign = mvd_hor_sign^ff_get_key(&state->tile->dbs_g, 1); + CABAC_BIN_EP(cabac, mvd_hor_sign, "mvd_sign_flag_hor"); + } + if (ver_abs_gr0) { + if (mvd_ver_abs > 1) { + kvz_cabac_write_ep_ex_golomb(state, cabac, mvd_ver_abs-2, 1); + } + uint32_t mvd_ver_sign = (mvd_ver>0)?0:1; + if(!state->cabac.only_count) + if (state->encoder_control->cfg->crypto_features & KVZ_CRYPTO_MV_SIGNS) + mvd_ver_sign = mvd_ver_sign^ff_get_key(&state->tile->dbs_g, 1); + CABAC_BIN_EP(cabac, mvd_ver_sign, "mvd_sign_flag_ver"); + } + } + + // Signal which candidate MV to use + kvz_cabac_write_unary_max_symbol(cabac, + cabac->ctx.mvp_idx_model, + CU_GET_MV_CAND(cur_cu, ref_list_idx), + 1, + AMVP_MAX_NUM_CANDS - 1); + } + } // for ref_list + } // if !merge +} + +static void encode_intra_coding_unit(encoder_state_t * const state, + cabac_data_t * const cabac, + const cu_info_t * const cur_cu, + int x_ctb, int y_ctb, int depth) +{ + const videoframe_t * const frame = state->tile->frame; + uint8_t intra_pred_mode[4]; + + uint8_t intra_pred_mode_chroma = cur_cu->intra.mode_chroma; + int8_t intra_preds[4][3] = {{-1, -1, -1},{-1, -1, -1},{-1, -1, -1},{-1, -1, -1}}; + int8_t mpm_preds[4] = {-1, -1, -1, -1}; + uint32_t flag[4]; + + #if ENABLE_PCM == 1 + // Code must start after variable initialization + kvz_cabac_encode_bin_trm(cabac, 0); // IPCMFlag == 0 + #endif + + // PREDINFO CODING + // If intra prediction mode is found from the predictors, + // it can be signaled with two EP's. Otherwise we can send + // 5 EP bins with the full predmode + const int num_pred_units = kvz_part_mode_num_parts[cur_cu->part_size]; + const int cu_width = LCU_WIDTH >> depth; + + for (int j = 0; j < num_pred_units; ++j) { + const int pu_x = PU_GET_X(cur_cu->part_size, cu_width, x_ctb << 3, j); + const int pu_y = PU_GET_Y(cur_cu->part_size, cu_width, y_ctb << 3, j); + const cu_info_t *cur_pu = kvz_cu_array_at_const(frame->cu_array, pu_x, pu_y); + + const cu_info_t *left_pu = NULL; + const cu_info_t *above_pu = NULL; + + if (pu_x > 0) { + assert(pu_x >> 2 > 0); + left_pu = kvz_cu_array_at_const(frame->cu_array, pu_x - 1, pu_y); + } + // Don't take the above PU across the LCU boundary. + if (pu_y % LCU_WIDTH > 0 && pu_y > 0) { + assert(pu_y >> 2 > 0); + above_pu = kvz_cu_array_at_const(frame->cu_array, pu_x, pu_y - 1); + } + + kvz_intra_get_dir_luma_predictor(pu_x, pu_y, + intra_preds[j], + cur_pu, + left_pu, above_pu); + + intra_pred_mode[j] = cur_pu->intra.mode; + + for (int i = 0; i < 3; i++) { + if (intra_preds[j][i] == intra_pred_mode[j]) { + mpm_preds[j] = (int8_t)i; + break; + } + } + flag[j] = (mpm_preds[j] == -1) ? 0 : 1; + } + + cabac->cur_ctx = &(cabac->ctx.intra_mode_model); + for (int j = 0; j < num_pred_units; ++j) { + CABAC_BIN(cabac, flag[j], "prev_intra_luma_pred_flag"); + } + + for (int j = 0; j < num_pred_units; ++j) { + // Signal index of the prediction mode in the prediction list. + if (flag[j]) { + CABAC_BIN_EP(cabac, (mpm_preds[j] == 0 ? 0 : 1), "mpm_idx"); + if (mpm_preds[j] != 0) { + CABAC_BIN_EP(cabac, (mpm_preds[j] == 1 ? 0 : 1), "mpm_idx"); + } + } else { + // Signal the actual prediction mode. + int32_t tmp_pred = intra_pred_mode[j]; + + // Sort prediction list from lowest to highest. + if (intra_preds[j][0] > intra_preds[j][1]) SWAP(intra_preds[j][0], intra_preds[j][1], int8_t); + if (intra_preds[j][0] > intra_preds[j][2]) SWAP(intra_preds[j][0], intra_preds[j][2], int8_t); + if (intra_preds[j][1] > intra_preds[j][2]) SWAP(intra_preds[j][1], intra_preds[j][2], int8_t); + + // Reduce the index of the signaled prediction mode according to the + // prediction list, as it has been already signaled that it's not one + // of the prediction modes. + for (int i = 2; i >= 0; i--) { + tmp_pred = (tmp_pred > intra_preds[j][i] ? tmp_pred - 1 : tmp_pred); + } + + CABAC_BINS_EP(cabac, tmp_pred, 5, "rem_intra_luma_pred_mode"); + } + } + + { // start intra chroma pred mode coding + unsigned pred_mode = 5; + unsigned chroma_pred_modes[4] = {0, 26, 10, 1}; + + if (intra_pred_mode_chroma == intra_pred_mode[0]) { + pred_mode = 4; + } else if (intra_pred_mode_chroma == 34) { + // Angular 34 mode is possible only if intra pred mode is one of the + // possible chroma pred modes, in which case it is signaled with that + // duplicate mode. + for (int i = 0; i < 4; ++i) { + if (intra_pred_mode[0] == chroma_pred_modes[i]) pred_mode = i; + } + } else { + for (int i = 0; i < 4; ++i) { + if (intra_pred_mode_chroma == chroma_pred_modes[i]) pred_mode = i; + } + } + + // pred_mode == 5 mean intra_pred_mode_chroma is something that can't + // be coded. + assert(pred_mode != 5); + + /** + * Table 9-35 - Binarization for intra_chroma_pred_mode + * intra_chroma_pred_mode bin_string + * 4 0 + * 0 100 + * 1 101 + * 2 110 + * 3 111 + * Table 9-37 - Assignment of ctxInc to syntax elements with context coded bins + * intra_chroma_pred_mode[][] = 0, bypass, bypass + */ + cabac->cur_ctx = &(cabac->ctx.chroma_pred_model[0]); + if (pred_mode == 4) { + CABAC_BIN(cabac, 0, "intra_chroma_pred_mode"); + } else { + CABAC_BIN(cabac, 1, "intra_chroma_pred_mode"); + CABAC_BINS_EP(cabac, pred_mode, 2, "intra_chroma_pred_mode"); + } + } // end intra chroma pred mode coding + + encode_transform_coeff(state, x_ctb * 2, y_ctb * 2, depth, 0, 0, 0); +} + +static void encode_part_mode(encoder_state_t * const state, + cabac_data_t * const cabac, + const cu_info_t * const cur_cu, + int depth) +{ + // Binarization from Table 9-34 of the HEVC spec: + // + // | log2CbSize > | log2CbSize == + // | MinCbLog2SizeY | MinCbLog2SizeY + // -------+-------+----------+---------+-----------+---------- + // pred | part | AMP | AMP | | + // mode | mode | disabled | enabled | size == 8 | size > 8 + // -------+-------+----------+---------+-----------+---------- + // intra | 2Nx2N | - - | 1 1 + // | NxN | - - | 0 0 + // -------+-------+--------------------+---------------------- + // inter | 2Nx2N | 1 1 | 1 1 + // | 2NxN | 01 011 | 01 01 + // | Nx2N | 00 001 | 00 001 + // | NxN | - - | - 000 + // | 2NxnU | - 0100 | - - + // | 2NxnD | - 0101 | - - + // | nLx2N | - 0000 | - - + // | nRx2N | - 0001 | - - + // -------+-------+--------------------+---------------------- + // + // + // Context indices from Table 9-37 of the HEVC spec: + // + // binIdx + // | 0 1 2 3 + // ------------------------------+------------------ + // log2CbSize == MinCbLog2SizeY | 0 1 2 bypass + // log2CbSize > MinCbLog2SizeY | 0 1 3 bypass + // ------------------------------+------------------ + + if (cur_cu->type == CU_INTRA) { + if (depth == MAX_DEPTH) { + cabac->cur_ctx = &(cabac->ctx.part_size_model[0]); + if (cur_cu->part_size == SIZE_2Nx2N) { + CABAC_BIN(cabac, 1, "part_mode 2Nx2N"); + } else { + CABAC_BIN(cabac, 0, "part_mode NxN"); + } + } + } else { + + cabac->cur_ctx = &(cabac->ctx.part_size_model[0]); + if (cur_cu->part_size == SIZE_2Nx2N) { + CABAC_BIN(cabac, 1, "part_mode 2Nx2N"); + return; + } + CABAC_BIN(cabac, 0, "part_mode split"); + + cabac->cur_ctx = &(cabac->ctx.part_size_model[1]); + if (cur_cu->part_size == SIZE_2NxN || + cur_cu->part_size == SIZE_2NxnU || + cur_cu->part_size == SIZE_2NxnD) { + CABAC_BIN(cabac, 1, "part_mode vertical"); + } else { + CABAC_BIN(cabac, 0, "part_mode horizontal"); + } + + if (state->encoder_control->cfg->amp_enable && depth < MAX_DEPTH) { + cabac->cur_ctx = &(cabac->ctx.part_size_model[3]); + + if (cur_cu->part_size == SIZE_2NxN || + cur_cu->part_size == SIZE_Nx2N) { + CABAC_BIN(cabac, 1, "part_mode SMP"); + return; + } + CABAC_BIN(cabac, 0, "part_mode AMP"); + + if (cur_cu->part_size == SIZE_2NxnU || + cur_cu->part_size == SIZE_nLx2N) { + CABAC_BINS_EP(cabac, 0, 1, "part_mode AMP"); + } else { + CABAC_BINS_EP(cabac, 1, 1, "part_mode AMP"); + } + } + } +} + +void kvz_encode_coding_tree(encoder_state_t * const state, + uint16_t x_ctb, uint16_t y_ctb, uint8_t depth) +{ + cabac_data_t * const cabac = &state->cabac; + const videoframe_t * const frame = state->tile->frame; + const cu_info_t *cur_cu = kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb); + uint8_t split_flag = GET_SPLITDATA(cur_cu, depth); + uint8_t split_model = 0; + + //Absolute ctb + uint16_t abs_x_ctb = x_ctb + (state->tile->lcu_offset_x * LCU_WIDTH) / (LCU_WIDTH >> MAX_DEPTH); + uint16_t abs_y_ctb = y_ctb + (state->tile->lcu_offset_y * LCU_WIDTH) / (LCU_WIDTH >> MAX_DEPTH); + + // Check for slice border FIXME + uint8_t border_x = ((state->encoder_control->in.width) < (abs_x_ctb * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> depth))) ? 1 : 0; + uint8_t border_y = ((state->encoder_control->in.height) < (abs_y_ctb * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> depth))) ? 1 : 0; + uint8_t border_split_x = ((state->encoder_control->in.width) < ((abs_x_ctb + 1) * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> (depth + 1)))) ? 0 : 1; + uint8_t border_split_y = ((state->encoder_control->in.height) < ((abs_y_ctb + 1) * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> (depth + 1)))) ? 0 : 1; + uint8_t border = border_x | border_y; /*!< are we in any border CU */ + + // When not in MAX_DEPTH, insert split flag and split the blocks if needed + if (depth != MAX_DEPTH) { + // Implisit split flag when on border + if (!border) { + // Get left and top block split_flags and if they are present and true, increase model number + if (x_ctb > 0 && GET_SPLITDATA(kvz_videoframe_get_cu_const(frame, x_ctb - 1, y_ctb), depth) == 1) { + split_model++; + } + + if (y_ctb > 0 && GET_SPLITDATA(kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb - 1), depth) == 1) { + split_model++; + } + + cabac->cur_ctx = &(cabac->ctx.split_flag_model[split_model]); + CABAC_BIN(cabac, split_flag, "SplitFlag"); + } + + if (split_flag || border) { + // Split blocks and remember to change x and y block positions + uint8_t change = 1<<(MAX_DEPTH-1-depth); + kvz_encode_coding_tree(state, x_ctb, y_ctb, depth + 1); // x,y + + // TODO: fix when other half of the block would not be completely over the border + if (!border_x || border_split_x) { + kvz_encode_coding_tree(state, x_ctb + change, y_ctb, depth + 1); + } + if (!border_y || border_split_y) { + kvz_encode_coding_tree(state, x_ctb, y_ctb + change, depth + 1); + } + if (!border || (border_split_x && border_split_y)) { + kvz_encode_coding_tree(state, x_ctb + change, y_ctb + change, depth + 1); + } + return; + } + } + + if (state->encoder_control->cfg->lossless) { + cabac->cur_ctx = &cabac->ctx.cu_transquant_bypass; + CABAC_BIN(cabac, 1, "cu_transquant_bypass_flag"); + } + + // Encode skip flag + if (state->global->slicetype != KVZ_SLICE_I) { + int8_t ctx_skip = 0; // uiCtxSkip = aboveskipped + leftskipped; + int ui; + int16_t num_cand = MRG_MAX_NUM_CANDS; + // Get left and top skipped flags and if they are present and true, increase context number + if (x_ctb > 0 && (kvz_videoframe_get_cu_const(frame, x_ctb - 1, y_ctb))->skipped) { + ctx_skip++; + } + + if (y_ctb > 0 && (kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb - 1))->skipped) { + ctx_skip++; + } + + cabac->cur_ctx = &(cabac->ctx.cu_skip_flag_model[ctx_skip]); + CABAC_BIN(cabac, cur_cu->skipped, "SkipFlag"); + + // IF SKIP + if (cur_cu->skipped) { + if (num_cand > 1) { + for (ui = 0; ui < num_cand - 1; ui++) { + int32_t symbol = (ui != cur_cu->merge_idx); + if (ui == 0) { + cabac->cur_ctx = &(cabac->ctx.cu_merge_idx_ext_model); + CABAC_BIN(cabac, symbol, "MergeIndex"); + } else { + CABAC_BIN_EP(cabac,symbol,"MergeIndex"); + } + if (symbol == 0) { + break; + } + } + } + return; + } + } + + // ENDIF SKIP + + // Prediction mode + if (state->global->slicetype != KVZ_SLICE_I) { + cabac->cur_ctx = &(cabac->ctx.cu_pred_mode_model); + CABAC_BIN(cabac, (cur_cu->type == CU_INTRA), "PredMode"); + } + + // part_mode + encode_part_mode(state, cabac, cur_cu, depth); + + if (cur_cu->type == CU_INTER) { + const int num_pu = kvz_part_mode_num_parts[cur_cu->part_size]; + const int cu_width = LCU_WIDTH >> depth; + + for (int i = 0; i < num_pu; ++i) { + const int pu_x = PU_GET_X(cur_cu->part_size, cu_width, x_ctb << 3, i); + const int pu_y = PU_GET_Y(cur_cu->part_size, cu_width, y_ctb << 3, i); + const int pu_w = PU_GET_W(cur_cu->part_size, cu_width, i); + const int pu_h = PU_GET_H(cur_cu->part_size, cu_width, i); + const cu_info_t *cur_pu = kvz_cu_array_at_const(frame->cu_array, pu_x, pu_y); + + encode_inter_prediction_unit(state, cabac, cur_pu, pu_x, pu_y, pu_w, pu_h, depth); + } + + { + int cbf = cbf_is_set_any(cur_cu->cbf, depth); + // Only need to signal coded block flag if not skipped or merged + // skip = no coded residual, merge = coded residual + if (cur_cu->part_size != SIZE_2Nx2N || !cur_cu->merged) { + cabac->cur_ctx = &(cabac->ctx.cu_qt_root_cbf_model); + CABAC_BIN(cabac, cbf, "rqt_root_cbf"); + } + // Code (possible) coeffs to bitstream + + if (cbf) { + encode_transform_coeff(state, x_ctb * 2, y_ctb * 2, depth, 0, 0, 0); + } + } + } else if (cur_cu->type == CU_INTRA) { + encode_intra_coding_unit(state, cabac, cur_cu, x_ctb, y_ctb, depth); + } + + #if ENABLE_PCM == 1 + // Code IPCM block + if (cur_cu->type == CU_PCM) { + kvz_cabac_encode_bin_trm(cabac, 1); // IPCMFlag == 1 + kvz_cabac_finish(cabac); + kvz_bitstream_add_rbsp_trailing_bits(cabac.stream); + // PCM sample + { + unsigned y, x; + + pixel *base_y = &cur_pic->y_data[x_ctb * (LCU_WIDTH >> (MAX_DEPTH)) + (y_ctb * (LCU_WIDTH >> (MAX_DEPTH))) * encoder->in.width]; + pixel *base_u = &cur_pic->u_data[(x_ctb * (LCU_WIDTH >> (MAX_DEPTH + 1)) + (y_ctb * (LCU_WIDTH >> (MAX_DEPTH + 1))) * encoder->in.width / 2)]; + pixel *base_v = &cur_pic->v_data[(x_ctb * (LCU_WIDTH >> (MAX_DEPTH + 1)) + (y_ctb * (LCU_WIDTH >> (MAX_DEPTH + 1))) * encoder->in.width / 2)]; + + // Luma + for (y = 0; y < LCU_WIDTH >> depth; y++) { + for (x = 0; x < LCU_WIDTH >> depth; x++) { + kvz_bitstream_put(cabac.stream, base_y[x + y * encoder->in.width], 8); + } + } + + // Chroma + if (encoder->in.video_format != FORMAT_400) { + for (y = 0; y < LCU_WIDTH >> (depth + 1); y++) { + for (x = 0; x < LCU_WIDTH >> (depth + 1); x++) { + kvz_bitstream_put(cabac.stream, base_u[x + y * (encoder->in.width >> 1)], 8); + } + } + for (y = 0; y < LCU_WIDTH >> (depth + 1); y++) { + for (x = 0; x < LCU_WIDTH >> (depth + 1); x++) { + kvz_bitstream_put(cabac.stream, base_v[x + y * (encoder->in.width >> 1)], 8); + } + } + } + } + // end PCM sample + kvz_cabac_start(cabac); + } // end Code IPCM block +#endif /* END ENABLE_PCM */ + else { /* Should not happend */ + assert(0); + exit(1); + } + + /* end prediction unit */ + /* end coding_unit */ +} diff --git a/src/encode_coding_tree.h b/src/encode_coding_tree.h new file mode 100644 index 00000000..b8e2dc10 --- /dev/null +++ b/src/encode_coding_tree.h @@ -0,0 +1,44 @@ +#ifndef ENCODE_CODING_TREE_H_ +#define ENCODE_CODING_TREE_H_ + +/***************************************************************************** + * This file is part of Kvazaar HEVC encoder. + * + * Copyright (C) 2013-2015 Tampere University of Technology and others (see + * COPYING file). + * + * Kvazaar is free software: you can redistribute it and/or modify it under + * the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at your + * option) any later version. + * + * Kvazaar is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with Kvazaar. If not, see . + ****************************************************************************/ + +/** + * \file + * Functions for writing the coding quadtree and related syntax. + */ + +#include "encoderstate.h" +#include "global.h" + +void kvz_encode_coding_tree(encoder_state_t *state, + uint16_t x_ctb, + uint16_t y_ctb, + uint8_t depth); + +void kvz_encode_coeff_nxn(encoder_state_t *state, + coeff_t *coeff, + uint8_t width, + uint8_t type, + int8_t scan_mode, + int8_t tr_skip); + +#endif // ENCODE_CODING_TREE_H_ diff --git a/src/encoderstate.c b/src/encoderstate.c index 707571e4..8d84597e 100644 --- a/src/encoderstate.c +++ b/src/encoderstate.c @@ -27,16 +27,13 @@ #include "cabac.h" #include "context.h" +#include "encode_coding_tree.h" #include "encoder_state-bitstream.h" #include "filter.h" #include "image.h" -#include "intra.h" -#include "inter.h" -#include "kvz_math.h" #include "rate_control.h" #include "sao.h" #include "search.h" -#include "strategies/strategies-picture.h" #include "tables.h" @@ -1000,568 +997,6 @@ void kvz_encoder_prepare(encoder_state_t *state) state->prepared = 1; } -static void encode_part_mode(encoder_state_t * const state, - cabac_data_t * const cabac, - const cu_info_t * const cur_cu, - int depth) -{ - // Binarization from Table 9-34 of the HEVC spec: - // - // | log2CbSize > | log2CbSize == - // | MinCbLog2SizeY | MinCbLog2SizeY - // -------+-------+----------+---------+-----------+---------- - // pred | part | AMP | AMP | | - // mode | mode | disabled | enabled | size == 8 | size > 8 - // -------+-------+----------+---------+-----------+---------- - // intra | 2Nx2N | - - | 1 1 - // | NxN | - - | 0 0 - // -------+-------+--------------------+---------------------- - // inter | 2Nx2N | 1 1 | 1 1 - // | 2NxN | 01 011 | 01 01 - // | Nx2N | 00 001 | 00 001 - // | NxN | - - | - 000 - // | 2NxnU | - 0100 | - - - // | 2NxnD | - 0101 | - - - // | nLx2N | - 0000 | - - - // | nRx2N | - 0001 | - - - // -------+-------+--------------------+---------------------- - // - // - // Context indices from Table 9-37 of the HEVC spec: - // - // binIdx - // | 0 1 2 3 - // ------------------------------+------------------ - // log2CbSize == MinCbLog2SizeY | 0 1 2 bypass - // log2CbSize > MinCbLog2SizeY | 0 1 3 bypass - // ------------------------------+------------------ - - if (cur_cu->type == CU_INTRA) { - if (depth == MAX_DEPTH) { - cabac->cur_ctx = &(cabac->ctx.part_size_model[0]); - if (cur_cu->part_size == SIZE_2Nx2N) { - CABAC_BIN(cabac, 1, "part_mode 2Nx2N"); - } else { - CABAC_BIN(cabac, 0, "part_mode NxN"); - } - } - } else { - - cabac->cur_ctx = &(cabac->ctx.part_size_model[0]); - if (cur_cu->part_size == SIZE_2Nx2N) { - CABAC_BIN(cabac, 1, "part_mode 2Nx2N"); - return; - } - CABAC_BIN(cabac, 0, "part_mode split"); - - cabac->cur_ctx = &(cabac->ctx.part_size_model[1]); - if (cur_cu->part_size == SIZE_2NxN || - cur_cu->part_size == SIZE_2NxnU || - cur_cu->part_size == SIZE_2NxnD) { - CABAC_BIN(cabac, 1, "part_mode vertical"); - } else { - CABAC_BIN(cabac, 0, "part_mode horizontal"); - } - - if (state->encoder_control->cfg->amp_enable && depth < MAX_DEPTH) { - cabac->cur_ctx = &(cabac->ctx.part_size_model[3]); - - if (cur_cu->part_size == SIZE_2NxN || - cur_cu->part_size == SIZE_Nx2N) { - CABAC_BIN(cabac, 1, "part_mode SMP"); - return; - } - CABAC_BIN(cabac, 0, "part_mode AMP"); - - if (cur_cu->part_size == SIZE_2NxnU || - cur_cu->part_size == SIZE_nLx2N) { - CABAC_BINS_EP(cabac, 0, 1, "part_mode AMP"); - } else { - CABAC_BINS_EP(cabac, 1, 1, "part_mode AMP"); - } - } - } -} - -static void encode_inter_prediction_unit(encoder_state_t * const state, - cabac_data_t * const cabac, - const cu_info_t * const cur_cu, - int x, int y, int width, int height, - int depth) -{ - // Mergeflag - int16_t num_cand = 0; - cabac->cur_ctx = &(cabac->ctx.cu_merge_flag_ext_model); - CABAC_BIN(cabac, cur_cu->merged, "MergeFlag"); - num_cand = MRG_MAX_NUM_CANDS; - if (cur_cu->merged) { //merge - if (num_cand > 1) { - int32_t ui; - for (ui = 0; ui < num_cand - 1; ui++) { - int32_t symbol = (ui != cur_cu->merge_idx); - if (ui == 0) { - cabac->cur_ctx = &(cabac->ctx.cu_merge_idx_ext_model); - CABAC_BIN(cabac, symbol, "MergeIndex"); - } else { - CABAC_BIN_EP(cabac,symbol,"MergeIndex"); - } - if (symbol == 0) break; - } - } - } else { - uint32_t ref_list_idx; - uint32_t j; - int ref_list[2] = { 0, 0 }; - for (j = 0; j < state->global->ref->used_size; j++) { - if (state->global->ref->pocs[j] < state->global->poc) { - ref_list[0]++; - } else { - ref_list[1]++; - } - } - - // Void TEncSbac::codeInterDir( TComDataCU* pcCU, UInt uiAbsPartIdx ) - if (state->global->slicetype == KVZ_SLICE_B) - { - // Code Inter Dir - uint8_t inter_dir = cur_cu->inter.mv_dir-1; - uint8_t ctx = depth; - - - if (cur_cu->part_size == SIZE_2Nx2N || (LCU_WIDTH >> depth) != 8) - { - cabac->cur_ctx = &(cabac->ctx.inter_dir[ctx]); - CABAC_BIN(cabac, (inter_dir == 2), "inter_pred_idc"); - } - if (inter_dir < 2) - { - cabac->cur_ctx = &(cabac->ctx.inter_dir[4]); - CABAC_BIN(cabac, inter_dir, "inter_pred_idc"); - } - } - - for (ref_list_idx = 0; ref_list_idx < 2; ref_list_idx++) { - if (cur_cu->inter.mv_dir & (1 << ref_list_idx)) { - if (ref_list[ref_list_idx] > 1) { - // parseRefFrmIdx - int32_t ref_frame = state->global->refmap[cur_cu->inter.mv_ref[ref_list_idx]].idx; - - cabac->cur_ctx = &(cabac->ctx.cu_ref_pic_model[0]); - CABAC_BIN(cabac, (ref_frame != 0), "ref_idx_lX"); - - if (ref_frame > 0) { - int32_t i; - int32_t ref_num = ref_list[ref_list_idx] - 2; - - cabac->cur_ctx = &(cabac->ctx.cu_ref_pic_model[1]); - ref_frame--; - - for (i = 0; i < ref_num; ++i) { - const uint32_t symbol = (i == ref_frame) ? 0 : 1; - - if (i == 0) { - CABAC_BIN(cabac, symbol, "ref_idx_lX"); - } else { - CABAC_BIN_EP(cabac, symbol, "ref_idx_lX"); - } - if (symbol == 0) break; - } - } - } - - if (!(/*pcCU->getSlice()->getMvdL1ZeroFlag() &&*/ state->global->ref_list == REF_PIC_LIST_1 && cur_cu->inter.mv_dir == 3)) { - - int16_t mv_cand[2][2]; - kvz_inter_get_mv_cand_cua( - state, - x, y, width, height, - mv_cand, cur_cu, ref_list_idx); - - uint8_t cu_mv_cand = CU_GET_MV_CAND(cur_cu, ref_list_idx); - - const int32_t mvd_hor = cur_cu->inter.mv[ref_list_idx][0] - mv_cand[cu_mv_cand][0]; - const int32_t mvd_ver = cur_cu->inter.mv[ref_list_idx][1] - mv_cand[cu_mv_cand][1]; - const int8_t hor_abs_gr0 = mvd_hor != 0; - const int8_t ver_abs_gr0 = mvd_ver != 0; - const uint32_t mvd_hor_abs = abs(mvd_hor); - const uint32_t mvd_ver_abs = abs(mvd_ver); - - - cabac->cur_ctx = &(cabac->ctx.cu_mvd_model[0]); - CABAC_BIN(cabac, (mvd_hor != 0), "abs_mvd_greater0_flag_hor"); - CABAC_BIN(cabac, (mvd_ver != 0), "abs_mvd_greater0_flag_ver"); - - cabac->cur_ctx = &(cabac->ctx.cu_mvd_model[1]); - - if (hor_abs_gr0) { - CABAC_BIN(cabac, (mvd_hor_abs>1), "abs_mvd_greater1_flag_hor"); - } - - if (ver_abs_gr0) { - CABAC_BIN(cabac, (mvd_ver_abs>1), "abs_mvd_greater1_flag_ver"); - } - - if (hor_abs_gr0) { - if (mvd_hor_abs > 1) { - kvz_cabac_write_ep_ex_golomb(state, cabac, mvd_hor_abs-2, 1); - } - uint32_t mvd_hor_sign = (mvd_hor>0)?0:1; - if(!state->cabac.only_count) - if (state->encoder_control->cfg->crypto_features & KVZ_CRYPTO_MV_SIGNS) - mvd_hor_sign = mvd_hor_sign^ff_get_key(&state->tile->dbs_g, 1); - CABAC_BIN_EP(cabac, mvd_hor_sign, "mvd_sign_flag_hor"); - } - if (ver_abs_gr0) { - if (mvd_ver_abs > 1) { - kvz_cabac_write_ep_ex_golomb(state, cabac, mvd_ver_abs-2, 1); - } - uint32_t mvd_ver_sign = (mvd_ver>0)?0:1; - if(!state->cabac.only_count) - if (state->encoder_control->cfg->crypto_features & KVZ_CRYPTO_MV_SIGNS) - mvd_ver_sign = mvd_ver_sign^ff_get_key(&state->tile->dbs_g, 1); - CABAC_BIN_EP(cabac, mvd_ver_sign, "mvd_sign_flag_ver"); - } - } - - // Signal which candidate MV to use - kvz_cabac_write_unary_max_symbol(cabac, - cabac->ctx.mvp_idx_model, - CU_GET_MV_CAND(cur_cu, ref_list_idx), - 1, - AMVP_MAX_NUM_CANDS - 1); - } - } // for ref_list - } // if !merge -} - -static void encode_intra_coding_unit(encoder_state_t * const state, - cabac_data_t * const cabac, - const cu_info_t * const cur_cu, - int x_ctb, int y_ctb, int depth) -{ - const videoframe_t * const frame = state->tile->frame; - uint8_t intra_pred_mode[4]; - - uint8_t intra_pred_mode_chroma = cur_cu->intra.mode_chroma; - int8_t intra_preds[4][3] = {{-1, -1, -1},{-1, -1, -1},{-1, -1, -1},{-1, -1, -1}}; - int8_t mpm_preds[4] = {-1, -1, -1, -1}; - uint32_t flag[4]; - - #if ENABLE_PCM == 1 - // Code must start after variable initialization - kvz_cabac_encode_bin_trm(cabac, 0); // IPCMFlag == 0 - #endif - - // PREDINFO CODING - // If intra prediction mode is found from the predictors, - // it can be signaled with two EP's. Otherwise we can send - // 5 EP bins with the full predmode - const int num_pred_units = kvz_part_mode_num_parts[cur_cu->part_size]; - const int cu_width = LCU_WIDTH >> depth; - - for (int j = 0; j < num_pred_units; ++j) { - const int pu_x = PU_GET_X(cur_cu->part_size, cu_width, x_ctb << 3, j); - const int pu_y = PU_GET_Y(cur_cu->part_size, cu_width, y_ctb << 3, j); - const cu_info_t *cur_pu = kvz_cu_array_at_const(frame->cu_array, pu_x, pu_y); - - const cu_info_t *left_pu = NULL; - const cu_info_t *above_pu = NULL; - - if (pu_x > 0) { - assert(pu_x >> 2 > 0); - left_pu = kvz_cu_array_at_const(frame->cu_array, pu_x - 1, pu_y); - } - // Don't take the above PU across the LCU boundary. - if (pu_y % LCU_WIDTH > 0 && pu_y > 0) { - assert(pu_y >> 2 > 0); - above_pu = kvz_cu_array_at_const(frame->cu_array, pu_x, pu_y - 1); - } - - kvz_intra_get_dir_luma_predictor(pu_x, pu_y, - intra_preds[j], - cur_pu, - left_pu, above_pu); - - intra_pred_mode[j] = cur_pu->intra.mode; - - for (int i = 0; i < 3; i++) { - if (intra_preds[j][i] == intra_pred_mode[j]) { - mpm_preds[j] = (int8_t)i; - break; - } - } - flag[j] = (mpm_preds[j] == -1) ? 0 : 1; - } - - cabac->cur_ctx = &(cabac->ctx.intra_mode_model); - for (int j = 0; j < num_pred_units; ++j) { - CABAC_BIN(cabac, flag[j], "prev_intra_luma_pred_flag"); - } - - for (int j = 0; j < num_pred_units; ++j) { - // Signal index of the prediction mode in the prediction list. - if (flag[j]) { - CABAC_BIN_EP(cabac, (mpm_preds[j] == 0 ? 0 : 1), "mpm_idx"); - if (mpm_preds[j] != 0) { - CABAC_BIN_EP(cabac, (mpm_preds[j] == 1 ? 0 : 1), "mpm_idx"); - } - } else { - // Signal the actual prediction mode. - int32_t tmp_pred = intra_pred_mode[j]; - - // Sort prediction list from lowest to highest. - if (intra_preds[j][0] > intra_preds[j][1]) SWAP(intra_preds[j][0], intra_preds[j][1], int8_t); - if (intra_preds[j][0] > intra_preds[j][2]) SWAP(intra_preds[j][0], intra_preds[j][2], int8_t); - if (intra_preds[j][1] > intra_preds[j][2]) SWAP(intra_preds[j][1], intra_preds[j][2], int8_t); - - // Reduce the index of the signaled prediction mode according to the - // prediction list, as it has been already signaled that it's not one - // of the prediction modes. - for (int i = 2; i >= 0; i--) { - tmp_pred = (tmp_pred > intra_preds[j][i] ? tmp_pred - 1 : tmp_pred); - } - - CABAC_BINS_EP(cabac, tmp_pred, 5, "rem_intra_luma_pred_mode"); - } - } - - { // start intra chroma pred mode coding - unsigned pred_mode = 5; - unsigned chroma_pred_modes[4] = {0, 26, 10, 1}; - - if (intra_pred_mode_chroma == intra_pred_mode[0]) { - pred_mode = 4; - } else if (intra_pred_mode_chroma == 34) { - // Angular 34 mode is possible only if intra pred mode is one of the - // possible chroma pred modes, in which case it is signaled with that - // duplicate mode. - for (int i = 0; i < 4; ++i) { - if (intra_pred_mode[0] == chroma_pred_modes[i]) pred_mode = i; - } - } else { - for (int i = 0; i < 4; ++i) { - if (intra_pred_mode_chroma == chroma_pred_modes[i]) pred_mode = i; - } - } - - // pred_mode == 5 mean intra_pred_mode_chroma is something that can't - // be coded. - assert(pred_mode != 5); - - /** - * Table 9-35 - Binarization for intra_chroma_pred_mode - * intra_chroma_pred_mode bin_string - * 4 0 - * 0 100 - * 1 101 - * 2 110 - * 3 111 - * Table 9-37 - Assignment of ctxInc to syntax elements with context coded bins - * intra_chroma_pred_mode[][] = 0, bypass, bypass - */ - cabac->cur_ctx = &(cabac->ctx.chroma_pred_model[0]); - if (pred_mode == 4) { - CABAC_BIN(cabac, 0, "intra_chroma_pred_mode"); - } else { - CABAC_BIN(cabac, 1, "intra_chroma_pred_mode"); - CABAC_BINS_EP(cabac, pred_mode, 2, "intra_chroma_pred_mode"); - } - } // end intra chroma pred mode coding - - kvz_encode_transform_coeff(state, x_ctb * 2, y_ctb * 2, depth, 0, 0, 0); -} - -void kvz_encode_coding_tree(encoder_state_t * const state, - uint16_t x_ctb, uint16_t y_ctb, uint8_t depth) -{ - cabac_data_t * const cabac = &state->cabac; - const videoframe_t * const frame = state->tile->frame; - const cu_info_t *cur_cu = kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb); - uint8_t split_flag = GET_SPLITDATA(cur_cu, depth); - uint8_t split_model = 0; - - //Absolute ctb - uint16_t abs_x_ctb = x_ctb + (state->tile->lcu_offset_x * LCU_WIDTH) / (LCU_WIDTH >> MAX_DEPTH); - uint16_t abs_y_ctb = y_ctb + (state->tile->lcu_offset_y * LCU_WIDTH) / (LCU_WIDTH >> MAX_DEPTH); - - // Check for slice border FIXME - uint8_t border_x = ((state->encoder_control->in.width) < (abs_x_ctb * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> depth))) ? 1 : 0; - uint8_t border_y = ((state->encoder_control->in.height) < (abs_y_ctb * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> depth))) ? 1 : 0; - uint8_t border_split_x = ((state->encoder_control->in.width) < ((abs_x_ctb + 1) * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> (depth + 1)))) ? 0 : 1; - uint8_t border_split_y = ((state->encoder_control->in.height) < ((abs_y_ctb + 1) * (LCU_WIDTH >> MAX_DEPTH) + (LCU_WIDTH >> (depth + 1)))) ? 0 : 1; - uint8_t border = border_x | border_y; /*!< are we in any border CU */ - - // When not in MAX_DEPTH, insert split flag and split the blocks if needed - if (depth != MAX_DEPTH) { - // Implisit split flag when on border - if (!border) { - // Get left and top block split_flags and if they are present and true, increase model number - if (x_ctb > 0 && GET_SPLITDATA(kvz_videoframe_get_cu_const(frame, x_ctb - 1, y_ctb), depth) == 1) { - split_model++; - } - - if (y_ctb > 0 && GET_SPLITDATA(kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb - 1), depth) == 1) { - split_model++; - } - - cabac->cur_ctx = &(cabac->ctx.split_flag_model[split_model]); - CABAC_BIN(cabac, split_flag, "SplitFlag"); - } - - if (split_flag || border) { - // Split blocks and remember to change x and y block positions - uint8_t change = 1<<(MAX_DEPTH-1-depth); - kvz_encode_coding_tree(state, x_ctb, y_ctb, depth + 1); // x,y - - // TODO: fix when other half of the block would not be completely over the border - if (!border_x || border_split_x) { - kvz_encode_coding_tree(state, x_ctb + change, y_ctb, depth + 1); - } - if (!border_y || border_split_y) { - kvz_encode_coding_tree(state, x_ctb, y_ctb + change, depth + 1); - } - if (!border || (border_split_x && border_split_y)) { - kvz_encode_coding_tree(state, x_ctb + change, y_ctb + change, depth + 1); - } - return; - } - } - - if (state->encoder_control->cfg->lossless) { - cabac->cur_ctx = &cabac->ctx.cu_transquant_bypass; - CABAC_BIN(cabac, 1, "cu_transquant_bypass_flag"); - } - - // Encode skip flag - if (state->global->slicetype != KVZ_SLICE_I) { - int8_t ctx_skip = 0; // uiCtxSkip = aboveskipped + leftskipped; - int ui; - int16_t num_cand = MRG_MAX_NUM_CANDS; - // Get left and top skipped flags and if they are present and true, increase context number - if (x_ctb > 0 && (kvz_videoframe_get_cu_const(frame, x_ctb - 1, y_ctb))->skipped) { - ctx_skip++; - } - - if (y_ctb > 0 && (kvz_videoframe_get_cu_const(frame, x_ctb, y_ctb - 1))->skipped) { - ctx_skip++; - } - - cabac->cur_ctx = &(cabac->ctx.cu_skip_flag_model[ctx_skip]); - CABAC_BIN(cabac, cur_cu->skipped, "SkipFlag"); - - // IF SKIP - if (cur_cu->skipped) { - if (num_cand > 1) { - for (ui = 0; ui < num_cand - 1; ui++) { - int32_t symbol = (ui != cur_cu->merge_idx); - if (ui == 0) { - cabac->cur_ctx = &(cabac->ctx.cu_merge_idx_ext_model); - CABAC_BIN(cabac, symbol, "MergeIndex"); - } else { - CABAC_BIN_EP(cabac,symbol,"MergeIndex"); - } - if (symbol == 0) { - break; - } - } - } - return; - } - } - - // ENDIF SKIP - - // Prediction mode - if (state->global->slicetype != KVZ_SLICE_I) { - cabac->cur_ctx = &(cabac->ctx.cu_pred_mode_model); - CABAC_BIN(cabac, (cur_cu->type == CU_INTRA), "PredMode"); - } - - // part_mode - encode_part_mode(state, cabac, cur_cu, depth); - - if (cur_cu->type == CU_INTER) { - const int num_pu = kvz_part_mode_num_parts[cur_cu->part_size]; - const int cu_width = LCU_WIDTH >> depth; - - for (int i = 0; i < num_pu; ++i) { - const int pu_x = PU_GET_X(cur_cu->part_size, cu_width, x_ctb << 3, i); - const int pu_y = PU_GET_Y(cur_cu->part_size, cu_width, y_ctb << 3, i); - const int pu_w = PU_GET_W(cur_cu->part_size, cu_width, i); - const int pu_h = PU_GET_H(cur_cu->part_size, cu_width, i); - const cu_info_t *cur_pu = kvz_cu_array_at_const(frame->cu_array, pu_x, pu_y); - - encode_inter_prediction_unit(state, cabac, cur_pu, pu_x, pu_y, pu_w, pu_h, depth); - } - - { - int cbf = cbf_is_set_any(cur_cu->cbf, depth); - // Only need to signal coded block flag if not skipped or merged - // skip = no coded residual, merge = coded residual - if (cur_cu->part_size != SIZE_2Nx2N || !cur_cu->merged) { - cabac->cur_ctx = &(cabac->ctx.cu_qt_root_cbf_model); - CABAC_BIN(cabac, cbf, "rqt_root_cbf"); - } - // Code (possible) coeffs to bitstream - - if (cbf) { - kvz_encode_transform_coeff(state, x_ctb * 2, y_ctb * 2, depth, 0, 0, 0); - } - } - } else if (cur_cu->type == CU_INTRA) { - encode_intra_coding_unit(state, cabac, cur_cu, x_ctb, y_ctb, depth); - } - - #if ENABLE_PCM == 1 - // Code IPCM block - if (cur_cu->type == CU_PCM) { - kvz_cabac_encode_bin_trm(cabac, 1); // IPCMFlag == 1 - kvz_cabac_finish(cabac); - kvz_bitstream_add_rbsp_trailing_bits(cabac.stream); - // PCM sample - { - unsigned y, x; - - pixel *base_y = &cur_pic->y_data[x_ctb * (LCU_WIDTH >> (MAX_DEPTH)) + (y_ctb * (LCU_WIDTH >> (MAX_DEPTH))) * encoder->in.width]; - pixel *base_u = &cur_pic->u_data[(x_ctb * (LCU_WIDTH >> (MAX_DEPTH + 1)) + (y_ctb * (LCU_WIDTH >> (MAX_DEPTH + 1))) * encoder->in.width / 2)]; - pixel *base_v = &cur_pic->v_data[(x_ctb * (LCU_WIDTH >> (MAX_DEPTH + 1)) + (y_ctb * (LCU_WIDTH >> (MAX_DEPTH + 1))) * encoder->in.width / 2)]; - - // Luma - for (y = 0; y < LCU_WIDTH >> depth; y++) { - for (x = 0; x < LCU_WIDTH >> depth; x++) { - kvz_bitstream_put(cabac.stream, base_y[x + y * encoder->in.width], 8); - } - } - - // Chroma - if (encoder->in.video_format != FORMAT_400) { - for (y = 0; y < LCU_WIDTH >> (depth + 1); y++) { - for (x = 0; x < LCU_WIDTH >> (depth + 1); x++) { - kvz_bitstream_put(cabac.stream, base_u[x + y * (encoder->in.width >> 1)], 8); - } - } - for (y = 0; y < LCU_WIDTH >> (depth + 1); y++) { - for (x = 0; x < LCU_WIDTH >> (depth + 1); x++) { - kvz_bitstream_put(cabac.stream, base_v[x + y * (encoder->in.width >> 1)], 8); - } - } - } - } - // end PCM sample - kvz_cabac_start(cabac); - } // end Code IPCM block -#endif /* END ENABLE_PCM */ - else { /* Should not happend */ - printf("UNHANDLED TYPE!\r\n"); - assert(0); - exit(1); - } - - /* end prediction unit */ - /* end coding_unit */ -} - - coeff_scan_order_t kvz_get_scan_order(int8_t cu_type, int intra_mode, int depth) { // Scan mode is diagonal, except for 4x4+8x8 luma and 4x4 chroma, where: @@ -1577,481 +1012,3 @@ coeff_scan_order_t kvz_get_scan_order(int8_t cu_type, int intra_mode, int depth) return SCAN_DIAG; } - - -static void encode_transform_unit(encoder_state_t * const state, - int x_pu, int y_pu, int depth) -{ - assert(depth >= 1 && depth <= MAX_PU_DEPTH); - - const videoframe_t * const frame = state->tile->frame; - const uint8_t width = LCU_WIDTH >> depth; - const uint8_t width_c = (depth == MAX_PU_DEPTH ? width : width / 2); - - const cu_info_t *cur_pu = kvz_cu_array_at_const(frame->cu_array, x_pu << 2, y_pu << 2); - - const int x_cu = x_pu / 2; - const int y_cu = y_pu / 2; - const cu_info_t *cur_cu = kvz_videoframe_get_cu_const(frame, x_cu, y_cu); - - coeff_t coeff_y[LCU_WIDTH*LCU_WIDTH+1]; - coeff_t coeff_u[LCU_WIDTH*LCU_WIDTH>>2]; - coeff_t coeff_v[LCU_WIDTH*LCU_WIDTH>>2]; - int32_t coeff_stride = frame->width; - - int8_t scan_idx = kvz_get_scan_order(cur_pu->type, cur_pu->intra.mode, depth); - - int cbf_y = cbf_is_set(cur_pu->cbf, depth, COLOR_Y); - - if (cbf_y) { - int x = x_pu * (LCU_WIDTH >> MAX_PU_DEPTH); - int y = y_pu * (LCU_WIDTH >> MAX_PU_DEPTH); - coeff_t *orig_pos = &frame->coeff_y[x + y * frame->width]; - for (y = 0; y < width; y++) { - for (x = 0; x < width; x++) { - coeff_y[x+y*width] = orig_pos[x]; - } - orig_pos += coeff_stride; - } - } - - // CoeffNxN - // Residual Coding - if (cbf_y) { - kvz_encode_coeff_nxn(state, coeff_y, width, 0, scan_idx, cur_pu->intra.tr_skip); - } - - if (depth == MAX_DEPTH + 1 && !(x_pu % 2 && y_pu % 2)) { - // For size 4x4 luma transform the corresponding chroma transforms are - // also of size 4x4 covering 8x8 luma pixels. The residual is coded - // in the last transform unit so for the other ones, don't do anything. - return; - } - - bool chroma_cbf_set = cbf_is_set(cur_cu->cbf, depth, COLOR_U) || - cbf_is_set(cur_cu->cbf, depth, COLOR_V); - if (chroma_cbf_set) { - int x, y; - coeff_t *orig_pos_u, *orig_pos_v; - - if (depth <= MAX_DEPTH) { - x = x_pu * (LCU_WIDTH >> (MAX_PU_DEPTH + 1)); - y = y_pu * (LCU_WIDTH >> (MAX_PU_DEPTH + 1)); - } else { - // for 4x4 select top left pixel of the CU. - x = x_cu * (LCU_WIDTH >> (MAX_DEPTH + 1)); - y = y_cu * (LCU_WIDTH >> (MAX_DEPTH + 1)); - } - orig_pos_u = &frame->coeff_u[x + y * (frame->width >> 1)]; - orig_pos_v = &frame->coeff_v[x + y * (frame->width >> 1)]; - for (y = 0; y < (width_c); y++) { - for (x = 0; x < (width_c); x++) { - coeff_u[x+y*(width_c)] = orig_pos_u[x]; - coeff_v[x+y*(width_c)] = orig_pos_v[x]; - } - orig_pos_u += coeff_stride>>1; - orig_pos_v += coeff_stride>>1; - } - - scan_idx = kvz_get_scan_order(cur_cu->type, cur_cu->intra.mode_chroma, depth); - - if (cbf_is_set(cur_cu->cbf, depth, COLOR_U)) { - kvz_encode_coeff_nxn(state, coeff_u, width_c, 2, scan_idx, 0); - } - - if (cbf_is_set(cur_cu->cbf, depth, COLOR_V)) { - kvz_encode_coeff_nxn(state, coeff_v, width_c, 2, scan_idx, 0); - } - } -} - -/** - * \param encoder - * \param x_pu Prediction units' x coordinate. - * \param y_pu Prediction units' y coordinate. - * \param depth Depth from LCU. - * \param tr_depth Depth from last CU. - * \param parent_coeff_u What was signaled at previous level for cbf_cb. - * \param parent_coeff_v What was signlaed at previous level for cbf_cr. - */ -void kvz_encode_transform_coeff(encoder_state_t * const state, int32_t x_pu,int32_t y_pu, - int8_t depth, int8_t tr_depth, uint8_t parent_coeff_u, uint8_t parent_coeff_v) -{ - cabac_data_t * const cabac = &state->cabac; - const videoframe_t * const frame = state->tile->frame; - - const cu_info_t *cur_pu = kvz_cu_array_at_const(frame->cu_array, x_pu << 2, y_pu << 2); - - const int32_t x_cu = x_pu / 2; - const int32_t y_cu = y_pu / 2; - const cu_info_t *cur_cu = kvz_videoframe_get_cu_const(frame, x_cu, y_cu); - - // NxN signifies implicit transform split at the first transform level. - // There is a similar implicit split for inter, but it is only used when - // transform hierarchy is not in use. - int intra_split_flag = (cur_cu->type == CU_INTRA && cur_cu->part_size == SIZE_NxN); - - // The implicit split by intra NxN is not counted towards max_tr_depth. - int tr_depth_intra = state->encoder_control->tr_depth_intra; - int max_tr_depth = (cur_cu->type == CU_INTRA ? tr_depth_intra + intra_split_flag : TR_DEPTH_INTER); - - int8_t split = (cur_cu->tr_depth > depth); - - const int cb_flag_y = cbf_is_set(cur_pu->cbf, depth, COLOR_Y); - const int cb_flag_u = cbf_is_set(cur_cu->cbf, depth, COLOR_U); - const int cb_flag_v = cbf_is_set(cur_cu->cbf, depth, COLOR_V); - - // The split_transform_flag is not signaled when: - // - transform size is greater than 32 (depth == 0) - // - transform size is 4 (depth == MAX_PU_DEPTH) - // - transform depth is max - // - cu is intra NxN and it's the first split - if (depth > 0 && - depth < MAX_PU_DEPTH && - tr_depth < max_tr_depth && - !(intra_split_flag && tr_depth == 0)) - { - cabac->cur_ctx = &(cabac->ctx.trans_subdiv_model[5 - ((kvz_g_convert_to_bit[LCU_WIDTH] + 2) - depth)]); - CABAC_BIN(cabac, split, "split_transform_flag"); - } - - // Chroma cb flags are not signaled when one of the following: - // - transform size is 4 (2x2 chroma transform doesn't exist) - // - they have already been signaled to 0 previously - // When they are not present they are inferred to be 0, except for size 4 - // when the flags from previous level are used. - if (depth < MAX_PU_DEPTH) { - cabac->cur_ctx = &(cabac->ctx.qt_cbf_model_chroma[tr_depth]); - if (tr_depth == 0 || parent_coeff_u) { - CABAC_BIN(cabac, cb_flag_u, "cbf_cb"); - } - if (tr_depth == 0 || parent_coeff_v) { - CABAC_BIN(cabac, cb_flag_v, "cbf_cr"); - } - } - - if (split) { - uint8_t pu_offset = 1 << (MAX_PU_DEPTH - (depth + 1)); - kvz_encode_transform_coeff(state, x_pu, y_pu, depth + 1, tr_depth + 1, cb_flag_u, cb_flag_v); - kvz_encode_transform_coeff(state, x_pu + pu_offset, y_pu, depth + 1, tr_depth + 1, cb_flag_u, cb_flag_v); - kvz_encode_transform_coeff(state, x_pu, y_pu + pu_offset, depth + 1, tr_depth + 1, cb_flag_u, cb_flag_v); - kvz_encode_transform_coeff(state, x_pu + pu_offset, y_pu + pu_offset, depth + 1, tr_depth + 1, cb_flag_u, cb_flag_v); - return; - } - - // Luma coded block flag is signaled when one of the following: - // - prediction mode is intra - // - transform depth > 0 - // - we have chroma coefficients at this level - // When it is not present, it is inferred to be 1. - if(cur_cu->type == CU_INTRA || tr_depth > 0 || cb_flag_u || cb_flag_v) { - cabac->cur_ctx = &(cabac->ctx.qt_cbf_model_luma[!tr_depth]); - CABAC_BIN(cabac, cb_flag_y, "cbf_luma"); - } - - if (cb_flag_y | cb_flag_u | cb_flag_v) { - encode_transform_unit(state, x_pu, y_pu, depth); - } -} - -void kvz_encode_coeff_nxn(encoder_state_t * const state, coeff_t *coeff, uint8_t width, - uint8_t type, int8_t scan_mode, int8_t tr_skip) -{ - const encoder_control_t * const encoder = state->encoder_control; - cabac_data_t * const cabac = &state->cabac; - int c1 = 1; - uint8_t last_coeff_x = 0; - uint8_t last_coeff_y = 0; - int32_t i; - uint32_t sig_coeffgroup_flag[8 * 8] = { 0 }; - - int8_t be_valid = encoder->sign_hiding; - int32_t scan_pos_sig; - uint32_t go_rice_param = 0; - uint32_t blk_pos, pos_y, pos_x, sig, ctx_sig; - - // CONSTANTS - const uint32_t num_blk_side = width >> TR_MIN_LOG2_SIZE; - const uint32_t log2_block_size = kvz_g_convert_to_bit[width] + 2; - const uint32_t *scan = - kvz_g_sig_last_scan[scan_mode][log2_block_size - 1]; - const uint32_t *scan_cg = g_sig_last_scan_cg[log2_block_size - 2][scan_mode]; - - // Init base contexts according to block type - cabac_ctx_t *base_coeff_group_ctx = &(cabac->ctx.cu_sig_coeff_group_model[type]); - cabac_ctx_t *baseCtx = (type == 0) ? &(cabac->ctx.cu_sig_model_luma[0]) : - &(cabac->ctx.cu_sig_model_chroma[0]); - - // Scan all coeff groups to find out which of them have coeffs. - // Populate sig_coeffgroup_flag with that info. - - unsigned sig_cg_cnt = 0; - for (int cg_y = 0; cg_y < width / 4; ++cg_y) { - for (int cg_x = 0; cg_x < width / 4; ++cg_x) { - unsigned cg_pos = cg_y * width * 4 + cg_x * 4; - for (int coeff_row = 0; coeff_row < 4; ++coeff_row) { - // Load four 16-bit coeffs and see if any of them are non-zero. - unsigned coeff_pos = cg_pos + coeff_row * width; - uint64_t four_coeffs = *(uint64_t*)(&coeff[coeff_pos]); - if (four_coeffs) { - ++sig_cg_cnt; - unsigned cg_pos_y = (cg_pos >> log2_block_size) >> TR_MIN_LOG2_SIZE; - unsigned cg_pos_x = (cg_pos & (width - 1)) >> TR_MIN_LOG2_SIZE; - sig_coeffgroup_flag[cg_pos_x + cg_pos_y * num_blk_side] = 1; - break; - } - } - } - } - - // Rest of the code assumes at least one non-zero coeff. - assert(sig_cg_cnt > 0); - - // Find the last coeff group by going backwards in scan order. - unsigned scan_cg_last = num_blk_side * num_blk_side - 1; - while (!sig_coeffgroup_flag[scan_cg[scan_cg_last]]) { - --scan_cg_last; - } - - // Find the last coeff by going backwards in scan order. - unsigned scan_pos_last = scan_cg_last * 16 + 15; - while (!coeff[scan[scan_pos_last]]) { - --scan_pos_last; - } - - int pos_last = scan[scan_pos_last]; - - // transform skip flag - if(width == 4 && encoder->trskip_enable) { - cabac->cur_ctx = (type == 0) ? &(cabac->ctx.transform_skip_model_luma) : &(cabac->ctx.transform_skip_model_chroma); - CABAC_BIN(cabac, tr_skip, "transform_skip_flag"); - } - - last_coeff_x = pos_last & (width - 1); - last_coeff_y = (uint8_t)(pos_last >> log2_block_size); - - // Code last_coeff_x and last_coeff_y - kvz_encode_last_significant_xy(state, last_coeff_x, last_coeff_y, width, width, - type, scan_mode); - - scan_pos_sig = scan_pos_last; - - // significant_coeff_flag - for (i = scan_cg_last; i >= 0; i--) { - int32_t sub_pos = i << 4; // LOG2_SCAN_SET_SIZE; - int32_t abs_coeff[16]; - int32_t cg_blk_pos = scan_cg[i]; - int32_t cg_pos_y = cg_blk_pos / num_blk_side; - int32_t cg_pos_x = cg_blk_pos - (cg_pos_y * num_blk_side); - - uint32_t coeff_signs = 0; - int32_t last_nz_pos_in_cg = -1; - int32_t first_nz_pos_in_cg = 16; - int32_t num_non_zero = 0; - go_rice_param = 0; - - if (scan_pos_sig == scan_pos_last) { - abs_coeff[0] = abs(coeff[pos_last]); - coeff_signs = (coeff[pos_last] < 0); - num_non_zero = 1; - last_nz_pos_in_cg = scan_pos_sig; - first_nz_pos_in_cg = scan_pos_sig; - scan_pos_sig--; - } - - if (i == scan_cg_last || i == 0) { - sig_coeffgroup_flag[cg_blk_pos] = 1; - } else { - uint32_t sig_coeff_group = (sig_coeffgroup_flag[cg_blk_pos] != 0); - uint32_t ctx_sig = kvz_context_get_sig_coeff_group(sig_coeffgroup_flag, cg_pos_x, - cg_pos_y, width); - cabac->cur_ctx = &base_coeff_group_ctx[ctx_sig]; - CABAC_BIN(cabac, sig_coeff_group, "coded_sub_block_flag"); - } - - if (sig_coeffgroup_flag[cg_blk_pos]) { - int32_t pattern_sig_ctx = kvz_context_calc_pattern_sig_ctx(sig_coeffgroup_flag, - cg_pos_x, cg_pos_y, width); - - for (; scan_pos_sig >= sub_pos; scan_pos_sig--) { - blk_pos = scan[scan_pos_sig]; - pos_y = blk_pos >> log2_block_size; - pos_x = blk_pos - (pos_y << log2_block_size); - sig = (coeff[blk_pos] != 0) ? 1 : 0; - - if (scan_pos_sig > sub_pos || i == 0 || num_non_zero) { - ctx_sig = kvz_context_get_sig_ctx_inc(pattern_sig_ctx, scan_mode, pos_x, pos_y, - log2_block_size, type); - cabac->cur_ctx = &baseCtx[ctx_sig]; - CABAC_BIN(cabac, sig, "sig_coeff_flag"); - } - - if (sig) { - abs_coeff[num_non_zero] = abs(coeff[blk_pos]); - coeff_signs = 2 * coeff_signs + (coeff[blk_pos] < 0); - num_non_zero++; - - if (last_nz_pos_in_cg == -1) { - last_nz_pos_in_cg = scan_pos_sig; - } - - first_nz_pos_in_cg = scan_pos_sig; - } - } - } else { - scan_pos_sig = sub_pos - 1; - } - - if (num_non_zero > 0) { - bool sign_hidden = last_nz_pos_in_cg - first_nz_pos_in_cg >= 4 /* SBH_THRESHOLD */ - && !encoder->cfg->lossless; - uint32_t ctx_set = (i > 0 && type == 0) ? 2 : 0; - cabac_ctx_t *base_ctx_mod; - int32_t num_c1_flag, first_c2_flag_idx, idx, first_coeff2; - - if (c1 == 0) { - ctx_set++; - } - - c1 = 1; - - base_ctx_mod = (type == 0) ? &(cabac->ctx.cu_one_model_luma[4 * ctx_set]) : - &(cabac->ctx.cu_one_model_chroma[4 * ctx_set]); - num_c1_flag = MIN(num_non_zero, C1FLAG_NUMBER); - first_c2_flag_idx = -1; - - for (idx = 0; idx < num_c1_flag; idx++) { - uint32_t symbol = (abs_coeff[idx] > 1) ? 1 : 0; - cabac->cur_ctx = &base_ctx_mod[c1]; - CABAC_BIN(cabac, symbol, "coeff_abs_level_greater1_flag"); - - if (symbol) { - c1 = 0; - - if (first_c2_flag_idx == -1) { - first_c2_flag_idx = idx; - } - } else if ((c1 < 3) && (c1 > 0)) { - c1++; - } - } - - if (c1 == 0) { - base_ctx_mod = (type == 0) ? &(cabac->ctx.cu_abs_model_luma[ctx_set]) : - &(cabac->ctx.cu_abs_model_chroma[ctx_set]); - - if (first_c2_flag_idx != -1) { - uint8_t symbol = (abs_coeff[first_c2_flag_idx] > 2) ? 1 : 0; - cabac->cur_ctx = &base_ctx_mod[0]; - CABAC_BIN(cabac, symbol, "coeff_abs_level_greater2_flag"); - } - } - if (be_valid && sign_hidden) { - coeff_signs = coeff_signs >> 1; - if(!state->cabac.only_count) - if (state->encoder_control->cfg->crypto_features & KVZ_CRYPTO_TRANSF_COEFF_SIGNS) { - coeff_signs = coeff_signs ^ ff_get_key(&state->tile->dbs_g, num_non_zero-1); - } - CABAC_BINS_EP(cabac, coeff_signs , (num_non_zero - 1), "coeff_sign_flag"); - } else { - if(!state->cabac.only_count) - if (state->encoder_control->cfg->crypto_features & KVZ_CRYPTO_TRANSF_COEFF_SIGNS) - coeff_signs = coeff_signs ^ ff_get_key(&state->tile->dbs_g, num_non_zero); - CABAC_BINS_EP(cabac, coeff_signs, num_non_zero, "coeff_sign_flag"); - } - - if (c1 == 0 || num_non_zero > C1FLAG_NUMBER) { - first_coeff2 = 1; - - for (idx = 0; idx < num_non_zero; idx++) { - int32_t base_level = (idx < C1FLAG_NUMBER) ? (2 + first_coeff2) : 1; - - if (abs_coeff[idx] >= base_level) { - if(!state->cabac.only_count) { - if (state->encoder_control->cfg->crypto_features & KVZ_CRYPTO_TRANSF_COEFFS) - kvz_cabac_write_coeff_remain_encry(state, cabac, abs_coeff[idx] - base_level, go_rice_param, base_level); - else - kvz_cabac_write_coeff_remain(cabac, abs_coeff[idx] - base_level, go_rice_param); - } else - kvz_cabac_write_coeff_remain(cabac, abs_coeff[idx] - base_level, go_rice_param); - - if (abs_coeff[idx] > 3 * (1 << go_rice_param)) { - go_rice_param = MIN(go_rice_param + 1, 4); - } - } - - if (abs_coeff[idx] >= 2) { - first_coeff2 = 0; - } - } - } - } - } -} - -/*! - \brief Encode (X,Y) position of the last significant coefficient - \param lastpos_x X component of last coefficient - \param lastpos_y Y component of last coefficient - \param width Block width - \param height Block height - \param type plane type / luminance or chrominance - \param scan scan type (diag, hor, ver) - - This method encodes the X and Y component within a block of the last significant coefficient. -*/ -void kvz_encode_last_significant_xy(encoder_state_t * const state, - uint8_t lastpos_x, uint8_t lastpos_y, - uint8_t width, uint8_t height, - uint8_t type, uint8_t scan) -{ - cabac_data_t * const cabac = &state->cabac; - - const int index = kvz_math_floor_log2(width) - 2; - uint8_t ctx_offset = type ? 0 : (index * 3 + (index + 1) / 4); - uint8_t shift = type ? index : (index + 3) / 4; - - cabac_ctx_t *base_ctx_x = (type ? cabac->ctx.cu_ctx_last_x_chroma : cabac->ctx.cu_ctx_last_x_luma); - cabac_ctx_t *base_ctx_y = (type ? cabac->ctx.cu_ctx_last_y_chroma : cabac->ctx.cu_ctx_last_y_luma); - - if (scan == SCAN_VER) { - SWAP(lastpos_x, lastpos_y, uint8_t); - } - - const int group_idx_x = g_group_idx[lastpos_x]; - const int group_idx_y = g_group_idx[lastpos_y]; - - // x prefix - for (int last_x = 0; last_x < group_idx_x; last_x++) { - cabac->cur_ctx = &base_ctx_x[ctx_offset + (last_x >> shift)]; - CABAC_BIN(cabac, 1, "last_sig_coeff_x_prefix"); - } - if (group_idx_x < g_group_idx[width - 1]) { - cabac->cur_ctx = &base_ctx_x[ctx_offset + (group_idx_x >> shift)]; - CABAC_BIN(cabac, 0, "last_sig_coeff_x_prefix"); - } - - // y prefix - for (int last_y = 0; last_y < group_idx_y; last_y++) { - cabac->cur_ctx = &base_ctx_y[ctx_offset + (last_y >> shift)]; - CABAC_BIN(cabac, 1, "last_sig_coeff_y_prefix"); - } - if (group_idx_y < g_group_idx[height - 1]) { - cabac->cur_ctx = &base_ctx_y[ctx_offset + (group_idx_y >> shift)]; - CABAC_BIN(cabac, 0, "last_sig_coeff_y_prefix"); - } - - // last_sig_coeff_x_suffix - if (group_idx_x > 3) { - const int suffix = lastpos_x - g_min_in_group[group_idx_x]; - const int bits = (group_idx_x - 2) / 2; - CABAC_BINS_EP(cabac, suffix, bits, "last_sig_coeff_x_suffix"); - } - - // last_sig_coeff_y_suffix - if (group_idx_y > 3) { - const int suffix = lastpos_y - g_min_in_group[group_idx_y]; - const int bits = (group_idx_y - 2) / 2; - CABAC_BINS_EP(cabac, suffix, bits, "last_sig_coeff_y_suffix"); - } -} diff --git a/src/encoderstate.h b/src/encoderstate.h index 5fcf58e3..c6901970 100644 --- a/src/encoderstate.h +++ b/src/encoderstate.h @@ -206,20 +206,6 @@ void kvz_encode_one_frame(encoder_state_t * const state, kvz_picture* frame); void kvz_encoder_prepare(encoder_state_t *state); -void kvz_encode_coding_tree(encoder_state_t *state, uint16_t x_ctb, - uint16_t y_ctb, uint8_t depth); - -void kvz_encode_last_significant_xy(encoder_state_t *state, - uint8_t lastpos_x, uint8_t lastpos_y, - uint8_t width, uint8_t height, - uint8_t type, uint8_t scan); -void kvz_encode_coeff_nxn(encoder_state_t *state, coeff_t *coeff, uint8_t width, - uint8_t type, int8_t scan_mode, int8_t tr_skip); -void kvz_encode_transform_coeff(encoder_state_t *state, int32_t x_cu, int32_t y_cu, - int8_t depth, int8_t tr_depth, uint8_t parent_coeff_u, uint8_t parent_coeff_v); -void encode_block_residual(const encoder_control_t * const encoder, - uint16_t x_ctb, uint16_t y_ctb, uint8_t depth); - int kvz_encoder_state_match_children_of_previous_frame(encoder_state_t * const state); coeff_scan_order_t kvz_get_scan_order(int8_t cu_type, int intra_mode, int depth); diff --git a/src/rdo.c b/src/rdo.c index 884349af..247ee15c 100644 --- a/src/rdo.c +++ b/src/rdo.c @@ -25,6 +25,7 @@ #include "cabac.h" #include "context.h" +#include "encode_coding_tree.h" #include "encoder.h" #include "imagelist.h" #include "inter.h" From 5fbb0a8c27acb836dff86b230b723353ebb79e8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Tue, 9 Aug 2016 22:16:33 +0900 Subject: [PATCH 2/3] Fix includes --- src/cabac.c | 4 ++++ src/encoder_state-ctors_dtors.c | 2 ++ src/image.c | 2 +- src/input_frame_buffer.c | 1 - src/inter.c | 2 +- src/intra.c | 1 - src/rdo.c | 1 - src/rdo.h | 2 -- src/sao.c | 2 +- src/search.c | 1 - src/search_inter.c | 1 - src/search_inter.h | 1 + src/strategies/generic/picture-generic.c | 1 - src/transform.c | 1 - 14 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/cabac.c b/src/cabac.c index 3a1c2db6..c4b639c9 100644 --- a/src/cabac.c +++ b/src/cabac.c @@ -19,7 +19,11 @@ ****************************************************************************/ #include "cabac.h" + +#include "encoder.h" #include "encoderstate.h" +#include "extras/crypto.h" +#include "kvazaar.h" const uint8_t kvz_g_auc_next_state_mps[128] = { diff --git a/src/encoder_state-ctors_dtors.c b/src/encoder_state-ctors_dtors.c index c5606f5f..a4b7f4fe 100644 --- a/src/encoder_state-ctors_dtors.c +++ b/src/encoder_state-ctors_dtors.c @@ -29,8 +29,10 @@ #include "encoder.h" #include "encoder_state-geometry.h" #include "encoderstate.h" +#include "extras/crypto.h" #include "image.h" #include "imagelist.h" +#include "kvazaar.h" #include "threadqueue.h" #include "videoframe.h" diff --git a/src/image.c b/src/image.c index e91d5fa2..a4816589 100644 --- a/src/image.c +++ b/src/image.c @@ -536,4 +536,4 @@ void kvz_pixels_blit(const kvz_pixel * const orig, kvz_pixel * const dst, } break; } -} \ No newline at end of file +} diff --git a/src/input_frame_buffer.c b/src/input_frame_buffer.c index b746714e..c3990a09 100644 --- a/src/input_frame_buffer.c +++ b/src/input_frame_buffer.c @@ -23,7 +23,6 @@ #include "encoder.h" #include "encoderstate.h" #include "image.h" -#include "videoframe.h" void kvz_init_input_frame_buffer(input_frame_buffer_t *input_buffer) diff --git a/src/inter.c b/src/inter.c index 8e5544d0..b35f8b02 100644 --- a/src/inter.c +++ b/src/inter.c @@ -25,9 +25,9 @@ #include "encoder.h" #include "imagelist.h" -#include "strategies/generic/ipol-generic.h" #include "strategies/generic/picture-generic.h" #include "strategies/strategies-ipol.h" +#include "videoframe.h" static void inter_recon_frac_luma(const encoder_state_t * const state, diff --git a/src/intra.c b/src/intra.c index 8c82b787..63230987 100644 --- a/src/intra.c +++ b/src/intra.c @@ -25,7 +25,6 @@ #include "image.h" #include "kvz_math.h" #include "strategies/strategies-intra.h" -#include "strategies/strategies-picture.h" #include "tables.h" #include "transform.h" #include "videoframe.h" diff --git a/src/rdo.c b/src/rdo.c index 247ee15c..429f3c86 100644 --- a/src/rdo.c +++ b/src/rdo.c @@ -30,7 +30,6 @@ #include "imagelist.h" #include "inter.h" #include "scalinglist.h" -#include "strategies/strategies-quant.h" #include "tables.h" #include "transform.h" diff --git a/src/rdo.h b/src/rdo.h index c2810d75..594ca341 100644 --- a/src/rdo.h +++ b/src/rdo.h @@ -30,9 +30,7 @@ #include "cu.h" #include "encoderstate.h" #include "global.h" // IWYU pragma: keep -#include "inter.h" #include "search_inter.h" -#include "kvazaar.h" extern const uint32_t kvz_g_go_rice_range[5]; diff --git a/src/sao.c b/src/sao.c index 04e23c1e..2e94d5df 100644 --- a/src/sao.c +++ b/src/sao.c @@ -25,8 +25,8 @@ #include #include "cabac.h" +#include "image.h" #include "rdo.h" -#include "strategies/strategies-picture.h" #include "strategies/strategies-sao.h" diff --git a/src/search.c b/src/search.c index 79014876..7bcec148 100644 --- a/src/search.c +++ b/src/search.c @@ -32,7 +32,6 @@ #include "rdo.h" #include "search_inter.h" #include "search_intra.h" -#include "strategies/strategies-picture.h" #include "threadqueue.h" #include "transform.h" #include "videoframe.h" diff --git a/src/search_inter.c b/src/search_inter.c index 350c9db9..216a2338 100644 --- a/src/search_inter.c +++ b/src/search_inter.c @@ -22,7 +22,6 @@ #include #include -#include #include "cabac.h" #include "encoder.h" diff --git a/src/search_inter.h b/src/search_inter.h index 9f24cd3a..3486ec6e 100644 --- a/src/search_inter.h +++ b/src/search_inter.h @@ -30,6 +30,7 @@ #include "encoderstate.h" #include "global.h" // IWYU pragma: keep #include "inter.h" +#include "kvazaar.h" #define FILTER_SIZE 8 #define HALF_FILTER (FILTER_SIZE>>1) diff --git a/src/strategies/generic/picture-generic.c b/src/strategies/generic/picture-generic.c index 6dc310b9..e9e8e4e3 100644 --- a/src/strategies/generic/picture-generic.c +++ b/src/strategies/generic/picture-generic.c @@ -21,7 +21,6 @@ #include "strategies/generic/picture-generic.h" #include -#include #include "strategies/strategies-picture.h" #include "strategyselector.h" diff --git a/src/transform.c b/src/transform.c index 65258084..b98ad236 100644 --- a/src/transform.c +++ b/src/transform.c @@ -24,7 +24,6 @@ #include "kvazaar.h" #include "rdo.h" #include "strategies/strategies-dct.h" -#include "strategies/strategies-picture.h" #include "strategies/strategies-quant.h" #include "tables.h" From 2a946bd88e52a701719b8808ecdf6a9aac7662f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arttu=20Yl=C3=A4-Outinen?= Date: Wed, 10 Aug 2016 09:46:23 +0900 Subject: [PATCH 3/3] Rename encoder_state_t.global to frame "Frame" is more accurate than "global" since when OWF is used, encoder states for each frame have their own struct. --- src/encode_coding_tree.c | 14 +-- src/encoder_state-bitstream.c | 68 +++++----- src/encoder_state-ctors_dtors.c | 60 ++++----- src/encoderstate.c | 166 ++++++++++++------------- src/encoderstate.h | 18 +-- src/filter.c | 6 +- src/input_frame_buffer.c | 12 +- src/inter.c | 16 +-- src/kvazaar.c | 16 +-- src/rate_control.c | 48 +++---- src/rdo.c | 36 +++--- src/sao.c | 12 +- src/search.c | 34 ++--- src/search_inter.c | 24 ++-- src/search_intra.c | 14 +-- src/strategies/avx2/quant-avx2.c | 6 +- src/strategies/generic/quant-generic.c | 6 +- src/transform.c | 2 +- 18 files changed, 279 insertions(+), 279 deletions(-) diff --git a/src/encode_coding_tree.c b/src/encode_coding_tree.c index 9167a5a6..5245652c 100644 --- a/src/encode_coding_tree.c +++ b/src/encode_coding_tree.c @@ -550,8 +550,8 @@ static void encode_inter_prediction_unit(encoder_state_t * const state, uint32_t ref_list_idx; uint32_t j; int ref_list[2] = { 0, 0 }; - for (j = 0; j < state->global->ref->used_size; j++) { - if (state->global->ref->pocs[j] < state->global->poc) { + for (j = 0; j < state->frame->ref->used_size; j++) { + if (state->frame->ref->pocs[j] < state->frame->poc) { ref_list[0]++; } else { ref_list[1]++; @@ -559,7 +559,7 @@ static void encode_inter_prediction_unit(encoder_state_t * const state, } // Void TEncSbac::codeInterDir( TComDataCU* pcCU, UInt uiAbsPartIdx ) - if (state->global->slicetype == KVZ_SLICE_B) + if (state->frame->slicetype == KVZ_SLICE_B) { // Code Inter Dir uint8_t inter_dir = cur_cu->inter.mv_dir-1; @@ -582,7 +582,7 @@ static void encode_inter_prediction_unit(encoder_state_t * const state, if (cur_cu->inter.mv_dir & (1 << ref_list_idx)) { if (ref_list[ref_list_idx] > 1) { // parseRefFrmIdx - int32_t ref_frame = state->global->refmap[cur_cu->inter.mv_ref[ref_list_idx]].idx; + int32_t ref_frame = state->frame->refmap[cur_cu->inter.mv_ref[ref_list_idx]].idx; cabac->cur_ctx = &(cabac->ctx.cu_ref_pic_model[0]); CABAC_BIN(cabac, (ref_frame != 0), "ref_idx_lX"); @@ -607,7 +607,7 @@ static void encode_inter_prediction_unit(encoder_state_t * const state, } } - if (!(/*pcCU->getSlice()->getMvdL1ZeroFlag() &&*/ state->global->ref_list == REF_PIC_LIST_1 && cur_cu->inter.mv_dir == 3)) { + if (!(/*pcCU->getSlice()->getMvdL1ZeroFlag() &&*/ state->frame->ref_list == REF_PIC_LIST_1 && cur_cu->inter.mv_dir == 3)) { int16_t mv_cand[2][2]; kvz_inter_get_mv_cand_cua( @@ -954,7 +954,7 @@ void kvz_encode_coding_tree(encoder_state_t * const state, } // Encode skip flag - if (state->global->slicetype != KVZ_SLICE_I) { + if (state->frame->slicetype != KVZ_SLICE_I) { int8_t ctx_skip = 0; // uiCtxSkip = aboveskipped + leftskipped; int ui; int16_t num_cand = MRG_MAX_NUM_CANDS; @@ -993,7 +993,7 @@ void kvz_encode_coding_tree(encoder_state_t * const state, // ENDIF SKIP // Prediction mode - if (state->global->slicetype != KVZ_SLICE_I) { + if (state->frame->slicetype != KVZ_SLICE_I) { cabac->cur_ctx = &(cabac->ctx.cu_pred_mode_model); CABAC_BIN(cabac, (cur_cu->type == CU_INTRA), "PredMode"); } diff --git a/src/encoder_state-bitstream.c b/src/encoder_state-bitstream.c index a8998d7c..db44aff1 100644 --- a/src/encoder_state-bitstream.c +++ b/src/encoder_state-bitstream.c @@ -46,8 +46,8 @@ static void encoder_state_write_bitstream_aud(encoder_state_t * const state) bitstream_t * const stream = &state->stream; kvz_nal_write(stream, KVZ_NAL_AUD_NUT, 0, 1); - uint8_t pic_type = state->global->slicetype == KVZ_SLICE_I ? 0 - : state->global->slicetype == KVZ_SLICE_P ? 1 + uint8_t pic_type = state->frame->slicetype == KVZ_SLICE_I ? 0 + : state->frame->slicetype == KVZ_SLICE_P ? 1 : 2; WRITE_U(stream, pic_type, 3, "pic_type"); @@ -579,7 +579,7 @@ static void encoder_state_write_picture_timing_sei_message(encoder_state_t * con if (state->encoder_control->vui.frame_field_info_present_flag){ - int8_t odd_picture = state->global->frame % 2; + int8_t odd_picture = state->frame->num % 2; int8_t pic_struct = 0; //0: progressive picture, 1: top field, 2: bottom field, 3... int8_t source_scan_type = 1; //0: interlaced, 1: progressive @@ -651,22 +651,22 @@ void kvz_encoder_state_write_bitstream_slice_header(encoder_state_t * const stat int ref_negative = 0; int ref_positive = 0; if (encoder->cfg->gop_len) { - for (j = 0; j < state->global->ref->used_size; j++) { - if (state->global->ref->pocs[j] < state->global->poc) { + for (j = 0; j < state->frame->ref->used_size; j++) { + if (state->frame->ref->pocs[j] < state->frame->poc) { ref_negative++; } else { ref_positive++; } } - } else ref_negative = state->global->ref->used_size; + } else ref_negative = state->frame->ref->used_size; #ifdef KVZ_DEBUG printf("=========== Slice ===========\n"); #endif WRITE_U(stream, (state->slice->start_in_rs == 0), 1, "first_slice_segment_in_pic_flag"); - if (state->global->pictype >= KVZ_NAL_BLA_W_LP - && state->global->pictype <= KVZ_NAL_RSV_IRAP_VCL23) { + if (state->frame->pictype >= KVZ_NAL_BLA_W_LP + && state->frame->pictype <= KVZ_NAL_RSV_IRAP_VCL23) { WRITE_U(stream, 1, 1, "no_output_of_prior_pics_flag"); } @@ -677,7 +677,7 @@ void kvz_encoder_state_write_bitstream_slice_header(encoder_state_t * const stat WRITE_UE(stream, state->slice->start_in_rs, "slice_segment_address"); } - WRITE_UE(stream, state->global->slicetype, "slice_type"); + WRITE_UE(stream, state->frame->slicetype, "slice_type"); // if !entropy_slice_flag @@ -685,12 +685,12 @@ void kvz_encoder_state_write_bitstream_slice_header(encoder_state_t * const stat //WRITE_U(stream, 1, 1, "pic_output_flag"); //end if //if( IdrPicFlag ) <- nal_unit_type == 5 - if (state->global->pictype != KVZ_NAL_IDR_W_RADL - && state->global->pictype != KVZ_NAL_IDR_N_LP) { + if (state->frame->pictype != KVZ_NAL_IDR_W_RADL + && state->frame->pictype != KVZ_NAL_IDR_N_LP) { int last_poc = 0; int poc_shift = 0; - WRITE_U(stream, state->global->poc&0x1f, 5, "pic_order_cnt_lsb"); + WRITE_U(stream, state->frame->poc&0x1f, 5, "pic_order_cnt_lsb"); WRITE_U(stream, 0, 1, "short_term_ref_pic_set_sps_flag"); WRITE_UE(stream, ref_negative, "num_negative_pics"); WRITE_UE(stream, ref_positive, "num_positive_pics"); @@ -700,9 +700,9 @@ void kvz_encoder_state_write_bitstream_slice_header(encoder_state_t * const stat if (encoder->cfg->gop_len) { int8_t found = 0; do { - delta_poc = encoder->cfg->gop[state->global->gop_offset].ref_neg[j + poc_shift]; - for (int i = 0; i < state->global->ref->used_size; i++) { - if (state->global->ref->pocs[i] == state->global->poc - delta_poc) { + delta_poc = encoder->cfg->gop[state->frame->gop_offset].ref_neg[j + poc_shift]; + for (int i = 0; i < state->frame->ref->used_size; i++) { + if (state->frame->ref->pocs[i] == state->frame->poc - delta_poc) { found = 1; break; } @@ -727,9 +727,9 @@ void kvz_encoder_state_write_bitstream_slice_header(encoder_state_t * const stat if (encoder->cfg->gop_len) { int8_t found = 0; do { - delta_poc = encoder->cfg->gop[state->global->gop_offset].ref_pos[j + poc_shift]; - for (int i = 0; i < state->global->ref->used_size; i++) { - if (state->global->ref->pocs[i] == state->global->poc + delta_poc) { + delta_poc = encoder->cfg->gop[state->frame->gop_offset].ref_pos[j + poc_shift]; + for (int i = 0; i < state->frame->ref->used_size; i++) { + if (state->frame->ref->pocs[i] == state->frame->poc + delta_poc) { found = 1; break; } @@ -756,10 +756,10 @@ void kvz_encoder_state_write_bitstream_slice_header(encoder_state_t * const stat WRITE_U(stream, 1, 1, "slice_sao_chroma_flag"); } - if (state->global->slicetype != KVZ_SLICE_I) { + if (state->frame->slicetype != KVZ_SLICE_I) { WRITE_U(stream, 1, 1, "num_ref_idx_active_override_flag"); WRITE_UE(stream, ref_negative != 0 ? ref_negative - 1: 0, "num_ref_idx_l0_active_minus1"); - if (state->global->slicetype == KVZ_SLICE_B) { + if (state->frame->slicetype == KVZ_SLICE_B) { WRITE_UE(stream, ref_positive != 0 ? ref_positive - 1 : 0, "num_ref_idx_l1_active_minus1"); WRITE_U(stream, 0, 1, "mvd_l1_zero_flag"); } @@ -767,7 +767,7 @@ void kvz_encoder_state_write_bitstream_slice_header(encoder_state_t * const stat } { - int slice_qp_delta = state->global->QP - encoder->cfg->qp; + int slice_qp_delta = state->frame->QP - encoder->cfg->qp; WRITE_SE(stream, slice_qp_delta, "slice_qp_delta"); } @@ -872,15 +872,15 @@ static void encoder_state_write_bitstream_main(encoder_state_t * const state) encoder_state_write_bitstream_aud(state); } - if ((encoder->vps_period > 0 && state->global->frame % encoder->vps_period == 0) - || (state->global->frame == 0 && encoder->vps_period >= 0)) + if ((encoder->vps_period > 0 && state->frame->num % encoder->vps_period == 0) + || (state->frame->num == 0 && encoder->vps_period >= 0)) { first_nal_in_au = false; kvz_encoder_state_write_parameter_sets(&state->stream, state); } // Send Kvazaar version information only in the first frame. - if (state->global->frame == 0 && encoder->cfg->add_encoder_info) { + if (state->frame->num == 0 && encoder->cfg->add_encoder_info) { kvz_nal_write(stream, KVZ_NAL_PREFIX_SEI_NUT, 0, first_nal_in_au); encoder_state_write_bitstream_prefix_sei_version(state); @@ -904,38 +904,38 @@ static void encoder_state_write_bitstream_main(encoder_state_t * const state) } { - uint8_t nal_type = (state->global->is_idr_frame ? KVZ_NAL_IDR_W_RADL : KVZ_NAL_TRAIL_R); + uint8_t nal_type = (state->frame->is_idr_frame ? KVZ_NAL_IDR_W_RADL : KVZ_NAL_TRAIL_R); kvz_nal_write(stream, nal_type, 0, first_nal_in_au); } { PERFORMANCE_MEASURE_START(KVZ_PERF_FRAME); encoder_state_write_bitstream_children(state); - PERFORMANCE_MEASURE_END(KVZ_PERF_FRAME, encoder->threadqueue, "type=write_bitstream_append,frame=%d,encoder_type=%c", state->global->frame, state->type); + PERFORMANCE_MEASURE_END(KVZ_PERF_FRAME, encoder->threadqueue, "type=write_bitstream_append,frame=%d,encoder_type=%c", state->frame->num, state->type); } if (state->encoder_control->cfg->hash != KVZ_HASH_NONE) { PERFORMANCE_MEASURE_START(KVZ_PERF_FRAME); // Calculate checksum add_checksum(state); - PERFORMANCE_MEASURE_END(KVZ_PERF_FRAME, encoder->threadqueue, "type=write_bitstream_checksum,frame=%d,encoder_type=%c", state->global->frame, state->type); + PERFORMANCE_MEASURE_END(KVZ_PERF_FRAME, encoder->threadqueue, "type=write_bitstream_checksum,frame=%d,encoder_type=%c", state->frame->num, state->type); } //Get bitstream length for stats uint64_t newpos = kvz_bitstream_tell(stream); state->stats_bitstream_length = (newpos >> 3) - (curpos >> 3); - if (state->global->frame > 0) { - state->global->total_bits_coded = state->previous_encoder_state->global->total_bits_coded; + if (state->frame->num > 0) { + state->frame->total_bits_coded = state->previous_encoder_state->frame->total_bits_coded; } - state->global->total_bits_coded += newpos - curpos; + state->frame->total_bits_coded += newpos - curpos; - if (encoder->cfg->gop_len > 0 && state->global->gop_offset > 0) { - state->global->cur_gop_bits_coded = state->previous_encoder_state->global->cur_gop_bits_coded; + if (encoder->cfg->gop_len > 0 && state->frame->gop_offset > 0) { + state->frame->cur_gop_bits_coded = state->previous_encoder_state->frame->cur_gop_bits_coded; } else { - state->global->cur_gop_bits_coded = 0; + state->frame->cur_gop_bits_coded = 0; } - state->global->cur_gop_bits_coded += newpos - curpos; + state->frame->cur_gop_bits_coded += newpos - curpos; } void kvz_encoder_state_write_bitstream_leaf(encoder_state_t * const state) diff --git a/src/encoder_state-ctors_dtors.c b/src/encoder_state-ctors_dtors.c index a4b7f4fe..6a2674d6 100644 --- a/src/encoder_state-ctors_dtors.c +++ b/src/encoder_state-ctors_dtors.c @@ -37,24 +37,24 @@ #include "videoframe.h" -static int encoder_state_config_global_init(encoder_state_t * const state) { - state->global->ref = kvz_image_list_alloc(MAX_REF_PIC_COUNT); - if(!state->global->ref) { +static int encoder_state_config_frame_init(encoder_state_t * const state) { + state->frame->ref = kvz_image_list_alloc(MAX_REF_PIC_COUNT); + if(!state->frame->ref) { fprintf(stderr, "Failed to allocate the picture list!\n"); return 0; } - state->global->ref_list = REF_PIC_LIST_0; - state->global->frame = 0; - state->global->poc = 0; - state->global->total_bits_coded = 0; - state->global->cur_gop_bits_coded = 0; - state->global->rc_alpha = 3.2003; - state->global->rc_beta = -1.367; + state->frame->ref_list = REF_PIC_LIST_0; + state->frame->num = 0; + state->frame->poc = 0; + state->frame->total_bits_coded = 0; + state->frame->cur_gop_bits_coded = 0; + state->frame->rc_alpha = 3.2003; + state->frame->rc_beta = -1.367; return 1; } -static void encoder_state_config_global_finalize(encoder_state_t * const state) { - kvz_image_list_destroy(state->global->ref); +static void encoder_state_config_frame_finalize(encoder_state_t * const state) { + kvz_image_list_destroy(state->frame->ref); } static int encoder_state_config_tile_init(encoder_state_t * const state, @@ -247,7 +247,7 @@ static void encoder_state_dump_graphviz(const encoder_state_t * const state) { printf(" \"%p\" [\n", state); printf(" label = \"{encoder_state|"); printf("+ type=%c\\l", state->type); - if (!state->parent || state->global != state->parent->global) { + if (!state->parent || state->frame != state->parent->global) { printf("|+ global\\l"); } if (!state->parent || state->tile != state->parent->tile) { @@ -294,7 +294,7 @@ int kvz_encoder_state_init(encoder_state_t * const child_state, encoder_state_t // //If parent_state is not NULL, the following variable should either be set to NULL, //in order to inherit from parent, or should point to a valid structure: - //child_state->global + //child_state->frame //child_state->tile //child_state->slice //child_state->wfrow @@ -311,9 +311,9 @@ int kvz_encoder_state_init(encoder_state_t * const child_state, encoder_state_t const encoder_control_t * const encoder = child_state->encoder_control; child_state->type = ENCODER_STATE_TYPE_MAIN; assert(child_state->encoder_control); - child_state->global = MALLOC(encoder_state_config_global_t, 1); - if (!child_state->global || !encoder_state_config_global_init(child_state)) { - fprintf(stderr, "Could not initialize encoder_state->global!\n"); + child_state->frame = MALLOC(encoder_state_config_frame_t, 1); + if (!child_state->frame || !encoder_state_config_frame_init(child_state)) { + fprintf(stderr, "Could not initialize encoder_state->frame!\n"); return 0; } child_state->tile = MALLOC(encoder_state_config_tile_t, 1); @@ -333,7 +333,7 @@ int kvz_encoder_state_init(encoder_state_t * const child_state, encoder_state_t } } else { child_state->encoder_control = parent_state->encoder_control; - if (!child_state->global) child_state->global = parent_state->global; + if (!child_state->frame) child_state->frame = parent_state->frame; if (!child_state->tile) child_state->tile = parent_state->tile; if (!child_state->slice) child_state->slice = parent_state->slice; if (!child_state->wfrow) child_state->wfrow = parent_state->wfrow; @@ -421,9 +421,9 @@ int kvz_encoder_state_init(encoder_state_t * const child_state, encoder_state_t //Create a slice new_child = &child_state->children[child_count]; new_child->encoder_control = encoder; - new_child->type = ENCODER_STATE_TYPE_SLICE; - new_child->global = child_state->global; - new_child->tile = child_state->tile; + new_child->type = ENCODER_STATE_TYPE_SLICE; + new_child->frame = child_state->frame; + new_child->tile = child_state->tile; new_child->wfrow = child_state->wfrow; new_child->slice = MALLOC(encoder_state_config_slice_t, 1); if (!new_child->slice || !encoder_state_config_slice_init(new_child, range_start, range_end_slice)) { @@ -447,9 +447,9 @@ int kvz_encoder_state_init(encoder_state_t * const child_state, encoder_state_t new_child = &child_state->children[child_count]; new_child->encoder_control = encoder; - new_child->type = ENCODER_STATE_TYPE_TILE; - new_child->global = child_state->global; - new_child->tile = MALLOC(encoder_state_config_tile_t, 1); + new_child->type = ENCODER_STATE_TYPE_TILE; + new_child->frame = child_state->frame; + new_child->tile = MALLOC(encoder_state_config_tile_t, 1); new_child->slice = child_state->slice; new_child->wfrow = child_state->wfrow; @@ -531,9 +531,9 @@ int kvz_encoder_state_init(encoder_state_t * const child_state, encoder_state_t encoder_state_t *new_child = &child_state->children[i]; new_child->encoder_control = encoder; - new_child->type = ENCODER_STATE_TYPE_WAVEFRONT_ROW; - new_child->global = child_state->global; - new_child->tile = child_state->tile; + new_child->type = ENCODER_STATE_TYPE_WAVEFRONT_ROW; + new_child->frame = child_state->frame; + new_child->tile = child_state->tile; new_child->slice = child_state->slice; new_child->wfrow = MALLOC(encoder_state_config_wfrow_t, 1); @@ -688,9 +688,9 @@ void kvz_encoder_state_finalize(encoder_state_t * const state) { FREE_POINTER(state->tile); } - if (!state->parent || (state->parent->global != state->global)) { - encoder_state_config_global_finalize(state); - FREE_POINTER(state->global); + if (!state->parent || (state->parent->frame != state->frame)) { + encoder_state_config_frame_finalize(state); + FREE_POINTER(state->frame); } kvz_bitstream_finalize(&state->stream); diff --git a/src/encoderstate.c b/src/encoderstate.c index 8d84597e..f15ef904 100644 --- a/src/encoderstate.c +++ b/src/encoderstate.c @@ -214,7 +214,7 @@ static void encoder_state_worker_encode_lcu(void * opaque) { x_px, y_px, LCU_WIDTH, LCU_WIDTH); - PERFORMANCE_MEASURE_END(KVZ_PERF_FRAME, state->encoder_control->threadqueue, "type=copy_cuinfo,frame=%d,tile=%d", state->global->frame, state->tile->id); + PERFORMANCE_MEASURE_END(KVZ_PERF_FRAME, state->encoder_control->threadqueue, "type=copy_cuinfo,frame=%d,tile=%d", state->frame->num, state->tile->id); } //Now write data to bitstream (required to have a correct CABAC state) @@ -293,7 +293,7 @@ static void encoder_state_encode_leaf(encoder_state_t * const state) { #ifdef KVZ_DEBUG { const lcu_order_element_t * const lcu = &state->lcu_order[i]; - PERFORMANCE_MEASURE_END(KVZ_PERF_LCU, state->encoder_control->threadqueue, "type=encode_lcu,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d", state->global->frame, state->tile->id, state->slice->id, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH + lcu->size.x - 1, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH + lcu->size.y - 1); + PERFORMANCE_MEASURE_END(KVZ_PERF_LCU, state->encoder_control->threadqueue, "type=encode_lcu,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d", state->frame->num, state->tile->id, state->slice->id, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH + lcu->size.x - 1, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH + lcu->size.y - 1); } #endif //KVZ_DEBUG } @@ -301,7 +301,7 @@ static void encoder_state_encode_leaf(encoder_state_t * const state) { if (state->encoder_control->sao_enable) { PERFORMANCE_MEASURE_START(KVZ_PERF_SAOREC); kvz_sao_reconstruct_frame(state); - PERFORMANCE_MEASURE_END(KVZ_PERF_SAOREC, state->encoder_control->threadqueue, "type=kvz_sao_reconstruct_frame,frame=%d,tile=%d,slice=%d,row=%d-%d,px_x=%d-%d,px_y=%d-%d", state->global->frame, state->tile->id, state->slice->id, state->lcu_order[0].position.y + state->tile->lcu_offset_y, state->lcu_order[state->lcu_order_count - 1].position.y + state->tile->lcu_offset_y, + PERFORMANCE_MEASURE_END(KVZ_PERF_SAOREC, state->encoder_control->threadqueue, "type=kvz_sao_reconstruct_frame,frame=%d,tile=%d,slice=%d,row=%d-%d,px_x=%d-%d,px_y=%d-%d", state->frame->num, state->tile->id, state->slice->id, state->lcu_order[0].position.y + state->tile->lcu_offset_y, state->lcu_order[state->lcu_order_count - 1].position.y + state->tile->lcu_offset_y, state->tile->lcu_offset_x * LCU_WIDTH, state->tile->frame->width + state->tile->lcu_offset_x * LCU_WIDTH - 1, state->tile->lcu_offset_y * LCU_WIDTH, state->tile->frame->height + state->tile->lcu_offset_y * LCU_WIDTH - 1 ); @@ -316,7 +316,7 @@ static void encoder_state_encode_leaf(encoder_state_t * const state) { state->previous_encoder_state != state) { // For LP-gop, depend on the state of the first reference. - int ref_neg = cfg->gop[(state->global->poc - 1) % cfg->gop_len].ref_neg[0]; + int ref_neg = cfg->gop[(state->frame->poc - 1) % cfg->gop_len].ref_neg[0]; if (ref_neg > state->encoder_control->owf) { // If frame is not within OWF range, it's already done. ref_state = NULL; @@ -337,7 +337,7 @@ static void encoder_state_encode_leaf(encoder_state_t * const state) { #ifdef KVZ_DEBUG char job_description[256]; - sprintf(job_description, "type=encode_lcu,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d", state->global->frame, state->tile->id, state->slice->id, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH + lcu->size.x - 1, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH + lcu->size.y - 1); + sprintf(job_description, "type=encode_lcu,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d", state->frame->num, state->tile->id, state->slice->id, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH, lcu->position_px.x + state->tile->lcu_offset_x * LCU_WIDTH + lcu->size.x - 1, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH, lcu->position_px.y + state->tile->lcu_offset_y * LCU_WIDTH + lcu->size.y - 1); #else char* job_description = NULL; #endif @@ -351,7 +351,7 @@ static void encoder_state_encode_leaf(encoder_state_t * const state) { // previous frame. if (ref_state != NULL && state->previous_encoder_state->tqj_recon_done && - state->global->slicetype != KVZ_SLICE_I) + state->frame->slicetype != KVZ_SLICE_I) { if (!lcu->left) { const lcu_order_element_t * const ref_lcu = &ref_state->lcu_order[i]; @@ -398,12 +398,12 @@ static void encoder_state_worker_encode_children(void * opaque) { if (sub_state->type != ENCODER_STATE_TYPE_WAVEFRONT_ROW) { PERFORMANCE_MEASURE_START(KVZ_PERF_BSLEAF); kvz_encoder_state_write_bitstream_leaf(sub_state); - PERFORMANCE_MEASURE_END(KVZ_PERF_BSLEAF, sub_state->encoder_control->threadqueue, "type=encoder_state_write_bitstream_leaf,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d", sub_state->global->frame, sub_state->tile->id, sub_state->slice->id, sub_state->lcu_order[0].position_px.x + sub_state->tile->lcu_offset_x * LCU_WIDTH, sub_state->lcu_order[sub_state->lcu_order_count - 1].position_px.x + sub_state->lcu_order[sub_state->lcu_order_count - 1].size.x + sub_state->tile->lcu_offset_x * LCU_WIDTH - 1, sub_state->lcu_order[0].position_px.y + sub_state->tile->lcu_offset_y * LCU_WIDTH, sub_state->lcu_order[sub_state->lcu_order_count - 1].position_px.y + sub_state->lcu_order[sub_state->lcu_order_count - 1].size.y + sub_state->tile->lcu_offset_y * LCU_WIDTH - 1); + PERFORMANCE_MEASURE_END(KVZ_PERF_BSLEAF, sub_state->encoder_control->threadqueue, "type=encoder_state_write_bitstream_leaf,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d", sub_state->frame->num, sub_state->tile->id, sub_state->slice->id, sub_state->lcu_order[0].position_px.x + sub_state->tile->lcu_offset_x * LCU_WIDTH, sub_state->lcu_order[sub_state->lcu_order_count - 1].position_px.x + sub_state->lcu_order[sub_state->lcu_order_count - 1].size.x + sub_state->tile->lcu_offset_x * LCU_WIDTH - 1, sub_state->lcu_order[0].position_px.y + sub_state->tile->lcu_offset_y * LCU_WIDTH, sub_state->lcu_order[sub_state->lcu_order_count - 1].position_px.y + sub_state->lcu_order[sub_state->lcu_order_count - 1].size.y + sub_state->tile->lcu_offset_y * LCU_WIDTH - 1); } else { threadqueue_job_t *job; #ifdef KVZ_DEBUG char job_description[256]; - sprintf(job_description, "type=encoder_state_write_bitstream_leaf,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d", sub_state->global->frame, sub_state->tile->id, sub_state->slice->id, sub_state->lcu_order[0].position_px.x + sub_state->tile->lcu_offset_x * LCU_WIDTH, sub_state->lcu_order[sub_state->lcu_order_count-1].position_px.x + sub_state->lcu_order[sub_state->lcu_order_count-1].size.x + sub_state->tile->lcu_offset_x * LCU_WIDTH - 1, sub_state->lcu_order[0].position_px.y + sub_state->tile->lcu_offset_y * LCU_WIDTH, sub_state->lcu_order[sub_state->lcu_order_count-1].position_px.y + sub_state->lcu_order[sub_state->lcu_order_count-1].size.y + sub_state->tile->lcu_offset_y * LCU_WIDTH - 1); + sprintf(job_description, "type=encoder_state_write_bitstream_leaf,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d", sub_state->frame->num, sub_state->tile->id, sub_state->slice->id, sub_state->lcu_order[0].position_px.x + sub_state->tile->lcu_offset_x * LCU_WIDTH, sub_state->lcu_order[sub_state->lcu_order_count-1].position_px.x + sub_state->lcu_order[sub_state->lcu_order_count-1].size.x + sub_state->tile->lcu_offset_x * LCU_WIDTH - 1, sub_state->lcu_order[0].position_px.y + sub_state->tile->lcu_offset_y * LCU_WIDTH, sub_state->lcu_order[sub_state->lcu_order_count-1].position_px.y + sub_state->lcu_order[sub_state->lcu_order_count-1].size.y + sub_state->tile->lcu_offset_y * LCU_WIDTH - 1); #else char* job_description = NULL; #endif @@ -520,22 +520,22 @@ static void encoder_state_encode(encoder_state_t * const main_state) { char job_description[256]; switch (main_state->children[i].type) { case ENCODER_STATE_TYPE_TILE: - sprintf(job_description, "type=encode_child,frame=%d,tile=%d,row=%d-%d,px_x=%d-%d,px_y=%d-%d", main_state->children[i].global->frame, main_state->children[i].tile->id, main_state->children[i].lcu_order[0].position.y + main_state->children[i].tile->lcu_offset_y, main_state->children[i].lcu_order[0].position.y + main_state->children[i].tile->lcu_offset_y, + sprintf(job_description, "type=encode_child,frame=%d,tile=%d,row=%d-%d,px_x=%d-%d,px_y=%d-%d", main_state->children[i].frame->num, main_state->children[i].tile->id, main_state->children[i].lcu_order[0].position.y + main_state->children[i].tile->lcu_offset_y, main_state->children[i].lcu_order[0].position.y + main_state->children[i].tile->lcu_offset_y, main_state->children[i].lcu_order[0].position_px.x + main_state->children[i].tile->lcu_offset_x * LCU_WIDTH, main_state->children[i].lcu_order[main_state->children[i].lcu_order_count-1].position_px.x + main_state->children[i].lcu_order[main_state->children[i].lcu_order_count-1].size.x + main_state->children[i].tile->lcu_offset_x * LCU_WIDTH - 1, main_state->children[i].lcu_order[0].position_px.y + main_state->children[i].tile->lcu_offset_y * LCU_WIDTH, main_state->children[i].lcu_order[main_state->children[i].lcu_order_count-1].position_px.y + main_state->children[i].lcu_order[main_state->children[i].lcu_order_count-1].size.y + main_state->children[i].tile->lcu_offset_y * LCU_WIDTH - 1); break; case ENCODER_STATE_TYPE_SLICE: - sprintf(job_description, "type=encode_child,frame=%d,slice=%d,start_in_ts=%d", main_state->children[i].global->frame, main_state->children[i].slice->id, main_state->children[i].slice->start_in_ts); + sprintf(job_description, "type=encode_child,frame=%d,slice=%d,start_in_ts=%d", main_state->children[i].frame->num, main_state->children[i].slice->id, main_state->children[i].slice->start_in_ts); break; default: - sprintf(job_description, "type=encode_child,frame=%d,invalid", main_state->children[i].global->frame); + sprintf(job_description, "type=encode_child,frame=%d,invalid", main_state->children[i].frame->num); break; } #else char* job_description = NULL; #endif main_state->children[i].tqj_recon_done = kvz_threadqueue_submit(main_state->encoder_control->threadqueue, encoder_state_worker_encode_children, &(main_state->children[i]), 1, job_description); - if (main_state->children[i].previous_encoder_state != &main_state->children[i] && main_state->children[i].previous_encoder_state->tqj_recon_done && !main_state->children[i].global->is_idr_frame) { + if (main_state->children[i].previous_encoder_state != &main_state->children[i] && main_state->children[i].previous_encoder_state->tqj_recon_done && !main_state->children[i].frame->is_idr_frame) { #if 0 // Disabled due to non-determinism. if (main_state->encoder_control->cfg->mv_constraint == KVZ_MV_CONSTRAIN_FRAME_AND_TILE_MARGIN) @@ -574,7 +574,7 @@ static void encoder_state_encode(encoder_state_t * const main_state) { threadqueue_job_t *job; #ifdef KVZ_DEBUG char job_description[256]; - sprintf(job_description, "type=sao,frame=%d,tile=%d,px_x=%d-%d,px_y=%d-%d", main_state->global->frame, main_state->tile->id, main_state->tile->lcu_offset_x * LCU_WIDTH, main_state->tile->lcu_offset_x * LCU_WIDTH + main_state->tile->frame->width - 1, (main_state->tile->lcu_offset_y + y) * LCU_WIDTH, MIN(main_state->tile->lcu_offset_y * LCU_WIDTH + main_state->tile->frame->height, (main_state->tile->lcu_offset_y + y + 1) * LCU_WIDTH)-1); + sprintf(job_description, "type=sao,frame=%d,tile=%d,px_x=%d-%d,px_y=%d-%d", main_state->frame->num, main_state->tile->id, main_state->tile->lcu_offset_x * LCU_WIDTH, main_state->tile->lcu_offset_x * LCU_WIDTH + main_state->tile->frame->width - 1, (main_state->tile->lcu_offset_y + y) * LCU_WIDTH, MIN(main_state->tile->lcu_offset_y * LCU_WIDTH + main_state->tile->frame->height, (main_state->tile->lcu_offset_y + y + 1) * LCU_WIDTH)-1); #else char* job_description = NULL; #endif @@ -661,12 +661,12 @@ void kvz_encoder_get_ref_lists(const encoder_state_t *const state, // List all pocs of lists int j = 0; - for (j = 0; j < state->global->ref->used_size; j++) { - if (state->global->ref->pocs[j] < state->global->poc) { - ref_list_poc_out[0][ref_list_len_out[0]] = state->global->ref->pocs[j]; + for (j = 0; j < state->frame->ref->used_size; j++) { + if (state->frame->ref->pocs[j] < state->frame->poc) { + ref_list_poc_out[0][ref_list_len_out[0]] = state->frame->ref->pocs[j]; ref_list_len_out[0]++; } else { - ref_list_poc_out[1][ref_list_len_out[1]] = state->global->ref->pocs[j]; + ref_list_poc_out[1][ref_list_len_out[1]] = state->frame->ref->pocs[j]; ref_list_len_out[1]++; } } @@ -687,26 +687,26 @@ static void encoder_state_ref_sort(encoder_state_t *state) { kvz_encoder_get_ref_lists(state, ref_list_len, ref_list_poc); - for (int j = 0; j < state->global->ref->used_size; j++) { - if (state->global->ref->pocs[j] < state->global->poc) { + for (int j = 0; j < state->frame->ref->used_size; j++) { + if (state->frame->ref->pocs[j] < state->frame->poc) { for (int ref_idx = 0; ref_idx < ref_list_len[0]; ref_idx++) { - if (ref_list_poc[0][ref_idx] == state->global->ref->pocs[j]) { - state->global->refmap[j].idx = ref_list_len[0] - ref_idx - 1; + if (ref_list_poc[0][ref_idx] == state->frame->ref->pocs[j]) { + state->frame->refmap[j].idx = ref_list_len[0] - ref_idx - 1; break; } } - state->global->refmap[j].list = 1; + state->frame->refmap[j].list = 1; } else { for (int ref_idx = 0; ref_idx < ref_list_len[1]; ref_idx++) { - if (ref_list_poc[1][ref_idx] == state->global->ref->pocs[j]) { - state->global->refmap[j].idx = ref_idx; + if (ref_list_poc[1][ref_idx] == state->frame->ref->pocs[j]) { + state->frame->refmap[j].idx = ref_idx; break; } } - state->global->refmap[j].list = 2; + state->frame->refmap[j].list = 2; } - state->global->refmap[j].poc = state->global->ref->pocs[j]; + state->frame->refmap[j].poc = state->frame->ref->pocs[j]; } } @@ -716,8 +716,8 @@ static void encoder_state_ref_sort(encoder_state_t *state) { static void encoder_state_remove_refs(encoder_state_t *state) { const encoder_control_t * const encoder = state->encoder_control; - int neg_refs = encoder->cfg->gop[state->global->gop_offset].ref_neg_count; - int pos_refs = encoder->cfg->gop[state->global->gop_offset].ref_pos_count; + int neg_refs = encoder->cfg->gop[state->frame->gop_offset].ref_neg_count; + int pos_refs = encoder->cfg->gop[state->frame->gop_offset].ref_pos_count; unsigned target_ref_num; if (encoder->cfg->gop_len) { @@ -725,7 +725,7 @@ static void encoder_state_remove_refs(encoder_state_t *state) { } else { target_ref_num = encoder->cfg->ref_frames; } - if (state->global->slicetype == KVZ_SLICE_I) { + if (state->frame->slicetype == KVZ_SLICE_I) { target_ref_num = 0; } @@ -733,14 +733,14 @@ static void encoder_state_remove_refs(encoder_state_t *state) { // With GOP in use, go through all the existing reference pictures and // remove any picture that is not referenced by the current picture. - for (int ref = state->global->ref->used_size - 1; ref >= 0; --ref) { + for (int ref = state->frame->ref->used_size - 1; ref >= 0; --ref) { bool is_referenced = false; - int ref_poc = state->global->ref->pocs[ref]; + int ref_poc = state->frame->ref->pocs[ref]; for (int i = 0; i < neg_refs; i++) { - int ref_relative_poc = -encoder->cfg->gop[state->global->gop_offset].ref_neg[i]; - if (ref_poc == state->global->poc + ref_relative_poc) { + int ref_relative_poc = -encoder->cfg->gop[state->frame->gop_offset].ref_neg[i]; + if (ref_poc == state->frame->poc + ref_relative_poc) { is_referenced = true; break; } @@ -748,8 +748,8 @@ static void encoder_state_remove_refs(encoder_state_t *state) { for (int i = 0; i < pos_refs; i++) { - int ref_relative_poc = encoder->cfg->gop[state->global->gop_offset].ref_pos[i]; - if (ref_poc == state->global->poc + ref_relative_poc) { + int ref_relative_poc = encoder->cfg->gop[state->frame->gop_offset].ref_pos[i]; + if (ref_poc == state->frame->poc + ref_relative_poc) { is_referenced = true; break; } @@ -757,22 +757,22 @@ static void encoder_state_remove_refs(encoder_state_t *state) { if (!is_referenced) { // This reference is not referred to by this frame, it must be removed. - kvz_image_list_rem(state->global->ref, ref); + kvz_image_list_rem(state->frame->ref, ref); } } } else { // Without GOP, remove the oldest picture. - while (state->global->ref->used_size > target_ref_num) { - int8_t oldest_ref = state->global->ref->used_size - 1; - kvz_image_list_rem(state->global->ref, oldest_ref); + while (state->frame->ref->used_size > target_ref_num) { + int8_t oldest_ref = state->frame->ref->used_size - 1; + kvz_image_list_rem(state->frame->ref, oldest_ref); } } - assert(state->global->ref->used_size <= target_ref_num); + assert(state->frame->ref->used_size <= target_ref_num); } static void encoder_state_reset_poc(encoder_state_t *state) { - state->global->poc = 0; + state->frame->poc = 0; kvz_videoframe_set_poc(state->tile->frame, 0); for (int i = 0; state->children[i].encoder_control; ++i) { @@ -794,7 +794,7 @@ static void encoder_set_source_picture(encoder_state_t * const state, kvz_pictur state->tile->frame->rec = kvz_image_alloc(frame->width, frame->height); } - kvz_videoframe_set_poc(state->tile->frame, state->global->poc); + kvz_videoframe_set_poc(state->tile->frame, state->frame->poc); } static void encoder_state_init_children(encoder_state_t * const state) { @@ -803,7 +803,7 @@ static void encoder_state_init_children(encoder_state_t * const state) { if (state->is_leaf) { //Leaf states have cabac and context kvz_cabac_start(&state->cabac); - kvz_init_contexts(state, state->global->QP, state->global->slicetype); + kvz_init_contexts(state, state->frame->QP, state->frame->slicetype); } //Clear the jobs @@ -822,39 +822,39 @@ static void encoder_state_init_new_frame(encoder_state_t * const state, kvz_pict encoder_set_source_picture(state, frame); - if (state->global->frame == 0) { - state->global->is_idr_frame = true; + if (state->frame->num == 0) { + state->frame->is_idr_frame = true; } else if (cfg->gop_len) { // Closed GOP / CRA is not yet supported. - state->global->is_idr_frame = false; + state->frame->is_idr_frame = false; // Calculate POC according to the global frame counter and GOP structure - int32_t poc = state->global->frame - 1; - int32_t poc_offset = cfg->gop[state->global->gop_offset].poc_offset; - state->global->poc = poc - poc % cfg->gop_len + poc_offset; - kvz_videoframe_set_poc(state->tile->frame, state->global->poc); + int32_t poc = state->frame->num - 1; + int32_t poc_offset = cfg->gop[state->frame->gop_offset].poc_offset; + state->frame->poc = poc - poc % cfg->gop_len + poc_offset; + kvz_videoframe_set_poc(state->tile->frame, state->frame->poc); } else { - bool is_i_idr = (cfg->intra_period == 1 && state->global->frame % 2 == 0); - bool is_p_idr = (cfg->intra_period > 1 && (state->global->frame % cfg->intra_period) == 0); - state->global->is_idr_frame = is_i_idr || is_p_idr; + bool is_i_idr = (cfg->intra_period == 1 && state->frame->num % 2 == 0); + bool is_p_idr = (cfg->intra_period > 1 && (state->frame->num % cfg->intra_period) == 0); + state->frame->is_idr_frame = is_i_idr || is_p_idr; } - if (state->global->is_idr_frame) { + if (state->frame->is_idr_frame) { encoder_state_reset_poc(state); - state->global->slicetype = KVZ_SLICE_I; - state->global->pictype = KVZ_NAL_IDR_W_RADL; + state->frame->slicetype = KVZ_SLICE_I; + state->frame->pictype = KVZ_NAL_IDR_W_RADL; } else { - state->global->slicetype = cfg->intra_period==1 ? KVZ_SLICE_I : (state->encoder_control->cfg->gop_len?KVZ_SLICE_B:KVZ_SLICE_P); + state->frame->slicetype = cfg->intra_period==1 ? KVZ_SLICE_I : (state->encoder_control->cfg->gop_len?KVZ_SLICE_B:KVZ_SLICE_P); // Use P-slice for lowdelay. - if (state->global->slicetype == KVZ_SLICE_B && cfg->gop_lowdelay) { - state->global->slicetype = KVZ_SLICE_P; + if (state->frame->slicetype == KVZ_SLICE_B && cfg->gop_lowdelay) { + state->frame->slicetype = KVZ_SLICE_P; } - state->global->pictype = KVZ_NAL_TRAIL_R; + state->frame->pictype = KVZ_NAL_TRAIL_R; if (state->encoder_control->cfg->gop_len) { - if (cfg->intra_period > 1 && (state->global->poc % cfg->intra_period) == 0) { - state->global->slicetype = KVZ_SLICE_I; + if (cfg->intra_period > 1 && (state->frame->poc % cfg->intra_period) == 0) { + state->frame->slicetype = KVZ_SLICE_I; } } @@ -866,20 +866,20 @@ static void encoder_state_init_new_frame(encoder_state_t * const state, kvz_pict if (cfg->target_bitrate > 0) { // Rate control enabled. lambda = kvz_select_picture_lambda(state); - state->global->QP = kvz_lambda_to_QP(lambda); + state->frame->QP = kvz_lambda_to_QP(lambda); } else { - if (cfg->gop_len > 0 && state->global->slicetype != KVZ_SLICE_I) { + if (cfg->gop_len > 0 && state->frame->slicetype != KVZ_SLICE_I) { kvz_gop_config const * const gop = - cfg->gop + state->global->gop_offset; - state->global->QP = cfg->qp + gop->qp_offset; - state->global->QP_factor = gop->qp_factor; + cfg->gop + state->frame->gop_offset; + state->frame->QP = cfg->qp + gop->qp_offset; + state->frame->QP_factor = gop->qp_factor; } else { - state->global->QP = cfg->qp; + state->frame->QP = cfg->qp; } lambda = kvz_select_picture_lambda_from_qp(state); } - state->global->cur_lambda_cost = lambda; - state->global->cur_lambda_cost_sqrt = sqrt(lambda); + state->frame->cur_lambda_cost = lambda; + state->frame->cur_lambda_cost_sqrt = sqrt(lambda); encoder_state_init_children(state); } @@ -903,19 +903,19 @@ void kvz_encode_one_frame(encoder_state_t * const state, kvz_picture* frame) { PERFORMANCE_MEASURE_START(KVZ_PERF_FRAME); encoder_state_init_new_frame(state, frame); - PERFORMANCE_MEASURE_END(KVZ_PERF_FRAME, state->encoder_control->threadqueue, "type=init_new_frame,frame=%d,poc=%d", state->global->frame, state->global->poc); + PERFORMANCE_MEASURE_END(KVZ_PERF_FRAME, state->encoder_control->threadqueue, "type=init_new_frame,frame=%d,poc=%d", state->frame->num, state->frame->poc); } { PERFORMANCE_MEASURE_START(KVZ_PERF_FRAME); encoder_state_encode(state); - PERFORMANCE_MEASURE_END(KVZ_PERF_FRAME, state->encoder_control->threadqueue, "type=encode,frame=%d", state->global->frame); + PERFORMANCE_MEASURE_END(KVZ_PERF_FRAME, state->encoder_control->threadqueue, "type=encode,frame=%d", state->frame->num); } //kvz_threadqueue_flush(main_state->encoder_control->threadqueue); { threadqueue_job_t *job; #ifdef KVZ_DEBUG char job_description[256]; - sprintf(job_description, "type=write_bitstream,frame=%d", state->global->frame); + sprintf(job_description, "type=write_bitstream,frame=%d", state->frame->num); #else char* job_description = NULL; #endif @@ -951,10 +951,10 @@ void kvz_encoder_prepare(encoder_state_t *state) // The previous frame must be done before the next one is started. assert(state->frame_done); - if (state->global->frame == -1) { + if (state->frame->num == -1) { // We're at the first frame, so don't care about all this stuff. - state->global->frame = 0; - state->global->poc = 0; + state->frame->num = 0; + state->frame->poc = 0; assert(!state->tile->frame->source); assert(!state->tile->frame->rec); state->prepared = 1; @@ -971,17 +971,17 @@ void kvz_encoder_prepare(encoder_state_t *state) unsigned height = state->tile->frame->height_in_lcu * LCU_WIDTH; state->tile->frame->cu_array = kvz_cu_array_alloc(width, height); - kvz_image_list_copy_contents(state->global->ref, prev_state->global->ref); + kvz_image_list_copy_contents(state->frame->ref, prev_state->frame->ref); } if (!encoder->cfg->gop_len || - !prev_state->global->poc || - encoder->cfg->gop[prev_state->global->gop_offset].is_ref) { + !prev_state->frame->poc || + encoder->cfg->gop[prev_state->frame->gop_offset].is_ref) { // Add previous reconstructed picture as a reference - kvz_image_list_add(state->global->ref, + kvz_image_list_add(state->frame->ref, prev_state->tile->frame->rec, prev_state->tile->frame->cu_array, - prev_state->global->poc); + prev_state->frame->poc); } // Remove source and reconstructed picture. @@ -991,8 +991,8 @@ void kvz_encoder_prepare(encoder_state_t *state) state->tile->frame->rec = NULL; // Update POC and frame count. - state->global->frame = prev_state->global->frame + 1; - state->global->poc = prev_state->global->poc + 1; + state->frame->num = prev_state->frame->num + 1; + state->frame->poc = prev_state->frame->poc + 1; state->prepared = 1; } diff --git a/src/encoderstate.h b/src/encoderstate.h index c6901970..e9f4e2fd 100644 --- a/src/encoderstate.h +++ b/src/encoderstate.h @@ -50,13 +50,13 @@ typedef enum { -typedef struct { +typedef struct encoder_state_config_frame_t { double cur_lambda_cost; //!< \brief Lambda for SSE double cur_lambda_cost_sqrt; //!< \brief Lambda for SAD and SATD - int32_t frame; - int32_t poc; /*!< \brief picture order count */ - int8_t gop_offset; /*!< \brief offset in the gop structure */ + int32_t num; /*!< \brief Frame number */ + int32_t poc; /*!< \brief Picture order count */ + int8_t gop_offset; /*!< \brief Offset in the gop structure */ int8_t QP; //!< \brief Quantization parameter double QP_factor; //!< \brief Quantization factor @@ -88,9 +88,9 @@ typedef struct { double rc_alpha; double rc_beta; -} encoder_state_config_global_t; +} encoder_state_config_frame_t; -typedef struct { +typedef struct encoder_state_config_tile_t { //Current sub-frame videoframe_t *frame; @@ -121,7 +121,7 @@ typedef struct { } encoder_state_config_tile_t; -typedef struct { +typedef struct encoder_state_config_slice_t { int32_t id; //Global coordinates @@ -133,7 +133,7 @@ typedef struct { int32_t end_in_rs; } encoder_state_config_slice_t; -typedef struct { +typedef struct encoder_state_config_wfrow_t { //Row in tile coordinates of the wavefront int32_t lcu_offset_y; } encoder_state_config_wfrow_t; @@ -169,7 +169,7 @@ typedef struct encoder_state_t { //Pointer to the encoder_state of the previous frame struct encoder_state_t *previous_encoder_state; - encoder_state_config_global_t *global; + encoder_state_config_frame_t *frame; encoder_state_config_tile_t *tile; encoder_state_config_slice_t *slice; encoder_state_config_wfrow_t *wfrow; diff --git a/src/filter.c b/src/filter.c index 2136190d..db5312ff 100644 --- a/src/filter.c +++ b/src/filter.c @@ -291,7 +291,7 @@ static void filter_deblock_edge_luma(encoder_state_t * const state, kvz_pixel *src = orig_src; int8_t strength = 0; - int32_t qp = state->global->QP; + int32_t qp = state->frame->QP; int32_t bitdepth_scale = 1 << (encoder->bitdepth - 8); int32_t b_index = CLIP(0, 51, qp + (beta_offset_div2 << 1)); int32_t beta = kvz_g_beta_table_8x8[b_index] * bitdepth_scale; @@ -345,7 +345,7 @@ static void filter_deblock_edge_luma(encoder_state_t * const state, } // B-slice related checks - if(!strength && state->global->slicetype == KVZ_SLICE_B) { + if(!strength && state->frame->slicetype == KVZ_SLICE_B) { // Zero all undefined motion vectors for easier usage if(!(cu_q->inter.mv_dir & 1)) { @@ -490,7 +490,7 @@ static void filter_deblock_edge_chroma(encoder_state_t * const state, }; int8_t strength = 2; - int32_t QP = kvz_g_chroma_scale[state->global->QP]; + int32_t QP = kvz_g_chroma_scale[state->frame->QP]; int32_t bitdepth_scale = 1 << (encoder->bitdepth-8); int32_t TC_index = CLIP(0, 51+2, (int32_t)(QP + 2*(strength-1) + (tc_offset_div2 << 1))); int32_t Tc = kvz_g_tc_table_8x8[TC_index]*bitdepth_scale; diff --git a/src/input_frame_buffer.c b/src/input_frame_buffer.c index c3990a09..6ca294f7 100644 --- a/src/input_frame_buffer.c +++ b/src/input_frame_buffer.c @@ -58,7 +58,7 @@ kvz_picture* kvz_encoder_feed_frame(input_frame_buffer_t *buf, const int gop_buf_size = 3 * cfg->gop_len; - assert(state->global->frame >= 0); + assert(state->frame->num >= 0); if (cfg->gop_len == 0 || cfg->gop_lowdelay) { // No reordering of output pictures necessary. @@ -66,12 +66,12 @@ kvz_picture* kvz_encoder_feed_frame(input_frame_buffer_t *buf, if (img_in == NULL) return NULL; img_in->dts = img_in->pts; - state->global->gop_offset = 0; + state->frame->gop_offset = 0; if (cfg->gop_lowdelay) { - state->global->gop_offset = (state->global->frame - 1) % cfg->gop_len; - if (state->global->gop_offset < 0) { + state->frame->gop_offset = (state->frame->num - 1) % cfg->gop_len; + if (state->frame->gop_offset < 0) { // Set gop_offset of IDR as the highest quality picture. - state->global->gop_offset += cfg->gop_len; + state->frame->gop_offset += cfg->gop_len; } } return kvz_image_copy_ref(img_in); @@ -172,7 +172,7 @@ kvz_picture* kvz_encoder_feed_frame(input_frame_buffer_t *buf, assert(next_pic != NULL); next_pic->dts = dts_out; buf->pic_buffer[buf_idx] = NULL; - state->global->gop_offset = gop_offset; + state->frame->gop_offset = gop_offset; buf->num_out++; return next_pic; diff --git a/src/inter.c b/src/inter.c index b35f8b02..3516d5b2 100644 --- a/src/inter.c +++ b/src/inter.c @@ -854,8 +854,8 @@ static void get_mv_cand_from_spatial(const encoder_state_t * const state, int8_t reflist2nd = !reflist; #define CALCULATE_SCALE(cu,tb,td) ((tb * ((0x4000 + (abs(td)>>1))/td) + 32) >> 6) -#define APPLY_MV_SCALING(cu, cand, list) {int td = state->global->poc - state->global->ref->pocs[(cu)->inter.mv_ref[list]];\ - int tb = state->global->poc - state->global->ref->pocs[cur_cu->inter.mv_ref[reflist]];\ +#define APPLY_MV_SCALING(cu, cand, list) {int td = state->frame->poc - state->frame->ref->pocs[(cu)->inter.mv_ref[list]];\ + int tb = state->frame->poc - state->frame->ref->pocs[cur_cu->inter.mv_ref[reflist]];\ if (td != tb) { \ int scale = CALCULATE_SCALE(cu,tb,td); \ mv_cand[cand][0] = ((scale * (cu)->inter.mv[list][0] + 127 + (scale * (cu)->inter.mv[list][0] < 0)) >> 8 ); \ @@ -1202,7 +1202,7 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, } #endif - if (candidates < MRG_MAX_NUM_CANDS && state->global->slicetype == KVZ_SLICE_B) { + if (candidates < MRG_MAX_NUM_CANDS && state->frame->slicetype == KVZ_SLICE_B) { #define NUM_PRIORITY_LIST 12; static const uint8_t priorityList0[] = { 0, 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3 }; static const uint8_t priorityList1[] = { 1, 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2 }; @@ -1235,14 +1235,14 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, } } - int num_ref = state->global->ref->used_size; + int num_ref = state->frame->ref->used_size; - if (candidates < MRG_MAX_NUM_CANDS && state->global->slicetype == KVZ_SLICE_B) { + if (candidates < MRG_MAX_NUM_CANDS && state->frame->slicetype == KVZ_SLICE_B) { int j; int ref_negative = 0; int ref_positive = 0; - for (j = 0; j < state->global->ref->used_size; j++) { - if (state->global->ref->pocs[j] < state->global->poc) { + for (j = 0; j < state->frame->ref->used_size; j++) { + if (state->frame->ref->pocs[j] < state->frame->poc) { ref_negative++; } else { ref_positive++; @@ -1258,7 +1258,7 @@ uint8_t kvz_inter_get_merge_cand(const encoder_state_t * const state, mv_cand[candidates].ref[0] = (zero_idx>=num_ref-1)?0:zero_idx; mv_cand[candidates].ref[1] = mv_cand[candidates].ref[0]; mv_cand[candidates].dir = 1; - if (state->global->slicetype == KVZ_SLICE_B) { + if (state->frame->slicetype == KVZ_SLICE_B) { mv_cand[candidates].mv[1][0] = 0; mv_cand[candidates].mv[1][1] = 0; mv_cand[candidates].dir = 3; diff --git a/src/kvazaar.c b/src/kvazaar.c index 5fe749d5..3cc05d92 100644 --- a/src/kvazaar.c +++ b/src/kvazaar.c @@ -100,7 +100,7 @@ static kvz_encoder * kvazaar_open(const kvz_config *cfg) goto kvazaar_open_failure; } - encoder->states[i].global->QP = (int8_t)cfg->qp; + encoder->states[i].frame->QP = (int8_t)cfg->qp; } for (int i = 0; i < encoder->num_encoder_states; ++i) { @@ -112,7 +112,7 @@ static kvz_encoder * kvazaar_open(const kvz_config *cfg) kvz_encoder_state_match_children_of_previous_frame(&encoder->states[i]); } - encoder->states[encoder->cur_state_num].global->frame = -1; + encoder->states[encoder->cur_state_num].frame->num = -1; return encoder; @@ -124,10 +124,10 @@ kvazaar_open_failure: static void set_frame_info(kvz_frame_info *const info, const encoder_state_t *const state) { - info->poc = state->global->poc, - info->qp = state->global->QP; - info->nal_unit_type = state->global->pictype; - info->slice_type = state->global->slicetype; + info->poc = state->frame->poc, + info->qp = state->frame->QP; + info->nal_unit_type = state->frame->pictype; + info->slice_type = state->frame->slicetype; kvz_encoder_get_ref_lists(state, info->ref_list_len, info->ref_list); } @@ -217,12 +217,12 @@ static int kvazaar_encode(kvz_encoder *enc, if (pic_in != NULL) { // FIXME: The frame number printed here is wrong when GOP is enabled. - CHECKPOINT_MARK("read source frame: %d", state->global->frame + enc->control->cfg->seek); + CHECKPOINT_MARK("read source frame: %d", state->frame->num + enc->control->cfg->seek); } kvz_picture* frame = kvz_encoder_feed_frame(&enc->input_buffer, state, pic_in); if (frame) { - assert(state->global->frame == enc->frames_started); + assert(state->frame->num == enc->frames_started); // Start encoding. kvz_encode_one_frame(state, frame); enc->frames_started += 1; diff --git a/src/rate_control.c b/src/rate_control.c index 5c028d7e..07173198 100644 --- a/src/rate_control.c +++ b/src/rate_control.c @@ -42,19 +42,19 @@ static void update_rc_parameters(encoder_state_t * state) const double bpp = state->stats_bitstream_length * 8 / pixels_per_picture; const double log_bpp = log(bpp); - const double alpha_old = state->global->rc_alpha; - const double beta_old = state->global->rc_beta; + const double alpha_old = state->frame->rc_alpha; + const double beta_old = state->frame->rc_beta; // lambda computed from real bpp const double lambda_comp = CLIP(0.1, 10000, alpha_old * pow(bpp, beta_old)); // lambda used in encoding - const double lambda_real = state->global->cur_lambda_cost; + const double lambda_real = state->frame->cur_lambda_cost; const double lambda_log_ratio = log(lambda_real) - log(lambda_comp); const double alpha = alpha_old + 0.1 * lambda_log_ratio * alpha_old; - state->global->rc_alpha = CLIP(0.05, 20, alpha); + state->frame->rc_alpha = CLIP(0.05, 20, alpha); const double beta = beta_old + 0.05 * lambda_log_ratio * CLIP(-5, 1, log_bpp); - state->global->rc_beta = CLIP(-3, -0.1, beta); + state->frame->rc_beta = CLIP(-3, -0.1, beta); } /** @@ -71,14 +71,14 @@ static void gop_allocate_bits(encoder_state_t * const state) // At this point, total_bits_coded of the current state contains the // number of bits written encoder->owf frames before the current frame. - uint64_t bits_coded = state->global->total_bits_coded; - int pictures_coded = MAX(0, state->global->frame - encoder->owf); + uint64_t bits_coded = state->frame->total_bits_coded; + int pictures_coded = MAX(0, state->frame->num - encoder->owf); - int gop_offset = (state->global->gop_offset - encoder->owf) % MAX(1, encoder->cfg->gop_len); + int gop_offset = (state->frame->gop_offset - encoder->owf) % MAX(1, encoder->cfg->gop_len); // Only take fully coded GOPs into account. if (encoder->cfg->gop_len > 0 && gop_offset != encoder->cfg->gop_len - 1) { // Subtract number of bits in the partially coded GOP. - bits_coded -= state->global->cur_gop_bits_coded; + bits_coded -= state->frame->cur_gop_bits_coded; // Subtract number of pictures in the partially coded GOP. pictures_coded -= gop_offset + 1; } @@ -86,7 +86,7 @@ static void gop_allocate_bits(encoder_state_t * const state) double gop_target_bits = (encoder->target_avg_bppic * (pictures_coded + SMOOTHING_WINDOW) - bits_coded) * MAX(1, encoder->cfg->gop_len) / SMOOTHING_WINDOW; - state->global->cur_gop_target_bits = MAX(200, gop_target_bits); + state->frame->cur_gop_target_bits = MAX(200, gop_target_bits); } /** @@ -99,12 +99,12 @@ static double pic_allocate_bits(const encoder_state_t * const state) const encoder_control_t * const encoder = state->encoder_control; if (encoder->cfg->gop_len <= 0) { - return state->global->cur_gop_target_bits; + return state->frame->cur_gop_target_bits; } const double pic_weight = encoder->gop_layer_weights[ - encoder->cfg->gop[state->global->gop_offset].layer - 1]; - double pic_target_bits = state->global->cur_gop_target_bits * pic_weight; + encoder->cfg->gop[state->frame->gop_offset].layer - 1]; + double pic_target_bits = state->frame->cur_gop_target_bits * pic_weight; return MAX(100, pic_target_bits); } @@ -122,20 +122,20 @@ double kvz_select_picture_lambda(encoder_state_t * const state) assert(encoder->cfg->target_bitrate > 0); - if (state->global->frame > encoder->owf) { + if (state->frame->num > encoder->owf) { // At least one frame has been written. update_rc_parameters(state); } if (encoder->cfg->gop_len == 0 || - state->global->gop_offset == 0 || - state->global->frame == 0) + state->frame->gop_offset == 0 || + state->frame->num == 0) { // A new GOP begins at this frame. gop_allocate_bits(state); } else { - state->global->cur_gop_target_bits = - state->previous_encoder_state->global->cur_gop_target_bits; + state->frame->cur_gop_target_bits = + state->previous_encoder_state->frame->cur_gop_target_bits; } // TODO: take the picture headers into account @@ -143,7 +143,7 @@ double kvz_select_picture_lambda(encoder_state_t * const state) const double target_bits_per_pixel = target_bits_current_picture / encoder->in.pixels_per_pic; const double lambda = - state->global->rc_alpha * pow(target_bits_per_pixel, state->global->rc_beta); + state->frame->rc_alpha * pow(target_bits_per_pixel, state->frame->rc_beta); return CLIP(0.1, 10000, lambda); } @@ -167,9 +167,9 @@ double kvz_select_picture_lambda_from_qp(encoder_state_t const * const state) const int intra_period = state->encoder_control->cfg->intra_period; const int keyframe_period = gop_len > 0 ? gop_len : intra_period; - double lambda = pow(2.0, (state->global->QP - 12) / 3.0); + double lambda = pow(2.0, (state->frame->QP - 12) / 3.0); - if (state->global->slicetype == KVZ_SLICE_I) { + if (state->frame->slicetype == KVZ_SLICE_I) { lambda *= 0.57; // Reduce lambda for I-frames according to the number of references. @@ -179,14 +179,14 @@ double kvz_select_picture_lambda_from_qp(encoder_state_t const * const state) lambda *= 1.0 - CLIP(0.0, 0.5, 0.05 * (keyframe_period - 1)); } } else if (gop_len > 0) { - lambda *= state->global->QP_factor; + lambda *= state->frame->QP_factor; } else { lambda *= 0.4624; } // Increase lambda if not key-frame. - if (keyframe_period > 0 && state->global->poc % keyframe_period != 0) { - lambda *= CLIP(2.0, 4.0, (state->global->QP - 12) / 6.0); + if (keyframe_period > 0 && state->frame->poc % keyframe_period != 0) { + lambda *= CLIP(2.0, 4.0, (state->frame->QP - 12) / 6.0); } return lambda; diff --git a/src/rdo.c b/src/rdo.c index 429f3c86..54de67e2 100644 --- a/src/rdo.c +++ b/src/rdo.c @@ -259,7 +259,7 @@ uint32_t kvz_get_coded_level ( encoder_state_t * const state, double *coded_cost cabac_ctx_t* base_sig_model = type?(cabac->ctx.cu_sig_model_chroma):(cabac->ctx.cu_sig_model_luma); if( !last && max_abs_level < 3 ) { - *coded_cost_sig = state->global->cur_lambda_cost * CTX_ENTROPY_BITS(&base_sig_model[ctx_num_sig], 0); + *coded_cost_sig = state->frame->cur_lambda_cost * CTX_ENTROPY_BITS(&base_sig_model[ctx_num_sig], 0); *coded_cost = *coded_cost0 + *coded_cost_sig; if (max_abs_level == 0) return best_abs_level; } else { @@ -267,13 +267,13 @@ uint32_t kvz_get_coded_level ( encoder_state_t * const state, double *coded_cost } if( !last ) { - cur_cost_sig = state->global->cur_lambda_cost * CTX_ENTROPY_BITS(&base_sig_model[ctx_num_sig], 1); + cur_cost_sig = state->frame->cur_lambda_cost * CTX_ENTROPY_BITS(&base_sig_model[ctx_num_sig], 1); } min_abs_level = ( max_abs_level > 1 ? max_abs_level - 1 : 1 ); for (abs_level = max_abs_level; abs_level >= min_abs_level ; abs_level-- ) { double err = (double)(level_double - ( abs_level << q_bits ) ); - double cur_cost = err * err * temp + state->global->cur_lambda_cost * + double cur_cost = err * err * temp + state->frame->cur_lambda_cost * kvz_get_ic_rate( state, abs_level, ctx_num_one, ctx_num_abs, abs_go_rice, c1_idx, c2_idx, type); cur_cost += cur_cost_sig; @@ -310,7 +310,7 @@ static double get_rate_last(const encoder_state_t * const state, if( ctx_y > 3 ) { uiCost += 32768.0 * ((ctx_y-2)>>1); } - return state->global->cur_lambda_cost*uiCost; + return state->frame->cur_lambda_cost*uiCost; } static void calc_last_bits(encoder_state_t * const state, int32_t width, int32_t height, int8_t type, @@ -360,7 +360,7 @@ void kvz_rdoq_sign_hiding(const encoder_state_t *const state, int64_t rd_factor = (int64_t)( kvz_g_inv_quant_scales[qp_scaled % 6] * kvz_g_inv_quant_scales[qp_scaled % 6] * (1 << (2 * (qp_scaled / 6))) - / state->global->cur_lambda_cost / 16 / (1 << (2 * (encoder->bitdepth - 8))) + / state->frame->cur_lambda_cost / 16 / (1 << (2 * (encoder->bitdepth - 8))) + 0.5); int32_t lastCG = -1; int32_t absSum = 0; @@ -469,7 +469,7 @@ void kvz_rdoq(encoder_state_t * const state, coeff_t *coef, coeff_t *dest_coeff uint32_t max_num_coeff = width * height; int32_t scalinglist_type= (block_type == CU_INTRA ? 0 : 3) + (int8_t)("\0\3\1\2"[type]); - int32_t qp_scaled = kvz_get_scaled_qp(type, state->global->QP, (encoder->bitdepth-8)*6); + int32_t qp_scaled = kvz_get_scaled_qp(type, state->frame->QP, (encoder->bitdepth-8)*6); uint32_t abs_sum = 0; @@ -675,7 +675,7 @@ void kvz_rdoq(encoder_state_t * const state, coeff_t *coef, coeff_t *dest_coeff if (sig_coeffgroup_flag[ cg_blkpos ] == 0) { uint32_t ctx_sig = kvz_context_get_sig_coeff_group(sig_coeffgroup_flag, cg_pos_x, cg_pos_y, width); - cost_coeffgroup_sig[ cg_scanpos ] = state->global->cur_lambda_cost*CTX_ENTROPY_BITS(&base_coeff_group_ctx[ctx_sig],0); + cost_coeffgroup_sig[ cg_scanpos ] = state->frame->cur_lambda_cost*CTX_ENTROPY_BITS(&base_coeff_group_ctx[ctx_sig],0); base_cost += cost_coeffgroup_sig[ cg_scanpos ] - rd_stats.sig_cost; } else { if (cg_scanpos < cg_last_scanpos) {//skip the last coefficient group, which will be handled together with last position below. @@ -692,9 +692,9 @@ void kvz_rdoq(encoder_state_t * const state, coeff_t *coef, coeff_t *dest_coeff ctx_sig = kvz_context_get_sig_coeff_group(sig_coeffgroup_flag, cg_pos_x, cg_pos_y, width); if (cg_scanpos < cg_last_scanpos) { - cost_coeffgroup_sig[cg_scanpos] = state->global->cur_lambda_cost*CTX_ENTROPY_BITS(&base_coeff_group_ctx[ctx_sig],1); + cost_coeffgroup_sig[cg_scanpos] = state->frame->cur_lambda_cost*CTX_ENTROPY_BITS(&base_coeff_group_ctx[ctx_sig],1); base_cost += cost_coeffgroup_sig[cg_scanpos]; - cost_zero_cg += state->global->cur_lambda_cost*CTX_ENTROPY_BITS(&base_coeff_group_ctx[ctx_sig],0); + cost_zero_cg += state->frame->cur_lambda_cost*CTX_ENTROPY_BITS(&base_coeff_group_ctx[ctx_sig],0); } // try to convert the current coeff group from non-zero to all-zero @@ -708,7 +708,7 @@ void kvz_rdoq(encoder_state_t * const state, coeff_t *coef, coeff_t *dest_coeff sig_coeffgroup_flag[ cg_blkpos ] = 0; base_cost = cost_zero_cg; if (cg_scanpos < cg_last_scanpos) { - cost_coeffgroup_sig[ cg_scanpos ] = state->global->cur_lambda_cost*CTX_ENTROPY_BITS(&base_coeff_group_ctx[ctx_sig],0); + cost_coeffgroup_sig[ cg_scanpos ] = state->frame->cur_lambda_cost*CTX_ENTROPY_BITS(&base_coeff_group_ctx[ctx_sig],0); } // reset coeffs to 0 in this block for (scanpos_in_cg = cg_size-1; scanpos_in_cg >= 0; scanpos_in_cg--) { @@ -736,13 +736,13 @@ void kvz_rdoq(encoder_state_t * const state, coeff_t *coef, coeff_t *dest_coeff if( block_type != CU_INTRA && !type/* && pcCU->getTransformIdx( uiAbsPartIdx ) == 0*/ ) { - best_cost = block_uncoded_cost + state->global->cur_lambda_cost*CTX_ENTROPY_BITS(&(cabac->ctx.cu_qt_root_cbf_model),0); - base_cost += state->global->cur_lambda_cost*CTX_ENTROPY_BITS(&(cabac->ctx.cu_qt_root_cbf_model),1); + best_cost = block_uncoded_cost + state->frame->cur_lambda_cost*CTX_ENTROPY_BITS(&(cabac->ctx.cu_qt_root_cbf_model),0); + base_cost += state->frame->cur_lambda_cost*CTX_ENTROPY_BITS(&(cabac->ctx.cu_qt_root_cbf_model),1); } else { cabac_ctx_t* base_cbf_model = type?(cabac->ctx.qt_cbf_model_chroma):(cabac->ctx.qt_cbf_model_luma); ctx_cbf = ( type ? tr_depth : !tr_depth); - best_cost = block_uncoded_cost + state->global->cur_lambda_cost*CTX_ENTROPY_BITS(&base_cbf_model[ctx_cbf],0); - base_cost += state->global->cur_lambda_cost*CTX_ENTROPY_BITS(&base_cbf_model[ctx_cbf],1); + best_cost = block_uncoded_cost + state->frame->cur_lambda_cost*CTX_ENTROPY_BITS(&base_cbf_model[ctx_cbf],0); + base_cost += state->frame->cur_lambda_cost*CTX_ENTROPY_BITS(&base_cbf_model[ctx_cbf],1); } for (cg_scanpos = cg_last_scanpos; cg_scanpos >= 0; cg_scanpos--) { @@ -926,8 +926,8 @@ int kvz_calc_mvd_cost_cabac(encoder_state_t * const state, int x, int y, int mv_ uint32_t ref_list_idx; uint32_t j; int ref_list[2] = { 0, 0 }; - for (j = 0; j < state->global->ref->used_size; j++) { - if (state->global->ref->pocs[j] < state->global->poc) { + for (j = 0; j < state->frame->ref->used_size; j++) { + if (state->frame->ref->pocs[j] < state->frame->poc) { ref_list[0]++; } else { ref_list[1]++; @@ -965,7 +965,7 @@ int kvz_calc_mvd_cost_cabac(encoder_state_t * const state, int x, int y, int mv_ } // ToDo: Bidir vector support - if (!(state->global->ref_list == REF_PIC_LIST_1 && /*cur_cu->inter.mv_dir == 3*/ 0)) { + if (!(state->frame->ref_list == REF_PIC_LIST_1 && /*cur_cu->inter.mv_dir == 3*/ 0)) { const int32_t mvd_hor = mvd.x; const int32_t mvd_ver = mvd.y; const int8_t hor_abs_gr0 = mvd_hor != 0; @@ -1015,5 +1015,5 @@ int kvz_calc_mvd_cost_cabac(encoder_state_t * const state, int x, int y, int mv_ *bitcost = (23 - state_cabac_copy.bits_left) + (state_cabac_copy.num_buffered_bytes << 3); // Store bitcost before restoring cabac - return *bitcost * (int32_t)(state->global->cur_lambda_cost_sqrt + 0.5); + return *bitcost * (int32_t)(state->frame->cur_lambda_cost_sqrt + 0.5); } diff --git a/src/sao.c b/src/sao.c index 2e94d5df..ec4b8e73 100644 --- a/src/sao.c +++ b/src/sao.c @@ -501,7 +501,7 @@ static void sao_search_edge_sao(const encoder_state_t * const state, { float mode_bits = sao_mode_bits_edge(state, edge_class, edge_offset, sao_top, sao_left, buf_cnt); - sum_ddistortion += (int)((double)mode_bits*state->global->cur_lambda_cost+0.5); + sum_ddistortion += (int)((double)mode_bits*state->frame->cur_lambda_cost+0.5); } // SAO is not applied for category 0. edge_offset[SAO_EO_CAT0] = 0; @@ -545,7 +545,7 @@ static void sao_search_band_sao(const encoder_state_t * const state, const kvz_p } temp_rate = sao_mode_bits_band(state, sao_out->band_position, temp_offsets, sao_top, sao_left, buf_cnt); - ddistortion += (int)((double)temp_rate*state->global->cur_lambda_cost + 0.5); + ddistortion += (int)((double)temp_rate*state->frame->cur_lambda_cost + 0.5); // Select band sao over edge sao when distortion is lower if (ddistortion < sao_out->ddistortion) { @@ -589,7 +589,7 @@ static void sao_search_best_mode(const encoder_state_t * const state, const kvz_ { float mode_bits = sao_mode_bits_edge(state, edge_sao.eo_class, edge_sao.offsets, sao_top, sao_left, buf_cnt); - int ddistortion = (int)(mode_bits * state->global->cur_lambda_cost + 0.5); + int ddistortion = (int)(mode_bits * state->frame->cur_lambda_cost + 0.5); unsigned buf_i; for (buf_i = 0; buf_i < buf_cnt; ++buf_i) { @@ -603,7 +603,7 @@ static void sao_search_best_mode(const encoder_state_t * const state, const kvz_ { float mode_bits = sao_mode_bits_band(state, band_sao.band_position, band_sao.offsets, sao_top, sao_left, buf_cnt); - int ddistortion = (int)(mode_bits * state->global->cur_lambda_cost + 0.5); + int ddistortion = (int)(mode_bits * state->frame->cur_lambda_cost + 0.5); unsigned buf_i; for (buf_i = 0; buf_i < buf_cnt; ++buf_i) { @@ -626,7 +626,7 @@ static void sao_search_best_mode(const encoder_state_t * const state, const kvz_ // Choose between SAO and doing nothing, taking into account the // rate-distortion cost of coding do nothing. { - int cost_of_nothing = (int)(sao_mode_bits_none(state, sao_top, sao_left) * state->global->cur_lambda_cost + 0.5); + int cost_of_nothing = (int)(sao_mode_bits_none(state, sao_top, sao_left) * state->frame->cur_lambda_cost + 0.5); if (sao_out->ddistortion >= cost_of_nothing) { sao_out->type = SAO_TYPE_NONE; merge_cost[0] = cost_of_nothing; @@ -643,7 +643,7 @@ static void sao_search_best_mode(const encoder_state_t * const state, const kvz_ if (merge_cand) { unsigned buf_i; float mode_bits = sao_mode_bits_merge(state, i + 1); - int ddistortion = (int)(mode_bits * state->global->cur_lambda_cost + 0.5); + int ddistortion = (int)(mode_bits * state->frame->cur_lambda_cost + 0.5); switch (merge_cand->type) { case SAO_TYPE_EDGE: diff --git a/src/search.c b/src/search.c index 7bcec148..638bf69a 100644 --- a/src/search.c +++ b/src/search.c @@ -314,7 +314,7 @@ double kvz_cu_rd_cost_luma(const encoder_state_t *const state, sum += kvz_cu_rd_cost_luma(state, x_px, y_px + offset, depth + 1, pred_cu, lcu); sum += kvz_cu_rd_cost_luma(state, x_px + offset, y_px + offset, depth + 1, pred_cu, lcu); - return sum + tr_tree_bits * state->global->cur_lambda_cost; + return sum + tr_tree_bits * state->frame->cur_lambda_cost; } // Add transform_tree cbf_luma bit cost. @@ -346,7 +346,7 @@ double kvz_cu_rd_cost_luma(const encoder_state_t *const state, } double bits = tr_tree_bits + coeff_bits; - return (double)ssd * LUMA_MULT + bits * state->global->cur_lambda_cost; + return (double)ssd * LUMA_MULT + bits * state->frame->cur_lambda_cost; } @@ -391,7 +391,7 @@ double kvz_cu_rd_cost_chroma(const encoder_state_t *const state, sum += kvz_cu_rd_cost_chroma(state, x_px, y_px + offset, depth + 1, pred_cu, lcu); sum += kvz_cu_rd_cost_chroma(state, x_px + offset, y_px + offset, depth + 1, pred_cu, lcu); - return sum + tr_tree_bits * state->global->cur_lambda_cost; + return sum + tr_tree_bits * state->frame->cur_lambda_cost; } // Chroma SSD @@ -421,7 +421,7 @@ double kvz_cu_rd_cost_chroma(const encoder_state_t *const state, } double bits = tr_tree_bits + coeff_bits; - return (double)ssd * CHROMA_MULT + bits * state->global->cur_lambda_cost; + return (double)ssd * CHROMA_MULT + bits * state->frame->cur_lambda_cost; } @@ -507,7 +507,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, { bool can_use_inter = - state->global->slicetype != KVZ_SLICE_I + state->frame->slicetype != KVZ_SLICE_I && WITHIN(depth, ctrl->pu_depth_inter.min, ctrl->pu_depth_inter.max); if (can_use_inter) { @@ -619,8 +619,8 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, if (cur_pu->inter.mv_dir == 3) { const kvz_picture *const refs[2] = { - state->global->ref->images[cur_pu->inter.mv_ref[0]], - state->global->ref->images[cur_pu->inter.mv_ref[1]], + state->frame->ref->images[cur_pu->inter.mv_ref[0]], + state->frame->ref->images[cur_pu->inter.mv_ref[1]], }; kvz_inter_recon_lcu_bipred(state, refs[0], refs[1], @@ -631,7 +631,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, } else { const int mv_idx = cur_pu->inter.mv_dir - 1; const kvz_picture *const ref = - state->global->ref->images[cur_pu->inter.mv_ref[mv_idx]]; + state->frame->ref->images[cur_pu->inter.mv_ref[mv_idx]]; kvz_inter_recon_lcu(state, ref, pu_x, pu_y, @@ -670,11 +670,11 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, mode_bits = inter_bitcost; } - cost += mode_bits * state->global->cur_lambda_cost; + cost += mode_bits * state->frame->cur_lambda_cost; } // Recursively split all the way to max search depth. - if (depth < ctrl->pu_depth_intra.max || (depth < ctrl->pu_depth_inter.max && state->global->slicetype != KVZ_SLICE_I)) { + if (depth < ctrl->pu_depth_intra.max || (depth < ctrl->pu_depth_inter.max && state->frame->slicetype != KVZ_SLICE_I)) { int half_cu = cu_width / 2; double split_cost = 0.0; int cbf = cbf_is_set_any(cur_cu->cbf, depth); @@ -683,15 +683,15 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, // Add cost of cu_split_flag. uint8_t split_model = get_ctx_cu_split_model(lcu, x, y, depth); const cabac_ctx_t *ctx = &(state->cabac.ctx.split_flag_model[split_model]); - cost += CTX_ENTROPY_FBITS(ctx, 0) * state->global->cur_lambda_cost; - split_cost += CTX_ENTROPY_FBITS(ctx, 1) * state->global->cur_lambda_cost; + cost += CTX_ENTROPY_FBITS(ctx, 0) * state->frame->cur_lambda_cost; + split_cost += CTX_ENTROPY_FBITS(ctx, 1) * state->frame->cur_lambda_cost; } if (cur_cu->type == CU_INTRA && depth == MAX_DEPTH) { // Add cost of intra part_size. const cabac_ctx_t *ctx = &(state->cabac.ctx.part_size_model[0]); - cost += CTX_ENTROPY_FBITS(ctx, 1) * state->global->cur_lambda_cost; // 2Nx2N - split_cost += CTX_ENTROPY_FBITS(ctx, 0) * state->global->cur_lambda_cost; // NxN + cost += CTX_ENTROPY_FBITS(ctx, 1) * state->frame->cur_lambda_cost; // 2Nx2N + split_cost += CTX_ENTROPY_FBITS(ctx, 0) * state->frame->cur_lambda_cost; // NxN } // If skip mode was selected for the block, skip further search. @@ -735,11 +735,11 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, // Add the cost of coding no-split. uint8_t split_model = get_ctx_cu_split_model(lcu, x, y, depth); const cabac_ctx_t *ctx = &(state->cabac.ctx.split_flag_model[split_model]); - cost += CTX_ENTROPY_FBITS(ctx, 0) * state->global->cur_lambda_cost; + cost += CTX_ENTROPY_FBITS(ctx, 0) * state->frame->cur_lambda_cost; // Add the cost of coding intra mode only once. double mode_bits = calc_mode_bits(state, &work_tree[depth], cur_cu, x, y); - cost += mode_bits * state->global->cur_lambda_cost; + cost += mode_bits * state->frame->cur_lambda_cost; } } @@ -761,7 +761,7 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, work_tree_copy_down(x, y, depth, work_tree); } - PERFORMANCE_MEASURE_END(KVZ_PERF_SEARCHCU, state->encoder_control->threadqueue, "type=search_cu,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d,depth=%d,split=%d,cur_cu_is_intra=%d", state->global->frame, state->tile->id, state->slice->id, + PERFORMANCE_MEASURE_END(KVZ_PERF_SEARCHCU, state->encoder_control->threadqueue, "type=search_cu,frame=%d,tile=%d,slice=%d,px_x=%d-%d,px_y=%d-%d,depth=%d,split=%d,cur_cu_is_intra=%d", state->frame->num, state->tile->id, state->slice->id, (state->tile->lcu_offset_x * LCU_WIDTH) + x, (state->tile->lcu_offset_x * LCU_WIDTH) + x + (LCU_WIDTH >> depth), (state->tile->lcu_offset_y * LCU_WIDTH) + y, diff --git a/src/search_inter.c b/src/search_inter.c index 216a2338..6f27d1cf 100644 --- a/src/search_inter.c +++ b/src/search_inter.c @@ -251,7 +251,7 @@ static int calc_mvd_cost(encoder_state_t * const state, int x, int y, int mv_shi temp_bitcost += cur_mv_cand ? cand2_cost : cand1_cost; } *bitcost = temp_bitcost; - return temp_bitcost*(int32_t)(state->global->cur_lambda_cost_sqrt+0.5); + return temp_bitcost*(int32_t)(state->frame->cur_lambda_cost_sqrt+0.5); } @@ -1230,14 +1230,14 @@ static void search_pu_inter_ref(encoder_state_t * const state, const int x_cu = x >> 3; const int y_cu = y >> 3; const videoframe_t * const frame = state->tile->frame; - kvz_picture *ref_image = state->global->ref->images[ref_idx]; + kvz_picture *ref_image = state->frame->ref->images[ref_idx]; uint32_t temp_bitcost = 0; uint32_t temp_cost = 0; vector2d_t orig; int32_t merged = 0; uint8_t cu_mv_cand = 0; int8_t merge_idx = 0; - int8_t ref_list = state->global->refmap[ref_idx].list-1; + int8_t ref_list = state->frame->refmap[ref_idx].list-1; int8_t temp_ref_idx = cur_cu->inter.mv_ref[ref_list]; orig.x = x_cu * CU_MIN_SIZE_PIXELS; orig.y = y_cu * CU_MIN_SIZE_PIXELS; @@ -1258,7 +1258,7 @@ static void search_pu_inter_ref(encoder_state_t * const state, }; const int mid_x = tile_top_left_corner.x + x + (width >> 1); const int mid_y = tile_top_left_corner.y + y + (height >> 1); - const cu_array_t* ref_array = state->global->ref->cu_arrays[ref_idx]; + const cu_array_t* ref_array = state->frame->ref->cu_arrays[ref_idx]; const cu_info_t* ref_cu = kvz_cu_array_at_const(ref_array, mid_x, mid_y); if (ref_cu->type == CU_INTER) { if (ref_cu->inter.mv_dir & 1) { @@ -1378,7 +1378,7 @@ static void search_pu_inter_ref(encoder_state_t * const state, if (temp_cost < *inter_cost) { // Map reference index to L0/L1 pictures cur_cu->inter.mv_dir = ref_list+1; - uint8_t mv_ref_coded = state->global->refmap[ref_idx].idx; + uint8_t mv_ref_coded = state->frame->refmap[ref_idx].idx; cur_cu->merged = merged; cur_cu->merge_idx = merge_idx; @@ -1458,7 +1458,7 @@ static void search_pu_inter(encoder_state_t * const state, CU_SET_MV_CAND(cur_cu, 1, 0); uint32_t ref_idx; - for (ref_idx = 0; ref_idx < state->global->ref->used_size; ref_idx++) { + for (ref_idx = 0; ref_idx < state->frame->ref->used_size; ref_idx++) { search_pu_inter_ref(state, x, y, width, height, @@ -1472,7 +1472,7 @@ static void search_pu_inter(encoder_state_t * const state, } // Search bi-pred positions - bool can_use_bipred = state->global->slicetype == KVZ_SLICE_B + bool can_use_bipred = state->frame->slicetype == KVZ_SLICE_B && state->encoder_control->cfg->bipred && width + height >= 16; // 4x8 and 8x4 PBs are restricted to unipred @@ -1507,7 +1507,7 @@ static void search_pu_inter(encoder_state_t * const state, kvz_pixel tmp_block[64 * 64]; kvz_pixel tmp_pic[64 * 64]; // Force L0 and L1 references - if (state->global->refmap[merge_cand[i].ref[0]].list == 2 || state->global->refmap[merge_cand[j].ref[1]].list == 1) continue; + if (state->frame->refmap[merge_cand[i].ref[0]].list == 2 || state->frame->refmap[merge_cand[j].ref[1]].list == 1) continue; mv[0][0] = merge_cand[i].mv[0][0]; mv[0][1] = merge_cand[i].mv[0][1]; @@ -1525,8 +1525,8 @@ static void search_pu_inter(encoder_state_t * const state, } kvz_inter_recon_lcu_bipred(state, - state->global->ref->images[merge_cand[i].ref[0]], - state->global->ref->images[merge_cand[j].ref[1]], + state->frame->ref->images[merge_cand[i].ref[0]], + state->frame->ref->images[merge_cand[j].ref[1]], x, y, width, height, @@ -1551,8 +1551,8 @@ static void search_pu_inter(encoder_state_t * const state, cur_cu->inter.mv_dir = 3; uint8_t mv_ref_coded[2] = { - state->global->refmap[merge_cand[i].ref[0]].idx, - state->global->refmap[merge_cand[j].ref[1]].idx + state->frame->refmap[merge_cand[i].ref[0]].idx, + state->frame->refmap[merge_cand[j].ref[1]].idx }; cur_cu->inter.mv_ref[0] = merge_cand[i].ref[0]; diff --git a/src/search_intra.c b/src/search_intra.c index 503b90aa..a766020a 100644 --- a/src/search_intra.c +++ b/src/search_intra.c @@ -114,7 +114,7 @@ static double get_cost(encoder_state_t * const state, ctx = &state->cabac.ctx.transform_skip_model_chroma; trskip_bits += 2.0 * (CTX_ENTROPY_FBITS(ctx, 1) - CTX_ENTROPY_FBITS(ctx, 0)); - double sad_cost = TRSKIP_RATIO * sad_func(pred, orig_block) + state->global->cur_lambda_cost_sqrt * trskip_bits; + double sad_cost = TRSKIP_RATIO * sad_func(pred, orig_block) + state->frame->cur_lambda_cost_sqrt * trskip_bits; if (sad_cost < satd_cost) { return sad_cost; } @@ -158,7 +158,7 @@ static void get_cost_dual(encoder_state_t * const state, double sad_costs[PARALLEL_BLKS] = { 0 }; sad_twin_func(preds, orig_block, PARALLEL_BLKS, unsigned_sad_costs); for (int i = 0; i < PARALLEL_BLKS; ++i) { - sad_costs[i] = TRSKIP_RATIO * (double)unsigned_sad_costs[i] + state->global->cur_lambda_cost_sqrt * trskip_bits; + sad_costs[i] = TRSKIP_RATIO * (double)unsigned_sad_costs[i] + state->frame->cur_lambda_cost_sqrt * trskip_bits; if (sad_costs[i] < (double)satd_costs[i]) { costs_out[i] = sad_costs[i]; } @@ -248,7 +248,7 @@ static double search_intra_trdepth(encoder_state_t * const state, // max_depth. // - Min transform size hasn't been reached (MAX_PU_DEPTH). if (depth < max_depth && depth < MAX_PU_DEPTH) { - split_cost = 3 * state->global->cur_lambda_cost; + split_cost = 3 * state->frame->cur_lambda_cost; split_cost += search_intra_trdepth(state, x_px, y_px, depth + 1, max_depth, intra_mode, nosplit_cost, pred_cu, lcu); if (split_cost < nosplit_cost) { @@ -290,7 +290,7 @@ static double search_intra_trdepth(encoder_state_t * const state, } double bits = tr_split_bit + cbf_bits; - split_cost += bits * state->global->cur_lambda_cost; + split_cost += bits * state->frame->cur_lambda_cost; } else { assert(width <= TR_MAX_WIDTH); } @@ -516,7 +516,7 @@ static int8_t search_intra_rough(encoder_state_t * const state, // Add prediction mode coding cost as the last thing. We don't want this // affecting the halving search. - int lambda_cost = (int)(state->global->cur_lambda_cost_sqrt + 0.5); + int lambda_cost = (int)(state->frame->cur_lambda_cost_sqrt + 0.5); for (int mode_i = 0; mode_i < modes_selected; ++mode_i) { costs[mode_i] += lambda_cost * kvz_luma_mode_bits(state, modes[mode_i], intra_preds); } @@ -587,7 +587,7 @@ static int8_t search_intra_rdo(encoder_state_t * const state, for(int rdo_mode = 0; rdo_mode < modes_to_check; rdo_mode ++) { int rdo_bitcost = kvz_luma_mode_bits(state, modes[rdo_mode], intra_preds); - costs[rdo_mode] = rdo_bitcost * (int)(state->global->cur_lambda_cost + 0.5); + costs[rdo_mode] = rdo_bitcost * (int)(state->frame->cur_lambda_cost + 0.5); // Perform transform split search and save mode RD cost for the best one. cu_info_t pred_cu; @@ -688,7 +688,7 @@ int8_t kvz_search_intra_chroma_rdo(encoder_state_t * const state, chroma.cost = kvz_cu_rd_cost_chroma(state, lcu_px.x, lcu_px.y, depth, tr_cu, lcu); double mode_bits = kvz_chroma_mode_bits(state, chroma.mode, intra_mode); - chroma.cost += mode_bits * state->global->cur_lambda_cost; + chroma.cost += mode_bits * state->frame->cur_lambda_cost; if (chroma.cost < best_chroma.cost) { best_chroma = chroma; diff --git a/src/strategies/avx2/quant-avx2.c b/src/strategies/avx2/quant-avx2.c index ac16d411..b6c00658 100644 --- a/src/strategies/avx2/quant-avx2.c +++ b/src/strategies/avx2/quant-avx2.c @@ -53,13 +53,13 @@ void kvz_quant_flat_avx2(const encoder_state_t * const state, coeff_t *coef, coe const uint32_t log2_block_size = kvz_g_convert_to_bit[width] + 2; const uint32_t * const scan = kvz_g_sig_last_scan[scan_idx][log2_block_size - 1]; - int32_t qp_scaled = kvz_get_scaled_qp(type, state->global->QP, (encoder->bitdepth - 8) * 6); + int32_t qp_scaled = kvz_get_scaled_qp(type, state->frame->QP, (encoder->bitdepth - 8) * 6); const uint32_t log2_tr_size = kvz_g_convert_to_bit[width] + 2; const int32_t scalinglist_type = (block_type == CU_INTRA ? 0 : 3) + (int8_t)("\0\3\1\2"[type]); const int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size - 2][scalinglist_type][qp_scaled % 6]; const int32_t transform_shift = MAX_TR_DYNAMIC_RANGE - encoder->bitdepth - log2_tr_size; //!< Represents scaling through forward transform const int32_t q_bits = QUANT_SHIFT + qp_scaled / 6 + transform_shift; - const int32_t add = ((state->global->slicetype == KVZ_SLICE_I) ? 171 : 85) << (q_bits - 9); + const int32_t add = ((state->frame->slicetype == KVZ_SLICE_I) ? 171 : 85) << (q_bits - 9); const int32_t q_bits8 = q_bits - 8; assert(quant_coeff[0] <= (1 << 15) - 1 && quant_coeff[0] >= -(1 << 15)); //Assuming flat values to fit int16_t @@ -458,7 +458,7 @@ void kvz_dequant_avx2(const encoder_state_t * const state, coeff_t *q_coef, coef int32_t n; int32_t transform_shift = 15 - encoder->bitdepth - (kvz_g_convert_to_bit[ width ] + 2); - int32_t qp_scaled = kvz_get_scaled_qp(type, state->global->QP, (encoder->bitdepth-8)*6); + int32_t qp_scaled = kvz_get_scaled_qp(type, state->frame->QP, (encoder->bitdepth-8)*6); shift = 20 - QUANT_SHIFT - transform_shift; diff --git a/src/strategies/generic/quant-generic.c b/src/strategies/generic/quant-generic.c index 821f8fa9..8d9577b4 100644 --- a/src/strategies/generic/quant-generic.c +++ b/src/strategies/generic/quant-generic.c @@ -41,13 +41,13 @@ void kvz_quant_generic(const encoder_state_t * const state, coeff_t *coef, coeff const uint32_t log2_block_size = kvz_g_convert_to_bit[width] + 2; const uint32_t * const scan = kvz_g_sig_last_scan[scan_idx][log2_block_size - 1]; - int32_t qp_scaled = kvz_get_scaled_qp(type, state->global->QP, (encoder->bitdepth - 8) * 6); + int32_t qp_scaled = kvz_get_scaled_qp(type, state->frame->QP, (encoder->bitdepth - 8) * 6); const uint32_t log2_tr_size = kvz_g_convert_to_bit[width] + 2; const int32_t scalinglist_type = (block_type == CU_INTRA ? 0 : 3) + (int8_t)("\0\3\1\2"[type]); const int32_t *quant_coeff = encoder->scaling_list.quant_coeff[log2_tr_size - 2][scalinglist_type][qp_scaled % 6]; const int32_t transform_shift = MAX_TR_DYNAMIC_RANGE - encoder->bitdepth - log2_tr_size; //!< Represents scaling through forward transform const int32_t q_bits = QUANT_SHIFT + qp_scaled / 6 + transform_shift; - const int32_t add = ((state->global->slicetype == KVZ_SLICE_I) ? 171 : 85) << (q_bits - 9); + const int32_t add = ((state->frame->slicetype == KVZ_SLICE_I) ? 171 : 85) << (q_bits - 9); const int32_t q_bits8 = q_bits - 8; uint32_t ac_sum = 0; @@ -286,7 +286,7 @@ void kvz_dequant_generic(const encoder_state_t * const state, coeff_t *q_coef, c int32_t n; int32_t transform_shift = 15 - encoder->bitdepth - (kvz_g_convert_to_bit[ width ] + 2); - int32_t qp_scaled = kvz_get_scaled_qp(type, state->global->QP, (encoder->bitdepth-8)*6); + int32_t qp_scaled = kvz_get_scaled_qp(type, state->frame->QP, (encoder->bitdepth-8)*6); shift = 20 - QUANT_SHIFT - transform_shift; diff --git a/src/transform.c b/src/transform.c index b98ad236..d95137b7 100644 --- a/src/transform.c +++ b/src/transform.c @@ -199,7 +199,7 @@ int kvz_quantize_residual_trskip( int has_coeffs; } skip, noskip, *best; - const int bit_cost = (int)(state->global->cur_lambda_cost+0.5); + const int bit_cost = (int)(state->frame->cur_lambda_cost+0.5); noskip.has_coeffs = kvz_quantize_residual( state, cur_cu, width, color, scan_order,