Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chromecast / media / cma / filters / demuxer_stream_adapter_unittest.cc
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
7 #include "base/basictypes.h"
8 #include "base/bind.h"
9 #include "base/memory/ref_counted.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/threading/thread.h"
12 #include "base/time/time.h"
13 #include "chromecast/media/cma/base/balanced_media_task_runner_factory.h"
14 #include "chromecast/media/cma/base/decoder_buffer_base.h"
15 #include "chromecast/media/cma/filters/demuxer_stream_adapter.h"
16 #include "media/base/audio_decoder_config.h"
17 #include "media/base/decoder_buffer.h"
18 #include "media/base/demuxer_stream.h"
19 #include "media/base/video_decoder_config.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 namespace chromecast {
23 namespace media {
24
25 namespace {
26
27 class DummyDemuxerStream : public ::media::DemuxerStream {
28  public:
29   // Creates a demuxer stream which provides frames either with a delay
30   // or instantly. The scheduling pattern is the following:
31   // - provides |delayed_frame_count| frames with a delay,
32   // - then provides the following |cycle_count| - |delayed_frame_count|
33   //   instantly,
34   // - then provides |delayed_frame_count| frames with a delay,
35   // - ... and so on.
36   // Special cases:
37   // - all frames are delayed: |delayed_frame_count| = |cycle_count|
38   // - all frames are provided instantly: |delayed_frame_count| = 0
39   // |config_idx| is a list of frame index before which there is
40   // a change of decoder configuration.
41   DummyDemuxerStream(int cycle_count,
42                      int delayed_frame_count,
43                      const std::list<int>& config_idx);
44   virtual ~DummyDemuxerStream();
45
46   // ::media::DemuxerStream implementation.
47   virtual void Read(const ReadCB& read_cb) override;
48   virtual ::media::AudioDecoderConfig audio_decoder_config() override;
49   virtual ::media::VideoDecoderConfig video_decoder_config() override;
50   virtual Type type() override;
51   virtual bool SupportsConfigChanges() override;
52   virtual ::media::VideoRotation video_rotation() override;
53
54   bool has_pending_read() const {
55     return has_pending_read_;
56   }
57
58  private:
59   void DoRead(const ReadCB& read_cb);
60
61   // Demuxer configuration.
62   const int cycle_count_;
63   const int delayed_frame_count_;
64   std::list<int> config_idx_;
65
66   // Number of frames sent so far.
67   int frame_count_;
68
69   bool has_pending_read_;
70
71   DISALLOW_COPY_AND_ASSIGN(DummyDemuxerStream);
72 };
73
74 DummyDemuxerStream::DummyDemuxerStream(
75     int cycle_count,
76     int delayed_frame_count,
77     const std::list<int>& config_idx)
78   : cycle_count_(cycle_count),
79     delayed_frame_count_(delayed_frame_count),
80     config_idx_(config_idx),
81     frame_count_(0),
82     has_pending_read_(false) {
83   DCHECK_LE(delayed_frame_count, cycle_count);
84 }
85
86 DummyDemuxerStream::~DummyDemuxerStream() {
87 }
88
89 void DummyDemuxerStream::Read(const ReadCB& read_cb) {
90   has_pending_read_ = true;
91   if (!config_idx_.empty() && config_idx_.front() == frame_count_) {
92     config_idx_.pop_front();
93     has_pending_read_ = false;
94     read_cb.Run(kConfigChanged,
95                 scoped_refptr< ::media::DecoderBuffer>());
96     return;
97   }
98
99   if ((frame_count_ % cycle_count_) < delayed_frame_count_) {
100     base::MessageLoopProxy::current()->PostDelayedTask(
101         FROM_HERE,
102         base::Bind(&DummyDemuxerStream::DoRead, base::Unretained(this),
103                    read_cb),
104         base::TimeDelta::FromMilliseconds(20));
105     return;
106   }
107   DoRead(read_cb);
108 }
109
110 ::media::AudioDecoderConfig DummyDemuxerStream::audio_decoder_config() {
111   LOG(FATAL) << "DummyDemuxerStream is a video DemuxerStream";
112   return ::media::AudioDecoderConfig();
113 }
114
115 ::media::VideoDecoderConfig DummyDemuxerStream::video_decoder_config() {
116   gfx::Size coded_size(640, 480);
117   gfx::Rect visible_rect(640, 480);
118   gfx::Size natural_size(640, 480);
119   return ::media::VideoDecoderConfig(
120       ::media::kCodecH264,
121       ::media::VIDEO_CODEC_PROFILE_UNKNOWN,
122       ::media::VideoFrame::YV12,
123       coded_size,
124       visible_rect,
125       natural_size,
126       NULL, 0,
127       false);
128 }
129
130 ::media::DemuxerStream::Type DummyDemuxerStream::type() {
131   return VIDEO;
132 }
133
134 bool DummyDemuxerStream::SupportsConfigChanges() {
135   return true;
136 }
137
138 ::media::VideoRotation DummyDemuxerStream::video_rotation() {
139   return ::media::VIDEO_ROTATION_0;
140 }
141
142 void DummyDemuxerStream::DoRead(const ReadCB& read_cb) {
143   has_pending_read_ = false;
144   scoped_refptr< ::media::DecoderBuffer> buffer(
145       new ::media::DecoderBuffer(16));
146   buffer->set_timestamp(frame_count_ * base::TimeDelta::FromMilliseconds(40));
147   frame_count_++;
148   read_cb.Run(kOk, buffer);
149 }
150
151 }  // namespace
152
153 class DemuxerStreamAdapterTest : public testing::Test {
154  public:
155   DemuxerStreamAdapterTest();
156   virtual ~DemuxerStreamAdapterTest();
157
158   void Initialize(::media::DemuxerStream* demuxer_stream);
159   void Start();
160
161  protected:
162   void OnTestTimeout();
163   void OnNewFrame(const scoped_refptr<DecoderBufferBase>& buffer,
164                   const ::media::AudioDecoderConfig& audio_config,
165                   const ::media::VideoDecoderConfig& video_config);
166   void OnFlushCompleted();
167
168   // Total number of frames to request.
169   int total_frames_;
170
171   // Number of demuxer read before issuing an early flush.
172   int early_flush_idx_;
173   bool use_post_task_for_flush_;
174
175   // Number of expected read frames.
176   int total_expected_frames_;
177
178   // Number of frames actually read so far.
179   int frame_received_count_;
180
181   // List of expected frame indices with decoder config changes.
182   std::list<int> config_idx_;
183
184   scoped_ptr<DummyDemuxerStream> demuxer_stream_;
185
186   scoped_ptr<CodedFrameProvider> coded_frame_provider_;
187
188   DISALLOW_COPY_AND_ASSIGN(DemuxerStreamAdapterTest);
189 };
190
191 DemuxerStreamAdapterTest::DemuxerStreamAdapterTest()
192     : use_post_task_for_flush_(false) {
193 }
194
195 DemuxerStreamAdapterTest::~DemuxerStreamAdapterTest() {
196 }
197
198 void DemuxerStreamAdapterTest::Initialize(
199     ::media::DemuxerStream* demuxer_stream) {
200   coded_frame_provider_.reset(
201       new DemuxerStreamAdapter(
202           base::MessageLoopProxy::current(),
203           scoped_refptr<BalancedMediaTaskRunnerFactory>(),
204           demuxer_stream));
205 }
206
207 void DemuxerStreamAdapterTest::Start() {
208   frame_received_count_ = 0;
209
210   // TODO(damienv): currently, test assertions which fail do not trigger the
211   // exit of the unit test, the message loop is still running. Find a different
212   // way to exit the unit test.
213   base::MessageLoop::current()->PostDelayedTask(
214       FROM_HERE,
215       base::Bind(&DemuxerStreamAdapterTest::OnTestTimeout,
216                  base::Unretained(this)),
217       base::TimeDelta::FromSeconds(5));
218
219   coded_frame_provider_->Read(
220       base::Bind(&DemuxerStreamAdapterTest::OnNewFrame,
221                  base::Unretained(this)));
222 }
223
224 void DemuxerStreamAdapterTest::OnTestTimeout() {
225   ADD_FAILURE() << "Test timed out";
226   if (base::MessageLoop::current())
227     base::MessageLoop::current()->QuitWhenIdle();
228 }
229
230 void DemuxerStreamAdapterTest::OnNewFrame(
231     const scoped_refptr<DecoderBufferBase>& buffer,
232     const ::media::AudioDecoderConfig& audio_config,
233     const ::media::VideoDecoderConfig& video_config) {
234   if (video_config.IsValidConfig()) {
235     ASSERT_GT(config_idx_.size(), 0);
236     ASSERT_EQ(frame_received_count_, config_idx_.front());
237     config_idx_.pop_front();
238   }
239
240   ASSERT_TRUE(buffer.get() != NULL);
241   ASSERT_EQ(buffer->timestamp(),
242             frame_received_count_ * base::TimeDelta::FromMilliseconds(40));
243   frame_received_count_++;
244
245   if (frame_received_count_ >= total_frames_) {
246     coded_frame_provider_->Flush(
247         base::Bind(&DemuxerStreamAdapterTest::OnFlushCompleted,
248                    base::Unretained(this)));
249     return;
250   }
251
252   coded_frame_provider_->Read(
253       base::Bind(&DemuxerStreamAdapterTest::OnNewFrame,
254                  base::Unretained(this)));
255
256   ASSERT_LE(frame_received_count_, early_flush_idx_);
257   if (frame_received_count_ == early_flush_idx_) {
258     base::Closure flush_cb =
259         base::Bind(&DemuxerStreamAdapterTest::OnFlushCompleted,
260                    base::Unretained(this));
261     if (use_post_task_for_flush_) {
262       base::MessageLoop::current()->PostTask(
263           FROM_HERE,
264           base::Bind(&CodedFrameProvider::Flush,
265                      base::Unretained(coded_frame_provider_.get()),
266                      flush_cb));
267     } else {
268       coded_frame_provider_->Flush(flush_cb);
269     }
270     return;
271   }
272 }
273
274 void DemuxerStreamAdapterTest::OnFlushCompleted() {
275   ASSERT_EQ(frame_received_count_, total_expected_frames_);
276   ASSERT_FALSE(demuxer_stream_->has_pending_read());
277   base::MessageLoop::current()->QuitWhenIdle();
278 }
279
280 TEST_F(DemuxerStreamAdapterTest, NoDelay) {
281   total_frames_ = 10;
282   early_flush_idx_ = total_frames_;   // No early flush.
283   total_expected_frames_ = 10;
284   config_idx_.push_back(0);
285   config_idx_.push_back(5);
286
287   int cycle_count = 1;
288   int delayed_frame_count = 0;
289   demuxer_stream_.reset(
290       new DummyDemuxerStream(
291           cycle_count, delayed_frame_count, config_idx_));
292
293   scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
294   Initialize(demuxer_stream_.get());
295   message_loop->PostTask(
296       FROM_HERE,
297       base::Bind(&DemuxerStreamAdapterTest::Start, base::Unretained(this)));
298   message_loop->Run();
299 }
300
301 TEST_F(DemuxerStreamAdapterTest, AllDelayed) {
302   total_frames_ = 10;
303   early_flush_idx_ = total_frames_;   // No early flush.
304   total_expected_frames_ = 10;
305   config_idx_.push_back(0);
306   config_idx_.push_back(5);
307
308   int cycle_count = 1;
309   int delayed_frame_count = 1;
310   demuxer_stream_.reset(
311       new DummyDemuxerStream(
312           cycle_count, delayed_frame_count, config_idx_));
313
314   scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
315   Initialize(demuxer_stream_.get());
316   message_loop->PostTask(
317       FROM_HERE,
318       base::Bind(&DemuxerStreamAdapterTest::Start, base::Unretained(this)));
319   message_loop->Run();
320 }
321
322 TEST_F(DemuxerStreamAdapterTest, AllDelayedEarlyFlush) {
323   total_frames_ = 10;
324   early_flush_idx_ = 5;
325   use_post_task_for_flush_ = true;
326   total_expected_frames_ = 5;
327   config_idx_.push_back(0);
328   config_idx_.push_back(3);
329
330   int cycle_count = 1;
331   int delayed_frame_count = 1;
332   demuxer_stream_.reset(
333       new DummyDemuxerStream(
334           cycle_count, delayed_frame_count, config_idx_));
335
336   scoped_ptr<base::MessageLoop> message_loop(new base::MessageLoop());
337   Initialize(demuxer_stream_.get());
338   message_loop->PostTask(
339       FROM_HERE,
340       base::Bind(&DemuxerStreamAdapterTest::Start, base::Unretained(this)));
341   message_loop->Run();
342 }
343
344 }  // namespace media
345 }  // namespace chromecast