Improve signaling of pbi->row_mt_cond_.
This CL reduces the thread wakeup overhead of row_mt_worker_hook() and
documents how the bit-stream parsing and decoding of superblocks are
synchronized.
Call pthread_cond_signal(), not pthread_cond_broadcast(), to wake up
only one waiting thread to handle a new superblock decode job.
Note: The code this CL modifies was originally added in
commit 36ff5b12d237d7d6ba95f2478f04df1788dd5b5d;
https://aomedia-review.googlesource.com/c/aom/+/64241
Change-Id: Icdbaea86b5e24fc51724b6bff0d6be9157d27fb4
diff --git a/av1/decoder/decodeframe.c b/av1/decoder/decodeframe.c
index 2c13564..04992c7 100644
--- a/av1/decoder/decodeframe.c
+++ b/av1/decoder/decodeframe.c
@@ -3346,6 +3346,16 @@
return !td->xd.corrupted;
}
+// The caller must hold pbi->row_mt_mutex_ when calling this function.
+// Returns 1 if either the next job is stored in *next_job_info or 1 is stored
+// in *end_of_frame.
+// NOTE: The caller waits on pbi->row_mt_cond_ if this function returns 0.
+// The return value of this function depends on the following variables:
+// - frame_row_mt_info->mi_rows_parse_done
+// - frame_row_mt_info->mi_rows_decode_started
+// - frame_row_mt_info->row_mt_exit
+// Therefore we may need to signal or broadcast pbi->row_mt_cond_ if any of
+// these variables is modified.
static int get_next_job_info(AV1Decoder *const pbi,
AV1DecRowMTJobInfo *next_job_info,
int *end_of_frame) {
@@ -3380,9 +3390,10 @@
}
// Decoding cannot start as bit-stream parsing is not complete.
- if (frame_row_mt_info->mi_rows_parse_done -
- frame_row_mt_info->mi_rows_decode_started ==
- 0)
+ assert(frame_row_mt_info->mi_rows_parse_done >=
+ frame_row_mt_info->mi_rows_decode_started);
+ if (frame_row_mt_info->mi_rows_parse_done ==
+ frame_row_mt_info->mi_rows_decode_started)
return 0;
// Choose the tile to decode.
@@ -3435,6 +3446,14 @@
dec_row_mt_sync->num_threads_working++;
dec_row_mt_sync->mi_rows_decode_started += sb_mi_size;
frame_row_mt_info->mi_rows_decode_started += sb_mi_size;
+ assert(frame_row_mt_info->mi_rows_parse_done >=
+ frame_row_mt_info->mi_rows_decode_started);
+#if CONFIG_MULTITHREAD
+ if (frame_row_mt_info->mi_rows_decode_started ==
+ frame_row_mt_info->mi_rows_to_decode) {
+ pthread_cond_broadcast(pbi->row_mt_cond_);
+ }
+#endif
return 1;
}
@@ -3446,10 +3465,16 @@
#if CONFIG_MULTITHREAD
pthread_mutex_lock(pbi->row_mt_mutex_);
#endif
+ assert(frame_row_mt_info->mi_rows_parse_done >=
+ frame_row_mt_info->mi_rows_decode_started);
tile_data->dec_row_mt_sync.mi_rows_parse_done += sb_mi_size;
frame_row_mt_info->mi_rows_parse_done += sb_mi_size;
#if CONFIG_MULTITHREAD
- pthread_cond_broadcast(pbi->row_mt_cond_);
+ // A new decode job is available. Wake up one worker thread to handle the
+ // new decode job.
+ // NOTE: This assumes we bump mi_rows_parse_done and mi_rows_decode_started
+ // by the same increment (sb_mi_size).
+ pthread_cond_signal(pbi->row_mt_cond_);
pthread_mutex_unlock(pbi->row_mt_mutex_);
#endif
}
diff --git a/av1/decoder/decoder.h b/av1/decoder/decoder.h
index 5ca939c..f16e75b 100644
--- a/av1/decoder/decoder.h
+++ b/av1/decoder/decoder.h
@@ -97,9 +97,26 @@
int tile_cols_end;
int start_tile;
int end_tile;
- int mi_rows_parse_done;
- int mi_rows_decode_started;
int mi_rows_to_decode;
+
+ // Invariant:
+ // mi_rows_parse_done >= mi_rows_decode_started.
+ // mi_rows_parse_done and mi_rows_decode_started are both initialized to 0.
+ // mi_rows_parse_done is incremented freely. mi_rows_decode_started may only
+ // be incremented to catch up with mi_rows_parse_done but is not allowed to
+ // surpass mi_rows_parse_done.
+ //
+ // When mi_rows_decode_started reaches mi_rows_to_decode, there are no more
+ // decode jobs.
+
+ // Indicates the progress of the bit-stream parsing of superblocks.
+ // Initialized to 0. Incremented by sb_mi_size when parse sb row is done.
+ int mi_rows_parse_done;
+ // Indicates the progress of the decoding of superblocks.
+ // Initialized to 0. Incremented by sb_mi_size when decode sb row is started.
+ int mi_rows_decode_started;
+ // Boolean: Initialized to 0 (false). Set to 1 (true) on error to abort
+ // decoding.
int row_mt_exit;
} AV1DecRowMTInfo;