ref: c9af3de1557a6c99fada8b9b608ef14ba8f24a85
parent: 64d94b4aa67a700393c26253d34760d81542487f
parent: f8797a5aac8b7c50646a177d63a273355e209d59
author: James Zern <[email protected]>
date: Tue Oct 22 09:00:33 EDT 2013
Merge changes I305fd55f,I13fe92b1 * changes: vp9/dec: use loop filter worker for all inline cases vp9_thread: add vp9_worker_execute()
--- a/test/vp9_thread_test.cc
+++ b/test/vp9_thread_test.cc
@@ -18,7 +18,7 @@
namespace {
-class VP9WorkerThreadTest : public ::testing::Test {
+class VP9WorkerThreadTest : public ::testing::TestWithParam<bool> {
protected:
virtual ~VP9WorkerThreadTest() {}
virtual void SetUp() {
@@ -38,7 +38,7 @@
return *reinterpret_cast<int*>(return_value);
}
-TEST_F(VP9WorkerThreadTest, HookSuccess) {
+TEST_P(VP9WorkerThreadTest, HookSuccess) {
EXPECT_TRUE(vp9_worker_sync(&worker_)); // should be a no-op.
for (int i = 0; i < 2; ++i) {
@@ -50,7 +50,12 @@
worker_.data1 = &hook_data;
worker_.data2 = &return_value;
- vp9_worker_launch(&worker_);
+ const bool synchronous = GetParam();
+ if (synchronous) {
+ vp9_worker_execute(&worker_);
+ } else {
+ vp9_worker_launch(&worker_);
+ }
EXPECT_TRUE(vp9_worker_sync(&worker_));
EXPECT_FALSE(worker_.had_error);
EXPECT_EQ(5, hook_data);
@@ -59,7 +64,7 @@
}
}
-TEST_F(VP9WorkerThreadTest, HookFailure) {
+TEST_P(VP9WorkerThreadTest, HookFailure) {
EXPECT_TRUE(vp9_worker_reset(&worker_));
int hook_data = 0;
@@ -68,7 +73,12 @@
worker_.data1 = &hook_data;
worker_.data2 = &return_value;
- vp9_worker_launch(&worker_);
+ const bool synchronous = GetParam();
+ if (synchronous) {
+ vp9_worker_execute(&worker_);
+ } else {
+ vp9_worker_launch(&worker_);
+ }
EXPECT_FALSE(vp9_worker_sync(&worker_));
EXPECT_TRUE(worker_.had_error);
@@ -105,5 +115,7 @@
}
EXPECT_STREQ("b35a1b707b28e82be025d960aba039bc", md5.Get());
}
+
+INSTANTIATE_TEST_CASE_P(Synchronous, VP9WorkerThreadTest, ::testing::Bool());
} // namespace
--- a/vp9/decoder/vp9_decodframe.c
+++ b/vp9/decoder/vp9_decodframe.c
@@ -583,14 +583,12 @@
YV12_BUFFER_CONFIG *const fb = &cm->yv12_fb[cm->new_fb_idx];
if (pbi->do_loopfilter_inline) {
- if (num_threads > 1) {
- LFWorkerData *const lf_data = (LFWorkerData*)pbi->lf_worker.data1;
- lf_data->frame_buffer = fb;
- lf_data->cm = cm;
- lf_data->xd = pbi->mb;
- lf_data->stop = 0;
- lf_data->y_only = 0;
- }
+ LFWorkerData *const lf_data = (LFWorkerData*)pbi->lf_worker.data1;
+ lf_data->frame_buffer = fb;
+ lf_data->cm = cm;
+ lf_data->xd = pbi->mb;
+ lf_data->stop = 0;
+ lf_data->y_only = 0;
vp9_loop_filter_frame_init(cm, cm->lf.filter_level);
}
@@ -604,39 +602,33 @@
decode_modes_sb(pbi, tile_col, mi_row, mi_col, r, BLOCK_64X64, 0);
if (pbi->do_loopfilter_inline) {
- // delay the loopfilter by 1 macroblock row.
const int lf_start = mi_row - MI_BLOCK_SIZE;
+ LFWorkerData *const lf_data = (LFWorkerData*)pbi->lf_worker.data1;
+
+ // delay the loopfilter by 1 macroblock row.
if (lf_start < 0) continue;
- if (num_threads > 1) {
- LFWorkerData *const lf_data = (LFWorkerData*)pbi->lf_worker.data1;
+ // decoding has completed: finish up the loop filter in this thread.
+ if (mi_row + MI_BLOCK_SIZE >= cm->cur_tile_mi_row_end) continue;
- // decoding has completed: finish up the loop filter in this thread.
- if (mi_row + MI_BLOCK_SIZE >= cm->cur_tile_mi_row_end) continue;
-
- vp9_worker_sync(&pbi->lf_worker);
- lf_data->start = lf_start;
- lf_data->stop = mi_row;
- pbi->lf_worker.hook = vp9_loop_filter_worker;
+ vp9_worker_sync(&pbi->lf_worker);
+ lf_data->start = lf_start;
+ lf_data->stop = mi_row;
+ if (num_threads > 1) {
vp9_worker_launch(&pbi->lf_worker);
} else {
- vp9_loop_filter_rows(fb, cm, &pbi->mb, lf_start, mi_row, 0);
+ vp9_worker_execute(&pbi->lf_worker);
}
}
}
if (pbi->do_loopfilter_inline) {
- int lf_start;
- if (num_threads > 1) {
- LFWorkerData *const lf_data = (LFWorkerData*)pbi->lf_worker.data1;
+ LFWorkerData *const lf_data = (LFWorkerData*)pbi->lf_worker.data1;
- vp9_worker_sync(&pbi->lf_worker);
- lf_start = lf_data->stop;
- } else {
- lf_start = mi_row - MI_BLOCK_SIZE;
- }
- vp9_loop_filter_rows(fb, cm, &pbi->mb,
- lf_start, cm->mi_rows, 0);
+ vp9_worker_sync(&pbi->lf_worker);
+ lf_data->start = lf_data->stop;
+ lf_data->stop = cm->mi_rows;
+ vp9_worker_execute(&pbi->lf_worker);
}
}
--- a/vp9/decoder/vp9_onyxd_if.c
+++ b/vp9/decoder/vp9_onyxd_if.c
@@ -141,14 +141,13 @@
cm->error.setjmp = 0;
pbi->decoded_key_frame = 0;
- if (pbi->oxcf.max_threads > 1) {
- vp9_worker_init(&pbi->lf_worker);
- pbi->lf_worker.data1 = vpx_malloc(sizeof(LFWorkerData));
- pbi->lf_worker.hook = (VP9WorkerHook)vp9_loop_filter_worker;
- if (pbi->lf_worker.data1 == NULL || !vp9_worker_reset(&pbi->lf_worker)) {
- vp9_remove_decompressor(pbi);
- return NULL;
- }
+ vp9_worker_init(&pbi->lf_worker);
+ pbi->lf_worker.data1 = vpx_malloc(sizeof(LFWorkerData));
+ pbi->lf_worker.hook = (VP9WorkerHook)vp9_loop_filter_worker;
+ if (pbi->lf_worker.data1 == NULL ||
+ (pbi->oxcf.max_threads > 1 && !vp9_worker_reset(&pbi->lf_worker))) {
+ vp9_remove_decompressor(pbi);
+ return NULL;
}
return pbi;
--- a/vp9/decoder/vp9_thread.c
+++ b/vp9/decoder/vp9_thread.c
@@ -145,9 +145,7 @@
pthread_cond_wait(&worker->condition_, &worker->mutex_);
}
if (worker->status_ == WORK) {
- if (worker->hook) {
- worker->had_error |= !worker->hook(worker->data1, worker->data2);
- }
+ vp9_worker_execute(worker);
worker->status_ = OK;
} else if (worker->status_ == NOT_OK) { // finish the worker
done = 1;
@@ -178,7 +176,7 @@
pthread_mutex_unlock(&worker->mutex_);
}
-#endif
+#endif // CONFIG_MULTITHREAD
//------------------------------------------------------------------------------
@@ -218,12 +216,17 @@
return ok;
}
+void vp9_worker_execute(VP9Worker* const worker) {
+ if (worker->hook != NULL) {
+ worker->had_error |= !worker->hook(worker->data1, worker->data2);
+ }
+}
+
void vp9_worker_launch(VP9Worker* const worker) {
#if CONFIG_MULTITHREAD
change_state(worker, WORK);
#else
- if (worker->hook)
- worker->had_error |= !worker->hook(worker->data1, worker->data2);
+ vp9_worker_execute(worker);
#endif
}
--- a/vp9/decoder/vp9_thread.h
+++ b/vp9/decoder/vp9_thread.h
@@ -80,6 +80,11 @@
// hook/data1/data2 can be changed at any time before calling this function,
// but not be changed afterward until the next call to vp9_worker_sync().
void vp9_worker_launch(VP9Worker* const worker);
+// This function is similar to vp9_worker_launch() except that it calls the
+// hook directly instead of using a thread. Convenient to bypass the thread
+// mechanism while still using the VP9Worker structs. vp9_worker_sync() must
+// still be called afterward (for error reporting).
+void vp9_worker_execute(VP9Worker* const worker);
// Kill the thread and terminate the object. To use the object again, one
// must call vp9_worker_reset() again.
void vp9_worker_end(VP9Worker* const worker);