From 9763f48c8cfdb9a286354c3e6f92a690a7ceee90 Mon Sep 17 00:00:00 2001 From: Jianle Date: Fri, 24 Jul 2026 22:10:21 +0000 Subject: [PATCH 1/2] Add frame level on/off bawp enable frame level bwap based on histogram --- av2/av2_cx_iface.c | 4 ++ av2/encoder/encodeframe.c | 71 +++++++++++++++++++++++++++++++++ av2/encoder/encoder.h | 5 +++ cmake/avm_config_defaults.cmake | 3 ++ 4 files changed, 83 insertions(+) diff --git a/av2/av2_cx_iface.c b/av2/av2_cx_iface.c index b419afb5b4..11a435a934 100644 --- a/av2/av2_cx_iface.c +++ b/av2/av2_cx_iface.c @@ -1535,6 +1535,10 @@ static avm_codec_err_t set_encoder_config(AV2EncoderConfig *oxcf, oxcf->speed = extra_cfg->cpu_used; +#if CONFIG_FAST_BAWP + oxcf->enable_fast_bawp = oxcf->speed >= 1 ? 1 : 0; +#endif + // Set Color related configuration. color_cfg->color_primaries = extra_cfg->color_primaries; color_cfg->transfer_characteristics = extra_cfg->transfer_characteristics; diff --git a/av2/encoder/encodeframe.c b/av2/encoder/encodeframe.c index 8adf93a66d..73da9f424e 100644 --- a/av2/encoder/encodeframe.c +++ b/av2/encoder/encodeframe.c @@ -1952,6 +1952,73 @@ static AVM_INLINE void av2_enc_setup_tip_frame(AV2_COMP *cpi) { } } +#if CONFIG_FAST_BAWP +void get_histogram(int32_t *hist, const YV12_BUFFER_CONFIG *buf, int width, + int height) { + uint16_t *y_buf = buf->y_buffer; + int stride = buf->y_stride; + for (int i = 0; i < height; i++) { + for (int j = 0; j < width; j++) { + hist[y_buf[j]]++; + } + y_buf += stride; + } +} + +int av2_set_on_bawp_picture_level(AV2_COMP *cpi) { + int enable_curr_pic_bawp = 0; + assert(cpi->oxcf.enable_fast_bawp == 1); + AV2_COMMON *const cm = &cpi->common; + const YV12_BUFFER_CONFIG *source = cpi->source; + + int numValues = 1 << cm->seq_params.bit_depth; + + int32_t *curr_hist = (int32_t *)avm_calloc(numValues, sizeof(int32_t)); + int32_t *ref_hist = (int32_t *)avm_calloc(numValues, sizeof(int32_t)); + + int width = source->y_width; + int height = source->y_height; + int num_samples = width * height; + + //----- get histogram diff threshold ----- + double sample_thres = + cm->features.allow_screen_content_tools ? 0.0875 : 0.1125; + int32_t hist_diff_thres = (int32_t)(sample_thres * num_samples); + + // get histogram of the current picture + get_histogram(curr_hist, source, width, height); + + for (MV_REFERENCE_FRAME rf = 0; rf < cm->ref_frames_info.num_total_refs; + ++rf) { + const RefCntBuffer *ref_buf = get_ref_frame_buf(cm, rf); + if (ref_buf != NULL) { + int ref_width = ref_buf->mi_cols * 4; + int ref_height = ref_buf->mi_rows * 4; + + if (width == ref_width && height == ref_height) { + memset(ref_hist, 0, sizeof(int32_t) * numValues); + // get histogram of the reference picture + get_histogram(ref_hist, &ref_buf->buf, width, height); + + // get SAD of delta histogram + int32_t diffHist = 0; + for (int i = 0; i < numValues; i++) { + diffHist += abs(curr_hist[i] - ref_hist[i]); + } + + if (diffHist > hist_diff_thres) { + enable_curr_pic_bawp = 1; + break; + } + } + } + } + avm_free(curr_hist); + avm_free(ref_hist); + return enable_curr_pic_bawp; +} +#endif + /*!\brief Set the lossless flags for a frame before encoding it * * \ingroup high_level_algo @@ -2229,6 +2296,10 @@ static AVM_INLINE void encode_frame_internal(AV2_COMP *cpi) { start_timing(cpi, av2_compute_global_motion_time); #endif av2_compute_global_motion_facade(cpi); +#if CONFIG_FAST_BAWP + if (features->enable_bawp && cpi->oxcf.enable_fast_bawp) + features->enable_bawp = av2_set_on_bawp_picture_level(cpi); +#endif #if CONFIG_COLLECT_COMPONENT_TIMING end_timing(cpi, av2_compute_global_motion_time); #endif diff --git a/av2/encoder/encoder.h b/av2/encoder/encoder.h index b0656d6b72..a76fd3de88 100644 --- a/av2/encoder/encoder.h +++ b/av2/encoder/encoder.h @@ -1184,6 +1184,11 @@ typedef struct AV2EncoderConfig { // Indicates the spped preset to be used. int speed; +#if CONFIG_FAST_BAWP + // Indicates whenter frame level on/off fast bawp is used. + int enable_fast_bawp; +#endif + // Indicates the target sequence level index for each operating point(OP). AV2_LEVEL target_seq_level_idx[MAX_NUM_OPERATING_POINTS]; diff --git a/cmake/avm_config_defaults.cmake b/cmake/avm_config_defaults.cmake index 395f9ae210..ff8ac816eb 100644 --- a/cmake/avm_config_defaults.cmake +++ b/cmake/avm_config_defaults.cmake @@ -149,6 +149,9 @@ set_avm_config_var( "Encoder only flag to configure encoder to enable mixed lossy/lossless coding" ) +set_avm_config_var(CONFIG_FAST_BAWP 0 + "Enable fast BAWP based on histogram difference") + # # Variables in this section control optional features of the build system. # From 9a7e4aef26f3e67486f4714dab2cca6782380a98 Mon Sep 17 00:00:00 2001 From: Jianle Date: Sat, 25 Jul 2026 05:44:17 +0000 Subject: [PATCH 2/2] Address Yeqing's review --- av2/av2_cx_iface.c | 4 --- av2/encoder/encodeframe.c | 48 ++++++++++++++++----------------- av2/encoder/encoder.h | 5 ---- av2/encoder/speed_features.c | 2 ++ av2/encoder/speed_features.h | 5 ++++ cmake/avm_config_defaults.cmake | 3 --- 6 files changed, 31 insertions(+), 36 deletions(-) diff --git a/av2/av2_cx_iface.c b/av2/av2_cx_iface.c index 11a435a934..b419afb5b4 100644 --- a/av2/av2_cx_iface.c +++ b/av2/av2_cx_iface.c @@ -1535,10 +1535,6 @@ static avm_codec_err_t set_encoder_config(AV2EncoderConfig *oxcf, oxcf->speed = extra_cfg->cpu_used; -#if CONFIG_FAST_BAWP - oxcf->enable_fast_bawp = oxcf->speed >= 1 ? 1 : 0; -#endif - // Set Color related configuration. color_cfg->color_primaries = extra_cfg->color_primaries; color_cfg->transfer_characteristics = extra_cfg->transfer_characteristics; diff --git a/av2/encoder/encodeframe.c b/av2/encoder/encodeframe.c index 73da9f424e..67b7b7f0e2 100644 --- a/av2/encoder/encodeframe.c +++ b/av2/encoder/encodeframe.c @@ -1952,9 +1952,8 @@ static AVM_INLINE void av2_enc_setup_tip_frame(AV2_COMP *cpi) { } } -#if CONFIG_FAST_BAWP -void get_histogram(int32_t *hist, const YV12_BUFFER_CONFIG *buf, int width, - int height) { +static void get_histogram(int32_t *hist, const YV12_BUFFER_CONFIG *buf, + int width, int height) { uint16_t *y_buf = buf->y_buffer; int stride = buf->y_stride; for (int i = 0; i < height; i++) { @@ -1965,25 +1964,27 @@ void get_histogram(int32_t *hist, const YV12_BUFFER_CONFIG *buf, int width, } } -int av2_set_on_bawp_picture_level(AV2_COMP *cpi) { +static int av2_set_on_bawp_picture_level(AV2_COMP *const cpi) { int enable_curr_pic_bawp = 0; - assert(cpi->oxcf.enable_fast_bawp == 1); + assert(cpi->sf.inter_sf.enable_fast_bawp == 1); AV2_COMMON *const cm = &cpi->common; const YV12_BUFFER_CONFIG *source = cpi->source; - int numValues = 1 << cm->seq_params.bit_depth; + const int num_values = 1 << cm->seq_params.bit_depth; - int32_t *curr_hist = (int32_t *)avm_calloc(numValues, sizeof(int32_t)); - int32_t *ref_hist = (int32_t *)avm_calloc(numValues, sizeof(int32_t)); + int32_t *curr_hist; + int32_t *ref_hist; + CHECK_MEM_ERROR(cm, curr_hist, avm_calloc(num_values, sizeof(int32_t))); + CHECK_MEM_ERROR(cm, ref_hist, avm_calloc(num_values, sizeof(int32_t))); - int width = source->y_width; - int height = source->y_height; - int num_samples = width * height; + const int width = source->y_width; + const int height = source->y_height; + const int num_samples = width * height; //----- get histogram diff threshold ----- - double sample_thres = + const double sample_thres = cm->features.allow_screen_content_tools ? 0.0875 : 0.1125; - int32_t hist_diff_thres = (int32_t)(sample_thres * num_samples); + const int32_t hist_diff_thres = (int32_t)(sample_thres * num_samples); // get histogram of the current picture get_histogram(curr_hist, source, width, height); @@ -1992,21 +1993,21 @@ int av2_set_on_bawp_picture_level(AV2_COMP *cpi) { ++rf) { const RefCntBuffer *ref_buf = get_ref_frame_buf(cm, rf); if (ref_buf != NULL) { - int ref_width = ref_buf->mi_cols * 4; - int ref_height = ref_buf->mi_rows * 4; + int ref_width = ref_buf->mi_cols * MI_SIZE; + int ref_height = ref_buf->mi_rows * MI_SIZE; if (width == ref_width && height == ref_height) { - memset(ref_hist, 0, sizeof(int32_t) * numValues); + memset(ref_hist, 0, sizeof(int32_t) * num_values); // get histogram of the reference picture get_histogram(ref_hist, &ref_buf->buf, width, height); // get SAD of delta histogram - int32_t diffHist = 0; - for (int i = 0; i < numValues; i++) { - diffHist += abs(curr_hist[i] - ref_hist[i]); + int32_t diff_hist = 0; + for (int i = 0; i < num_values; i++) { + diff_hist += abs(curr_hist[i] - ref_hist[i]); } - if (diffHist > hist_diff_thres) { + if (diff_hist > hist_diff_thres) { enable_curr_pic_bawp = 1; break; } @@ -2017,7 +2018,6 @@ int av2_set_on_bawp_picture_level(AV2_COMP *cpi) { avm_free(ref_hist); return enable_curr_pic_bawp; } -#endif /*!\brief Set the lossless flags for a frame before encoding it * @@ -2296,10 +2296,10 @@ static AVM_INLINE void encode_frame_internal(AV2_COMP *cpi) { start_timing(cpi, av2_compute_global_motion_time); #endif av2_compute_global_motion_facade(cpi); -#if CONFIG_FAST_BAWP - if (features->enable_bawp && cpi->oxcf.enable_fast_bawp) + + if (features->enable_bawp && cpi->sf.inter_sf.enable_fast_bawp) features->enable_bawp = av2_set_on_bawp_picture_level(cpi); -#endif + #if CONFIG_COLLECT_COMPONENT_TIMING end_timing(cpi, av2_compute_global_motion_time); #endif diff --git a/av2/encoder/encoder.h b/av2/encoder/encoder.h index a76fd3de88..b0656d6b72 100644 --- a/av2/encoder/encoder.h +++ b/av2/encoder/encoder.h @@ -1184,11 +1184,6 @@ typedef struct AV2EncoderConfig { // Indicates the spped preset to be used. int speed; -#if CONFIG_FAST_BAWP - // Indicates whenter frame level on/off fast bawp is used. - int enable_fast_bawp; -#endif - // Indicates the target sequence level index for each operating point(OP). AV2_LEVEL target_seq_level_idx[MAX_NUM_OPERATING_POINTS]; diff --git a/av2/encoder/speed_features.c b/av2/encoder/speed_features.c index 17420d102b..f2526d7696 100644 --- a/av2/encoder/speed_features.c +++ b/av2/encoder/speed_features.c @@ -388,6 +388,7 @@ static void set_good_speed_features_framesize_independent( sf->tx_sf.adaptive_tcq_threshold_qidx = 185; sf->inter_sf.enable_enhanced_inter_mode_cache_reuse = 1; sf->inter_sf.skip_temporary_pred_for_opfl = 1; + sf->inter_sf.enable_fast_bawp = 1; // Enable the optimized inter-SDP fast method (requires >=1 intra coded // block, prunes when inter-mode ratio exceeds 50%, and early skips when @@ -794,6 +795,7 @@ static AVM_INLINE void init_inter_sf(INTER_MODE_SPEED_FEATURES *inter_sf) { inter_sf->reuse_erp_mode_flag = 0; inter_sf->prune_warpmv_prob_thresh = 32; inter_sf->enable_enhanced_inter_mode_cache_reuse = 0; + inter_sf->enable_fast_bawp = 0; } static AVM_INLINE void init_interp_sf(INTERP_FILTER_SPEED_FEATURES *interp_sf) { diff --git a/av2/encoder/speed_features.h b/av2/encoder/speed_features.h index 1b76aa5fed..5c5b8ca38f 100644 --- a/av2/encoder/speed_features.h +++ b/av2/encoder/speed_features.h @@ -756,6 +756,11 @@ typedef struct INTER_MODE_SPEED_FEATURES { // 0: original cache reuse logic. // 1: enhanced cache reuse logic (more modes are searched). int enable_enhanced_inter_mode_cache_reuse; + + // Histogram based frame level on/off decision for BAWP + // 0: no frame level on/off decision + // 1: enable histogram based frame level on/off + int enable_fast_bawp; } INTER_MODE_SPEED_FEATURES; typedef struct INTERP_FILTER_SPEED_FEATURES { diff --git a/cmake/avm_config_defaults.cmake b/cmake/avm_config_defaults.cmake index ff8ac816eb..395f9ae210 100644 --- a/cmake/avm_config_defaults.cmake +++ b/cmake/avm_config_defaults.cmake @@ -149,9 +149,6 @@ set_avm_config_var( "Encoder only flag to configure encoder to enable mixed lossy/lossless coding" ) -set_avm_config_var(CONFIG_FAST_BAWP 0 - "Enable fast BAWP based on histogram difference") - # # Variables in this section control optional features of the build system. #