Resolve issue 3491
BUG=aomedia:3491
Change-Id: I54916846c9dadc7263826c4d0dc8601880bab4fb
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index a3bd682..fe195f3 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -3126,8 +3126,10 @@
if (ppi->p_mt_info.prev_num_enc_workers < num_enc_workers &&
num_enc_workers <= ppi->p_mt_info.num_workers) {
free_thread_data(ppi);
- for (int j = 0; j < ppi->num_fp_contexts; j++)
+ for (int j = 0; j < ppi->num_fp_contexts; j++) {
aom_free(ppi->parallel_cpi[j]->td.tctx);
+ ppi->parallel_cpi[j]->td.tctx = NULL;
+ }
av1_init_tile_thread_data(ppi, cpi->oxcf.pass == AOM_RC_FIRST_PASS);
}
diff --git a/av1/common/thread_common.c b/av1/common/thread_common.c
index 54d78f7..c215ee7 100644
--- a/av1/common/thread_common.c
+++ b/av1/common/thread_common.c
@@ -631,7 +631,7 @@
}
// Deallocate loop restoration synchronization related mutex and data
-void av1_loop_restoration_dealloc(AV1LrSync *lr_sync, int num_workers) {
+void av1_loop_restoration_dealloc(AV1LrSync *lr_sync) {
if (lr_sync != NULL) {
int j;
#if CONFIG_MULTITHREAD
@@ -662,7 +662,8 @@
aom_free(lr_sync->job_queue);
if (lr_sync->lrworkerdata) {
- for (int worker_idx = 0; worker_idx < num_workers - 1; worker_idx++) {
+ for (int worker_idx = 0; worker_idx < lr_sync->num_workers - 1;
+ worker_idx++) {
LRWorkerData *const workerdata_data =
lr_sync->lrworkerdata + worker_idx;
@@ -856,7 +857,7 @@
if (!lr_sync->sync_range || num_rows_lr > lr_sync->rows ||
num_workers > lr_sync->num_workers || num_planes > lr_sync->num_planes) {
- av1_loop_restoration_dealloc(lr_sync, num_workers);
+ av1_loop_restoration_dealloc(lr_sync);
av1_loop_restoration_alloc(lr_sync, cm, num_workers, num_rows_lr,
num_planes, cm->width);
}
diff --git a/av1/common/thread_common.h b/av1/common/thread_common.h
index e38b9a8..cfbdc2f 100644
--- a/av1/common/thread_common.h
+++ b/av1/common/thread_common.h
@@ -186,7 +186,7 @@
int optimized_lr, AVxWorker *workers,
int num_workers, AV1LrSync *lr_sync,
void *lr_ctxt, int do_extend_border);
-void av1_loop_restoration_dealloc(AV1LrSync *lr_sync, int num_workers);
+void av1_loop_restoration_dealloc(AV1LrSync *lr_sync);
void av1_loop_restoration_alloc(AV1LrSync *lr_sync, AV1_COMMON *cm,
int num_workers, int num_rows_lr,
int num_planes, int width);
diff --git a/av1/decoder/decoder.c b/av1/decoder/decoder.c
index 4559dc6..33554a6 100644
--- a/av1/decoder/decoder.c
+++ b/av1/decoder/decoder.c
@@ -217,7 +217,7 @@
if (pbi->num_workers > 0) {
av1_loop_filter_dealloc(&pbi->lf_row_sync);
- av1_loop_restoration_dealloc(&pbi->lr_row_sync, pbi->num_workers);
+ av1_loop_restoration_dealloc(&pbi->lr_row_sync);
av1_dealloc_dec_jobs(&pbi->tile_mt_info);
}
diff --git a/av1/encoder/encoder.c b/av1/encoder/encoder.c
index 3d2e8f8..9bb9482 100644
--- a/av1/encoder/encoder.c
+++ b/av1/encoder/encoder.c
@@ -1728,9 +1728,7 @@
av1_loop_filter_dealloc(&mt_info->lf_row_sync);
av1_cdef_mt_dealloc(&mt_info->cdef_sync);
#if !CONFIG_REALTIME_ONLY
- int num_lr_workers =
- av1_get_num_mod_workers_for_alloc(&cpi->ppi->p_mt_info, MOD_LR);
- av1_loop_restoration_dealloc(&mt_info->lr_row_sync, num_lr_workers);
+ av1_loop_restoration_dealloc(&mt_info->lr_row_sync);
av1_tf_mt_dealloc(&mt_info->tf_sync);
#endif
}
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c
index fb9b85a..6f3cbd7 100644
--- a/av1/encoder/ethread.c
+++ b/av1/encoder/ethread.c
@@ -896,7 +896,7 @@
if (!lr_sync->sync_range || num_rows_lr > lr_sync->rows ||
num_lr_workers > lr_sync->num_workers ||
MAX_MB_PLANE > lr_sync->num_planes) {
- av1_loop_restoration_dealloc(lr_sync, num_lr_workers);
+ av1_loop_restoration_dealloc(lr_sync);
av1_loop_restoration_alloc(lr_sync, cm, num_lr_workers, num_rows_lr,
MAX_MB_PLANE, cm->width);
}
@@ -3273,7 +3273,8 @@
return AOMMIN(num_mb_rows, cpi->oxcf.max_threads);
}
-int compute_num_mod_workers(AV1_COMP *cpi, MULTI_THREADED_MODULES mod_name) {
+static int compute_num_mod_workers(AV1_COMP *cpi,
+ MULTI_THREADED_MODULES mod_name) {
int num_mod_workers = 0;
switch (mod_name) {
case MOD_FP:
@@ -3313,7 +3314,8 @@
}
// Computes the number of workers for each MT modules in the encoder
void av1_compute_num_workers_for_mt(AV1_COMP *cpi) {
- for (int i = MOD_FP; i < NUM_MT_MODULES; i++)
+ for (int i = MOD_FP; i < NUM_MT_MODULES; i++) {
cpi->ppi->p_mt_info.num_mod_workers[i] =
compute_num_mod_workers(cpi, (MULTI_THREADED_MODULES)i);
+ }
}
diff --git a/test/resize_test.cc b/test/resize_test.cc
index dbfabe0..8083163 100644
--- a/test/resize_test.cc
+++ b/test/resize_test.cc
@@ -1054,4 +1054,91 @@
EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
}
+TEST(ResizeSimpleTest, TemporarySmallerFrameSizeMultiThread) {
+ constexpr int kWidth = 512;
+ constexpr int kHeight = 512;
+ constexpr int kFirstWidth = 256;
+ constexpr int kFirstHeight = 256;
+ // Buffer of zero samples.
+ constexpr size_t kBufferSize = 3 * kWidth * kHeight;
+ std::vector<unsigned char> buffer(kBufferSize, static_cast<unsigned char>(0));
+
+ aom_image_t img1;
+ EXPECT_EQ(&img1, aom_img_wrap(&img1, AOM_IMG_FMT_I420, kFirstWidth,
+ kFirstHeight, 1, buffer.data()));
+
+ aom_image_t img2;
+ EXPECT_EQ(&img2, aom_img_wrap(&img2, AOM_IMG_FMT_I420, kWidth, kHeight, 1,
+ buffer.data()));
+
+ aom_codec_iface_t *iface = aom_codec_av1_cx();
+ aom_codec_enc_cfg_t cfg;
+ EXPECT_EQ(AOM_CODEC_OK,
+ aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_GOOD_QUALITY));
+ cfg.g_threads = 4;
+ cfg.g_lag_in_frames = 1;
+ cfg.g_w = kFirstWidth;
+ cfg.g_h = kFirstHeight;
+ cfg.g_forced_max_frame_width = kWidth;
+ cfg.g_forced_max_frame_height = kHeight;
+ aom_codec_ctx_t enc;
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0));
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 6));
+
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img1, 0, 1, 0));
+
+ cfg.g_w = kWidth;
+ cfg.g_h = kHeight;
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_set(&enc, &cfg));
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img2, 1, 1, 0));
+
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 0, 0));
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
+}
+
+// This test differs from "TemporarySmallerFrameSizeMultiThread" in that
+// it changes the number of threads from 4 to 2 before coding the second frame.
+TEST(ResizeSimpleTest, TemporarySmallerFrameSizeMultiThread2) {
+ constexpr int kWidth = 512;
+ constexpr int kHeight = 512;
+ constexpr int kFirstWidth = 256;
+ constexpr int kFirstHeight = 256;
+ // Buffer of zero samples.
+ constexpr size_t kBufferSize = 3 * kWidth * kHeight;
+ std::vector<unsigned char> buffer(kBufferSize, static_cast<unsigned char>(0));
+
+ aom_image_t img1;
+ EXPECT_EQ(&img1, aom_img_wrap(&img1, AOM_IMG_FMT_I420, kFirstWidth,
+ kFirstHeight, 1, buffer.data()));
+
+ aom_image_t img2;
+ EXPECT_EQ(&img2, aom_img_wrap(&img2, AOM_IMG_FMT_I420, kWidth, kHeight, 1,
+ buffer.data()));
+
+ aom_codec_iface_t *iface = aom_codec_av1_cx();
+ aom_codec_enc_cfg_t cfg;
+ EXPECT_EQ(AOM_CODEC_OK,
+ aom_codec_enc_config_default(iface, &cfg, AOM_USAGE_GOOD_QUALITY));
+ cfg.g_threads = 4;
+ cfg.g_lag_in_frames = 1;
+ cfg.g_w = kFirstWidth;
+ cfg.g_h = kFirstHeight;
+ cfg.g_forced_max_frame_width = kWidth;
+ cfg.g_forced_max_frame_height = kHeight;
+ aom_codec_ctx_t enc;
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_init(&enc, iface, &cfg, 0));
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_control(&enc, AOME_SET_CPUUSED, 6));
+
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img1, 0, 1, 0));
+
+ cfg.g_threads = 2;
+ cfg.g_w = kWidth;
+ cfg.g_h = kHeight;
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_enc_config_set(&enc, &cfg));
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, &img2, 1, 1, 0));
+
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_encode(&enc, nullptr, 0, 0, 0));
+ EXPECT_EQ(AOM_CODEC_OK, aom_codec_destroy(&enc));
+}
+
} // namespace