diff --git a/src/intra.c b/src/intra.c index bd1e520a..0d22f085 100644 --- a/src/intra.c +++ b/src/intra.c @@ -671,6 +671,6 @@ void kvz_intra_recon_cu( intra_recon_tb_leaf(state, x, y, depth, mode_chroma, lcu, COLOR_V); } - kvz_quantize_lcu_residual(state, has_luma, has_chroma, x, y, depth, cur_cu, lcu); + kvz_quantize_lcu_residual(state, has_luma, has_chroma, x, y, depth, cur_cu, lcu, false); } } diff --git a/src/search.c b/src/search.c index a09dacb4..4cc5a03b 100644 --- a/src/search.c +++ b/src/search.c @@ -637,7 +637,8 @@ static double search_cu(encoder_state_t * const state, int x, int y, int depth, true, has_chroma, x, y, depth, NULL, - lcu); + lcu, + false); int cbf = cbf_is_set_any(cur_cu->cbf, depth); diff --git a/src/search_inter.c b/src/search_inter.c index 5da5003f..3d8221e6 100644 --- a/src/search_inter.c +++ b/src/search_inter.c @@ -1714,14 +1714,14 @@ static void search_pu_inter(encoder_state_t * const state, cur_cu->inter.mv[1][1] = info.merge_cand[merge_idx].mv[1][1]; kvz_lcu_fill_trdepth(lcu, x, y, depth, MAX(1, depth)); kvz_inter_recon_cu(state, lcu, x, y, width, true, false); - kvz_quantize_lcu_residual(state, true, false, x, y, depth, cur_cu, lcu); + kvz_quantize_lcu_residual(state, true, false, x, y, depth, cur_cu, lcu, true); if (cbf_is_set(cur_cu->cbf, depth, COLOR_Y)) { continue; } else if (has_chroma) { kvz_inter_recon_cu(state, lcu, x, y, width, false, has_chroma); - kvz_quantize_lcu_residual(state, false, has_chroma, x, y, depth, cur_cu, lcu); + kvz_quantize_lcu_residual(state, false, has_chroma, x, y, depth, cur_cu, lcu, true); if (!cbf_is_set_any(cur_cu->cbf, depth)) { cur_cu->type = CU_INTER; cur_cu->merge_idx = merge_idx; @@ -1921,7 +1921,8 @@ void kvz_cu_cost_inter_rd2(encoder_state_t * const state, kvz_quantize_lcu_residual(state, true, reconstruct_chroma, x, y, depth, NULL, - lcu); + lcu, + false); *inter_cost = kvz_cu_rd_cost_luma(state, SUB_SCU(x), SUB_SCU(y), depth, cur_cu, lcu); if (reconstruct_chroma) { diff --git a/src/strategies/avx2/quant-avx2.c b/src/strategies/avx2/quant-avx2.c index bc5b1402..77759cb2 100644 --- a/src/strategies/avx2/quant-avx2.c +++ b/src/strategies/avx2/quant-avx2.c @@ -621,6 +621,7 @@ static void get_quantized_recon_avx2(int16_t *residual, const kvz_pixel *pred_in * \param pred_in Predicted pixels. * \param rec_out Reconstructed pixels. * \param coeff_out Coefficients used for reconstruction of rec_out. +* \param early_skip if this is used for early skip, bypass IT and IQ * * \returns Whether coeff_out contains any non-zero coefficients. */ @@ -629,7 +630,8 @@ int kvz_quantize_residual_avx2(encoder_state_t *const state, const coeff_scan_order_t scan_order, const int use_trskip, const int in_stride, const int out_stride, const kvz_pixel *const ref_in, const kvz_pixel *const pred_in, - kvz_pixel *rec_out, coeff_t *coeff_out) + kvz_pixel *rec_out, coeff_t *coeff_out, + bool early_skip) { // Temporary arrays to pass data to and from kvz_quant and transform functions. ALIGNED(64) int16_t residual[TR_MAX_WIDTH * TR_MAX_WIDTH]; @@ -673,7 +675,7 @@ int kvz_quantize_residual_avx2(encoder_state_t *const state, // Do the inverse quantization and transformation and the reconstruction to // rec_out. - if (has_coeffs) { + if (has_coeffs && !early_skip) { // Get quantized residual. (coeff_out -> coeff -> residual) kvz_dequant(state, coeff_out, coeff, width, width, (color == COLOR_Y ? 0 : (color == COLOR_U ? 2 : 3)), cur_cu->type); diff --git a/src/strategies/generic/quant-generic.c b/src/strategies/generic/quant-generic.c index dbb59a85..8f4aaaf7 100644 --- a/src/strategies/generic/quant-generic.c +++ b/src/strategies/generic/quant-generic.c @@ -178,6 +178,7 @@ void kvz_quant_generic(const encoder_state_t * const state, coeff_t *coef, coeff * \param pred_in Predicted pixels. * \param rec_out Reconstructed pixels. * \param coeff_out Coefficients used for reconstruction of rec_out. +* \param early_skip if this is used for early skip, bypass IT and IQ * * \returns Whether coeff_out contains any non-zero coefficients. */ @@ -186,7 +187,8 @@ int kvz_quantize_residual_generic(encoder_state_t *const state, const coeff_scan_order_t scan_order, const int use_trskip, const int in_stride, const int out_stride, const kvz_pixel *const ref_in, const kvz_pixel *const pred_in, - kvz_pixel *rec_out, coeff_t *coeff_out) + kvz_pixel *rec_out, coeff_t *coeff_out, + bool early_skip) { // Temporary arrays to pass data to and from kvz_quant and transform functions. ALIGNED(64) int16_t residual[TR_MAX_WIDTH * TR_MAX_WIDTH]; @@ -241,7 +243,7 @@ int kvz_quantize_residual_generic(encoder_state_t *const state, // Do the inverse quantization and transformation and the reconstruction to // rec_out. - if (has_coeffs) { + if (has_coeffs && !early_skip) { int y, x; // Get quantized residual. (coeff_out -> coeff -> residual) diff --git a/src/strategies/generic/quant-generic.h b/src/strategies/generic/quant-generic.h index ed4f3c63..13d24cb9 100644 --- a/src/strategies/generic/quant-generic.h +++ b/src/strategies/generic/quant-generic.h @@ -1,48 +1,49 @@ -#ifndef STRATEGIES_QUANT_GENERIC_H_ -#define STRATEGIES_QUANT_GENERIC_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 . - ****************************************************************************/ - -/** - * \ingroup Optimization - * \file - * Generic C implementations of optimized functions. - */ - -#include "cu.h" -#include "encoderstate.h" -#include "global.h" // IWYU pragma: keep -#include "kvazaar.h" -#include "tables.h" - -#define QUANT_SHIFT 14 - -int kvz_strategy_register_quant_generic(void* opaque, uint8_t bitdepth); -void kvz_quant_generic(const encoder_state_t * const state, coeff_t *coef, coeff_t *q_coef, int32_t width, - int32_t height, int8_t type, int8_t scan_idx, int8_t block_type); - -int kvz_quantize_residual_generic(encoder_state_t *const state, - const cu_info_t *const cur_cu, const int width, const color_t color, - const coeff_scan_order_t scan_order, const int use_trskip, - const int in_stride, const int out_stride, - const kvz_pixel *const ref_in, const kvz_pixel *const pred_in, - kvz_pixel *rec_out, coeff_t *coeff_out); - -#endif //STRATEGIES_QUANT_GENERIC_H_ +#ifndef STRATEGIES_QUANT_GENERIC_H_ +#define STRATEGIES_QUANT_GENERIC_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 . + ****************************************************************************/ + +/** + * \ingroup Optimization + * \file + * Generic C implementations of optimized functions. + */ + +#include "cu.h" +#include "encoderstate.h" +#include "global.h" // IWYU pragma: keep +#include "kvazaar.h" +#include "tables.h" + +#define QUANT_SHIFT 14 + +int kvz_strategy_register_quant_generic(void* opaque, uint8_t bitdepth); +void kvz_quant_generic(const encoder_state_t * const state, coeff_t *coef, coeff_t *q_coef, int32_t width, + int32_t height, int8_t type, int8_t scan_idx, int8_t block_type); + +int kvz_quantize_residual_generic(encoder_state_t *const state, + const cu_info_t *const cur_cu, const int width, const color_t color, + const coeff_scan_order_t scan_order, const int use_trskip, + const int in_stride, const int out_stride, + const kvz_pixel *const ref_in, const kvz_pixel *const pred_in, + kvz_pixel *rec_out, coeff_t *coeff_out, + bool early_skip); + +#endif //STRATEGIES_QUANT_GENERIC_H_ diff --git a/src/strategies/strategies-quant.h b/src/strategies/strategies-quant.h index 48e25d08..dbeef0b4 100644 --- a/src/strategies/strategies-quant.h +++ b/src/strategies/strategies-quant.h @@ -41,7 +41,8 @@ typedef unsigned (quant_residual_func)(encoder_state_t *const state, const coeff_scan_order_t scan_order, const int use_trskip, const int in_stride, const int out_stride, const kvz_pixel *const ref_in, const kvz_pixel *const pred_in, - kvz_pixel *rec_out, coeff_t *coeff_out); + kvz_pixel *rec_out, coeff_t *coeff_out, + bool early_skip); typedef unsigned (dequant_func)(const encoder_state_t * const state, coeff_t *q_coef, coeff_t *coef, int32_t width, int32_t height, int8_t type, int8_t block_type); typedef uint32_t (fast_coeff_cost_func)(const coeff_t *coeff, int32_t width, int32_t qp); diff --git a/src/transform.c b/src/transform.c index 33535062..363ecab1 100644 --- a/src/transform.c +++ b/src/transform.c @@ -247,14 +247,14 @@ int kvz_quantize_residual_trskip( noskip.has_coeffs = kvz_quantize_residual( state, cur_cu, width, color, scan_order, 0, in_stride, 4, - ref_in, pred_in, noskip.rec, noskip.coeff); + ref_in, pred_in, noskip.rec, noskip.coeff, false); noskip.cost = kvz_pixels_calc_ssd(ref_in, noskip.rec, in_stride, 4, 4); noskip.cost += kvz_get_coeff_cost(state, noskip.coeff, 4, 0, scan_order) * bit_cost; skip.has_coeffs = kvz_quantize_residual( state, cur_cu, width, color, scan_order, 1, in_stride, 4, - ref_in, pred_in, skip.rec, skip.coeff); + ref_in, pred_in, skip.rec, skip.coeff, false); skip.cost = kvz_pixels_calc_ssd(ref_in, skip.rec, in_stride, 4, 4); skip.cost += kvz_get_coeff_cost(state, skip.coeff, 4, 0, scan_order) * bit_cost; @@ -278,6 +278,8 @@ int kvz_quantize_residual_trskip( /** * Calculate the residual coefficients for a single TU. + * + * \param early_skip if this is used for early skip, bypass IT and IQ */ static void quantize_tr_residual(encoder_state_t * const state, const color_t color, @@ -285,7 +287,8 @@ static void quantize_tr_residual(encoder_state_t * const state, const int32_t y, const uint8_t depth, cu_info_t *cur_pu, - lcu_t* lcu) + lcu_t* lcu, + bool early_skip) { const kvz_config *cfg = &state->encoder_control->cfg; const int32_t shift = color == COLOR_Y ? 0 : 1; @@ -398,7 +401,8 @@ static void quantize_tr_residual(encoder_state_t * const state, ref, pred, pred, - coeff); + coeff, + early_skip); } if (has_coeffs) { @@ -412,9 +416,10 @@ static void quantize_tr_residual(encoder_state_t * const state, * kvantized residual. Processes the TU tree recursively. * * Inputs are: - * - lcu->rec pixels after prediction for the area - * - lcu->ref reference pixels for the area - * - lcu->cu for the area + * - lcu->rec pixels after prediction for the area + * - lcu->ref reference pixels for the area + * - lcu->cu for the area + * - early_skip if this is used for early skip, bypass IT and IQ * * Outputs are: * - lcu->rec reconstruction after quantized residual @@ -429,7 +434,8 @@ void kvz_quantize_lcu_residual(encoder_state_t * const state, const int32_t y, const uint8_t depth, cu_info_t *cur_pu, - lcu_t* lcu) + lcu_t* lcu, + bool early_skip) { const int32_t width = LCU_WIDTH >> depth; const vector2d_t lcu_px = { SUB_SCU(x), SUB_SCU(y) }; @@ -463,10 +469,10 @@ void kvz_quantize_lcu_residual(encoder_state_t * const state, const int32_t x2 = x + offset; const int32_t y2 = y + offset; - kvz_quantize_lcu_residual(state, luma, chroma, x, y, depth + 1, NULL, lcu); - kvz_quantize_lcu_residual(state, luma, chroma, x2, y, depth + 1, NULL, lcu); - kvz_quantize_lcu_residual(state, luma, chroma, x, y2, depth + 1, NULL, lcu); - kvz_quantize_lcu_residual(state, luma, chroma, x2, y2, depth + 1, NULL, lcu); + kvz_quantize_lcu_residual(state, luma, chroma, x, y, depth + 1, NULL, lcu, early_skip); + kvz_quantize_lcu_residual(state, luma, chroma, x2, y, depth + 1, NULL, lcu, early_skip); + kvz_quantize_lcu_residual(state, luma, chroma, x, y2, depth + 1, NULL, lcu, early_skip); + kvz_quantize_lcu_residual(state, luma, chroma, x2, y2, depth + 1, NULL, lcu, early_skip); // Propagate coded block flags from child CUs to parent CU. uint16_t child_cbfs[3] = { @@ -484,11 +490,11 @@ void kvz_quantize_lcu_residual(encoder_state_t * const state, } else { // Process a leaf TU. if (luma) { - quantize_tr_residual(state, COLOR_Y, x, y, depth, cur_pu, lcu); + quantize_tr_residual(state, COLOR_Y, x, y, depth, cur_pu, lcu, early_skip); } if (chroma) { - quantize_tr_residual(state, COLOR_U, x, y, depth, cur_pu, lcu); - quantize_tr_residual(state, COLOR_V, x, y, depth, cur_pu, lcu); + quantize_tr_residual(state, COLOR_U, x, y, depth, cur_pu, lcu, early_skip); + quantize_tr_residual(state, COLOR_V, x, y, depth, cur_pu, lcu, early_skip); } } } diff --git a/src/transform.h b/src/transform.h index ebbc983b..1e567535 100644 --- a/src/transform.h +++ b/src/transform.h @@ -60,6 +60,7 @@ void kvz_quantize_lcu_residual(encoder_state_t *state, int32_t y, uint8_t depth, cu_info_t *cur_cu, - lcu_t* lcu); + lcu_t* lcu, + bool early_skip); #endif