OLD | NEW |
| (Empty) |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include <stddef.h> | |
6 #include <stdint.h> | |
7 | |
8 #include <list> | |
9 #include <memory> | |
10 #include <utility> | |
11 #include <vector> | |
12 | |
13 #include "base/bind.h" | |
14 #include "base/macros.h" | |
15 #include "base/memory/ref_counted.h" | |
16 #include "base/threading/thread.h" | |
17 #include "base/threading/thread_task_runner_handle.h" | |
18 #include "base/time/time.h" | |
19 #include "chromecast/media/cma/ipc/media_memory_chunk.h" | |
20 #include "chromecast/media/cma/ipc/media_message_fifo.h" | |
21 #include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h" | |
22 #include "chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h" | |
23 #include "chromecast/media/cma/test/frame_generator_for_test.h" | |
24 #include "chromecast/media/cma/test/mock_frame_consumer.h" | |
25 #include "chromecast/media/cma/test/mock_frame_provider.h" | |
26 #include "chromecast/public/media/cast_decoder_buffer.h" | |
27 #include "media/base/audio_decoder_config.h" | |
28 #include "media/base/decoder_buffer.h" | |
29 #include "media/base/video_decoder_config.h" | |
30 #include "testing/gtest/include/gtest/gtest.h" | |
31 | |
32 namespace chromecast { | |
33 namespace media { | |
34 | |
35 namespace { | |
36 | |
37 class FifoMemoryChunk : public MediaMemoryChunk { | |
38 public: | |
39 FifoMemoryChunk(void* mem, size_t size) | |
40 : mem_(mem), size_(size) {} | |
41 ~FifoMemoryChunk() override {} | |
42 | |
43 void* data() const override { return mem_; } | |
44 size_t size() const override { return size_; } | |
45 bool valid() const override { return true; } | |
46 | |
47 private: | |
48 void* mem_; | |
49 size_t size_; | |
50 | |
51 DISALLOW_COPY_AND_ASSIGN(FifoMemoryChunk); | |
52 }; | |
53 | |
54 } // namespace | |
55 | |
56 class AvStreamerTest : public testing::Test { | |
57 public: | |
58 AvStreamerTest(); | |
59 ~AvStreamerTest() override; | |
60 | |
61 // Setups the test. | |
62 void Configure(size_t frame_count, | |
63 const std::vector<bool>& provider_delayed_pattern, | |
64 const std::vector<bool>& consumer_delayed_pattern, | |
65 bool delay_flush); | |
66 | |
67 // Starts the test. | |
68 void Start(); | |
69 | |
70 // Back to back flush | |
71 void FlushThenStop(); | |
72 | |
73 // Timeout indicates test failure | |
74 void OnTestTimeout(); | |
75 | |
76 protected: | |
77 std::unique_ptr<uint64_t[]> fifo_mem_; | |
78 | |
79 std::unique_ptr<AvStreamerProxy> av_buffer_proxy_; | |
80 std::unique_ptr<CodedFrameProviderHost> coded_frame_provider_host_; | |
81 std::unique_ptr<MockFrameConsumer> frame_consumer_; | |
82 | |
83 // number of pending cb in StopAndFlush | |
84 int stop_and_flush_cb_count_; | |
85 | |
86 private: | |
87 void OnTestCompleted(); | |
88 | |
89 void OnFifoRead(); | |
90 void OnFifoWrite(); | |
91 | |
92 void OnStopAndFlush(); | |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(AvStreamerTest); | |
95 }; | |
96 | |
97 AvStreamerTest::AvStreamerTest() { | |
98 } | |
99 | |
100 AvStreamerTest::~AvStreamerTest() { | |
101 } | |
102 | |
103 void AvStreamerTest::Configure( | |
104 size_t frame_count, | |
105 const std::vector<bool>& provider_delayed_pattern, | |
106 const std::vector<bool>& consumer_delayed_pattern, | |
107 bool delay_flush) { | |
108 // Frame generation on the producer and consumer side. | |
109 std::vector<FrameGeneratorForTest::FrameSpec> frame_specs; | |
110 frame_specs.resize(frame_count); | |
111 for (size_t k = 0; k < frame_specs.size() - 1; k++) { | |
112 frame_specs[k].has_config = (k == 0); | |
113 frame_specs[k].timestamp = base::TimeDelta::FromMilliseconds(40) * k; | |
114 frame_specs[k].size = 512; | |
115 frame_specs[k].has_decrypt_config = ((k % 3) == 0); | |
116 } | |
117 frame_specs.back().is_eos = true; | |
118 | |
119 std::unique_ptr<FrameGeneratorForTest> frame_generator_provider( | |
120 new FrameGeneratorForTest(frame_specs)); | |
121 std::unique_ptr<FrameGeneratorForTest> frame_generator_consumer( | |
122 new FrameGeneratorForTest(frame_specs)); | |
123 | |
124 std::unique_ptr<MockFrameProvider> frame_provider(new MockFrameProvider()); | |
125 frame_provider->Configure(provider_delayed_pattern, | |
126 std::move(frame_generator_provider)); | |
127 frame_provider->SetDelayFlush(delay_flush); | |
128 | |
129 size_t fifo_size_div_8 = 512; | |
130 fifo_mem_.reset(new uint64_t[fifo_size_div_8]); | |
131 std::unique_ptr<MediaMessageFifo> producer_fifo(new MediaMessageFifo( | |
132 std::unique_ptr<MediaMemoryChunk>( | |
133 new FifoMemoryChunk(&fifo_mem_[0], fifo_size_div_8 * 8)), | |
134 true)); | |
135 std::unique_ptr<MediaMessageFifo> consumer_fifo(new MediaMessageFifo( | |
136 std::unique_ptr<MediaMemoryChunk>( | |
137 new FifoMemoryChunk(&fifo_mem_[0], fifo_size_div_8 * 8)), | |
138 false)); | |
139 producer_fifo->ObserveWriteActivity( | |
140 base::Bind(&AvStreamerTest::OnFifoWrite, base::Unretained(this))); | |
141 consumer_fifo->ObserveReadActivity( | |
142 base::Bind(&AvStreamerTest::OnFifoRead, base::Unretained(this))); | |
143 | |
144 av_buffer_proxy_.reset( | |
145 new AvStreamerProxy()); | |
146 av_buffer_proxy_->SetCodedFrameProvider( | |
147 std::unique_ptr<CodedFrameProvider>(frame_provider.release())); | |
148 av_buffer_proxy_->SetMediaMessageFifo(std::move(producer_fifo)); | |
149 | |
150 coded_frame_provider_host_.reset( | |
151 new CodedFrameProviderHost(std::move(consumer_fifo))); | |
152 | |
153 frame_consumer_.reset( | |
154 new MockFrameConsumer(coded_frame_provider_host_.get())); | |
155 frame_consumer_->Configure(consumer_delayed_pattern, false, | |
156 std::move(frame_generator_consumer)); | |
157 | |
158 stop_and_flush_cb_count_ = 0; | |
159 } | |
160 | |
161 void AvStreamerTest::Start() { | |
162 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
163 FROM_HERE, base::Bind(&AvStreamerProxy::Start, | |
164 base::Unretained(av_buffer_proxy_.get()))); | |
165 | |
166 frame_consumer_->Start( | |
167 base::Bind(&AvStreamerTest::OnTestCompleted, | |
168 base::Unretained(this))); | |
169 } | |
170 | |
171 void AvStreamerTest::FlushThenStop() { | |
172 base::Closure cb = | |
173 base::Bind(&AvStreamerTest::OnStopAndFlush, base::Unretained(this)); | |
174 | |
175 stop_and_flush_cb_count_++; | |
176 av_buffer_proxy_->StopAndFlush(cb); | |
177 | |
178 ASSERT_EQ(stop_and_flush_cb_count_, 1); | |
179 | |
180 stop_and_flush_cb_count_++; | |
181 av_buffer_proxy_->StopAndFlush(cb); | |
182 } | |
183 | |
184 void AvStreamerTest::OnTestTimeout() { | |
185 ADD_FAILURE() << "Test timed out"; | |
186 if (base::MessageLoop::current()) | |
187 base::MessageLoop::current()->QuitWhenIdle(); | |
188 } | |
189 | |
190 void AvStreamerTest::OnTestCompleted() { | |
191 base::MessageLoop::current()->QuitWhenIdle(); | |
192 } | |
193 | |
194 void AvStreamerTest::OnFifoWrite() { | |
195 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
196 FROM_HERE, | |
197 base::Bind(&CodedFrameProviderHost::OnFifoWriteEvent, | |
198 base::Unretained(coded_frame_provider_host_.get()))); | |
199 } | |
200 | |
201 void AvStreamerTest::OnFifoRead() { | |
202 base::ThreadTaskRunnerHandle::Get()->PostTask( | |
203 FROM_HERE, base::Bind(&AvStreamerProxy::OnFifoReadEvent, | |
204 base::Unretained(av_buffer_proxy_.get()))); | |
205 } | |
206 | |
207 void AvStreamerTest::OnStopAndFlush() { | |
208 stop_and_flush_cb_count_--; | |
209 if (stop_and_flush_cb_count_ == 0) { | |
210 OnTestCompleted(); | |
211 } | |
212 } | |
213 | |
214 TEST_F(AvStreamerTest, FastProviderSlowConsumer) { | |
215 bool provider_delayed_pattern[] = { false }; | |
216 bool consumer_delayed_pattern[] = { true }; | |
217 | |
218 const size_t frame_count = 100u; | |
219 Configure(frame_count, | |
220 std::vector<bool>( | |
221 provider_delayed_pattern, | |
222 provider_delayed_pattern + arraysize(provider_delayed_pattern)), | |
223 std::vector<bool>( | |
224 consumer_delayed_pattern, | |
225 consumer_delayed_pattern + arraysize(consumer_delayed_pattern)), | |
226 false); | |
227 | |
228 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); | |
229 message_loop->PostTask( | |
230 FROM_HERE, | |
231 base::Bind(&AvStreamerTest::Start, base::Unretained(this))); | |
232 message_loop->Run(); | |
233 } | |
234 | |
235 TEST_F(AvStreamerTest, SlowProviderFastConsumer) { | |
236 bool provider_delayed_pattern[] = { true }; | |
237 bool consumer_delayed_pattern[] = { false }; | |
238 | |
239 const size_t frame_count = 100u; | |
240 Configure(frame_count, | |
241 std::vector<bool>( | |
242 provider_delayed_pattern, | |
243 provider_delayed_pattern + arraysize(provider_delayed_pattern)), | |
244 std::vector<bool>( | |
245 consumer_delayed_pattern, | |
246 consumer_delayed_pattern + arraysize(consumer_delayed_pattern)), | |
247 false); | |
248 | |
249 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); | |
250 message_loop->PostTask( | |
251 FROM_HERE, | |
252 base::Bind(&AvStreamerTest::Start, base::Unretained(this))); | |
253 message_loop->Run(); | |
254 } | |
255 | |
256 TEST_F(AvStreamerTest, SlowFastProducerConsumer) { | |
257 // Pattern lengths are prime between each other | |
258 // so that a lot of combinations can be tested. | |
259 bool provider_delayed_pattern[] = { | |
260 true, true, true, true, true, | |
261 false, false, false, false | |
262 }; | |
263 bool consumer_delayed_pattern[] = { | |
264 true, true, true, true, true, true, true, | |
265 false, false, false, false, false, false, false | |
266 }; | |
267 | |
268 const size_t frame_count = 100u; | |
269 Configure(frame_count, | |
270 std::vector<bool>( | |
271 provider_delayed_pattern, | |
272 provider_delayed_pattern + arraysize(provider_delayed_pattern)), | |
273 std::vector<bool>( | |
274 consumer_delayed_pattern, | |
275 consumer_delayed_pattern + arraysize(consumer_delayed_pattern)), | |
276 false); | |
277 | |
278 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); | |
279 message_loop->PostTask( | |
280 FROM_HERE, | |
281 base::Bind(&AvStreamerTest::Start, base::Unretained(this))); | |
282 message_loop->Run(); | |
283 } | |
284 | |
285 // Test case for when AvStreamerProxy::StopAndFlush is invoked while a previous | |
286 // flush is pending. This can happen when pipeline is stopped while a seek/flush | |
287 // is pending. | |
288 TEST_F(AvStreamerTest, StopInFlush) { | |
289 // We don't care about the delayed pattern. Setting to true to make sure the | |
290 // test won't exit before flush is called. | |
291 bool dummy_delayed_pattern[] = {true}; | |
292 std::vector<bool> dummy_delayed_pattern_vector( | |
293 dummy_delayed_pattern, | |
294 dummy_delayed_pattern + arraysize(dummy_delayed_pattern)); | |
295 const size_t frame_count = 100u; | |
296 | |
297 // Delay flush callback in frame provider | |
298 Configure(frame_count, dummy_delayed_pattern_vector, | |
299 dummy_delayed_pattern_vector, true); | |
300 | |
301 std::unique_ptr<base::MessageLoop> message_loop(new base::MessageLoop()); | |
302 | |
303 // Flush takes 10ms to finish. 1s timeout is enough for this test. | |
304 message_loop->PostDelayedTask( | |
305 FROM_HERE, | |
306 base::Bind(&AvStreamerTest::OnTestTimeout, base::Unretained(this)), | |
307 base::TimeDelta::FromSeconds(1)); | |
308 | |
309 message_loop->PostTask( | |
310 FROM_HERE, base::Bind(&AvStreamerTest::Start, base::Unretained(this))); | |
311 | |
312 // Let AvStreamerProxy run for a while. Fire flush and stop later | |
313 message_loop->PostDelayedTask( | |
314 FROM_HERE, | |
315 base::Bind(&AvStreamerTest::FlushThenStop, base::Unretained(this)), | |
316 base::TimeDelta::FromMilliseconds(10)); | |
317 | |
318 message_loop->Run(); | |
319 } | |
320 | |
321 } // namespace media | |
322 } // namespace chromecast | |
OLD | NEW |