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/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,