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