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.
8 #include "base/basictypes.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/thread_task_runner_handle.h"
13 #include "base/threading/thread.h"
14 #include "base/time/time.h"
15 #include "chromecast/media/cma/ipc/media_memory_chunk.h"
16 #include "chromecast/media/cma/ipc/media_message_fifo.h"
17 #include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h"
18 #include "chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h"
19 #include "chromecast/media/cma/test/frame_generator_for_test.h"
20 #include "chromecast/media/cma/test/mock_frame_consumer.h"
21 #include "chromecast/media/cma/test/mock_frame_provider.h"
22 #include "chromecast/public/media/cast_decoder_buffer.h"
23 #include "media/base/audio_decoder_config.h"
24 #include "media/base/decoder_buffer.h"
25 #include "media/base/video_decoder_config.h"
26 #include "testing/gtest/include/gtest/gtest.h"
28 namespace chromecast
{
33 class FifoMemoryChunk
: public MediaMemoryChunk
{
35 FifoMemoryChunk(void* mem
, size_t size
)
36 : mem_(mem
), size_(size
) {}
37 ~FifoMemoryChunk() override
{}
39 void* data() const override
{ return mem_
; }
40 size_t size() const override
{ return size_
; }
41 bool valid() const override
{ return true; }
47 DISALLOW_COPY_AND_ASSIGN(FifoMemoryChunk
);
52 class AvStreamerTest
: public testing::Test
{
55 ~AvStreamerTest() override
;
58 void Configure(size_t frame_count
,
59 const std::vector
<bool>& provider_delayed_pattern
,
60 const std::vector
<bool>& consumer_delayed_pattern
,
69 // Timeout indicates test failure
73 scoped_ptr
<uint64
[]> fifo_mem_
;
75 scoped_ptr
<AvStreamerProxy
> av_buffer_proxy_
;
76 scoped_ptr
<CodedFrameProviderHost
> coded_frame_provider_host_
;
77 scoped_ptr
<MockFrameConsumer
> frame_consumer_
;
79 // number of pending cb in StopAndFlush
80 int stop_and_flush_cb_count_
;
83 void OnTestCompleted();
88 void OnStopAndFlush();
90 DISALLOW_COPY_AND_ASSIGN(AvStreamerTest
);
93 AvStreamerTest::AvStreamerTest() {
96 AvStreamerTest::~AvStreamerTest() {
99 void AvStreamerTest::Configure(
101 const std::vector
<bool>& provider_delayed_pattern
,
102 const std::vector
<bool>& consumer_delayed_pattern
,
104 // Frame generation on the producer and consumer side.
105 std::vector
<FrameGeneratorForTest::FrameSpec
> frame_specs
;
106 frame_specs
.resize(frame_count
);
107 for (size_t k
= 0; k
< frame_specs
.size() - 1; k
++) {
108 frame_specs
[k
].has_config
= (k
== 0);
109 frame_specs
[k
].timestamp
= base::TimeDelta::FromMilliseconds(40) * k
;
110 frame_specs
[k
].size
= 512;
111 frame_specs
[k
].has_decrypt_config
= ((k
% 3) == 0);
113 frame_specs
[frame_specs
.size() - 1].is_eos
= true;
115 scoped_ptr
<FrameGeneratorForTest
> frame_generator_provider(
116 new FrameGeneratorForTest(frame_specs
));
117 scoped_ptr
<FrameGeneratorForTest
> frame_generator_consumer(
118 new FrameGeneratorForTest(frame_specs
));
120 scoped_ptr
<MockFrameProvider
> frame_provider(new MockFrameProvider());
121 frame_provider
->Configure(provider_delayed_pattern
,
122 frame_generator_provider
.Pass());
123 frame_provider
->SetDelayFlush(delay_flush
);
125 size_t fifo_size_div_8
= 512;
126 fifo_mem_
.reset(new uint64
[fifo_size_div_8
]);
127 scoped_ptr
<MediaMessageFifo
> producer_fifo(
128 new MediaMessageFifo(
129 scoped_ptr
<MediaMemoryChunk
>(
130 new FifoMemoryChunk(&fifo_mem_
[0], fifo_size_div_8
* 8)),
132 scoped_ptr
<MediaMessageFifo
> consumer_fifo(
133 new MediaMessageFifo(
134 scoped_ptr
<MediaMemoryChunk
>(
135 new FifoMemoryChunk(&fifo_mem_
[0], fifo_size_div_8
* 8)),
137 producer_fifo
->ObserveWriteActivity(
138 base::Bind(&AvStreamerTest::OnFifoWrite
, base::Unretained(this)));
139 consumer_fifo
->ObserveReadActivity(
140 base::Bind(&AvStreamerTest::OnFifoRead
, base::Unretained(this)));
142 av_buffer_proxy_
.reset(
143 new AvStreamerProxy());
144 av_buffer_proxy_
->SetCodedFrameProvider(
145 scoped_ptr
<CodedFrameProvider
>(frame_provider
.release()));
146 av_buffer_proxy_
->SetMediaMessageFifo(producer_fifo
.Pass());
148 coded_frame_provider_host_
.reset(
149 new CodedFrameProviderHost(consumer_fifo
.Pass()));
151 frame_consumer_
.reset(
152 new MockFrameConsumer(coded_frame_provider_host_
.get()));
153 frame_consumer_
->Configure(
154 consumer_delayed_pattern
,
156 frame_generator_consumer
.Pass());
158 stop_and_flush_cb_count_
= 0;
161 void AvStreamerTest::Start() {
162 base::ThreadTaskRunnerHandle::Get()->PostTask(
163 FROM_HERE
, base::Bind(&AvStreamerProxy::Start
,
164 base::Unretained(av_buffer_proxy_
.get())));
166 frame_consumer_
->Start(
167 base::Bind(&AvStreamerTest::OnTestCompleted
,
168 base::Unretained(this)));
171 void AvStreamerTest::FlushThenStop() {
173 base::Bind(&AvStreamerTest::OnStopAndFlush
, base::Unretained(this));
175 stop_and_flush_cb_count_
++;
176 av_buffer_proxy_
->StopAndFlush(cb
);
178 ASSERT_EQ(stop_and_flush_cb_count_
, 1);
180 stop_and_flush_cb_count_
++;
181 av_buffer_proxy_
->StopAndFlush(cb
);
184 void AvStreamerTest::OnTestTimeout() {
185 ADD_FAILURE() << "Test timed out";
186 if (base::MessageLoop::current())
187 base::MessageLoop::current()->QuitWhenIdle();
190 void AvStreamerTest::OnTestCompleted() {
191 base::MessageLoop::current()->QuitWhenIdle();
194 void AvStreamerTest::OnFifoWrite() {
195 base::ThreadTaskRunnerHandle::Get()->PostTask(
197 base::Bind(&CodedFrameProviderHost::OnFifoWriteEvent
,
198 base::Unretained(coded_frame_provider_host_
.get())));
201 void AvStreamerTest::OnFifoRead() {
202 base::ThreadTaskRunnerHandle::Get()->PostTask(
203 FROM_HERE
, base::Bind(&AvStreamerProxy::OnFifoReadEvent
,
204 base::Unretained(av_buffer_proxy_
.get())));
207 void AvStreamerTest::OnStopAndFlush() {
208 stop_and_flush_cb_count_
--;
209 if (stop_and_flush_cb_count_
== 0) {
214 TEST_F(AvStreamerTest
, FastProviderSlowConsumer
) {
215 bool provider_delayed_pattern
[] = { false };
216 bool consumer_delayed_pattern
[] = { true };
218 const size_t frame_count
= 100u;
219 Configure(frame_count
,
221 provider_delayed_pattern
,
222 provider_delayed_pattern
+ arraysize(provider_delayed_pattern
)),
224 consumer_delayed_pattern
,
225 consumer_delayed_pattern
+ arraysize(consumer_delayed_pattern
)),
228 scoped_ptr
<base::MessageLoop
> message_loop(new base::MessageLoop());
229 message_loop
->PostTask(
231 base::Bind(&AvStreamerTest::Start
, base::Unretained(this)));
235 TEST_F(AvStreamerTest
, SlowProviderFastConsumer
) {
236 bool provider_delayed_pattern
[] = { true };
237 bool consumer_delayed_pattern
[] = { false };
239 const size_t frame_count
= 100u;
240 Configure(frame_count
,
242 provider_delayed_pattern
,
243 provider_delayed_pattern
+ arraysize(provider_delayed_pattern
)),
245 consumer_delayed_pattern
,
246 consumer_delayed_pattern
+ arraysize(consumer_delayed_pattern
)),
249 scoped_ptr
<base::MessageLoop
> message_loop(new base::MessageLoop());
250 message_loop
->PostTask(
252 base::Bind(&AvStreamerTest::Start
, base::Unretained(this)));
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
263 bool consumer_delayed_pattern
[] = {
264 true, true, true, true, true, true, true,
265 false, false, false, false, false, false, false
268 const size_t frame_count
= 100u;
269 Configure(frame_count
,
271 provider_delayed_pattern
,
272 provider_delayed_pattern
+ arraysize(provider_delayed_pattern
)),
274 consumer_delayed_pattern
,
275 consumer_delayed_pattern
+ arraysize(consumer_delayed_pattern
)),
278 scoped_ptr
<base::MessageLoop
> message_loop(new base::MessageLoop());
279 message_loop
->PostTask(
281 base::Bind(&AvStreamerTest::Start
, base::Unretained(this)));
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
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;
297 // Delay flush callback in frame provider
298 Configure(frame_count
, dummy_delayed_pattern_vector
,
299 dummy_delayed_pattern_vector
, true);
301 scoped_ptr
<base::MessageLoop
> message_loop(new base::MessageLoop());
303 // Flush takes 10ms to finish. 1s timeout is enough for this test.
304 message_loop
->PostDelayedTask(
306 base::Bind(&AvStreamerTest::OnTestTimeout
, base::Unretained(this)),
307 base::TimeDelta::FromSeconds(1));
309 message_loop
->PostTask(
310 FROM_HERE
, base::Bind(&AvStreamerTest::Start
, base::Unretained(this)));
312 // Let AvStreamerProxy run for a while. Fire flush and stop later
313 message_loop
->PostDelayedTask(
315 base::Bind(&AvStreamerTest::FlushThenStop
, base::Unretained(this)),
316 base::TimeDelta::FromMilliseconds(10));
322 } // namespace chromecast