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 <list>
6#include <vector>
7
8#include "base/basictypes.h"
9#include "base/bind.h"
10#include "base/memory/ref_counted.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/threading/thread.h"
13#include "base/time/time.h"
14#include "chromecast/media/cma/base/decoder_buffer_base.h"
15#include "chromecast/media/cma/base/frame_generator_for_test.h"
16#include "chromecast/media/cma/base/mock_frame_consumer.h"
17#include "chromecast/media/cma/base/mock_frame_provider.h"
18#include "chromecast/media/cma/ipc/media_memory_chunk.h"
19#include "chromecast/media/cma/ipc/media_message_fifo.h"
20#include "chromecast/media/cma/ipc_streamer/av_streamer_proxy.h"
21#include "chromecast/media/cma/ipc_streamer/coded_frame_provider_host.h"
22#include "media/base/audio_decoder_config.h"
23#include "media/base/decoder_buffer.h"
24#include "media/base/video_decoder_config.h"
25#include "testing/gtest/include/gtest/gtest.h"
26
27namespace chromecast {
28namespace media {
29
30namespace {
31
32class FifoMemoryChunk : public MediaMemoryChunk {
33 public:
34  FifoMemoryChunk(void* mem, size_t size)
35      : mem_(mem), size_(size) {}
36  virtual ~FifoMemoryChunk() {}
37
38  virtual void* data() const OVERRIDE { return mem_; }
39  virtual size_t size() const OVERRIDE { return size_; }
40  virtual bool valid() const OVERRIDE { return true; }
41
42 private:
43  void* mem_;
44  size_t size_;
45
46  DISALLOW_COPY_AND_ASSIGN(FifoMemoryChunk);
47};
48
49}  // namespace
50
51class AvStreamerTest : public testing::Test {
52 public:
53  AvStreamerTest();
54  virtual ~AvStreamerTest();
55
56  // Setups the test.
57  void Configure(
58      size_t frame_count,
59      const std::vector<bool>& provider_delayed_pattern,
60      const std::vector<bool>& consumer_delayed_pattern);
61
62  // Starts the test.
63  void Start();
64
65 protected:
66  scoped_ptr<uint64[]> fifo_mem_;
67
68  scoped_ptr<AvStreamerProxy> av_buffer_proxy_;
69  scoped_ptr<CodedFrameProviderHost> coded_frame_provider_host_;
70  scoped_ptr<MockFrameConsumer> frame_consumer_;
71
72 private:
73  void OnTestTimeout();
74  void OnTestCompleted();
75
76  void OnFifoRead();
77  void OnFifoWrite();
78
79  DISALLOW_COPY_AND_ASSIGN(AvStreamerTest);
80};
81
82AvStreamerTest::AvStreamerTest() {
83}
84
85AvStreamerTest::~AvStreamerTest() {
86}
87
88void AvStreamerTest::Configure(
89    size_t frame_count,
90    const std::vector<bool>& provider_delayed_pattern,
91    const std::vector<bool>& consumer_delayed_pattern) {
92  // Frame generation on the producer and consumer side.
93  std::vector<FrameGeneratorForTest::FrameSpec> frame_specs;
94  frame_specs.resize(frame_count);
95  for (size_t k = 0; k < frame_specs.size() - 1; k++) {
96    frame_specs[k].has_config = (k == 0);
97    frame_specs[k].timestamp = base::TimeDelta::FromMilliseconds(40) * k;
98    frame_specs[k].size = 512;
99    frame_specs[k].has_decrypt_config = ((k % 3) == 0);
100  }
101  frame_specs[frame_specs.size() - 1].is_eos = true;
102
103  scoped_ptr<FrameGeneratorForTest> frame_generator_provider(
104      new FrameGeneratorForTest(frame_specs));
105  scoped_ptr<FrameGeneratorForTest> frame_generator_consumer(
106      new FrameGeneratorForTest(frame_specs));
107
108  scoped_ptr<MockFrameProvider> frame_provider(new MockFrameProvider());
109  frame_provider->Configure(provider_delayed_pattern,
110                            frame_generator_provider.Pass());
111
112  size_t fifo_size_div_8 = 512;
113  fifo_mem_.reset(new uint64[fifo_size_div_8]);
114  scoped_ptr<MediaMessageFifo> producer_fifo(
115      new MediaMessageFifo(
116          scoped_ptr<MediaMemoryChunk>(
117              new FifoMemoryChunk(&fifo_mem_[0], fifo_size_div_8 * 8)),
118          true));
119  scoped_ptr<MediaMessageFifo> consumer_fifo(
120      new MediaMessageFifo(
121          scoped_ptr<MediaMemoryChunk>(
122              new FifoMemoryChunk(&fifo_mem_[0], fifo_size_div_8 * 8)),
123          false));
124  producer_fifo->ObserveWriteActivity(
125      base::Bind(&AvStreamerTest::OnFifoWrite, base::Unretained(this)));
126  consumer_fifo->ObserveReadActivity(
127      base::Bind(&AvStreamerTest::OnFifoRead, base::Unretained(this)));
128
129  av_buffer_proxy_.reset(
130      new AvStreamerProxy());
131  av_buffer_proxy_->SetCodedFrameProvider(
132      scoped_ptr<CodedFrameProvider>(frame_provider.release()));
133  av_buffer_proxy_->SetMediaMessageFifo(producer_fifo.Pass());
134
135  coded_frame_provider_host_.reset(
136      new CodedFrameProviderHost(consumer_fifo.Pass()));
137
138  frame_consumer_.reset(
139      new MockFrameConsumer(coded_frame_provider_host_.get()));
140  frame_consumer_->Configure(
141      consumer_delayed_pattern,
142      false,
143      frame_generator_consumer.Pass());
144}
145
146void AvStreamerTest::Start() {
147  base::MessageLoopProxy::current()->PostTask(
148      FROM_HERE,
149      base::Bind(&AvStreamerProxy::Start,
150                 base::Unretained(av_buffer_proxy_.get())));
151
152  frame_consumer_->Start(
153      base::Bind(&AvStreamerTest::OnTestCompleted,
154                 base::Unretained(this)));
155}
156
157void AvStreamerTest::OnTestTimeout() {
158  ADD_FAILURE() << "Test timed out";
159  if (base::MessageLoop::current())
160    base::MessageLoop::current()->QuitWhenIdle();
161}
162
163void AvStreamerTest::OnTestCompleted() {
164  base::MessageLoop::current()->QuitWhenIdle();
165}
166
167void AvStreamerTest::OnFifoWrite() {
168  base::MessageLoopProxy::current()->PostTask(
169      FROM_HERE,
170      base::Bind(&CodedFrameProviderHost::OnFifoWriteEvent,
171                 base::Unretained(coded_frame_provider_host_.get())));
172}
173
174void AvStreamerTest::OnFifoRead() {
175  base::MessageLoopProxy::current()->PostTask(
176      FROM_HERE,
177      base::Bind(&AvStreamerProxy::OnFifoReadEvent,
178                 base::Unretained(av_buffer_proxy_.get())));
179}
180
181TEST_F(AvStreamerTest, FastProviderSlowConsumer) {
182  bool provider_delayed_pattern[] = { false };
183  bool consumer_delayed_pattern[] = { true };
184
185  const size_t frame_count = 100u;
186  Configure(
187      frame_count,
188      std::vector<bool>(
189          provider_delayed_pattern,
190          provider_delayed_pattern + arraysize(provider_delayed_pattern)),
191      std::vector<bool>(
192          consumer_delayed_pattern,
193          consumer_delayed_pattern + arraysize(consumer_delayed_pattern)));
194
195  scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
196  message_loop->PostTask(
197      FROM_HERE,
198      base::Bind(&AvStreamerTest::Start, base::Unretained(this)));
199  message_loop->Run();
200};
201
202TEST_F(AvStreamerTest, SlowProviderFastConsumer) {
203  bool provider_delayed_pattern[] = { true };
204  bool consumer_delayed_pattern[] = { false };
205
206  const size_t frame_count = 100u;
207  Configure(
208      frame_count,
209      std::vector<bool>(
210          provider_delayed_pattern,
211          provider_delayed_pattern + arraysize(provider_delayed_pattern)),
212      std::vector<bool>(
213          consumer_delayed_pattern,
214          consumer_delayed_pattern + arraysize(consumer_delayed_pattern)));
215
216  scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
217  message_loop->PostTask(
218      FROM_HERE,
219      base::Bind(&AvStreamerTest::Start, base::Unretained(this)));
220  message_loop->Run();
221};
222
223TEST_F(AvStreamerTest, SlowFastProducerConsumer) {
224  // Pattern lengths are prime between each other
225  // so that a lot of combinations can be tested.
226  bool provider_delayed_pattern[] = {
227    true, true, true, true, true,
228    false, false, false, false
229  };
230  bool consumer_delayed_pattern[] = {
231    true, true, true, true, true, true, true,
232    false, false, false, false, false, false, false
233  };
234
235  const size_t frame_count = 100u;
236  Configure(
237      frame_count,
238      std::vector<bool>(
239          provider_delayed_pattern,
240          provider_delayed_pattern + arraysize(provider_delayed_pattern)),
241      std::vector<bool>(
242          consumer_delayed_pattern,
243          consumer_delayed_pattern + arraysize(consumer_delayed_pattern)));
244
245  scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
246  message_loop->PostTask(
247      FROM_HERE,
248      base::Bind(&AvStreamerTest::Start, base::Unretained(this)));
249  message_loop->Run();
250};
251
252}  // namespace media
253}  // namespace chromecast
254