Refactor memory alloc/dealloc of mb_wiener_var buffers The temporary 'pred_buffer' used during the wiener variance computation was allocated and deallocated for every row in av1_calc_mb_wiener_var_row(). This CL introduces a pointer to a temporary pred buffer (wiener_tmp_pred_buf) in ThreadData structure which is allocated/deallocated once per frame. Also added the necessary calls to free weiner variance buffers in encoder destroy to avoid memory leaks in case of early termination. Bug: aomedia:3276 Change-Id: I56227f1f5dab916db77349b522a6216b359ec6f7
diff --git a/av1/encoder/allintra_vis.c b/av1/encoder/allintra_vis.c index 236b296..a59d0d7 100644 --- a/av1/encoder/allintra_vis.c +++ b/av1/encoder/allintra_vis.c
@@ -29,6 +29,26 @@ #include "av1/encoder/model_rd.h" #include "av1/encoder/rdopt_utils.h" +#define MB_WIENER_PRED_BLOCK_SIZE BLOCK_128X128 +#define MB_WIENER_PRED_BUF_STRIDE 128 + +void av1_alloc_mb_wiener_var_pred_buf(AV1_COMMON *cm, ThreadData *td) { + const int is_high_bitdepth = is_cur_buf_hbd(&td->mb.e_mbd); + assert(MB_WIENER_PRED_BLOCK_SIZE < BLOCK_SIZES_ALL); + const int buf_width = block_size_wide[MB_WIENER_PRED_BLOCK_SIZE]; + const int buf_height = block_size_high[MB_WIENER_PRED_BLOCK_SIZE]; + assert(buf_width == MB_WIENER_PRED_BUF_STRIDE); + const size_t buf_size = + (buf_width * buf_height * sizeof(*td->wiener_tmp_pred_buf)) + << is_high_bitdepth; + CHECK_MEM_ERROR(cm, td->wiener_tmp_pred_buf, aom_memalign(32, buf_size)); +} + +void av1_dealloc_mb_wiener_var_pred_buf(ThreadData *td) { + aom_free(td->wiener_tmp_pred_buf); + td->wiener_tmp_pred_buf = NULL; +} + void av1_init_mb_wiener_var_buffer(AV1_COMP *cpi) { AV1_COMMON *cm = &cpi->common; @@ -236,7 +256,7 @@ int16_t *src_diff, tran_low_t *coeff, tran_low_t *qcoeff, tran_low_t *dqcoeff, double *sum_rec_distortion, - double *sum_est_rate) { + double *sum_est_rate, uint8_t *pred_buffer) { AV1_COMMON *const cm = &cpi->common; uint8_t *buffer = cpi->source->y_buffer; int buf_stride = cpi->source->y_stride; @@ -261,16 +281,9 @@ int mt_unit_col = 0; const int is_high_bitdepth = is_cur_buf_hbd(xd); - // We use a scratch buffer to store the prediction. - // The stride is the max block size (128). - uint8_t *pred_buffer; - const int dst_buffer_stride = 128; - const int buf_width = 128; - const int buf_height = 128; - const size_t buf_size = (buf_width * buf_height * sizeof(*pred_buffer)) - << is_high_bitdepth; - CHECK_MEM_ERROR(cm, pred_buffer, aom_memalign(32, buf_size)); uint8_t *dst_buffer = pred_buffer; + const int dst_buffer_stride = MB_WIENER_PRED_BUF_STRIDE; + if (is_high_bitdepth) { uint16_t *pred_buffer_16 = (uint16_t *)pred_buffer; dst_buffer = CONVERT_TO_BYTEPTR(pred_buffer_16); @@ -434,7 +447,6 @@ } // Set the pointer to null since mbmi is only allocated inside this function. xd->mi = NULL; - aom_free(pred_buffer); } static void calc_mb_wiener_var(AV1_COMP *const cpi, double *sum_rec_distortion, @@ -449,7 +461,8 @@ DECLARE_ALIGNED(32, tran_low_t, dqcoeff[32 * 32]); for (int mi_row = 0; mi_row < cpi->frame_info.mi_rows; mi_row += mb_step) { av1_calc_mb_wiener_var_row(cpi, x, xd, mi_row, src_diff, coeff, qcoeff, - dqcoeff, sum_rec_distortion, sum_est_rate); + dqcoeff, sum_rec_distortion, sum_est_rate, + cpi->td.wiener_tmp_pred_buf); } } @@ -565,6 +578,7 @@ NULL, cpi->image_pyramid_levels, 0)) aom_internal_error(cm->error, AOM_CODEC_MEM_ERROR, "Failed to allocate frame buffer"); + av1_alloc_mb_wiener_var_pred_buf(&cpi->common, &cpi->td); cpi->norm_wiener_variance = 0; MACROBLOCK *x = &cpi->td.mb; @@ -647,6 +661,7 @@ // Set the pointer to null since mbmi is only allocated inside this function. xd->mi = NULL; aom_free_frame_buffer(&cm->cur_frame->buf); + av1_dealloc_mb_wiener_var_pred_buf(&cpi->td); } static int get_rate_guided_quantizer(AV1_COMP *const cpi, BLOCK_SIZE bsize,
diff --git a/av1/encoder/allintra_vis.h b/av1/encoder/allintra_vis.h index 9e10566..ab39968 100644 --- a/av1/encoder/allintra_vis.h +++ b/av1/encoder/allintra_vis.h
@@ -27,7 +27,7 @@ int16_t *src_diff, tran_low_t *coeff, tran_low_t *qcoeff, tran_low_t *dqcoeff, double *sum_rec_distortion, - double *sum_est_rate); + double *sum_est_rate, uint8_t *pred_buffer); void av1_set_mb_wiener_variance(AV1_COMP *cpi);
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c index 3c00553..6a4332c 100644 --- a/av1/encoder/encoder.c +++ b/av1/encoder/encoder.c
@@ -1727,6 +1727,7 @@ av1_row_mt_mem_dealloc(cpi); if (mt_info->num_workers > 1) { + av1_row_mt_sync_mem_dealloc(&cpi->ppi->intra_row_mt_sync); av1_loop_filter_dealloc(&mt_info->lf_row_sync); av1_cdef_mt_dealloc(&mt_info->cdef_sync); #if !CONFIG_REALTIME_ONLY
diff --git a/av1/encoder/encoder.h b/av1/encoder/encoder.h index 04c2d87..92d0840 100644 --- a/av1/encoder/encoder.h +++ b/av1/encoder/encoder.h
@@ -1456,6 +1456,7 @@ CONV_BUF_TYPE *tmp_conv_dst; uint64_t abs_sum_level; uint8_t *tmp_pred_bufs[2]; + uint8_t *wiener_tmp_pred_buf; int intrabc_used; int deltaq_used; int coefficient_size; @@ -3804,6 +3805,10 @@ int av1_convert_sect5obus_to_annexb(uint8_t *buffer, size_t *input_size); +void av1_alloc_mb_wiener_var_pred_buf(AV1_COMMON *cm, ThreadData *td); + +void av1_dealloc_mb_wiener_var_pred_buf(ThreadData *td); + // Set screen content options. // This function estimates whether to use screen content tools, by counting // the portion of blocks that have few luma colors.
diff --git a/av1/encoder/encoder_alloc.h b/av1/encoder/encoder_alloc.h index 3ed5dc2..def0069 100644 --- a/av1/encoder/encoder_alloc.h +++ b/av1/encoder/encoder_alloc.h
@@ -290,6 +290,8 @@ av1_dealloc_mb_data(&cpi->td.mb, av1_num_planes(cm)); + av1_dealloc_mb_wiener_var_pred_buf(&cpi->td); + av1_free_txb_buf(cpi); av1_free_context_buffers(cm); @@ -502,6 +504,7 @@ av1_free_pc_tree_recursive(thread_data->td->pc_root, num_planes, 0, 0, SEARCH_PARTITION); thread_data->td->pc_root = NULL; + av1_dealloc_mb_wiener_var_pred_buf(thread_data->td); aom_free(thread_data->td); } }
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c index 2bb546f..b878797 100644 --- a/av1/encoder/ethread.c +++ b/av1/encoder/ethread.c
@@ -196,7 +196,7 @@ } // Deallocate row based multi-threading synchronization related mutex and data -static void row_mt_sync_mem_dealloc(AV1EncRowMultiThreadSync *row_mt_sync) { +void av1_row_mt_sync_mem_dealloc(AV1EncRowMultiThreadSync *row_mt_sync) { if (row_mt_sync != NULL) { #if CONFIG_MULTITHREAD int i; @@ -282,7 +282,7 @@ int tile_index = tile_row * tile_cols + tile_col; TileDataEnc *const this_tile = &cpi->tile_data[tile_index]; - row_mt_sync_mem_dealloc(&this_tile->row_mt_sync); + av1_row_mt_sync_mem_dealloc(&this_tile->row_mt_sync); if (cpi->oxcf.algo_cfg.cdf_update_mode) aom_free(this_tile->row_ctx); } @@ -2696,6 +2696,7 @@ if (thread_data->td != &cpi->td) { thread_data->td->mb = cpi->td.mb; + av1_alloc_mb_wiener_var_pred_buf(&cpi->common, thread_data->td); } } } @@ -2737,7 +2738,8 @@ // TODO(chengchen): properly accumulate the distortion and rate. av1_calc_mb_wiener_var_row(cpi, x, xd, current_mi_row, src_diff, coeff, qcoeff, dqcoeff, &sum_rec_distortion, - &sum_est_rate); + &sum_est_rate, + thread_data->td->wiener_tmp_pred_buf); #if CONFIG_MULTITHREAD pthread_mutex_lock(enc_row_mt_mutex_); #endif @@ -2749,6 +2751,17 @@ return 1; } +static void dealloc_mb_wiener_var_mt_data(AV1_COMP *cpi, int num_workers) { + av1_row_mt_sync_mem_dealloc(&cpi->ppi->intra_row_mt_sync); + + MultiThreadInfo *mt_info = &cpi->mt_info; + for (int j = 0; j < num_workers; ++j) { + EncWorkerData *thread_data = &mt_info->tile_thr_data[j]; + ThreadData *td = thread_data->td; + if (td != &cpi->td) av1_dealloc_mb_wiener_var_pred_buf(td); + } +} + // This function is the multi-threading version of computing the wiener // variance. // Note that the wiener variance is used for allintra mode (1 pass) and its @@ -2778,8 +2791,7 @@ prepare_wiener_var_workers(cpi, cal_mb_wiener_var_hook, num_workers); launch_workers(mt_info, num_workers); sync_enc_workers(mt_info, cm, num_workers); - - row_mt_sync_mem_dealloc(intra_row_mt_sync); + dealloc_mb_wiener_var_mt_data(cpi, num_workers); } // Compare and order tiles based on absolute sum of tx coeffs.
diff --git a/av1/encoder/ethread.h b/av1/encoder/ethread.h index fc9150c..4f4c232 100644 --- a/av1/encoder/ethread.h +++ b/av1/encoder/ethread.h
@@ -53,6 +53,8 @@ void av1_row_mt_mem_dealloc(AV1_COMP *cpi); +void av1_row_mt_sync_mem_dealloc(AV1EncRowMultiThreadSync *row_mt_sync); + void av1_global_motion_estimation_mt(AV1_COMP *cpi); #if !CONFIG_REALTIME_ONLY