OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <stdint.h> | 5 #include <stdint.h> |
6 | 6 |
7 #include <vector> | 7 #include <vector> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
46 CallbackHelper() {} | 46 CallbackHelper() {} |
47 virtual ~CallbackHelper() {} | 47 virtual ~CallbackHelper() {} |
48 | 48 |
49 MOCK_METHOD1(OnInitialize, void(PipelineStatus)); | 49 MOCK_METHOD1(OnInitialize, void(PipelineStatus)); |
50 MOCK_METHOD0(OnFlushed, void()); | 50 MOCK_METHOD0(OnFlushed, void()); |
51 MOCK_METHOD0(OnEnded, void()); | 51 MOCK_METHOD0(OnEnded, void()); |
52 MOCK_METHOD1(OnError, void(PipelineStatus)); | 52 MOCK_METHOD1(OnError, void(PipelineStatus)); |
53 MOCK_METHOD1(OnUpdateStatistics, void(const PipelineStatistics&)); | 53 MOCK_METHOD1(OnUpdateStatistics, void(const PipelineStatistics&)); |
54 MOCK_METHOD1(OnBufferingStateChange, void(BufferingState)); | 54 MOCK_METHOD1(OnBufferingStateChange, void(BufferingState)); |
55 MOCK_METHOD0(OnWaitingForDecryptionKey, void()); | 55 MOCK_METHOD0(OnWaitingForDecryptionKey, void()); |
| 56 MOCK_METHOD1(OnCdmAttached, void(bool)); |
56 | 57 |
57 private: | 58 private: |
58 DISALLOW_COPY_AND_ASSIGN(CallbackHelper); | 59 DISALLOW_COPY_AND_ASSIGN(CallbackHelper); |
59 }; | 60 }; |
60 | 61 |
61 RendererImplTest() | 62 RendererImplTest() |
62 : demuxer_(new StrictMock<MockDemuxer>()), | 63 : demuxer_(new StrictMock<MockDemuxer>()), |
63 video_renderer_(new StrictMock<MockVideoRenderer>()), | 64 video_renderer_(new StrictMock<MockVideoRenderer>()), |
64 audio_renderer_(new StrictMock<MockAudioRenderer>()), | 65 audio_renderer_(new StrictMock<MockAudioRenderer>()), |
65 renderer_impl_( | 66 renderer_impl_( |
66 new RendererImpl(message_loop_.task_runner(), | 67 new RendererImpl(message_loop_.task_runner(), |
67 scoped_ptr<AudioRenderer>(audio_renderer_), | 68 scoped_ptr<AudioRenderer>(audio_renderer_), |
68 scoped_ptr<VideoRenderer>(video_renderer_))) { | 69 scoped_ptr<VideoRenderer>(video_renderer_))), |
| 70 cdm_context_(new StrictMock<MockCdmContext>()), |
| 71 initialization_status_(PIPELINE_ERROR_OPERATION_PENDING) { |
69 // SetDemuxerExpectations() adds overriding expectations for expected | 72 // SetDemuxerExpectations() adds overriding expectations for expected |
70 // non-NULL streams. | 73 // non-NULL streams. |
71 DemuxerStream* null_pointer = NULL; | 74 DemuxerStream* null_pointer = NULL; |
72 EXPECT_CALL(*demuxer_, GetStream(_)) | 75 EXPECT_CALL(*demuxer_, GetStream(_)) |
73 .WillRepeatedly(Return(null_pointer)); | 76 .WillRepeatedly(Return(null_pointer)); |
74 } | 77 } |
75 | 78 |
76 virtual ~RendererImplTest() { | 79 virtual ~RendererImplTest() { Destroy(); } |
| 80 |
| 81 protected: |
| 82 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; |
| 83 |
| 84 void Destroy() { |
77 renderer_impl_.reset(); | 85 renderer_impl_.reset(); |
78 base::RunLoop().RunUntilIdle(); | 86 base::RunLoop().RunUntilIdle(); |
79 } | 87 } |
80 | 88 |
81 protected: | |
82 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; | |
83 | |
84 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream( | 89 scoped_ptr<StrictMock<MockDemuxerStream> > CreateStream( |
85 DemuxerStream::Type type) { | 90 DemuxerStream::Type type) { |
86 scoped_ptr<StrictMock<MockDemuxerStream> > stream( | 91 scoped_ptr<StrictMock<MockDemuxerStream> > stream( |
87 new StrictMock<MockDemuxerStream>(type)); | 92 new StrictMock<MockDemuxerStream>(type)); |
88 return stream; | 93 return stream; |
89 } | 94 } |
90 | 95 |
91 // Sets up expectations to allow the audio renderer to initialize. | 96 // Sets up expectations to allow the audio renderer to initialize. |
92 void SetAudioRendererInitializeExpectations(PipelineStatus status) { | 97 void SetAudioRendererInitializeExpectations(PipelineStatus status) { |
93 EXPECT_CALL(*audio_renderer_, | 98 EXPECT_CALL(*audio_renderer_, |
94 Initialize(audio_stream_.get(), _, _, _, _, _, _, _)) | 99 Initialize(audio_stream_.get(), _, _, _, _, _, _, _)) |
95 .WillOnce(DoAll(SaveArg<4>(&audio_buffering_state_cb_), | 100 .WillOnce(DoAll(SaveArg<4>(&audio_buffering_state_cb_), |
96 SaveArg<5>(&audio_ended_cb_), | 101 SaveArg<5>(&audio_ended_cb_), |
97 SaveArg<6>(&audio_error_cb_), RunCallback<1>(status))); | 102 SaveArg<6>(&audio_error_cb_), RunCallback<1>(status))); |
98 } | 103 } |
99 | 104 |
100 // Sets up expectations to allow the video renderer to initialize. | 105 // Sets up expectations to allow the video renderer to initialize. |
101 void SetVideoRendererInitializeExpectations(PipelineStatus status) { | 106 void SetVideoRendererInitializeExpectations(PipelineStatus status) { |
102 EXPECT_CALL(*video_renderer_, | 107 EXPECT_CALL(*video_renderer_, |
103 Initialize(video_stream_.get(), _, _, _, _, _, _, _, _)) | 108 Initialize(video_stream_.get(), _, _, _, _, _, _, _, _)) |
104 .WillOnce(DoAll(SaveArg<4>(&video_buffering_state_cb_), | 109 .WillOnce(DoAll(SaveArg<4>(&video_buffering_state_cb_), |
105 SaveArg<5>(&video_ended_cb_), RunCallback<1>(status))); | 110 SaveArg<5>(&video_ended_cb_), RunCallback<1>(status))); |
106 } | 111 } |
107 | 112 |
108 void InitializeAndExpect(PipelineStatus start_status) { | 113 void InitializeAndExpect(PipelineStatus start_status) { |
109 EXPECT_CALL(callbacks_, OnInitialize(start_status)); | 114 EXPECT_CALL(callbacks_, OnInitialize(start_status)) |
| 115 .WillOnce(SaveArg<0>(&initialization_status_)); |
110 EXPECT_CALL(callbacks_, OnWaitingForDecryptionKey()).Times(0); | 116 EXPECT_CALL(callbacks_, OnWaitingForDecryptionKey()).Times(0); |
111 | 117 |
112 if (start_status == PIPELINE_OK && audio_stream_) { | 118 if (start_status == PIPELINE_OK && audio_stream_) { |
113 EXPECT_CALL(*audio_renderer_, GetTimeSource()) | 119 EXPECT_CALL(*audio_renderer_, GetTimeSource()) |
114 .WillOnce(Return(&time_source_)); | 120 .WillOnce(Return(&time_source_)); |
115 } else { | 121 } else { |
116 renderer_impl_->set_time_source_for_testing(&time_source_); | 122 renderer_impl_->set_time_source_for_testing(&time_source_); |
117 } | 123 } |
118 | 124 |
119 renderer_impl_->Initialize( | 125 renderer_impl_->Initialize( |
(...skipping 11 matching lines...) Expand all Loading... |
131 base::RunLoop().RunUntilIdle(); | 137 base::RunLoop().RunUntilIdle(); |
132 } | 138 } |
133 | 139 |
134 void CreateAudioStream() { | 140 void CreateAudioStream() { |
135 audio_stream_ = CreateStream(DemuxerStream::AUDIO); | 141 audio_stream_ = CreateStream(DemuxerStream::AUDIO); |
136 streams_.push_back(audio_stream_.get()); | 142 streams_.push_back(audio_stream_.get()); |
137 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO)) | 143 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO)) |
138 .WillRepeatedly(Return(audio_stream_.get())); | 144 .WillRepeatedly(Return(audio_stream_.get())); |
139 } | 145 } |
140 | 146 |
141 void CreateVideoStream() { | 147 void CreateVideoStream(bool is_encrypted = false) { |
142 video_stream_ = CreateStream(DemuxerStream::VIDEO); | 148 video_stream_ = CreateStream(DemuxerStream::VIDEO); |
143 video_stream_->set_video_decoder_config(video_decoder_config_); | 149 video_stream_->set_video_decoder_config( |
| 150 is_encrypted ? TestVideoConfig::NormalEncrypted() |
| 151 : TestVideoConfig::Normal()); |
144 streams_.push_back(video_stream_.get()); | 152 streams_.push_back(video_stream_.get()); |
145 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO)) | 153 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO)) |
146 .WillRepeatedly(Return(video_stream_.get())); | 154 .WillRepeatedly(Return(video_stream_.get())); |
147 } | 155 } |
148 | 156 |
| 157 void CreateEncryptedVideoStream() { CreateVideoStream(true); } |
| 158 |
149 void CreateAudioAndVideoStream() { | 159 void CreateAudioAndVideoStream() { |
150 CreateAudioStream(); | 160 CreateAudioStream(); |
151 CreateVideoStream(); | 161 CreateVideoStream(); |
152 } | 162 } |
153 | 163 |
154 void InitializeWithAudio() { | 164 void InitializeWithAudio() { |
155 CreateAudioStream(); | 165 CreateAudioStream(); |
156 SetAudioRendererInitializeExpectations(PIPELINE_OK); | 166 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
157 InitializeAndExpect(PIPELINE_OK); | 167 InitializeAndExpect(PIPELINE_OK); |
158 } | 168 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
241 return true; | 251 return true; |
242 | 252 |
243 DCHECK_EQ(start_time_ms, GetMediaTimeMs()); | 253 DCHECK_EQ(start_time_ms, GetMediaTimeMs()); |
244 return false; | 254 return false; |
245 } | 255 } |
246 | 256 |
247 bool IsMediaTimeAdvancing() { | 257 bool IsMediaTimeAdvancing() { |
248 return IsMediaTimeAdvancing(1.0); | 258 return IsMediaTimeAdvancing(1.0); |
249 } | 259 } |
250 | 260 |
| 261 void SetCdmAndExpect(bool expected_result) { |
| 262 EXPECT_CALL(callbacks_, OnCdmAttached(expected_result)); |
| 263 renderer_impl_->SetCdm(cdm_context_.get(), |
| 264 base::Bind(&CallbackHelper::OnCdmAttached, |
| 265 base::Unretained(&callbacks_))); |
| 266 base::RunLoop().RunUntilIdle(); |
| 267 } |
| 268 |
251 // Fixture members. | 269 // Fixture members. |
252 base::MessageLoop message_loop_; | 270 base::MessageLoop message_loop_; |
253 StrictMock<CallbackHelper> callbacks_; | 271 StrictMock<CallbackHelper> callbacks_; |
254 base::SimpleTestTickClock test_tick_clock_; | 272 base::SimpleTestTickClock test_tick_clock_; |
255 | 273 |
256 scoped_ptr<StrictMock<MockDemuxer> > demuxer_; | 274 scoped_ptr<StrictMock<MockDemuxer> > demuxer_; |
257 StrictMock<MockVideoRenderer>* video_renderer_; | 275 StrictMock<MockVideoRenderer>* video_renderer_; |
258 StrictMock<MockAudioRenderer>* audio_renderer_; | 276 StrictMock<MockAudioRenderer>* audio_renderer_; |
259 scoped_ptr<RendererImpl> renderer_impl_; | 277 scoped_ptr<RendererImpl> renderer_impl_; |
| 278 scoped_ptr<StrictMock<MockCdmContext>> cdm_context_; |
260 | 279 |
261 StrictMock<MockTimeSource> time_source_; | 280 StrictMock<MockTimeSource> time_source_; |
262 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_; | 281 scoped_ptr<StrictMock<MockDemuxerStream> > audio_stream_; |
263 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_; | 282 scoped_ptr<StrictMock<MockDemuxerStream> > video_stream_; |
264 MockDemuxerStreamVector streams_; | 283 MockDemuxerStreamVector streams_; |
265 BufferingStateCB audio_buffering_state_cb_; | 284 BufferingStateCB audio_buffering_state_cb_; |
266 BufferingStateCB video_buffering_state_cb_; | 285 BufferingStateCB video_buffering_state_cb_; |
267 base::Closure audio_ended_cb_; | 286 base::Closure audio_ended_cb_; |
268 base::Closure video_ended_cb_; | 287 base::Closure video_ended_cb_; |
269 PipelineStatusCB audio_error_cb_; | 288 PipelineStatusCB audio_error_cb_; |
270 VideoDecoderConfig video_decoder_config_; | 289 VideoDecoderConfig video_decoder_config_; |
| 290 PipelineStatus initialization_status_; |
271 | 291 |
272 private: | 292 private: |
273 DISALLOW_COPY_AND_ASSIGN(RendererImplTest); | 293 DISALLOW_COPY_AND_ASSIGN(RendererImplTest); |
274 }; | 294 }; |
275 | 295 |
276 TEST_F(RendererImplTest, DestroyBeforeInitialize) { | 296 TEST_F(RendererImplTest, Destroy_BeforeInitialize) { |
277 // |renderer_impl_| will be destroyed in the dtor. | 297 Destroy(); |
| 298 } |
| 299 |
| 300 TEST_F(RendererImplTest, Destroy_PendingInitialize) { |
| 301 CreateAudioAndVideoStream(); |
| 302 |
| 303 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
| 304 // Not returning the video initialization callback. |
| 305 EXPECT_CALL(*video_renderer_, |
| 306 Initialize(video_stream_.get(), _, _, _, _, _, _, _, _)); |
| 307 |
| 308 InitializeAndExpect(PIPELINE_ERROR_ABORT); |
| 309 EXPECT_EQ(PIPELINE_ERROR_OPERATION_PENDING, initialization_status_); |
| 310 |
| 311 Destroy(); |
| 312 } |
| 313 |
| 314 TEST_F(RendererImplTest, Destroy_PendingInitializeWithoutCdm) { |
| 315 CreateAudioStream(); |
| 316 CreateEncryptedVideoStream(); |
| 317 |
| 318 // Audio is clear and video is encrypted. Initialization will not start |
| 319 // because no CDM is set. So neither AudioRenderer::Initialize() nor |
| 320 // VideoRenderer::Initialize() should not be called. The InitCB will be |
| 321 // aborted when |renderer_impl_| is destructed. |
| 322 InitializeAndExpect(PIPELINE_ERROR_ABORT); |
| 323 EXPECT_EQ(PIPELINE_ERROR_OPERATION_PENDING, initialization_status_); |
| 324 |
| 325 Destroy(); |
| 326 } |
| 327 |
| 328 TEST_F(RendererImplTest, Destroy_PendingInitializeAfterSetCdm) { |
| 329 CreateAudioStream(); |
| 330 CreateEncryptedVideoStream(); |
| 331 |
| 332 // Audio is clear and video is encrypted. Initialization will not start |
| 333 // because no CDM is set. |
| 334 InitializeAndExpect(PIPELINE_ERROR_ABORT); |
| 335 EXPECT_EQ(PIPELINE_ERROR_OPERATION_PENDING, initialization_status_); |
| 336 |
| 337 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
| 338 // Not returning the video initialization callback. So initialization will |
| 339 // be pending. |
| 340 EXPECT_CALL(*video_renderer_, |
| 341 Initialize(video_stream_.get(), _, _, _, _, _, _, _, _)); |
| 342 |
| 343 // SetCdm() will trigger the initialization to start. But it will not complete |
| 344 // because the |video_renderer_| is not returning the initialization callback. |
| 345 SetCdmAndExpect(false); |
| 346 EXPECT_EQ(PIPELINE_ERROR_OPERATION_PENDING, initialization_status_); |
| 347 |
| 348 Destroy(); |
278 } | 349 } |
279 | 350 |
280 TEST_F(RendererImplTest, InitializeWithAudio) { | 351 TEST_F(RendererImplTest, InitializeWithAudio) { |
281 InitializeWithAudio(); | 352 InitializeWithAudio(); |
282 } | 353 } |
283 | 354 |
284 TEST_F(RendererImplTest, InitializeWithVideo) { | 355 TEST_F(RendererImplTest, InitializeWithVideo) { |
285 InitializeWithVideo(); | 356 InitializeWithVideo(); |
286 } | 357 } |
287 | 358 |
(...skipping 20 matching lines...) Expand all Loading... |
308 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED); | 379 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED); |
309 } | 380 } |
310 | 381 |
311 TEST_F(RendererImplTest, InitializeWithAudioVideo_VideoRendererFailed) { | 382 TEST_F(RendererImplTest, InitializeWithAudioVideo_VideoRendererFailed) { |
312 CreateAudioAndVideoStream(); | 383 CreateAudioAndVideoStream(); |
313 SetAudioRendererInitializeExpectations(PIPELINE_OK); | 384 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
314 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED); | 385 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED); |
315 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED); | 386 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED); |
316 } | 387 } |
317 | 388 |
| 389 TEST_F(RendererImplTest, SetCdmBeforeInitialize) { |
| 390 // CDM will be successfully attached immediately if set before RendererImpl |
| 391 // initialization, regardless of the later initialization result. |
| 392 SetCdmAndExpect(true); |
| 393 } |
| 394 |
| 395 TEST_F(RendererImplTest, SetCdmAfterInitialize_ClearStream) { |
| 396 InitializeWithAudioAndVideo(); |
| 397 EXPECT_EQ(PIPELINE_OK, initialization_status_); |
| 398 |
| 399 // CDM will be successfully attached immediately since initialization is |
| 400 // completed. |
| 401 SetCdmAndExpect(true); |
| 402 } |
| 403 |
| 404 TEST_F(RendererImplTest, SetCdmAfterInitialize_EncryptedStream_Success) { |
| 405 CreateAudioStream(); |
| 406 CreateEncryptedVideoStream(); |
| 407 |
| 408 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
| 409 SetVideoRendererInitializeExpectations(PIPELINE_OK); |
| 410 InitializeAndExpect(PIPELINE_OK); |
| 411 // Initialization is pending until CDM is set. |
| 412 EXPECT_EQ(PIPELINE_ERROR_OPERATION_PENDING, initialization_status_); |
| 413 |
| 414 SetCdmAndExpect(true); |
| 415 EXPECT_EQ(PIPELINE_OK, initialization_status_); |
| 416 } |
| 417 |
| 418 TEST_F(RendererImplTest, SetCdmAfterInitialize_EncryptedStream_Failure) { |
| 419 CreateAudioStream(); |
| 420 CreateEncryptedVideoStream(); |
| 421 |
| 422 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
| 423 SetVideoRendererInitializeExpectations(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 424 InitializeAndExpect(PIPELINE_ERROR_INITIALIZATION_FAILED); |
| 425 // Initialization is pending until CDM is set. |
| 426 EXPECT_EQ(PIPELINE_ERROR_OPERATION_PENDING, initialization_status_); |
| 427 |
| 428 SetCdmAndExpect(false); |
| 429 EXPECT_EQ(PIPELINE_ERROR_INITIALIZATION_FAILED, initialization_status_); |
| 430 } |
| 431 |
| 432 TEST_F(RendererImplTest, SetCdmMultipleTimes) { |
| 433 SetCdmAndExpect(true); |
| 434 SetCdmAndExpect(false); // Do not support switching CDM. |
| 435 } |
| 436 |
318 TEST_F(RendererImplTest, StartPlayingFrom) { | 437 TEST_F(RendererImplTest, StartPlayingFrom) { |
319 InitializeWithAudioAndVideo(); | 438 InitializeWithAudioAndVideo(); |
320 Play(); | 439 Play(); |
321 } | 440 } |
322 | 441 |
323 TEST_F(RendererImplTest, StartPlayingFromWithPlaybackRate) { | 442 TEST_F(RendererImplTest, StartPlayingFromWithPlaybackRate) { |
324 InitializeWithAudioAndVideo(); | 443 InitializeWithAudioAndVideo(); |
325 | 444 |
326 // Play with a zero playback rate shouldn't start time. | 445 // Play with a zero playback rate shouldn't start time. |
327 Play(); | 446 Play(); |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 .WillOnce( | 718 .WillOnce( |
600 SetBufferingState(&audio_buffering_state_cb_, BUFFERING_HAVE_ENOUGH)); | 719 SetBufferingState(&audio_buffering_state_cb_, BUFFERING_HAVE_ENOUGH)); |
601 EXPECT_CALL(*video_renderer_, StartPlayingFrom(kStartTime)); | 720 EXPECT_CALL(*video_renderer_, StartPlayingFrom(kStartTime)); |
602 renderer_impl_->StartPlayingFrom(kStartTime); | 721 renderer_impl_->StartPlayingFrom(kStartTime); |
603 | 722 |
604 // Nothing else should primed on the message loop. | 723 // Nothing else should primed on the message loop. |
605 base::RunLoop().RunUntilIdle(); | 724 base::RunLoop().RunUntilIdle(); |
606 } | 725 } |
607 | 726 |
608 } // namespace media | 727 } // namespace media |
OLD | NEW |