Merge changes I305fd55f,I13fe92b1
* changes: vp9/dec: use loop filter worker for all inline cases vp9_thread: add vp9_worker_execute()
This commit is contained in:
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
class VP9WorkerThreadTest : public ::testing::Test {
|
class VP9WorkerThreadTest : public ::testing::TestWithParam<bool> {
|
||||||
protected:
|
protected:
|
||||||
virtual ~VP9WorkerThreadTest() {}
|
virtual ~VP9WorkerThreadTest() {}
|
||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
@@ -38,7 +38,7 @@ int ThreadHook(void* data, void* return_value) {
|
|||||||
return *reinterpret_cast<int*>(return_value);
|
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.
|
EXPECT_TRUE(vp9_worker_sync(&worker_)); // should be a no-op.
|
||||||
|
|
||||||
for (int i = 0; i < 2; ++i) {
|
for (int i = 0; i < 2; ++i) {
|
||||||
@@ -50,7 +50,12 @@ TEST_F(VP9WorkerThreadTest, HookSuccess) {
|
|||||||
worker_.data1 = &hook_data;
|
worker_.data1 = &hook_data;
|
||||||
worker_.data2 = &return_value;
|
worker_.data2 = &return_value;
|
||||||
|
|
||||||
|
const bool synchronous = GetParam();
|
||||||
|
if (synchronous) {
|
||||||
|
vp9_worker_execute(&worker_);
|
||||||
|
} else {
|
||||||
vp9_worker_launch(&worker_);
|
vp9_worker_launch(&worker_);
|
||||||
|
}
|
||||||
EXPECT_TRUE(vp9_worker_sync(&worker_));
|
EXPECT_TRUE(vp9_worker_sync(&worker_));
|
||||||
EXPECT_FALSE(worker_.had_error);
|
EXPECT_FALSE(worker_.had_error);
|
||||||
EXPECT_EQ(5, hook_data);
|
EXPECT_EQ(5, hook_data);
|
||||||
@@ -59,7 +64,7 @@ TEST_F(VP9WorkerThreadTest, HookSuccess) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(VP9WorkerThreadTest, HookFailure) {
|
TEST_P(VP9WorkerThreadTest, HookFailure) {
|
||||||
EXPECT_TRUE(vp9_worker_reset(&worker_));
|
EXPECT_TRUE(vp9_worker_reset(&worker_));
|
||||||
|
|
||||||
int hook_data = 0;
|
int hook_data = 0;
|
||||||
@@ -68,7 +73,12 @@ TEST_F(VP9WorkerThreadTest, HookFailure) {
|
|||||||
worker_.data1 = &hook_data;
|
worker_.data1 = &hook_data;
|
||||||
worker_.data2 = &return_value;
|
worker_.data2 = &return_value;
|
||||||
|
|
||||||
|
const bool synchronous = GetParam();
|
||||||
|
if (synchronous) {
|
||||||
|
vp9_worker_execute(&worker_);
|
||||||
|
} else {
|
||||||
vp9_worker_launch(&worker_);
|
vp9_worker_launch(&worker_);
|
||||||
|
}
|
||||||
EXPECT_FALSE(vp9_worker_sync(&worker_));
|
EXPECT_FALSE(vp9_worker_sync(&worker_));
|
||||||
EXPECT_TRUE(worker_.had_error);
|
EXPECT_TRUE(worker_.had_error);
|
||||||
|
|
||||||
@@ -106,4 +116,6 @@ TEST(VP9DecodeMTTest, MTDecode) {
|
|||||||
EXPECT_STREQ("b35a1b707b28e82be025d960aba039bc", md5.Get());
|
EXPECT_STREQ("b35a1b707b28e82be025d960aba039bc", md5.Get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_CASE_P(Synchronous, VP9WorkerThreadTest, ::testing::Bool());
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|||||||
@@ -583,14 +583,12 @@ static void decode_tile(VP9D_COMP *pbi, vp9_reader *r, int tile_col) {
|
|||||||
YV12_BUFFER_CONFIG *const fb = &cm->yv12_fb[cm->new_fb_idx];
|
YV12_BUFFER_CONFIG *const fb = &cm->yv12_fb[cm->new_fb_idx];
|
||||||
|
|
||||||
if (pbi->do_loopfilter_inline) {
|
if (pbi->do_loopfilter_inline) {
|
||||||
if (num_threads > 1) {
|
|
||||||
LFWorkerData *const lf_data = (LFWorkerData*)pbi->lf_worker.data1;
|
LFWorkerData *const lf_data = (LFWorkerData*)pbi->lf_worker.data1;
|
||||||
lf_data->frame_buffer = fb;
|
lf_data->frame_buffer = fb;
|
||||||
lf_data->cm = cm;
|
lf_data->cm = cm;
|
||||||
lf_data->xd = pbi->mb;
|
lf_data->xd = pbi->mb;
|
||||||
lf_data->stop = 0;
|
lf_data->stop = 0;
|
||||||
lf_data->y_only = 0;
|
lf_data->y_only = 0;
|
||||||
}
|
|
||||||
vp9_loop_filter_frame_init(cm, cm->lf.filter_level);
|
vp9_loop_filter_frame_init(cm, cm->lf.filter_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -604,39 +602,33 @@ static void decode_tile(VP9D_COMP *pbi, vp9_reader *r, int tile_col) {
|
|||||||
decode_modes_sb(pbi, tile_col, mi_row, mi_col, r, BLOCK_64X64, 0);
|
decode_modes_sb(pbi, tile_col, mi_row, mi_col, r, BLOCK_64X64, 0);
|
||||||
|
|
||||||
if (pbi->do_loopfilter_inline) {
|
if (pbi->do_loopfilter_inline) {
|
||||||
// delay the loopfilter by 1 macroblock row.
|
|
||||||
const int lf_start = mi_row - MI_BLOCK_SIZE;
|
const int lf_start = mi_row - MI_BLOCK_SIZE;
|
||||||
if (lf_start < 0) continue;
|
|
||||||
|
|
||||||
if (num_threads > 1) {
|
|
||||||
LFWorkerData *const lf_data = (LFWorkerData*)pbi->lf_worker.data1;
|
LFWorkerData *const lf_data = (LFWorkerData*)pbi->lf_worker.data1;
|
||||||
|
|
||||||
|
// delay the loopfilter by 1 macroblock row.
|
||||||
|
if (lf_start < 0) continue;
|
||||||
|
|
||||||
// decoding has completed: finish up the loop filter in this thread.
|
// decoding has completed: finish up the loop filter in this thread.
|
||||||
if (mi_row + MI_BLOCK_SIZE >= cm->cur_tile_mi_row_end) continue;
|
if (mi_row + MI_BLOCK_SIZE >= cm->cur_tile_mi_row_end) continue;
|
||||||
|
|
||||||
vp9_worker_sync(&pbi->lf_worker);
|
vp9_worker_sync(&pbi->lf_worker);
|
||||||
lf_data->start = lf_start;
|
lf_data->start = lf_start;
|
||||||
lf_data->stop = mi_row;
|
lf_data->stop = mi_row;
|
||||||
pbi->lf_worker.hook = vp9_loop_filter_worker;
|
if (num_threads > 1) {
|
||||||
vp9_worker_launch(&pbi->lf_worker);
|
vp9_worker_launch(&pbi->lf_worker);
|
||||||
} else {
|
} 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) {
|
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);
|
vp9_worker_sync(&pbi->lf_worker);
|
||||||
lf_start = lf_data->stop;
|
lf_data->start = lf_data->stop;
|
||||||
} else {
|
lf_data->stop = cm->mi_rows;
|
||||||
lf_start = mi_row - MI_BLOCK_SIZE;
|
vp9_worker_execute(&pbi->lf_worker);
|
||||||
}
|
|
||||||
vp9_loop_filter_rows(fb, cm, &pbi->mb,
|
|
||||||
lf_start, cm->mi_rows, 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -141,15 +141,14 @@ VP9D_PTR vp9_create_decompressor(VP9D_CONFIG *oxcf) {
|
|||||||
cm->error.setjmp = 0;
|
cm->error.setjmp = 0;
|
||||||
pbi->decoded_key_frame = 0;
|
pbi->decoded_key_frame = 0;
|
||||||
|
|
||||||
if (pbi->oxcf.max_threads > 1) {
|
|
||||||
vp9_worker_init(&pbi->lf_worker);
|
vp9_worker_init(&pbi->lf_worker);
|
||||||
pbi->lf_worker.data1 = vpx_malloc(sizeof(LFWorkerData));
|
pbi->lf_worker.data1 = vpx_malloc(sizeof(LFWorkerData));
|
||||||
pbi->lf_worker.hook = (VP9WorkerHook)vp9_loop_filter_worker;
|
pbi->lf_worker.hook = (VP9WorkerHook)vp9_loop_filter_worker;
|
||||||
if (pbi->lf_worker.data1 == NULL || !vp9_worker_reset(&pbi->lf_worker)) {
|
if (pbi->lf_worker.data1 == NULL ||
|
||||||
|
(pbi->oxcf.max_threads > 1 && !vp9_worker_reset(&pbi->lf_worker))) {
|
||||||
vp9_remove_decompressor(pbi);
|
vp9_remove_decompressor(pbi);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return pbi;
|
return pbi;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -145,9 +145,7 @@ static THREADFN thread_loop(void *ptr) { // thread loop
|
|||||||
pthread_cond_wait(&worker->condition_, &worker->mutex_);
|
pthread_cond_wait(&worker->condition_, &worker->mutex_);
|
||||||
}
|
}
|
||||||
if (worker->status_ == WORK) {
|
if (worker->status_ == WORK) {
|
||||||
if (worker->hook) {
|
vp9_worker_execute(worker);
|
||||||
worker->had_error |= !worker->hook(worker->data1, worker->data2);
|
|
||||||
}
|
|
||||||
worker->status_ = OK;
|
worker->status_ = OK;
|
||||||
} else if (worker->status_ == NOT_OK) { // finish the worker
|
} else if (worker->status_ == NOT_OK) { // finish the worker
|
||||||
done = 1;
|
done = 1;
|
||||||
@@ -178,7 +176,7 @@ static void change_state(VP9Worker* const worker,
|
|||||||
pthread_mutex_unlock(&worker->mutex_);
|
pthread_mutex_unlock(&worker->mutex_);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif // CONFIG_MULTITHREAD
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
@@ -218,12 +216,17 @@ int vp9_worker_reset(VP9Worker* const worker) {
|
|||||||
return ok;
|
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) {
|
void vp9_worker_launch(VP9Worker* const worker) {
|
||||||
#if CONFIG_MULTITHREAD
|
#if CONFIG_MULTITHREAD
|
||||||
change_state(worker, WORK);
|
change_state(worker, WORK);
|
||||||
#else
|
#else
|
||||||
if (worker->hook)
|
vp9_worker_execute(worker);
|
||||||
worker->had_error |= !worker->hook(worker->data1, worker->data2);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,11 @@ int vp9_worker_sync(VP9Worker* const worker);
|
|||||||
// hook/data1/data2 can be changed at any time before calling this function,
|
// 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().
|
// but not be changed afterward until the next call to vp9_worker_sync().
|
||||||
void vp9_worker_launch(VP9Worker* const worker);
|
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
|
// Kill the thread and terminate the object. To use the object again, one
|
||||||
// must call vp9_worker_reset() again.
|
// must call vp9_worker_reset() again.
|
||||||
void vp9_worker_end(VP9Worker* const worker);
|
void vp9_worker_end(VP9Worker* const worker);
|
||||||
|
|||||||
Reference in New Issue
Block a user