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_F(RendererImplTest, AudioTrackSwitchDuringFlush) { | |
952 CreateAudioAndVideoStream(); | |
953 std::unique_ptr<StrictMock<MockDemuxerStream>> primary_audio_stream = | |
954 std::move(audio_stream_); | |
955 CreateAudioStream(); | |
956 std::unique_ptr<StrictMock<MockDemuxerStream>> secondary_audio_stream = | |
957 std::move(audio_stream_); | |
958 audio_stream_ = std::move(primary_audio_stream); | |
959 | |
960 StreamStatusChangeCB stream_status_change_cb; | |
961 EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) | |
962 .WillOnce(SaveArg<0>(&stream_status_change_cb)); | |
963 SetAudioRendererInitializeExpectations(PIPELINE_OK); | |
964 SetVideoRendererInitializeExpectations(PIPELINE_OK); | |
965 InitializeAndExpect(PIPELINE_OK); | |
966 Play(); | |
967 | |
968 EXPECT_CALL(time_source_, StopTicking()).Times(testing::AnyNumber()); | |
969 EXPECT_CALL(*video_renderer_, Flush(_)) | |
970 .WillRepeatedly(DoAll( | |
971 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_NOTHING), | |
972 RunClosure<0>())); | |
973 | |
974 // Initiate RendererImpl::Flush, but postpone its completion by not calling | |
975 // audio renderer flush callback right away, i.e. pretending audio renderer | |
976 // flush takes a while. | |
977 base::Closure audio_renderer_flush_cb; | |
978 EXPECT_CALL(*audio_renderer_, Flush(_)) | |
979 .WillOnce(SaveArg<0>(&audio_renderer_flush_cb)); | |
980 EXPECT_CALL(callbacks_, OnFlushed()); | |
981 renderer_impl_->Flush( | |
982 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_))); | |
983 base::RunLoop().RunUntilIdle(); | |
984 EXPECT_TRUE(audio_renderer_flush_cb); | |
985 | |
986 // Now, while the RendererImpl::Flush is pending, perform an audio track | |
987 // switch. The handling of the track switch will be postponed until after | |
988 // RendererImpl::Flush completes. | |
989 stream_status_change_cb.Run(audio_stream_.get(), false, base::TimeDelta()); | |
990 stream_status_change_cb.Run(secondary_audio_stream.get(), true, | |
991 base::TimeDelta()); | |
992 | |
993 // Ensure that audio track switch occurs after Flush by verifying that the | |
994 // audio renderer is reinitialized with the secondary audio stream. | |
995 EXPECT_CALL(*audio_renderer_, | |
996 Initialize(secondary_audio_stream.get(), _, _, _)); | |
997 | |
998 audio_renderer_client_->OnBufferingStateChange(BUFFERING_HAVE_NOTHING); | |
999 audio_renderer_flush_cb.Run(); | |
1000 base::RunLoop().RunUntilIdle(); | |
1001 } | |
1002 | |
1003 TEST_F(RendererImplTest, VideoTrackSwitchDuringFlush) { | |
1004 CreateAudioAndVideoStream(); | |
1005 std::unique_ptr<StrictMock<MockDemuxerStream>> primary_video_stream = | |
1006 std::move(video_stream_); | |
1007 CreateVideoStream(); | |
1008 std::unique_ptr<StrictMock<MockDemuxerStream>> secondary_video_stream = | |
1009 std::move(video_stream_); | |
1010 video_stream_ = std::move(primary_video_stream); | |
1011 | |
1012 StreamStatusChangeCB stream_status_change_cb; | |
1013 EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) | |
1014 .WillOnce(SaveArg<0>(&stream_status_change_cb)); | |
1015 SetAudioRendererInitializeExpectations(PIPELINE_OK); | |
1016 SetVideoRendererInitializeExpectations(PIPELINE_OK); | |
1017 InitializeAndExpect(PIPELINE_OK); | |
1018 Play(); | |
1019 | |
1020 EXPECT_CALL(time_source_, StopTicking()).Times(testing::AnyNumber()); | |
1021 EXPECT_CALL(*video_renderer_, OnTimeStopped()).Times(testing::AnyNumber()); | |
1022 EXPECT_CALL(*audio_renderer_, Flush(_)) | |
1023 .WillRepeatedly(DoAll( | |
1024 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_NOTHING), | |
1025 RunClosure<0>())); | |
1026 | |
1027 // Initiate RendererImpl::Flush, but postpone its completion by not calling | |
1028 // video renderer flush callback right away, i.e. pretending video renderer | |
1029 // flush takes a while. | |
1030 base::Closure video_renderer_flush_cb; | |
1031 EXPECT_CALL(*video_renderer_, Flush(_)) | |
1032 .WillOnce(SaveArg<0>(&video_renderer_flush_cb)); | |
1033 EXPECT_CALL(callbacks_, OnFlushed()); | |
1034 renderer_impl_->Flush( | |
1035 base::Bind(&CallbackHelper::OnFlushed, base::Unretained(&callbacks_))); | |
1036 base::RunLoop().RunUntilIdle(); | |
1037 EXPECT_TRUE(video_renderer_flush_cb); | |
1038 | |
1039 // Now, while the RendererImpl::Flush is pending, perform a video track | |
1040 // switch. The handling of the track switch will be postponed until after | |
1041 // RendererImpl::Flush completes. | |
1042 stream_status_change_cb.Run(video_stream_.get(), false, base::TimeDelta()); | |
1043 stream_status_change_cb.Run(secondary_video_stream.get(), true, | |
1044 base::TimeDelta()); | |
1045 | |
1046 // Ensure that video track switch occurs after Flush by verifying that the | |
1047 // video renderer is reinitialized with the secondary video stream. | |
1048 EXPECT_CALL(*video_renderer_, | |
1049 Initialize(secondary_video_stream.get(), _, _, _, _)); | |
1050 | |
1051 video_renderer_client_->OnBufferingStateChange(BUFFERING_HAVE_NOTHING); | |
1052 video_renderer_flush_cb.Run(); | |
1053 base::RunLoop().RunUntilIdle(); | |
1054 } | |
xhwang
2017/04/10 18:57:30
Can you add test cases for:
- stream switch in "FL
servolk
2017/04/10 20:21:22
The *TrackSwitchDuringFlush actually include testi
xhwang
2017/04/11 00:29:41
Thanks, this is not obvious from the test name. Co
servolk
2017/04/11 01:14:05
Done.
| |
1055 | |
854 } // namespace media | 1056 } // namespace media |
OLD | NEW |