Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(10)

Side by Side Diff: media/renderers/renderer_impl_unittest.cc

Issue 2684103005: Allow media track switching. (Closed)
Patch Set: Fixed comments Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « media/renderers/renderer_impl.cc ('k') | media/renderers/video_renderer_impl.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
OLDNEW
« no previous file with comments | « media/renderers/renderer_impl.cc ('k') | media/renderers/video_renderer_impl.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698