diff --git a/av2/encoder/encodeframe.c b/av2/encoder/encodeframe.c index 8adf93a66d..67b7b7f0e2 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) { } } +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++) { + for (int j = 0; j < width; j++) { + hist[y_buf[j]]++; + } + y_buf += stride; + } +} + +static int av2_set_on_bawp_picture_level(AV2_COMP *const cpi) { + int enable_curr_pic_bawp = 0; + assert(cpi->sf.inter_sf.enable_fast_bawp == 1); + AV2_COMMON *const cm = &cpi->common; + const YV12_BUFFER_CONFIG *source = cpi->source; + + const int num_values = 1 << cm->seq_params.bit_depth; + + 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))); + + const int width = source->y_width; + const int height = source->y_height; + const int num_samples = width * height; + + //----- get histogram diff threshold ----- + const double sample_thres = + cm->features.allow_screen_content_tools ? 0.0875 : 0.1125; + 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); + + 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 * 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) * num_values); + // get histogram of the reference picture + get_histogram(ref_hist, &ref_buf->buf, width, height); + + // get SAD of delta histogram + int32_t diff_hist = 0; + for (int i = 0; i < num_values; i++) { + diff_hist += abs(curr_hist[i] - ref_hist[i]); + } + + if (diff_hist > hist_diff_thres) { + enable_curr_pic_bawp = 1; + break; + } + } + } + } + avm_free(curr_hist); + avm_free(ref_hist); + return enable_curr_pic_bawp; +} + /*!\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 (features->enable_bawp && cpi->sf.inter_sf.enable_fast_bawp) + features->enable_bawp = av2_set_on_bawp_picture_level(cpi); + #if CONFIG_COLLECT_COMPONENT_TIMING end_timing(cpi, av2_compute_global_motion_time); #endif 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 {