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

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

Issue 2684103005: Allow media track switching. (Closed)
Patch Set: Updated log message 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
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 <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
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
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.
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698