1// Copyright 2013 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 <string>
6
7#include "base/basictypes.h"
8#include "base/memory/scoped_ptr.h"
9#include "media/base/android/media_codec_bridge.h"
10#include "media/base/android/media_player_manager.h"
11#include "media/base/android/media_source_player.h"
12#include "media/base/decoder_buffer.h"
13#include "media/base/test_data_util.h"
14#include "testing/gmock/include/gmock/gmock.h"
15#include "ui/gl/android/surface_texture_bridge.h"
16
17namespace media {
18
19static const int kDefaultDurationInMs = 10000;
20
21// Mock of MediaPlayerManager for testing purpose
22class MockMediaPlayerManager : public MediaPlayerManager {
23 public:
24  MockMediaPlayerManager() : num_requests_(0), last_seek_request_id_(0) {}
25  virtual ~MockMediaPlayerManager() {};
26
27  // MediaPlayerManager implementation.
28  virtual void RequestMediaResources(int player_id) OVERRIDE {}
29  virtual void ReleaseMediaResources(int player_id) OVERRIDE {}
30  virtual MediaResourceGetter* GetMediaResourceGetter() OVERRIDE {
31    return NULL;
32  }
33  virtual void OnTimeUpdate(int player_id,
34                            base::TimeDelta current_time) OVERRIDE {}
35  virtual void OnMediaMetadataChanged(
36      int player_id, base::TimeDelta duration, int width, int height,
37      bool success) OVERRIDE {}
38  virtual void OnPlaybackComplete(int player_id) OVERRIDE {
39    if (message_loop_.is_running())
40      message_loop_.Quit();
41  }
42  virtual void OnMediaInterrupted(int player_id) OVERRIDE {}
43  virtual void OnBufferingUpdate(int player_id, int percentage) OVERRIDE {}
44  virtual void OnSeekComplete(int player_id,
45                              base::TimeDelta current_time) OVERRIDE {}
46  virtual void OnError(int player_id, int error) OVERRIDE {}
47  virtual void OnVideoSizeChanged(int player_id, int width,
48                                  int height) OVERRIDE {}
49  virtual MediaPlayerAndroid* GetFullscreenPlayer() OVERRIDE { return NULL; }
50  virtual MediaPlayerAndroid* GetPlayer(int player_id) OVERRIDE { return NULL; }
51  virtual void DestroyAllMediaPlayers() OVERRIDE {}
52  virtual void OnReadFromDemuxer(int player_id,
53                                 media::DemuxerStream::Type type) OVERRIDE {
54    num_requests_++;
55    if (message_loop_.is_running())
56      message_loop_.Quit();
57  }
58  virtual void OnMediaSeekRequest(int player_id, base::TimeDelta time_to_seek,
59                                  unsigned seek_request_id) OVERRIDE {
60    last_seek_request_id_ = seek_request_id;
61  }
62  virtual void OnMediaConfigRequest(int player_id) OVERRIDE {}
63  virtual media::MediaDrmBridge* GetDrmBridge(int media_keys_id) OVERRIDE {
64    return NULL;
65  }
66  virtual void OnProtectedSurfaceRequested(int player_id) OVERRIDE {}
67  virtual void OnKeyAdded(int key_id,
68                          const std::string& session_id) OVERRIDE {}
69  virtual void OnKeyError(int key_id,
70                          const std::string& session_id,
71                          media::MediaKeys::KeyError error_code,
72                          int system_code) OVERRIDE {}
73  virtual void OnKeyMessage(int key_id,
74                            const std::string& session_id,
75                            const std::vector<uint8>& message,
76                            const std::string& destination_url) OVERRIDE {}
77
78  int num_requests() const { return num_requests_; }
79  unsigned last_seek_request_id() const { return last_seek_request_id_; }
80  base::MessageLoop* message_loop() { return &message_loop_; }
81
82 private:
83  // The number of request this object sents for decoding data.
84  int num_requests_;
85  unsigned last_seek_request_id_;
86  base::MessageLoop message_loop_;
87};
88
89class MediaSourcePlayerTest : public testing::Test {
90 public:
91  MediaSourcePlayerTest() {
92    manager_.reset(new MockMediaPlayerManager());
93    player_.reset(new MediaSourcePlayer(0, manager_.get()));
94  }
95  virtual ~MediaSourcePlayerTest() {}
96
97 protected:
98  // Get the decoder job from the MediaSourcePlayer.
99  MediaDecoderJob* GetMediaDecoderJob(bool is_audio) {
100    if (is_audio) {
101      return reinterpret_cast<MediaDecoderJob*>(
102          player_->audio_decoder_job_.get());
103    }
104    return reinterpret_cast<MediaDecoderJob*>(
105        player_->video_decoder_job_.get());
106  }
107
108  // Starts an audio decoder job.
109  void StartAudioDecoderJob() {
110    MediaPlayerHostMsg_DemuxerReady_Params params;
111    params.audio_codec = kCodecVorbis;
112    params.audio_channels = 2;
113    params.audio_sampling_rate = 44100;
114    params.is_audio_encrypted = false;
115    params.duration_ms = kDefaultDurationInMs;
116    scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vorbis-extradata");
117    params.audio_extra_data = std::vector<uint8>(
118        buffer->data(),
119        buffer->data() + buffer->data_size());
120    Start(params);
121  }
122
123  void StartVideoDecoderJob() {
124    MediaPlayerHostMsg_DemuxerReady_Params params;
125    params.video_codec = kCodecVP8;
126    params.video_size = gfx::Size(320, 240);
127    params.is_video_encrypted = false;
128    params.duration_ms = kDefaultDurationInMs;
129    Start(params);
130  }
131
132  // Starts decoding the data.
133  void Start(const MediaPlayerHostMsg_DemuxerReady_Params& params) {
134    player_->DemuxerReady(params);
135    player_->Start();
136  }
137
138  MediaPlayerHostMsg_ReadFromDemuxerAck_Params
139      CreateReadFromDemuxerAckForAudio() {
140    MediaPlayerHostMsg_ReadFromDemuxerAck_Params ack_params;
141    ack_params.type = DemuxerStream::AUDIO;
142    ack_params.access_units.resize(1);
143    ack_params.access_units[0].status = DemuxerStream::kOk;
144    scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vorbis-packet-0");
145    ack_params.access_units[0].data = std::vector<uint8>(
146        buffer->data(), buffer->data() + buffer->data_size());
147    // Vorbis needs 4 extra bytes padding on Android to decode properly. Check
148    // NuMediaExtractor.cpp in Android source code.
149    uint8 padding[4] = { 0xff , 0xff , 0xff , 0xff };
150    ack_params.access_units[0].data.insert(
151        ack_params.access_units[0].data.end(), padding, padding + 4);
152    return ack_params;
153  }
154
155  MediaPlayerHostMsg_ReadFromDemuxerAck_Params
156        CreateReadFromDemuxerAckForVideo() {
157    MediaPlayerHostMsg_ReadFromDemuxerAck_Params ack_params;
158    ack_params.type = DemuxerStream::VIDEO;
159    ack_params.access_units.resize(1);
160    ack_params.access_units[0].status = DemuxerStream::kOk;
161    scoped_refptr<DecoderBuffer> buffer =
162        ReadTestDataFile("vp8-I-frame-320x240");
163    ack_params.access_units[0].data = std::vector<uint8>(
164        buffer->data(), buffer->data() + buffer->data_size());
165    return ack_params;
166  }
167
168  base::TimeTicks StartTimeTicks() {
169    return player_->start_time_ticks_;
170  }
171
172 protected:
173  scoped_ptr<MockMediaPlayerManager> manager_;
174  scoped_ptr<MediaSourcePlayer> player_;
175
176  DISALLOW_COPY_AND_ASSIGN(MediaSourcePlayerTest);
177};
178
179TEST_F(MediaSourcePlayerTest, StartAudioDecoderWithValidConfig) {
180  if (!MediaCodecBridge::IsAvailable())
181    return;
182
183  // Test audio decoder job will be created when codec is successfully started.
184  StartAudioDecoderJob();
185  EXPECT_TRUE(NULL != GetMediaDecoderJob(true));
186  EXPECT_EQ(1, manager_->num_requests());
187}
188
189TEST_F(MediaSourcePlayerTest, StartAudioDecoderWithInvalidConfig) {
190  if (!MediaCodecBridge::IsAvailable())
191    return;
192
193  // Test audio decoder job will not be created when failed to start the codec.
194  MediaPlayerHostMsg_DemuxerReady_Params params;
195  params.audio_codec = kCodecVorbis;
196  params.audio_channels = 2;
197  params.audio_sampling_rate = 44100;
198  params.is_audio_encrypted = false;
199  params.duration_ms = kDefaultDurationInMs;
200  uint8 invalid_codec_data[] = { 0x00, 0xff, 0xff, 0xff, 0xff };
201  params.audio_extra_data.insert(params.audio_extra_data.begin(),
202                                 invalid_codec_data, invalid_codec_data + 4);
203  Start(params);
204  EXPECT_EQ(NULL, GetMediaDecoderJob(true));
205  EXPECT_EQ(0, manager_->num_requests());
206}
207
208TEST_F(MediaSourcePlayerTest, StartVideoCodecWithValidSurface) {
209  if (!MediaCodecBridge::IsAvailable())
210    return;
211
212  // Test video decoder job will be created when surface is valid.
213  scoped_refptr<gfx::SurfaceTextureBridge> surface_texture(
214      new gfx::SurfaceTextureBridge(0));
215  gfx::ScopedJavaSurface surface(surface_texture.get());
216  StartVideoDecoderJob();
217  // Video decoder job will not be created until surface is available.
218  EXPECT_EQ(NULL, GetMediaDecoderJob(false));
219  EXPECT_EQ(0, manager_->num_requests());
220
221  player_->SetVideoSurface(surface.Pass());
222  EXPECT_EQ(1u, manager_->last_seek_request_id());
223  player_->OnSeekRequestAck(manager_->last_seek_request_id());
224  // The decoder job should be ready now.
225  EXPECT_TRUE(NULL != GetMediaDecoderJob(false));
226  EXPECT_EQ(1, manager_->num_requests());
227}
228
229TEST_F(MediaSourcePlayerTest, StartVideoCodecWithInvalidSurface) {
230  if (!MediaCodecBridge::IsAvailable())
231    return;
232
233  // Test video decoder job will be created when surface is valid.
234  scoped_refptr<gfx::SurfaceTextureBridge> surface_texture(
235      new gfx::SurfaceTextureBridge(0));
236  gfx::ScopedJavaSurface surface(surface_texture.get());
237  StartVideoDecoderJob();
238  // Video decoder job will not be created until surface is available.
239  EXPECT_EQ(NULL, GetMediaDecoderJob(false));
240  EXPECT_EQ(0, manager_->num_requests());
241
242  // Release the surface texture.
243  surface_texture = NULL;
244  player_->SetVideoSurface(surface.Pass());
245  EXPECT_EQ(1u, manager_->last_seek_request_id());
246  player_->OnSeekRequestAck(manager_->last_seek_request_id());
247  EXPECT_EQ(NULL, GetMediaDecoderJob(false));
248  EXPECT_EQ(0, manager_->num_requests());
249}
250
251TEST_F(MediaSourcePlayerTest, ReadFromDemuxerAfterSeek) {
252  if (!MediaCodecBridge::IsAvailable())
253    return;
254
255  // Test decoder job will resend a ReadFromDemuxer request after seek.
256  StartAudioDecoderJob();
257  EXPECT_TRUE(NULL != GetMediaDecoderJob(true));
258  EXPECT_EQ(1, manager_->num_requests());
259
260  // Initiate a seek
261  player_->SeekTo(base::TimeDelta());
262  EXPECT_EQ(1u, manager_->last_seek_request_id());
263  // Sending back the seek ACK, this should trigger the player to call
264  // OnReadFromDemuxer() again.
265  player_->OnSeekRequestAck(manager_->last_seek_request_id());
266  EXPECT_EQ(2, manager_->num_requests());
267}
268
269TEST_F(MediaSourcePlayerTest, SetSurfaceWhileSeeking) {
270  if (!MediaCodecBridge::IsAvailable())
271    return;
272
273  // Test SetVideoSurface() will not cause an extra seek while the player is
274  // waiting for a seek ACK.
275  scoped_refptr<gfx::SurfaceTextureBridge> surface_texture(
276      new gfx::SurfaceTextureBridge(0));
277  gfx::ScopedJavaSurface surface(surface_texture.get());
278  StartVideoDecoderJob();
279  // Player is still waiting for SetVideoSurface(), so no request is sent.
280  EXPECT_EQ(0, manager_->num_requests());
281  player_->SeekTo(base::TimeDelta());
282  EXPECT_EQ(1u, manager_->last_seek_request_id());
283
284  player_->SetVideoSurface(surface.Pass());
285  EXPECT_TRUE(NULL == GetMediaDecoderJob(false));
286  EXPECT_EQ(1u, manager_->last_seek_request_id());
287
288  // Send the seek ack, player should start requesting data afterwards.
289  player_->OnSeekRequestAck(manager_->last_seek_request_id());
290  EXPECT_TRUE(NULL != GetMediaDecoderJob(false));
291  EXPECT_EQ(1, manager_->num_requests());
292}
293
294TEST_F(MediaSourcePlayerTest, StartAfterSeekFinish) {
295  if (!MediaCodecBridge::IsAvailable())
296    return;
297
298  // Test decoder job will not start until all pending seek event is handled.
299  MediaPlayerHostMsg_DemuxerReady_Params params;
300  params.audio_codec = kCodecVorbis;
301  params.audio_channels = 2;
302  params.audio_sampling_rate = 44100;
303  params.is_audio_encrypted = false;
304  params.duration_ms = kDefaultDurationInMs;
305  player_->DemuxerReady(params);
306  EXPECT_EQ(NULL, GetMediaDecoderJob(true));
307  EXPECT_EQ(0, manager_->num_requests());
308
309  // Initiate a seek
310  player_->SeekTo(base::TimeDelta());
311  EXPECT_EQ(1u, manager_->last_seek_request_id());
312
313  player_->Start();
314  EXPECT_EQ(NULL, GetMediaDecoderJob(true));
315  EXPECT_EQ(0, manager_->num_requests());
316
317  // Sending back the seek ACK.
318  player_->OnSeekRequestAck(manager_->last_seek_request_id());
319  EXPECT_TRUE(NULL != GetMediaDecoderJob(true));
320  EXPECT_EQ(1, manager_->num_requests());
321}
322
323TEST_F(MediaSourcePlayerTest, StartImmediatelyAfterPause) {
324  if (!MediaCodecBridge::IsAvailable())
325    return;
326
327  // Test that if the decoding job is not fully stopped after Pause(),
328  // calling Start() will be a noop.
329  StartAudioDecoderJob();
330
331  MediaDecoderJob* decoder_job = GetMediaDecoderJob(true);
332  EXPECT_TRUE(NULL != decoder_job);
333  EXPECT_EQ(1, manager_->num_requests());
334  EXPECT_FALSE(GetMediaDecoderJob(true)->is_decoding());
335
336  // Sending data to player.
337  player_->ReadFromDemuxerAck(CreateReadFromDemuxerAckForAudio());
338  EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding());
339
340  // Decoder job will not immediately stop after Pause() since it is
341  // running on another thread.
342  player_->Pause();
343  EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding());
344
345  // Nothing happens when calling Start() again.
346  player_->Start();
347  // Verify that Start() will not destroy and recreate the decoder job.
348  EXPECT_EQ(decoder_job, GetMediaDecoderJob(true));
349  EXPECT_EQ(1, manager_->num_requests());
350  EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding());
351  manager_->message_loop()->Run();
352  // The decoder job should finish and a new request will be sent.
353  EXPECT_EQ(2, manager_->num_requests());
354  EXPECT_FALSE(GetMediaDecoderJob(true)->is_decoding());
355}
356
357TEST_F(MediaSourcePlayerTest, DecoderJobsCannotStartWithoutAudio) {
358  if (!MediaCodecBridge::IsAvailable())
359    return;
360
361  // Test that when Start() is called, video decoder jobs will wait for audio
362  // decoder job before start decoding the data.
363  MediaPlayerHostMsg_DemuxerReady_Params params;
364  params.audio_codec = kCodecVorbis;
365  params.audio_channels = 2;
366  params.audio_sampling_rate = 44100;
367  params.is_audio_encrypted = false;
368  scoped_refptr<DecoderBuffer> buffer = ReadTestDataFile("vorbis-extradata");
369  params.audio_extra_data = std::vector<uint8>(
370      buffer->data(),
371      buffer->data() + buffer->data_size());
372  params.video_codec = kCodecVP8;
373  params.video_size = gfx::Size(320, 240);
374  params.is_video_encrypted = false;
375  params.duration_ms = kDefaultDurationInMs;
376  Start(params);
377  EXPECT_EQ(0, manager_->num_requests());
378
379  scoped_refptr<gfx::SurfaceTextureBridge> surface_texture(
380      new gfx::SurfaceTextureBridge(0));
381  gfx::ScopedJavaSurface surface(surface_texture.get());
382  player_->SetVideoSurface(surface.Pass());
383  EXPECT_EQ(1u, manager_->last_seek_request_id());
384  player_->OnSeekRequestAck(manager_->last_seek_request_id());
385
386  MediaDecoderJob* audio_decoder_job = GetMediaDecoderJob(true);
387  MediaDecoderJob* video_decoder_job = GetMediaDecoderJob(false);
388  EXPECT_EQ(2, manager_->num_requests());
389  EXPECT_FALSE(audio_decoder_job->is_decoding());
390  EXPECT_FALSE(video_decoder_job->is_decoding());
391
392  // Sending audio data to player, audio decoder should not start.
393  player_->ReadFromDemuxerAck(CreateReadFromDemuxerAckForVideo());
394  EXPECT_FALSE(video_decoder_job->is_decoding());
395
396  // Sending video data to player, both decoders should start now.
397  player_->ReadFromDemuxerAck(CreateReadFromDemuxerAckForAudio());
398  EXPECT_TRUE(audio_decoder_job->is_decoding());
399  EXPECT_TRUE(video_decoder_job->is_decoding());
400}
401
402// Disabled due to http://crbug.com/266041.
403// TODO(xhwang/qinmin): Fix this test and reenable it.
404TEST_F(MediaSourcePlayerTest,
405       DISABLED_StartTimeTicksResetAfterDecoderUnderruns) {
406  if (!MediaCodecBridge::IsAvailable())
407    return;
408
409  // Test start time ticks will reset after decoder job underruns.
410  StartAudioDecoderJob();
411  EXPECT_TRUE(NULL != GetMediaDecoderJob(true));
412  EXPECT_EQ(1, manager_->num_requests());
413  player_->ReadFromDemuxerAck(CreateReadFromDemuxerAckForAudio());
414  EXPECT_TRUE(GetMediaDecoderJob(true)->is_decoding());
415
416  manager_->message_loop()->Run();
417  // The decoder job should finish and a new request will be sent.
418  EXPECT_EQ(2, manager_->num_requests());
419  EXPECT_FALSE(GetMediaDecoderJob(true)->is_decoding());
420  base::TimeTicks previous = StartTimeTicks();
421
422  // Let the decoder timeout and execute the OnDecoderStarved() callback.
423  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(100));
424  manager_->message_loop()->RunUntilIdle();
425
426  // Send new data to the decoder. This should reset the start time ticks.
427  player_->ReadFromDemuxerAck(CreateReadFromDemuxerAckForAudio());
428  base::TimeTicks current = StartTimeTicks();
429  EXPECT_LE(100.0, (current - previous).InMillisecondsF());
430}
431
432TEST_F(MediaSourcePlayerTest, NoRequestForDataAfterInputEOS) {
433  if (!MediaCodecBridge::IsAvailable())
434    return;
435
436  // Test MediaSourcePlayer will not request for new data after input EOS is
437  // reached.
438  scoped_refptr<gfx::SurfaceTextureBridge> surface_texture(
439      new gfx::SurfaceTextureBridge(0));
440  gfx::ScopedJavaSurface surface(surface_texture.get());
441  player_->SetVideoSurface(surface.Pass());
442  StartVideoDecoderJob();
443  player_->OnSeekRequestAck(manager_->last_seek_request_id());
444  EXPECT_EQ(1, manager_->num_requests());
445  // Send the first input chunk.
446  player_->ReadFromDemuxerAck(CreateReadFromDemuxerAckForVideo());
447  manager_->message_loop()->Run();
448  EXPECT_EQ(2, manager_->num_requests());
449
450  // Send EOS.
451  MediaPlayerHostMsg_ReadFromDemuxerAck_Params ack_params;
452  ack_params.type = DemuxerStream::VIDEO;
453  ack_params.access_units.resize(1);
454  ack_params.access_units[0].status = DemuxerStream::kOk;
455  ack_params.access_units[0].end_of_stream = true;
456  player_->ReadFromDemuxerAck(ack_params);
457  manager_->message_loop()->Run();
458  // No more request for data should be made.
459  EXPECT_EQ(2, manager_->num_requests());
460}
461
462}  // namespace media
463