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