Merge "Merge tag 'v2.0.1'"
diff --git a/aom_dsp/x86/aom_subpixel_8t_intrin_ssse3.c b/aom_dsp/x86/aom_subpixel_8t_intrin_ssse3.c
index 18e8a2a..b6ca63d 100644
--- a/aom_dsp/x86/aom_subpixel_8t_intrin_ssse3.c
+++ b/aom_dsp/x86/aom_subpixel_8t_intrin_ssse3.c
@@ -826,7 +826,7 @@
const ptrdiff_t src_stride,
uint8_t *const dst,
const int16_t *const filter) {
- __m128i s[4], ss[2];
+ __m128i s[4], ss[4];
__m128i temp;
load_8bit_8x4(src, src_stride, s);
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index cc681bc..9dade55 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -1541,6 +1541,7 @@
#endif
if (mt_info->num_workers > 1) {
av1_loop_filter_dealloc(&mt_info->lf_row_sync);
+ av1_cdef_mt_dealloc(&mt_info->cdef_sync);
#if !CONFIG_REALTIME_ONLY
av1_loop_restoration_dealloc(&mt_info->lr_row_sync, mt_info->num_workers);
av1_gm_dealloc(&mt_info->gm_sync);
@@ -2041,7 +2042,7 @@
start_timing(cpi, cdef_time);
#endif
// Find CDEF parameters
- av1_cdef_search(&cm->cur_frame->buf, cpi->source, cm, xd,
+ av1_cdef_search(&cpi->mt_info, &cm->cur_frame->buf, cpi->source, cm, xd,
cpi->sf.lpf_sf.cdef_pick_method, cpi->td.mb.rdmult);
// Apply the filter
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h
index ed79ba0..b4bc58d 100644
--- a/av1/encoder/encoder.h
+++ b/av1/encoder/encoder.h
@@ -40,6 +40,7 @@
#include "av1/encoder/level.h"
#include "av1/encoder/lookahead.h"
#include "av1/encoder/mcomp.h"
+#include "av1/encoder/pickcdef.h"
#include "av1/encoder/ratectrl.h"
#include "av1/encoder/rd.h"
#include "av1/encoder/speed_features.h"
@@ -1337,7 +1338,7 @@
/*!
* \brief Encoder parameters related to multi-threading.
*/
-typedef struct {
+typedef struct MultiThreadInfo {
/*!
* Number of workers created for multi-threading.
*/
@@ -1399,6 +1400,11 @@
* Temporal Filter multi-threading object.
*/
AV1TemporalFilterSync tf_sync;
+
+ /*!
+ * CDEF search multi-threading object.
+ */
+ AV1CdefSync cdef_sync;
} MultiThreadInfo;
/*!\cond */
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c
index bf22743..730eedb 100644
--- a/av1/encoder/ethread.c
+++ b/av1/encoder/ethread.c
@@ -545,6 +545,12 @@
CHECK_MEM_ERROR(cm, tf_sync->mutex_, aom_malloc(sizeof(*tf_sync->mutex_)));
if (tf_sync->mutex_) pthread_mutex_init(tf_sync->mutex_, NULL);
}
+ AV1CdefSync *cdef_sync = &mt_info->cdef_sync;
+ if (cdef_sync->mutex_ == NULL) {
+ CHECK_MEM_ERROR(cm, cdef_sync->mutex_,
+ aom_malloc(sizeof(*(cdef_sync->mutex_))));
+ if (cdef_sync->mutex_) pthread_mutex_init(cdef_sync->mutex_, NULL);
+ }
#endif
for (int i = num_workers - 1; i >= 0; i--) {
@@ -1662,3 +1668,110 @@
sync_enc_workers(&cpi->mt_info, &cpi->common, num_workers);
}
#endif // !CONFIG_REALTIME_ONLY
+
+// Deallocate memory for CDEF search multi-thread synchronization.
+void av1_cdef_mt_dealloc(AV1CdefSync *cdef_sync) {
+ (void)cdef_sync;
+ assert(cdef_sync != NULL);
+#if CONFIG_MULTITHREAD
+ if (cdef_sync->mutex_ != NULL) {
+ pthread_mutex_destroy(cdef_sync->mutex_);
+ aom_free(cdef_sync->mutex_);
+ }
+#endif // CONFIG_MULTITHREAD
+}
+
+// Updates the row and column indices of the next job to be processed.
+// Also updates end_of_frame flag when the processing of all blocks is complete.
+static void update_next_job_info(AV1CdefSync *cdef_sync, int nvfb, int nhfb) {
+ cdef_sync->fbc++;
+ if (cdef_sync->fbc == nhfb) {
+ cdef_sync->fbr++;
+ if (cdef_sync->fbr == nvfb) {
+ cdef_sync->end_of_frame = 1;
+ } else {
+ cdef_sync->fbc = 0;
+ }
+ }
+}
+
+// Initializes cdef_sync parameters.
+static AOM_INLINE void cdef_reset_job_info(AV1CdefSync *cdef_sync) {
+ cdef_sync->end_of_frame = 0;
+ cdef_sync->fbr = 0;
+ cdef_sync->fbc = 0;
+}
+
+// Checks if a job is available. If job is available,
+// populates next job information and returns 1, else returns 0.
+static AOM_INLINE int cdef_get_next_job(AV1CdefSync *cdef_sync,
+ CdefSearchCtx *cdef_search_ctx,
+ int *cur_fbr, int *cur_fbc,
+ int *sb_count) {
+#if CONFIG_MULTITHREAD
+ pthread_mutex_lock(cdef_sync->mutex_);
+#endif // CONFIG_MULTITHREAD
+ int do_next_block = 0;
+ const int nvfb = cdef_search_ctx->nvfb;
+ const int nhfb = cdef_search_ctx->nhfb;
+
+ // If a block is skip, do not process the block and
+ // check the skip condition for the next block.
+ while ((!cdef_sync->end_of_frame) &&
+ (cdef_sb_skip(cdef_search_ctx->mi_params, cdef_sync->fbr,
+ cdef_sync->fbc))) {
+ update_next_job_info(cdef_sync, nvfb, nhfb);
+ }
+
+ // Populates information needed for current job and update the row,
+ // column indices of the next block to be processed.
+ if (cdef_sync->end_of_frame == 0) {
+ do_next_block = 1;
+ *cur_fbr = cdef_sync->fbr;
+ *cur_fbc = cdef_sync->fbc;
+ *sb_count = cdef_search_ctx->sb_count;
+ cdef_search_ctx->sb_count++;
+ update_next_job_info(cdef_sync, nvfb, nhfb);
+ }
+#if CONFIG_MULTITHREAD
+ pthread_mutex_unlock(cdef_sync->mutex_);
+#endif // CONFIG_MULTITHREAD
+ return do_next_block;
+}
+
+// Hook function for each thread in CDEF search multi-threading.
+static int cdef_filter_block_worker_hook(void *arg1, void *arg2) {
+ AV1CdefSync *const cdef_sync = (AV1CdefSync *)arg1;
+ CdefSearchCtx *cdef_search_ctx = (CdefSearchCtx *)arg2;
+ int cur_fbr, cur_fbc, sb_count;
+ while (cdef_get_next_job(cdef_sync, cdef_search_ctx, &cur_fbr, &cur_fbc,
+ &sb_count)) {
+ av1_cdef_mse_calc_block(cdef_search_ctx, cur_fbr, cur_fbc, sb_count);
+ }
+ return 1;
+}
+
+// Assigns CDEF search hook function and thread data to each worker.
+static void prepare_cdef_workers(MultiThreadInfo *mt_info,
+ CdefSearchCtx *cdef_search_ctx,
+ AVxWorkerHook hook, int num_workers) {
+ for (int i = num_workers - 1; i >= 0; i--) {
+ AVxWorker *worker = &mt_info->workers[i];
+ worker->hook = hook;
+ worker->data1 = &mt_info->cdef_sync;
+ worker->data2 = cdef_search_ctx;
+ }
+}
+
+// Implements multi-threading for CDEF search.
+void av1_cdef_mse_calc_frame_mt(AV1_COMMON *cm, MultiThreadInfo *mt_info,
+ CdefSearchCtx *cdef_search_ctx) {
+ AV1CdefSync *cdef_sync = &mt_info->cdef_sync;
+ const int num_workers = mt_info->num_workers;
+
+ cdef_reset_job_info(cdef_sync);
+ prepare_cdef_workers(mt_info, cdef_search_ctx, cdef_filter_block_worker_hook,
+ num_workers);
+ launch_workers(mt_info, num_workers);
+ sync_enc_workers(mt_info, cm, num_workers);
+}
diff --git a/av1/encoder/ethread.h b/av1/encoder/ethread.h
index ab8e1bb..e8b8ad3 100644
--- a/av1/encoder/ethread.h
+++ b/av1/encoder/ethread.h
@@ -78,6 +78,11 @@
void av1_create_workers(AV1_COMP *cpi, int num_workers);
+void av1_cdef_mse_calc_frame_mt(AV1_COMMON *cm, MultiThreadInfo *mt_info,
+ CdefSearchCtx *cdef_search_ctx);
+
+void av1_cdef_mt_dealloc(AV1CdefSync *cdef_sync);
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/av1/encoder/pass2_strategy.c b/av1/encoder/pass2_strategy.c
index f16b0d2..d067d50e8 100644
--- a/av1/encoder/pass2_strategy.c
+++ b/av1/encoder/pass2_strategy.c
@@ -180,14 +180,24 @@
return fclamp(pow(error_term, power_term), 0.05, 5.0);
}
-static void twopass_update_bpm_factor(TWO_PASS *twopass) {
+static void twopass_update_bpm_factor(TWO_PASS *twopass, int err_estimate,
+ int rate_err_tol) {
// Based on recent history adjust expectations of bits per macroblock.
double last_group_rate_err =
(double)twopass->rolling_arf_group_actual_bits /
DOUBLE_DIVIDE_CHECK((double)twopass->rolling_arf_group_target_bits);
- last_group_rate_err = AOMMAX(0.25, AOMMIN(4.0, last_group_rate_err));
- twopass->bpm_factor *= (3.0 + last_group_rate_err) / 4.0;
- twopass->bpm_factor = AOMMAX(0.25, AOMMIN(4.0, twopass->bpm_factor));
+ double damp_fac = AOMMAX(5.0, rate_err_tol / 10.0);
+
+ last_group_rate_err = AOMMAX(0.75, AOMMIN(1.25, last_group_rate_err));
+ last_group_rate_err = 1.0 + ((last_group_rate_err - 1.0) / damp_fac);
+
+ // Is the last GOP error making the total error worse or better? Only make
+ // an adjustment if things are getting worse.
+ if ((last_group_rate_err < 1.0 && err_estimate > 0) ||
+ (last_group_rate_err > 1.0 && err_estimate < 0)) {
+ twopass->bpm_factor *= last_group_rate_err;
+ twopass->bpm_factor = AOMMAX(0.75, AOMMIN(1.25, twopass->bpm_factor));
+ }
}
static int qbpm_enumerator(int rate_err_tol) {
@@ -240,15 +250,12 @@
* Here we want to ignore the bands at the
* top and bottom.
* \param[in] av_target_bandwidth The target bits per frame
- * \param[in] group_weight_factor A correction factor allowing the algorithm
- * to correct for errors over time.
*
* \return The maximum Q for frames in the group.
*/
static int get_twopass_worst_quality(AV1_COMP *cpi, const double av_frame_err,
double inactive_zone,
- int av_target_bandwidth,
- double group_weight_factor) {
+ int av_target_bandwidth) {
const RATE_CONTROL *const rc = &cpi->rc;
const AV1EncoderConfig *const oxcf = &cpi->oxcf;
const RateControlCfg *const rc_cfg = &oxcf->rc_cfg;
@@ -266,12 +273,15 @@
(int)((uint64_t)av_target_bandwidth << BPER_MB_NORMBITS) / active_mbs;
int rate_err_tol = AOMMIN(rc_cfg->under_shoot_pct, rc_cfg->over_shoot_pct);
- twopass_update_bpm_factor(&cpi->twopass);
+ // Update bpm correction factor based on previous GOP rate error.
+ twopass_update_bpm_factor(&cpi->twopass, rc->rate_error_estimate,
+ rate_err_tol);
+
// Try and pick a max Q that will be high enough to encode the
// content at the given rate.
int q = find_qindex_by_rate_with_correction(
target_norm_bits_per_mb, cpi->common.seq_params.bit_depth,
- av_err_per_mb, group_weight_factor, rate_err_tol, rc->best_quality,
+ av_err_per_mb, cpi->twopass.bpm_factor, rate_err_tol, rc->best_quality,
rc->worst_quality);
// Restriction on active max q for constrained quality mode.
@@ -971,11 +981,6 @@
return 0;
}
-#if GROUP_ADAPTIVE_MAXQ
-#define RC_FACTOR_MIN 0.75
-#define RC_FACTOR_MAX 1.25
-#endif // GROUP_ADAPTIVE_MAXQ
-
#define MIN_FWD_KF_INTERVAL 8
#define MIN_SHRINK_LEN 6 // the minimum length of gf if we are shrinking
#define SMOOTH_FILT_LEN 7
@@ -2519,25 +2524,9 @@
(rc->baseline_gf_interval * (double)cm->mi_params.mb_rows));
int tmp_q;
- // rc factor is a weight factor that corrects for local rate control drift.
- double rc_factor = 1.0;
- int64_t bits = rc_cfg->target_bandwidth;
-
- if (bits > 0) {
- int rate_error;
-
- rate_error = (int)((rc->vbr_bits_off_target * 100) / bits);
- rate_error = clamp(rate_error, -100, 100);
- if (rate_error > 0) {
- rc_factor = AOMMAX(RC_FACTOR_MIN, (double)(100 - rate_error) / 100.0);
- } else {
- rc_factor = AOMMIN(RC_FACTOR_MAX, (double)(100 - rate_error) / 100.0);
- }
- }
-
tmp_q = get_twopass_worst_quality(
cpi, group_av_err, (group_av_skip_pct + group_av_inactive_zone),
- vbr_group_bits_per_frame, rc_factor);
+ vbr_group_bits_per_frame);
rc->active_worst_quality = AOMMAX(tmp_q, rc->active_worst_quality >> 1);
}
#endif
@@ -3321,7 +3310,6 @@
#if ARF_STATS_OUTPUT
unsigned int arf_count = 0;
#endif
-#define DEFAULT_GRP_WEIGHT 1.0
static int get_section_target_bandwidth(AV1_COMP *cpi) {
AV1_COMMON *const cm = &cpi->common;
@@ -3370,7 +3358,7 @@
((double)cm->mi_params.mb_rows * section_length);
const int tmp_q = get_twopass_worst_quality(
cpi, section_error, section_intra_skip + section_inactive_zone,
- section_target_bandwidth, DEFAULT_GRP_WEIGHT);
+ section_target_bandwidth);
rc->active_worst_quality = tmp_q;
rc->ni_av_qi = tmp_q;
@@ -3780,7 +3768,6 @@
void av1_twopass_postencode_update(AV1_COMP *cpi) {
TWO_PASS *const twopass = &cpi->twopass;
RATE_CONTROL *const rc = &cpi->rc;
- const int bits_used = rc->base_frame_target;
const RateControlCfg *const rc_cfg = &cpi->oxcf.rc_cfg;
// VBR correction is done through rc->vbr_bits_off_target. Based on the
@@ -3789,10 +3776,10 @@
// is designed to prevent extreme behaviour at the end of a clip
// or group of frames.
rc->vbr_bits_off_target += rc->base_frame_target - rc->projected_frame_size;
- twopass->bits_left = AOMMAX(twopass->bits_left - bits_used, 0);
+ twopass->bits_left = AOMMAX(twopass->bits_left - rc->base_frame_target, 0);
// Target vs actual bits for this arf group.
- twopass->rolling_arf_group_target_bits += rc->this_frame_target;
+ twopass->rolling_arf_group_target_bits += rc->base_frame_target;
twopass->rolling_arf_group_actual_bits += rc->projected_frame_size;
// Calculate the pct rc error.
@@ -3845,7 +3832,7 @@
#endif
if (cpi->common.current_frame.frame_type != KEY_FRAME) {
- twopass->kf_group_bits -= bits_used;
+ twopass->kf_group_bits -= rc->base_frame_target;
twopass->last_kfgroup_zeromotion_pct = twopass->kf_zeromotion_pct;
}
twopass->kf_group_bits = AOMMAX(twopass->kf_group_bits, 0);
diff --git a/av1/encoder/pickcdef.c b/av1/encoder/pickcdef.c
index c71ef31..55e466d 100644
--- a/av1/encoder/pickcdef.c
+++ b/av1/encoder/pickcdef.c
@@ -20,6 +20,7 @@
#include "av1/common/av1_common_int.h"
#include "av1/common/reconinter.h"
#include "av1/encoder/encoder.h"
+#include "av1/encoder/ethread.h"
#include "av1/encoder/pickcdef.h"
// Get primary and secondary filter strength for the given strength index and
@@ -289,11 +290,10 @@
// fbc: Column index in units of 64x64 block
// Returns:
// Nothing will be returned. Contents of cdef_search_ctx will be modified.
-static void cdef_mse_calc_block(CdefSearchCtx *cdef_search_ctx, int fbr,
- int fbc) {
- const CommonModeInfoParams *const mi_params = &cdef_search_ctx->cm->mi_params;
+void av1_cdef_mse_calc_block(CdefSearchCtx *cdef_search_ctx, int fbr, int fbc,
+ int sb_count) {
+ const CommonModeInfoParams *const mi_params = cdef_search_ctx->mi_params;
const YV12_BUFFER_CONFIG *ref = cdef_search_ctx->ref;
- const int sb_count = cdef_search_ctx->sb_count;
const int coeff_shift = cdef_search_ctx->coeff_shift;
const int *mi_wide_l2 = cdef_search_ctx->mi_wide_l2;
const int *mi_high_l2 = cdef_search_ctx->mi_high_l2;
@@ -387,14 +387,14 @@
// Returns:
// Nothing will be returned. Contents of cdef_search_ctx will be modified.
static void cdef_mse_calc_frame(CdefSearchCtx *cdef_search_ctx) {
- const CommonModeInfoParams *const mi_params = &cdef_search_ctx->cm->mi_params;
// Loop over each sb.
for (int fbr = 0; fbr < cdef_search_ctx->nvfb; ++fbr) {
for (int fbc = 0; fbc < cdef_search_ctx->nhfb; ++fbc) {
// Checks if cdef processing can be skipped for particular sb.
- if (cdef_sb_skip(mi_params, fbr, fbc)) continue;
+ if (cdef_sb_skip(cdef_search_ctx->mi_params, fbr, fbc)) continue;
// Calculate mse for each sb and store the relevant sb index.
- cdef_mse_calc_block(cdef_search_ctx, fbr, fbc);
+ av1_cdef_mse_calc_block(cdef_search_ctx, fbr, fbc,
+ cdef_search_ctx->sb_count);
cdef_search_ctx->sb_count++;
}
}
@@ -448,7 +448,7 @@
CDEF_PICK_METHOD pick_method) {
const CommonModeInfoParams *const mi_params = &cm->mi_params;
const int num_planes = av1_num_planes(cm);
- cdef_search_ctx->cm = cm;
+ cdef_search_ctx->mi_params = &cm->mi_params;
cdef_search_ctx->ref = ref;
cdef_search_ctx->nvfb =
(mi_params->mi_rows + MI_SIZE_64X64 - 1) / MI_SIZE_64X64;
@@ -549,7 +549,7 @@
}
}
-void av1_cdef_search(const YV12_BUFFER_CONFIG *frame,
+void av1_cdef_search(MultiThreadInfo *mt_info, const YV12_BUFFER_CONFIG *frame,
const YV12_BUFFER_CONFIG *ref, AV1_COMMON *cm,
MACROBLOCKD *xd, CDEF_PICK_METHOD pick_method,
int rdmult) {
@@ -568,7 +568,11 @@
// Allocate CDEF search context buffers.
cdef_alloc_data(&cdef_search_ctx);
// Frame level mse calculation.
- cdef_mse_calc_frame(&cdef_search_ctx);
+ if (mt_info->num_workers > 1) {
+ av1_cdef_mse_calc_frame_mt(cm, mt_info, &cdef_search_ctx);
+ } else {
+ cdef_mse_calc_frame(&cdef_search_ctx);
+ }
/* Search for different number of signaling bits. */
int nb_strength_bits = 0;
diff --git a/av1/encoder/pickcdef.h b/av1/encoder/pickcdef.h
index ef342dc..7fe1edb 100644
--- a/av1/encoder/pickcdef.h
+++ b/av1/encoder/pickcdef.h
@@ -19,6 +19,8 @@
#endif
/*!\cond */
+struct MultiThreadInfo;
+
#define REDUCED_PRI_STRENGTHS_LVL1 8
#define REDUCED_PRI_STRENGTHS_LVL2 5
#define REDUCED_SEC_STRENGTHS_LVL3 2
@@ -56,6 +58,20 @@
BLOCK_SIZE bsize, int coeff_shift,
int row, int col);
+// Data related to CDEF search multi-thread synchronization.
+typedef struct AV1CdefSyncData {
+#if CONFIG_MULTITHREAD
+ // Mutex lock used while dispatching jobs.
+ pthread_mutex_t *mutex_;
+#endif // CONFIG_MULTITHREAD
+ // Flag to indicate all blocks are processed and end of frame is reached
+ int end_of_frame;
+ // Row index in units of 64x64 block
+ int fbr;
+ // Column index in units of 64x64 block
+ int fbc;
+} AV1CdefSync;
+
/*! \brief CDEF search context.
*/
typedef struct {
@@ -64,9 +80,9 @@
*/
const YV12_BUFFER_CONFIG *ref;
/*!
- * Pointer to top level common structure
+ * Pointer to params related to MB_MODE_INFO arrays and related info
*/
- AV1_COMMON *cm;
+ CommonModeInfoParams *mi_params;
/*!
* Info specific to each plane
*/
@@ -190,6 +206,9 @@
return 1;
return 0;
}
+
+void av1_cdef_mse_calc_block(CdefSearchCtx *cdef_search_ctx, int fbr, int fbc,
+ int sb_count);
/*!\endcond */
/*!\brief AV1 CDEF parameter search
@@ -198,6 +217,7 @@
*
* Searches for optimal CDEF parameters for frame
*
+ * \param[in] mt_info Pointer to multi-threading parameters
* \param[in] frame Compressed frame buffer
* \param[in] ref Source frame buffer
* \param[in,out] cm Pointer to top level common structure
@@ -216,7 +236,8 @@
* \arg \c damping_factor: CDEF damping factor.
*
*/
-void av1_cdef_search(const YV12_BUFFER_CONFIG *frame,
+void av1_cdef_search(struct MultiThreadInfo *mt_info,
+ const YV12_BUFFER_CONFIG *frame,
const YV12_BUFFER_CONFIG *ref, AV1_COMMON *cm,
MACROBLOCKD *xd, CDEF_PICK_METHOD pick_method, int rdmult);
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
index aaa9dfd..7f595fc 100644
--- a/av1/encoder/ratectrl.c
+++ b/av1/encoder/ratectrl.c
@@ -310,7 +310,6 @@
rc->total_actual_bits = 0;
rc->total_target_bits = 0;
- rc->total_target_vs_actual = 0;
rc->frames_since_key = 8; // Sensible default for first frame.
rc->this_key_frame_forced = 0;
@@ -1829,8 +1828,6 @@
rc->total_actual_bits += rc->projected_frame_size;
rc->total_target_bits += cm->show_frame ? rc->avg_frame_bandwidth : 0;
- rc->total_target_vs_actual = rc->total_actual_bits - rc->total_target_bits;
-
if (is_altref_enabled(cpi->oxcf.gf_cfg.lag_in_frames,
cpi->oxcf.gf_cfg.enable_auto_arf) &&
refresh_frame_flags->alt_ref_frame &&
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
index aefb5b4..3f1756f 100644
--- a/av1/encoder/ratectrl.h
+++ b/av1/encoder/ratectrl.h
@@ -258,7 +258,6 @@
int64_t total_actual_bits;
int64_t total_target_bits;
- int64_t total_target_vs_actual;
/*!\endcond */
/*!
diff --git a/av1/encoder/svc_layercontext.c b/av1/encoder/svc_layercontext.c
index c43edf9..e75ad3c 100644
--- a/av1/encoder/svc_layercontext.c
+++ b/av1/encoder/svc_layercontext.c
@@ -38,7 +38,6 @@
RATE_CONTROL *const lrc = &lc->rc;
lrc->ni_av_qi = oxcf->rc_cfg.worst_allowed_q;
lrc->total_actual_bits = 0;
- lrc->total_target_vs_actual = 0;
lrc->ni_tot_qi = 0;
lrc->tot_q = 0.0;
lrc->avg_q = 0.0;
diff --git a/av1/encoder/var_based_part.c b/av1/encoder/var_based_part.c
index c6d0f05..c22dc10 100644
--- a/av1/encoder/var_based_part.c
+++ b/av1/encoder/var_based_part.c
@@ -847,6 +847,7 @@
const uint8_t *d;
int sp;
int dp;
+ NOISE_LEVEL noise_level = kLow;
int is_key_frame =
(frame_is_intra_only(cm) ||
@@ -923,6 +924,8 @@
d = AV1_VAR_OFFS;
dp = 0;
}
+ if (cpi->noise_estimate.enabled)
+ noise_level = av1_noise_estimate_extract_level(&cpi->noise_estimate);
if (low_res && threshold_4x4avg < INT64_MAX)
CHECK_MEM_ERROR(cm, vt2, aom_malloc(sizeof(*vt2)));
@@ -996,14 +999,18 @@
var_64x64 = vt->split[m].part_variances.none.variance;
max_var_64x64 = AOMMAX(var_64x64, max_var_64x64);
min_var_64x64 = AOMMIN(var_64x64, min_var_64x64);
- // If variance of this 64x64 block is above (some threshold of) the
- // average variance over the sub-32x32 blocks, then force this block to
- // split. Only checking this for noise level >= medium for now.
+ // If the difference of the max-min variances of sub-blocks or max
+ // variance of a sub-block is above some threshold of then force this
+ // block to split. Only checking this for noise level >= medium or if
+ // encoder is in SVC.
if (!is_key_frame &&
(max_var_32x32[m] - min_var_32x32[m]) > 3 * (thresholds[1] >> 3) &&
- max_var_32x32[m] > thresholds[1] >> 1)
+ max_var_32x32[m] > thresholds[1] >> 1 &&
+ (noise_level >= kMedium || cpi->use_svc)) {
force_split[1 + m] = 1;
+ force_split[0] = 1;
+ }
avg_64x64 += var_64x64;
}
if (is_small_sb) force_split[0] = 1;