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 17 namespace media { 18 19 static const int kDefaultDurationInMs = 10000; 20 21 // Mock of MediaPlayerManager for testing purpose 22 class 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 89 class 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 179 TEST_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 189 TEST_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 208 TEST_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 229 TEST_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 251 TEST_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 269 TEST_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 294 TEST_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 323 TEST_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 357 TEST_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. 404 TEST_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 432 TEST_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