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 |