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