Propagate error from worker to main thread during tile-MT
This change sets a longjmp target in enc_worker_hook() to
propagate error from worker threads to the main thread
during tile multi-threading. Also, derives the error_info
inside sync_enc_workers() to propagate the exact error
details further.
Bug: aomedia:3276
Change-Id: Iba50506d2aa386cfbd19a5785daf23d53ecc277e
diff --git a/av1/av1_cx_iface.c b/av1/av1_cx_iface.c
index 59cb8e9..32af35f 100644
--- a/av1/av1_cx_iface.c
+++ b/av1/av1_cx_iface.c
@@ -3147,7 +3147,8 @@
const int status = av1_get_compressed_data(cpi_lap, &cpi_lap_data);
if (status != -1) {
if (status != AOM_CODEC_OK) {
- aom_internal_error(&ppi->error, AOM_CODEC_ERROR, NULL);
+ aom_internal_error(&ppi->error, cpi->common.error->error_code, "%s",
+ cpi->common.error->detail);
}
}
av1_post_encode_updates(cpi_lap, &cpi_lap_data);
@@ -3203,7 +3204,8 @@
}
if (status == -1) break;
if (status != AOM_CODEC_OK) {
- aom_internal_error(&ppi->error, AOM_CODEC_ERROR, NULL);
+ aom_internal_error(&ppi->error, cpi->common.error->error_code, "%s",
+ cpi->common.error->detail);
}
if (ppi->num_fp_contexts > 0 && frame_is_intra_only(&cpi->common)) {
av1_init_sc_decisions(ppi);
diff --git a/av1/encoder/ethread.c b/av1/encoder/ethread.c
index 2a00999..d0b04ac 100644
--- a/av1/encoder/ethread.c
+++ b/av1/encoder/ethread.c
@@ -591,12 +591,26 @@
static int enc_worker_hook(void *arg1, void *unused) {
EncWorkerData *const thread_data = (EncWorkerData *)arg1;
AV1_COMP *const cpi = thread_data->cpi;
+ MACROBLOCKD *const xd = &thread_data->td->mb.e_mbd;
+ struct aom_internal_error_info *const error_info = &thread_data->error_info;
const AV1_COMMON *const cm = &cpi->common;
const int tile_cols = cm->tiles.cols;
const int tile_rows = cm->tiles.rows;
int t;
(void)unused;
+
+ xd->error_info = error_info;
+
+ // The jmp_buf is valid only for the duration of the function that calls
+ // setjmp(). Therefore, this function must reset the 'setjmp' field to 0
+ // before it returns.
+ if (setjmp(error_info->jmp)) {
+ error_info->setjmp = 0;
+ return 0;
+ }
+ error_info->setjmp = 1;
+
// Preallocate the pc_tree for realtime coding to reduce the cost of memory
// allocation.
thread_data->td->rt_pc_root =
@@ -619,6 +633,7 @@
av1_free_pc_tree_recursive(thread_data->td->rt_pc_root, av1_num_planes(cm), 0,
0, cpi->sf.part_sf.partition_search_type);
+ error_info->setjmp = 0;
return 1;
}
@@ -1265,16 +1280,26 @@
AV1_COMMON *const cm, int num_workers) {
const AVxWorkerInterface *const winterface = aom_get_worker_interface();
int had_error = mt_info->workers[0].had_error;
+ struct aom_internal_error_info error_info;
+
+ // Read the error_info of main thread.
+ if (had_error) {
+ AVxWorker *const worker = &mt_info->workers[0];
+ error_info = ((EncWorkerData *)worker->data1)->error_info;
+ }
// Encoding ends.
for (int i = num_workers - 1; i > 0; i--) {
AVxWorker *const worker = &mt_info->workers[i];
- had_error |= !winterface->sync(worker);
+ if (!winterface->sync(worker)) {
+ had_error = 1;
+ error_info = ((EncWorkerData *)worker->data1)->error_info;
+ }
}
if (had_error)
- aom_internal_error(cm->error, AOM_CODEC_ERROR,
- "Failed to encode tile data");
+ aom_internal_error(cm->error, error_info.error_code, "%s",
+ error_info.detail);
}
static AOM_INLINE void accumulate_counters_enc_workers(AV1_COMP *cpi,
diff --git a/av1/encoder/ethread.h b/av1/encoder/ethread.h
index 6c4bce4..62d4c7f 100644
--- a/av1/encoder/ethread.h
+++ b/av1/encoder/ethread.h
@@ -23,6 +23,7 @@
struct AV1_COMP *cpi;
struct ThreadData *td;
struct ThreadData *original_td;
+ struct aom_internal_error_info error_info;
AV1LfSync *lf_sync;
LFWorkerData *lf_data;
int start;