Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: source/libvpx/test/vp9_thread_test.cc

Issue 375983002: libvpx: Pull from upstream (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/deps/third_party/libvpx/
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « source/libvpx/test/vp9_lossless_test.cc ('k') | source/libvpx/test/y4m_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved. 2 * Copyright (c) 2013 The WebM project authors. All Rights Reserved.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license 4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source 5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found 6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may 7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree. 8 * be found in the AUTHORS file in the root of the source tree.
9 */ 9 */
10 10
(...skipping 10 matching lines...) Expand all
21 #include "vp9/decoder/vp9_thread.h" 21 #include "vp9/decoder/vp9_thread.h"
22 22
23 namespace { 23 namespace {
24 24
25 using std::string; 25 using std::string;
26 26
27 class VP9WorkerThreadTest : public ::testing::TestWithParam<bool> { 27 class VP9WorkerThreadTest : public ::testing::TestWithParam<bool> {
28 protected: 28 protected:
29 virtual ~VP9WorkerThreadTest() {} 29 virtual ~VP9WorkerThreadTest() {}
30 virtual void SetUp() { 30 virtual void SetUp() {
31 vp9_worker_init(&worker_); 31 vp9_get_worker_interface()->init(&worker_);
32 } 32 }
33 33
34 virtual void TearDown() { 34 virtual void TearDown() {
35 vp9_worker_end(&worker_); 35 vp9_get_worker_interface()->end(&worker_);
36 } 36 }
37 37
38 VP9Worker worker_; 38 VP9Worker worker_;
39 }; 39 };
40 40
41 int ThreadHook(void* data, void* return_value) { 41 int ThreadHook(void* data, void* return_value) {
42 int* const hook_data = reinterpret_cast<int*>(data); 42 int* const hook_data = reinterpret_cast<int*>(data);
43 *hook_data = 5; 43 *hook_data = 5;
44 return *reinterpret_cast<int*>(return_value); 44 return *reinterpret_cast<int*>(return_value);
45 } 45 }
46 46
47 TEST_P(VP9WorkerThreadTest, HookSuccess) { 47 TEST_P(VP9WorkerThreadTest, HookSuccess) {
48 EXPECT_NE(vp9_worker_sync(&worker_), 0); // should be a no-op. 48 // should be a no-op.
49 EXPECT_NE(vp9_get_worker_interface()->sync(&worker_), 0);
49 50
50 for (int i = 0; i < 2; ++i) { 51 for (int i = 0; i < 2; ++i) {
51 EXPECT_NE(vp9_worker_reset(&worker_), 0); 52 EXPECT_NE(vp9_get_worker_interface()->reset(&worker_), 0);
52 53
53 int hook_data = 0; 54 int hook_data = 0;
54 int return_value = 1; // return successfully from the hook 55 int return_value = 1; // return successfully from the hook
55 worker_.hook = ThreadHook; 56 worker_.hook = ThreadHook;
56 worker_.data1 = &hook_data; 57 worker_.data1 = &hook_data;
57 worker_.data2 = &return_value; 58 worker_.data2 = &return_value;
58 59
59 const bool synchronous = GetParam(); 60 const bool synchronous = GetParam();
60 if (synchronous) { 61 if (synchronous) {
61 vp9_worker_execute(&worker_); 62 vp9_get_worker_interface()->execute(&worker_);
62 } else { 63 } else {
63 vp9_worker_launch(&worker_); 64 vp9_get_worker_interface()->launch(&worker_);
64 } 65 }
65 EXPECT_NE(vp9_worker_sync(&worker_), 0); 66 EXPECT_NE(vp9_get_worker_interface()->sync(&worker_), 0);
66 EXPECT_FALSE(worker_.had_error); 67 EXPECT_FALSE(worker_.had_error);
67 EXPECT_EQ(5, hook_data); 68 EXPECT_EQ(5, hook_data);
68 69
69 EXPECT_NE(vp9_worker_sync(&worker_), 0); // should be a no-op. 70 // should be a no-op.
71 EXPECT_NE(vp9_get_worker_interface()->sync(&worker_), 0);
70 } 72 }
71 } 73 }
72 74
73 TEST_P(VP9WorkerThreadTest, HookFailure) { 75 TEST_P(VP9WorkerThreadTest, HookFailure) {
74 EXPECT_NE(vp9_worker_reset(&worker_), 0); 76 EXPECT_NE(vp9_get_worker_interface()->reset(&worker_), 0);
75 77
76 int hook_data = 0; 78 int hook_data = 0;
77 int return_value = 0; // return failure from the hook 79 int return_value = 0; // return failure from the hook
78 worker_.hook = ThreadHook; 80 worker_.hook = ThreadHook;
79 worker_.data1 = &hook_data; 81 worker_.data1 = &hook_data;
80 worker_.data2 = &return_value; 82 worker_.data2 = &return_value;
81 83
82 const bool synchronous = GetParam(); 84 const bool synchronous = GetParam();
83 if (synchronous) { 85 if (synchronous) {
84 vp9_worker_execute(&worker_); 86 vp9_get_worker_interface()->execute(&worker_);
85 } else { 87 } else {
86 vp9_worker_launch(&worker_); 88 vp9_get_worker_interface()->launch(&worker_);
87 } 89 }
88 EXPECT_FALSE(vp9_worker_sync(&worker_)); 90 EXPECT_FALSE(vp9_get_worker_interface()->sync(&worker_));
89 EXPECT_EQ(1, worker_.had_error); 91 EXPECT_EQ(1, worker_.had_error);
90 92
91 // Ensure _reset() clears the error and _launch() can be called again. 93 // Ensure _reset() clears the error and _launch() can be called again.
92 return_value = 1; 94 return_value = 1;
93 EXPECT_NE(vp9_worker_reset(&worker_), 0); 95 EXPECT_NE(vp9_get_worker_interface()->reset(&worker_), 0);
94 EXPECT_FALSE(worker_.had_error); 96 EXPECT_FALSE(worker_.had_error);
95 vp9_worker_launch(&worker_); 97 vp9_get_worker_interface()->launch(&worker_);
96 EXPECT_NE(vp9_worker_sync(&worker_), 0); 98 EXPECT_NE(vp9_get_worker_interface()->sync(&worker_), 0);
97 EXPECT_FALSE(worker_.had_error); 99 EXPECT_FALSE(worker_.had_error);
98 } 100 }
99 101
102 TEST(VP9WorkerThreadTest, TestInterfaceAPI) {
103 EXPECT_EQ(0, vp9_set_worker_interface(NULL));
104 EXPECT_TRUE(vp9_get_worker_interface() != NULL);
105 for (int i = 0; i < 6; ++i) {
106 VP9WorkerInterface winterface = *vp9_get_worker_interface();
107 switch (i) {
108 default:
109 case 0: winterface.init = NULL; break;
110 case 1: winterface.reset = NULL; break;
111 case 2: winterface.sync = NULL; break;
112 case 3: winterface.launch = NULL; break;
113 case 4: winterface.execute = NULL; break;
114 case 5: winterface.end = NULL; break;
115 }
116 EXPECT_EQ(0, vp9_set_worker_interface(&winterface));
117 }
118 }
119
100 // ----------------------------------------------------------------------------- 120 // -----------------------------------------------------------------------------
101 // Multi-threaded decode tests 121 // Multi-threaded decode tests
102 122
103 #if CONFIG_WEBM_IO 123 #if CONFIG_WEBM_IO
124 struct FileList {
125 const char *name;
126 const char *expected_md5;
127 };
128
104 // Decodes |filename| with |num_threads|. Returns the md5 of the decoded frames. 129 // Decodes |filename| with |num_threads|. Returns the md5 of the decoded frames.
105 string DecodeFile(const string& filename, int num_threads) { 130 string DecodeFile(const string& filename, int num_threads) {
106 libvpx_test::WebMVideoSource video(filename); 131 libvpx_test::WebMVideoSource video(filename);
107 video.Init(); 132 video.Init();
108 133
109 vpx_codec_dec_cfg_t cfg = {0}; 134 vpx_codec_dec_cfg_t cfg = {0};
110 cfg.threads = num_threads; 135 cfg.threads = num_threads;
111 libvpx_test::VP9Decoder decoder(cfg, 0); 136 libvpx_test::VP9Decoder decoder(cfg, 0);
112 137
113 libvpx_test::MD5 md5; 138 libvpx_test::MD5 md5;
114 for (video.Begin(); video.cxdata(); video.Next()) { 139 for (video.Begin(); video.cxdata(); video.Next()) {
115 const vpx_codec_err_t res = 140 const vpx_codec_err_t res =
116 decoder.DecodeFrame(video.cxdata(), video.frame_size()); 141 decoder.DecodeFrame(video.cxdata(), video.frame_size());
117 if (res != VPX_CODEC_OK) { 142 if (res != VPX_CODEC_OK) {
118 EXPECT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError(); 143 EXPECT_EQ(VPX_CODEC_OK, res) << decoder.DecodeError();
119 break; 144 break;
120 } 145 }
121 146
122 libvpx_test::DxDataIterator dec_iter = decoder.GetDxData(); 147 libvpx_test::DxDataIterator dec_iter = decoder.GetDxData();
123 const vpx_image_t *img = NULL; 148 const vpx_image_t *img = NULL;
124 149
125 // Get decompressed data 150 // Get decompressed data
126 while ((img = dec_iter.Next())) { 151 while ((img = dec_iter.Next())) {
127 md5.Add(img); 152 md5.Add(img);
128 } 153 }
129 } 154 }
130 return string(md5.Get()); 155 return string(md5.Get());
131 } 156 }
132 157
133 TEST(VP9DecodeMTTest, MTDecode) { 158 void DecodeFiles(const FileList files[]) {
134 // no tiles or frame parallel; this exercises loop filter threading. 159 for (const FileList *iter = files; iter->name != NULL; ++iter) {
135 EXPECT_STREQ("b35a1b707b28e82be025d960aba039bc", 160 SCOPED_TRACE(iter->name);
136 DecodeFile("vp90-2-03-size-226x226.webm", 2).c_str()); 161 for (int t = 2; t <= 8; ++t) {
162 EXPECT_EQ(iter->expected_md5, DecodeFile(iter->name, t))
163 << "threads = " << t;
164 }
165 }
137 } 166 }
138 167
139 TEST(VP9DecodeMTTest, MTDecode2) { 168 // Trivial serialized thread worker interface implementation.
140 static const struct { 169 // Note any worker that requires synchronization between other workers will
141 const char *name; 170 // hang.
142 const char *expected_md5; 171 namespace impl {
143 } files[] = { 172
173 void Init(VP9Worker *const worker) { memset(worker, 0, sizeof(*worker)); }
174 int Reset(VP9Worker *const /*worker*/) { return 1; }
175 int Sync(VP9Worker *const worker) { return !worker->had_error; }
176
177 void Execute(VP9Worker *const worker) {
178 worker->had_error |= worker->hook(worker->data1, worker->data2);
179 }
180
181 void Launch(VP9Worker *const worker) { Execute(worker); }
182 void End(VP9Worker *const /*worker*/) {}
183
184 } // namespace impl
185
186 TEST(VP9WorkerThreadTest, TestSerialInterface) {
187 static const VP9WorkerInterface serial_interface = {
188 impl::Init, impl::Reset, impl::Sync, impl::Launch, impl::Execute, impl::End
189 };
190 // TODO(jzern): Avoid using a file that will use the row-based thread
191 // loopfilter, with the simple serialized implementation it will hang. This is
192 // due to its expectation that rows will be run in parallel as they wait on
193 // progress in the row above before proceeding.
194 static const char expected_md5[] = "b35a1b707b28e82be025d960aba039bc";
195 static const char filename[] = "vp90-2-03-size-226x226.webm";
196 VP9WorkerInterface default_interface = *vp9_get_worker_interface();
197
198 EXPECT_NE(vp9_set_worker_interface(&serial_interface), 0);
199 EXPECT_EQ(expected_md5, DecodeFile(filename, 2));
200
201 // Reset the interface.
202 EXPECT_NE(vp9_set_worker_interface(&default_interface), 0);
203 EXPECT_EQ(expected_md5, DecodeFile(filename, 2));
204 }
205
206 TEST(VP9DecodeMultiThreadedTest, Decode) {
207 // no tiles or frame parallel; this exercises loop filter threading.
208 EXPECT_EQ("b35a1b707b28e82be025d960aba039bc",
209 DecodeFile("vp90-2-03-size-226x226.webm", 2));
210 }
211
212 TEST(VP9DecodeMultiThreadedTest, Decode2) {
213 static const FileList files[] = {
144 { "vp90-2-08-tile_1x2_frame_parallel.webm", 214 { "vp90-2-08-tile_1x2_frame_parallel.webm",
145 "68ede6abd66bae0a2edf2eb9232241b6" }, 215 "68ede6abd66bae0a2edf2eb9232241b6" },
146 { "vp90-2-08-tile_1x4_frame_parallel.webm", 216 { "vp90-2-08-tile_1x4_frame_parallel.webm",
147 "368ebc6ebf3a5e478d85b2c3149b2848" }, 217 "368ebc6ebf3a5e478d85b2c3149b2848" },
148 { "vp90-2-08-tile_1x8_frame_parallel.webm", 218 { "vp90-2-08-tile_1x8_frame_parallel.webm",
149 "17e439da2388aff3a0f69cb22579c6c1" }, 219 "17e439da2388aff3a0f69cb22579c6c1" },
220 { NULL, NULL }
150 }; 221 };
151 222
152 for (int i = 0; i < static_cast<int>(sizeof(files) / sizeof(files[0])); ++i) { 223 DecodeFiles(files);
153 for (int t = 2; t <= 8; ++t) {
154 EXPECT_STREQ(files[i].expected_md5, DecodeFile(files[i].name, t).c_str())
155 << "threads = " << t;
156 }
157 }
158 } 224 }
159 225
160 // Test tile quantity changes within one file. 226 // Test tile quantity changes within one file.
161 TEST(VP9DecodeMTTest, MTDecode3) { 227 TEST(VP9DecodeMultiThreadedTest, Decode3) {
162 static const struct { 228 static const FileList files[] = {
163 const char *name;
164 const char *expected_md5;
165 } files[] = {
166 { "vp90-2-14-resize-fp-tiles-1-16.webm", 229 { "vp90-2-14-resize-fp-tiles-1-16.webm",
167 "0cd5e632c326297e975f38949c31ea94" }, 230 "0cd5e632c326297e975f38949c31ea94" },
168 { "vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm", 231 { "vp90-2-14-resize-fp-tiles-1-2-4-8-16.webm",
169 "5c78a96a42e7f4a4f6b2edcdb791e44c" }, 232 "5c78a96a42e7f4a4f6b2edcdb791e44c" },
170 { "vp90-2-14-resize-fp-tiles-1-2.webm", 233 { "vp90-2-14-resize-fp-tiles-1-2.webm",
171 "e030450ae85c3277be2a418769df98e2" }, 234 "e030450ae85c3277be2a418769df98e2" },
172 { "vp90-2-14-resize-fp-tiles-1-4.webm", 235 { "vp90-2-14-resize-fp-tiles-1-4.webm",
173 "312eed4e2b64eb7a4e7f18916606a430" }, 236 "312eed4e2b64eb7a4e7f18916606a430" },
174 { "vp90-2-14-resize-fp-tiles-16-1.webm", 237 { "vp90-2-14-resize-fp-tiles-16-1.webm",
175 "1755c16d8af16a9cb3fe7338d90abe52" }, 238 "1755c16d8af16a9cb3fe7338d90abe52" },
(...skipping 24 matching lines...) Expand all
200 { "vp90-2-14-resize-fp-tiles-4-8.webm", 263 { "vp90-2-14-resize-fp-tiles-4-8.webm",
201 "7f76d96036382f45121e3d5aa6f8ec52" }, 264 "7f76d96036382f45121e3d5aa6f8ec52" },
202 { "vp90-2-14-resize-fp-tiles-8-16.webm", 265 { "vp90-2-14-resize-fp-tiles-8-16.webm",
203 "76a43fcdd7e658542913ea43216ec55d" }, 266 "76a43fcdd7e658542913ea43216ec55d" },
204 { "vp90-2-14-resize-fp-tiles-8-1.webm", 267 { "vp90-2-14-resize-fp-tiles-8-1.webm",
205 "8e3fbe89486ca60a59299dea9da91378" }, 268 "8e3fbe89486ca60a59299dea9da91378" },
206 { "vp90-2-14-resize-fp-tiles-8-2.webm", 269 { "vp90-2-14-resize-fp-tiles-8-2.webm",
207 "ae96f21f21b6370cc0125621b441fc52" }, 270 "ae96f21f21b6370cc0125621b441fc52" },
208 { "vp90-2-14-resize-fp-tiles-8-4.webm", 271 { "vp90-2-14-resize-fp-tiles-8-4.webm",
209 "3eb4f24f10640d42218f7fd7b9fd30d4" }, 272 "3eb4f24f10640d42218f7fd7b9fd30d4" },
273 { NULL, NULL }
210 }; 274 };
211 275
212 for (int i = 0; i < static_cast<int>(sizeof(files) / sizeof(files[0])); ++i) { 276 DecodeFiles(files);
213 for (int t = 2; t <= 8; ++t) {
214 EXPECT_STREQ(files[i].expected_md5, DecodeFile(files[i].name, t).c_str())
215 << "threads = " << t;
216 }
217 }
218 } 277 }
219 #endif // CONFIG_WEBM_IO 278 #endif // CONFIG_WEBM_IO
220 279
221 INSTANTIATE_TEST_CASE_P(Synchronous, VP9WorkerThreadTest, ::testing::Bool()); 280 INSTANTIATE_TEST_CASE_P(Synchronous, VP9WorkerThreadTest, ::testing::Bool());
222 281
223 } // namespace 282 } // namespace
OLDNEW
« no previous file with comments | « source/libvpx/test/vp9_lossless_test.cc ('k') | source/libvpx/test/y4m_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698