FPMT: Recompute frame parallel contexts Disabled FPMT when unsupported configurations are set through control calls. Recomputed maximum number of frame contexts at the beginning of each sub-gop to account for updates to supported configurations. Cleanup in is_fpmt_config function. Change-Id: I1c343110e0b8cebc1584895cd43ff1ba1779768e
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c index a396fb9..972b563 100644 --- a/av1/av1_cx_iface.c +++ b/av1/av1_cx_iface.c
@@ -1505,6 +1505,9 @@ if (res == AOM_CODEC_OK) { ctx->extra_cfg = *extra_cfg; set_encoder_config(&ctx->oxcf, &ctx->cfg, &ctx->extra_cfg); +#if CONFIG_FRAME_PARALLEL_ENCODE + av1_check_fpmt_config(ctx->ppi, &ctx->oxcf); +#endif bool is_sb_size_changed = false; av1_change_config_seq(ctx->ppi, &ctx->oxcf, &is_sb_size_changed); #if CONFIG_FRAME_PARALLEL_ENCODE @@ -2605,7 +2608,7 @@ if (ctx->ppi) { AV1_PRIMARY *ppi = ctx->ppi; #if CONFIG_FRAME_PARALLEL_ENCODE - for (int i = 0; i < ppi->num_fp_contexts - 1; i++) { + for (int i = 0; i < MAX_PARALLEL_FRAMES - 1; i++) { if (ppi->parallel_frames_data[i].cx_data) { free(ppi->parallel_frames_data[i].cx_data); } @@ -2619,7 +2622,7 @@ #endif #if CONFIG_FRAME_PARALLEL_ENCODE int i; - for (i = 0; i < ppi->num_fp_contexts; i++) { + for (i = 0; i < MAX_PARALLEL_FRAMES; i++) { destroy_context_and_bufferpool(ppi->parallel_cpi[i], &ctx->buffer_pool); } ppi->cpi = NULL; @@ -2909,6 +2912,15 @@ av1_post_encode_updates(cpi_lap, &cpi_lap_data); } +#if CONFIG_FRAME_PARALLEL_ENCODE + // Recalculate the maximum number of frames that can be encoded in + // parallel at the beginning of sub gop. + if (is_stat_consumption_stage(cpi) && ppi->gf_group.size > 0 && + cpi->gf_frame_index == ppi->gf_group.size) { + ppi->num_fp_contexts = av1_compute_num_fp_contexts(ppi, &cpi->oxcf); + } +#endif // CONFIG_FRAME_PARALLEL_ENCODE + // Get the next visible frame. Invisible frames get packed with the next // visible frame. while (cpi_data.cx_data_sz >= ctx->cx_data_sz / 2 && !is_frame_visible) { @@ -3238,6 +3250,9 @@ const int res = av1_set_internal_size( &ctx->ppi->cpi->oxcf, &ctx->ppi->cpi->resize_pending_params, (AOM_SCALING)mode->h_scaling_mode, (AOM_SCALING)mode->v_scaling_mode); +#if CONFIG_FRAME_PARALLEL_ENCODE + av1_check_fpmt_config(ctx->ppi, &ctx->ppi->cpi->oxcf); +#endif return (res == 0) ? AOM_CODEC_OK : AOM_CODEC_INVALID_PARAM; } else { return AOM_CODEC_INVALID_PARAM; @@ -3311,6 +3326,9 @@ } av1_update_layer_context_change_config(cpi, target_bandwidth); } +#if CONFIG_FRAME_PARALLEL_ENCODE + av1_check_fpmt_config(ctx->ppi, &ctx->ppi->cpi->oxcf); +#endif // CONFIG_FRAME_PARALLEL_ENCODE return AOM_CODEC_OK; }
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c index 0506170..c140c13 100644 --- a/av1/encoder/ethread.c +++ b/av1/encoder/ethread.c
@@ -838,7 +838,7 @@ // the current configuration. Returns 0 otherwise. static AOM_INLINE int is_fpmt_config(AV1_PRIMARY *ppi, AV1EncoderConfig *oxcf) { // FPMT is enabled for AOM_Q and AOM_VBR. - // TODO(Mufaddal, Aasaipriya): Test and enable multi-tile and resize config. + // TODO(Tarun): Test and enable resize config. if (oxcf->rc_cfg.mode == AOM_CBR || oxcf->rc_cfg.mode == AOM_CQ) { return 0; } @@ -860,13 +860,47 @@ if (oxcf->resize_cfg.resize_mode) { return 0; } - if (oxcf->passes == 1) { + if (oxcf->pass != AOM_RC_SECOND_PASS) { + return 0; + } + if (oxcf->max_threads < 2) { return 0; } return 1; } +int av1_check_fpmt_config(AV1_PRIMARY *const ppi, + AV1EncoderConfig *const oxcf) { + if (is_fpmt_config(ppi, oxcf)) return 1; + // Reset frame parallel configuration for unsupported config + if (ppi->num_fp_contexts > 1) { + for (int i = 1; i < ppi->num_fp_contexts; i++) { + // Release the previously-used frame-buffer + if (ppi->parallel_cpi[i]->common.cur_frame != NULL) { + --ppi->parallel_cpi[i]->common.cur_frame->ref_count; + ppi->parallel_cpi[i]->common.cur_frame = NULL; + } + } + + int cur_gf_index = ppi->cpi->gf_frame_index; + int reset_size = AOMMAX(0, ppi->gf_group.size - cur_gf_index); + av1_zero_array(&ppi->gf_group.frame_parallel_level[cur_gf_index], + reset_size); + av1_zero_array(&ppi->gf_group.is_frame_non_ref[cur_gf_index], reset_size); + av1_zero_array(&ppi->gf_group.src_offset[cur_gf_index], reset_size); +#if CONFIG_FRAME_PARALLEL_ENCODE_2 + memset(&ppi->gf_group.skip_frame_refresh[cur_gf_index][0], INVALID_IDX, + sizeof(ppi->gf_group.skip_frame_refresh[cur_gf_index][0]) * + reset_size * REF_FRAMES); + memset(&ppi->gf_group.skip_frame_as_ref[cur_gf_index], INVALID_IDX, + sizeof(ppi->gf_group.skip_frame_as_ref[cur_gf_index]) * reset_size); +#endif + ppi->num_fp_contexts = 1; + } + return 0; +} + // A large value for threads used to compute the max num_enc_workers // possible for each resolution. #define MAX_THREADS 100 @@ -875,7 +909,7 @@ // based on the number of max_enc_workers. int av1_compute_num_fp_contexts(AV1_PRIMARY *ppi, AV1EncoderConfig *oxcf) { ppi->p_mt_info.num_mod_workers[MOD_FRAME_ENC] = 0; - if (!is_fpmt_config(ppi, oxcf)) { + if (!av1_check_fpmt_config(ppi, oxcf)) { return 1; } int max_num_enc_workers = @@ -888,8 +922,11 @@ int num_fp_contexts = max_threads / workers_per_frame; num_fp_contexts = AOMMAX(1, AOMMIN(num_fp_contexts, MAX_PARALLEL_FRAMES)); + // Limit recalculated num_fp_contexts to ppi->num_fp_contexts. + num_fp_contexts = (ppi->num_fp_contexts == 1) + ? num_fp_contexts + : AOMMIN(num_fp_contexts, ppi->num_fp_contexts); if (num_fp_contexts > 1) { - assert(max_threads >= 2); ppi->p_mt_info.num_mod_workers[MOD_FRAME_ENC] = AOMMIN(max_num_enc_workers * num_fp_contexts, oxcf->max_threads); }
diff --git a/av1/encoder/ethread.h b/av1/encoder/ethread.h index bd75664..f56dcc0 100644 --- a/av1/encoder/ethread.h +++ b/av1/encoder/ethread.h
@@ -117,6 +117,8 @@ #if CONFIG_FRAME_PARALLEL_ENCODE int av1_compute_num_fp_contexts(AV1_PRIMARY *ppi, AV1EncoderConfig *oxcf); +int av1_check_fpmt_config(AV1_PRIMARY *const ppi, AV1EncoderConfig *const oxcf); + int av1_compress_parallel_frames(AV1_PRIMARY *const ppi, AV1_COMP_DATA *const first_cpi_data); #endif