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