| 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 <memory> |     7 #include <memory> | 
|     8 #include <vector> |     8 #include <vector> | 
|     9  |     9  | 
|    10 #include "base/bind.h" |    10 #include "base/bind.h" | 
| (...skipping 14 matching lines...) Expand all  Loading... | 
|    25 using ::testing::Mock; |    25 using ::testing::Mock; | 
|    26 using ::testing::Return; |    26 using ::testing::Return; | 
|    27 using ::testing::SaveArg; |    27 using ::testing::SaveArg; | 
|    28 using ::testing::StrictMock; |    28 using ::testing::StrictMock; | 
|    29 using ::testing::WithArg; |    29 using ::testing::WithArg; | 
|    30  |    30  | 
|    31 namespace media { |    31 namespace media { | 
|    32  |    32  | 
|    33 const int64_t kStartPlayingTimeInMs = 100; |    33 const int64_t kStartPlayingTimeInMs = 100; | 
|    34  |    34  | 
 |    35 ACTION_P2(SetBool, var, value) { | 
 |    36   *var = value; | 
 |    37 } | 
 |    38  | 
|    35 ACTION_P2(SetBufferingState, renderer_client, buffering_state) { |    39 ACTION_P2(SetBufferingState, renderer_client, buffering_state) { | 
|    36   (*renderer_client)->OnBufferingStateChange(buffering_state); |    40   (*renderer_client)->OnBufferingStateChange(buffering_state); | 
|    37 } |    41 } | 
|    38  |    42  | 
|    39 ACTION_P2(SetError, renderer_client, error) { |    43 ACTION_P2(SetError, renderer_client, error) { | 
|    40   (*renderer_client)->OnError(error); |    44   (*renderer_client)->OnError(error); | 
|    41 } |    45 } | 
|    42  |    46  | 
|    43 ACTION(PostCallback) { |    47 ACTION(PostCallback) { | 
|    44   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, arg0); |    48   base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, arg0); | 
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   219     if (video_stream_) { |   223     if (video_stream_) { | 
|   220       EXPECT_CALL(*video_renderer_, StartPlayingFrom(start_time)) |   224       EXPECT_CALL(*video_renderer_, StartPlayingFrom(start_time)) | 
|   221           .WillOnce(SetBufferingState(&video_renderer_client_, |   225           .WillOnce(SetBufferingState(&video_renderer_client_, | 
|   222                                       BUFFERING_HAVE_ENOUGH)); |   226                                       BUFFERING_HAVE_ENOUGH)); | 
|   223     } |   227     } | 
|   224  |   228  | 
|   225     renderer_impl_->StartPlayingFrom(start_time); |   229     renderer_impl_->StartPlayingFrom(start_time); | 
|   226     base::RunLoop().RunUntilIdle(); |   230     base::RunLoop().RunUntilIdle(); | 
|   227   } |   231   } | 
|   228  |   232  | 
|   229   void Flush(bool underflowed) { |   233   void SetFlushExpectationsForAVRenderers() { | 
|   230     if (!underflowed) |  | 
|   231       EXPECT_CALL(time_source_, StopTicking()); |  | 
|   232  |  | 
|   233     if (audio_stream_) { |   234     if (audio_stream_) { | 
|   234       EXPECT_CALL(*audio_renderer_, Flush(_)) |   235       EXPECT_CALL(*audio_renderer_, Flush(_)) | 
|   235           .WillOnce(DoAll(SetBufferingState(&audio_renderer_client_, |   236           .WillOnce(DoAll(SetBufferingState(&audio_renderer_client_, | 
|   236                                             BUFFERING_HAVE_NOTHING), |   237                                             BUFFERING_HAVE_NOTHING), | 
|   237                           RunClosure<0>())); |   238                           RunClosure<0>())); | 
|   238     } |   239     } | 
|   239  |   240  | 
|   240     if (video_stream_) { |   241     if (video_stream_) { | 
|   241       EXPECT_CALL(*video_renderer_, Flush(_)) |   242       EXPECT_CALL(*video_renderer_, Flush(_)) | 
|   242           .WillOnce(DoAll(SetBufferingState(&video_renderer_client_, |   243           .WillOnce(DoAll(SetBufferingState(&video_renderer_client_, | 
|   243                                             BUFFERING_HAVE_NOTHING), |   244                                             BUFFERING_HAVE_NOTHING), | 
|   244                           RunClosure<0>())); |   245                           RunClosure<0>())); | 
|   245     } |   246     } | 
 |   247   } | 
|   246  |   248  | 
 |   249   void Flush(bool underflowed) { | 
 |   250     if (!underflowed) | 
 |   251       EXPECT_CALL(time_source_, StopTicking()); | 
 |   252  | 
 |   253     SetFlushExpectationsForAVRenderers(); | 
|   247     EXPECT_CALL(callbacks_, OnFlushed()); |   254     EXPECT_CALL(callbacks_, OnFlushed()); | 
|   248  |   255  | 
|   249     renderer_impl_->Flush( |   256     renderer_impl_->Flush( | 
|   250         base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_))); |   257         base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_))); | 
|   251     base::RunLoop().RunUntilIdle(); |   258     base::RunLoop().RunUntilIdle(); | 
|   252   } |   259   } | 
|   253  |   260  | 
|   254   void SetPlaybackRate(double playback_rate) { |   261   void SetPlaybackRate(double playback_rate) { | 
|   255     EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate)); |   262     EXPECT_CALL(time_source_, SetPlaybackRate(playback_rate)); | 
|   256     renderer_impl_->SetPlaybackRate(playback_rate); |   263     renderer_impl_->SetPlaybackRate(playback_rate); | 
| (...skipping 587 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|   844   // The first stream status change will be processed immediately. Each status |   851   // The first stream status change will be processed immediately. Each status | 
|   845   // change processing involves Flush + StartPlaying when the Flush is done. The |   852   // change processing involves Flush + StartPlaying when the Flush is done. The | 
|   846   // Flush operation is async in this case, so the second status change will be |   853   // Flush operation is async in this case, so the second status change will be | 
|   847   // postponed by renderer until after processing the first one is finished. But |   854   // postponed by renderer until after processing the first one is finished. But | 
|   848   // we must still get two pairs of Flush/StartPlaying calls eventually. |   855   // we must still get two pairs of Flush/StartPlaying calls eventually. | 
|   849   stream_status_change_cb.Run(video_stream_.get(), false, base::TimeDelta()); |   856   stream_status_change_cb.Run(video_stream_.get(), false, base::TimeDelta()); | 
|   850   stream_status_change_cb.Run(video_stream_.get(), true, base::TimeDelta()); |   857   stream_status_change_cb.Run(video_stream_.get(), true, base::TimeDelta()); | 
|   851   base::RunLoop().Run(); |   858   base::RunLoop().Run(); | 
|   852 } |   859 } | 
|   853  |   860  | 
 |   861 // Verify that a RendererImpl::Flush gets postponed until after stream status | 
 |   862 // change handling is completed. | 
 |   863 TEST_F(RendererImplTest, FlushDuringAudioReinit) { | 
 |   864   CreateAudioAndVideoStream(); | 
 |   865  | 
 |   866   StreamStatusChangeCB stream_status_change_cb; | 
 |   867   EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) | 
 |   868       .WillOnce(SaveArg<0>(&stream_status_change_cb)); | 
 |   869   SetAudioRendererInitializeExpectations(PIPELINE_OK); | 
 |   870   SetVideoRendererInitializeExpectations(PIPELINE_OK); | 
 |   871   InitializeAndExpect(PIPELINE_OK); | 
 |   872   Play(); | 
 |   873  | 
 |   874   EXPECT_CALL(time_source_, StopTicking()).Times(testing::AnyNumber()); | 
 |   875   base::Closure audio_renderer_flush_cb; | 
 |   876   EXPECT_CALL(*audio_renderer_, Flush(_)) | 
 |   877       .WillOnce(SaveArg<0>(&audio_renderer_flush_cb)); | 
 |   878   EXPECT_CALL(*audio_renderer_, StartPlaying()) | 
 |   879       .Times(1) | 
 |   880       .WillOnce( | 
 |   881           SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH)); | 
 |   882  | 
 |   883   // This should start flushing the audio renderer (due to audio stream status | 
 |   884   // change) and should populate the |audio_renderer_flush_cb|. | 
 |   885   stream_status_change_cb.Run(audio_stream_.get(), false, base::TimeDelta()); | 
 |   886   EXPECT_TRUE(audio_renderer_flush_cb); | 
 |   887   base::RunLoop().RunUntilIdle(); | 
 |   888  | 
 |   889   bool flush_done = false; | 
 |   890  | 
 |   891   // Now that audio stream change is being handled the RendererImpl::Flush | 
 |   892   // should be postponed, instead of being executed immediately. | 
 |   893   EXPECT_CALL(callbacks_, OnFlushed()).WillOnce(SetBool(&flush_done, true)); | 
 |   894   renderer_impl_->Flush( | 
 |   895       base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_))); | 
 |   896   base::RunLoop().RunUntilIdle(); | 
 |   897   EXPECT_FALSE(flush_done); | 
 |   898  | 
 |   899   // The renderer_impl_->Flush invoked above should proceed after the first | 
 |   900   // audio renderer flush (initiated by the stream status change) completes. | 
 |   901   SetFlushExpectationsForAVRenderers(); | 
 |   902   audio_renderer_flush_cb.Run(); | 
 |   903   base::RunLoop().RunUntilIdle(); | 
 |   904   EXPECT_TRUE(flush_done); | 
 |   905 } | 
 |   906  | 
 |   907 TEST_F(RendererImplTest, FlushDuringVideoReinit) { | 
 |   908   CreateAudioAndVideoStream(); | 
 |   909  | 
 |   910   StreamStatusChangeCB stream_status_change_cb; | 
 |   911   EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) | 
 |   912       .WillOnce(SaveArg<0>(&stream_status_change_cb)); | 
 |   913   SetAudioRendererInitializeExpectations(PIPELINE_OK); | 
 |   914   SetVideoRendererInitializeExpectations(PIPELINE_OK); | 
 |   915   InitializeAndExpect(PIPELINE_OK); | 
 |   916   Play(); | 
 |   917  | 
 |   918   EXPECT_CALL(time_source_, StopTicking()).Times(testing::AnyNumber()); | 
 |   919   base::Closure video_renderer_flush_cb; | 
 |   920   EXPECT_CALL(*video_renderer_, Flush(_)) | 
 |   921       .WillOnce(SaveArg<0>(&video_renderer_flush_cb)); | 
 |   922   EXPECT_CALL(*video_renderer_, StartPlayingFrom(_)) | 
 |   923       .Times(1) | 
 |   924       .WillOnce( | 
 |   925           SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH)); | 
 |   926  | 
 |   927   // This should start flushing the video renderer (due to video stream status | 
 |   928   // change) and should populate the |video_renderer_flush_cb|. | 
 |   929   stream_status_change_cb.Run(video_stream_.get(), false, base::TimeDelta()); | 
 |   930   EXPECT_TRUE(video_renderer_flush_cb); | 
 |   931   base::RunLoop().RunUntilIdle(); | 
 |   932  | 
 |   933   bool flush_done = false; | 
 |   934  | 
 |   935   // Now that video stream change is being handled the RendererImpl::Flush | 
 |   936   // should be postponed, instead of being executed immediately. | 
 |   937   EXPECT_CALL(callbacks_, OnFlushed()).WillOnce(SetBool(&flush_done, true)); | 
 |   938   renderer_impl_->Flush( | 
 |   939       base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_))); | 
 |   940   base::RunLoop().RunUntilIdle(); | 
 |   941   EXPECT_FALSE(flush_done); | 
 |   942  | 
 |   943   // The renderer_impl_->Flush invoked above should proceed after the first | 
 |   944   // video renderer flush (initiated by the stream status change) completes. | 
 |   945   SetFlushExpectationsForAVRenderers(); | 
 |   946   video_renderer_flush_cb.Run(); | 
 |   947   base::RunLoop().RunUntilIdle(); | 
 |   948   EXPECT_TRUE(flush_done); | 
 |   949 } | 
 |   950  | 
 |   951 // Test audio track switching when the RendererImpl is in STATE_FLUSHING/FLUSHED | 
 |   952 TEST_F(RendererImplTest, AudioTrackSwitchDuringFlush) { | 
 |   953   CreateAudioAndVideoStream(); | 
 |   954   std::unique_ptr<StrictMock<MockDemuxerStream>> primary_audio_stream = | 
 |   955       std::move(audio_stream_); | 
 |   956   CreateAudioStream(); | 
 |   957   std::unique_ptr<StrictMock<MockDemuxerStream>> secondary_audio_stream = | 
 |   958       std::move(audio_stream_); | 
 |   959   audio_stream_ = std::move(primary_audio_stream); | 
 |   960  | 
 |   961   StreamStatusChangeCB stream_status_change_cb; | 
 |   962   EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) | 
 |   963       .WillOnce(SaveArg<0>(&stream_status_change_cb)); | 
 |   964   SetAudioRendererInitializeExpectations(PIPELINE_OK); | 
 |   965   SetVideoRendererInitializeExpectations(PIPELINE_OK); | 
 |   966   InitializeAndExpect(PIPELINE_OK); | 
 |   967   Play(); | 
 |   968  | 
 |   969   EXPECT_CALL(time_source_, StopTicking()).Times(testing::AnyNumber()); | 
 |   970   EXPECT_CALL(*video_renderer_, Flush(_)) | 
 |   971       .WillRepeatedly(DoAll( | 
 |   972           SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_NOTHING), | 
 |   973           RunClosure<0>())); | 
 |   974  | 
 |   975   // Initiate RendererImpl::Flush, but postpone its completion by not calling | 
 |   976   // audio renderer flush callback right away, i.e. pretending audio renderer | 
 |   977   // flush takes a while. | 
 |   978   base::Closure audio_renderer_flush_cb; | 
 |   979   EXPECT_CALL(*audio_renderer_, Flush(_)) | 
 |   980       .WillOnce(SaveArg<0>(&audio_renderer_flush_cb)); | 
 |   981   EXPECT_CALL(callbacks_, OnFlushed()); | 
 |   982   renderer_impl_->Flush( | 
 |   983       base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_))); | 
 |   984   base::RunLoop().RunUntilIdle(); | 
 |   985   EXPECT_TRUE(audio_renderer_flush_cb); | 
 |   986  | 
 |   987   // Now, while the RendererImpl::Flush is pending, perform an audio track | 
 |   988   // switch. The handling of the track switch will be postponed until after | 
 |   989   // RendererImpl::Flush completes. | 
 |   990   stream_status_change_cb.Run(audio_stream_.get(), false, base::TimeDelta()); | 
 |   991   stream_status_change_cb.Run(secondary_audio_stream.get(), true, | 
 |   992                               base::TimeDelta()); | 
 |   993  | 
 |   994   // Ensure that audio track switch occurs after Flush by verifying that the | 
 |   995   // audio renderer is reinitialized with the secondary audio stream. | 
 |   996   EXPECT_CALL(*audio_renderer_, | 
 |   997               Initialize(secondary_audio_stream.get(), _, _, _)); | 
 |   998  | 
 |   999   // Complete the audio renderer flush, thus completing the renderer_impl_ Flush | 
 |  1000   // initiated above. This will transition the RendererImpl into the FLUSHED | 
 |  1001   // state and will process pending track switch, which should result in the | 
 |  1002   // reinitialization of the audio renderer for the secondary audio stream. | 
 |  1003   audio_renderer_client_->OnBufferingStateChange(BUFFERING_HAVE_NOTHING); | 
 |  1004   audio_renderer_flush_cb.Run(); | 
 |  1005   base::RunLoop().RunUntilIdle(); | 
 |  1006 } | 
 |  1007  | 
 |  1008 // Test video track switching when the RendererImpl is in STATE_FLUSHING/FLUSHED | 
 |  1009 TEST_F(RendererImplTest, VideoTrackSwitchDuringFlush) { | 
 |  1010   CreateAudioAndVideoStream(); | 
 |  1011   std::unique_ptr<StrictMock<MockDemuxerStream>> primary_video_stream = | 
 |  1012       std::move(video_stream_); | 
 |  1013   CreateVideoStream(); | 
 |  1014   std::unique_ptr<StrictMock<MockDemuxerStream>> secondary_video_stream = | 
 |  1015       std::move(video_stream_); | 
 |  1016   video_stream_ = std::move(primary_video_stream); | 
 |  1017  | 
 |  1018   StreamStatusChangeCB stream_status_change_cb; | 
 |  1019   EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) | 
 |  1020       .WillOnce(SaveArg<0>(&stream_status_change_cb)); | 
 |  1021   SetAudioRendererInitializeExpectations(PIPELINE_OK); | 
 |  1022   SetVideoRendererInitializeExpectations(PIPELINE_OK); | 
 |  1023   InitializeAndExpect(PIPELINE_OK); | 
 |  1024   Play(); | 
 |  1025  | 
 |  1026   EXPECT_CALL(time_source_, StopTicking()).Times(testing::AnyNumber()); | 
 |  1027   EXPECT_CALL(*video_renderer_, OnTimeStopped()).Times(testing::AnyNumber()); | 
 |  1028   EXPECT_CALL(*audio_renderer_, Flush(_)) | 
 |  1029       .WillRepeatedly(DoAll( | 
 |  1030           SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_NOTHING), | 
 |  1031           RunClosure<0>())); | 
 |  1032  | 
 |  1033   // Initiate RendererImpl::Flush, but postpone its completion by not calling | 
 |  1034   // video renderer flush callback right away, i.e. pretending video renderer | 
 |  1035   // flush takes a while. | 
 |  1036   base::Closure video_renderer_flush_cb; | 
 |  1037   EXPECT_CALL(*video_renderer_, Flush(_)) | 
 |  1038       .WillOnce(SaveArg<0>(&video_renderer_flush_cb)); | 
 |  1039   EXPECT_CALL(callbacks_, OnFlushed()); | 
 |  1040   renderer_impl_->Flush( | 
 |  1041       base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_))); | 
 |  1042   base::RunLoop().RunUntilIdle(); | 
 |  1043   EXPECT_TRUE(video_renderer_flush_cb); | 
 |  1044  | 
 |  1045   // Now, while the RendererImpl::Flush is pending, perform a video track | 
 |  1046   // switch. The handling of the track switch will be postponed until after | 
 |  1047   // RendererImpl::Flush completes. | 
 |  1048   stream_status_change_cb.Run(video_stream_.get(), false, base::TimeDelta()); | 
 |  1049   stream_status_change_cb.Run(secondary_video_stream.get(), true, | 
 |  1050                               base::TimeDelta()); | 
 |  1051  | 
 |  1052   // Ensure that video track switch occurs after Flush by verifying that the | 
 |  1053   // video renderer is reinitialized with the secondary video stream. | 
 |  1054   EXPECT_CALL(*video_renderer_, | 
 |  1055               Initialize(secondary_video_stream.get(), _, _, _, _)); | 
 |  1056  | 
 |  1057   // Complete the video renderer flush, thus completing the renderer_impl_ Flush | 
 |  1058   // initiated above. This will transition the RendererImpl into the FLUSHED | 
 |  1059   // state and will process pending track switch, which should result in the | 
 |  1060   // reinitialization of the video renderer for the secondary video stream. | 
 |  1061   video_renderer_client_->OnBufferingStateChange(BUFFERING_HAVE_NOTHING); | 
 |  1062   video_renderer_flush_cb.Run(); | 
 |  1063   base::RunLoop().RunUntilIdle(); | 
 |  1064 } | 
 |  1065  | 
|   854 }  // namespace media |  1066 }  // namespace media | 
| OLD | NEW |