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

Side by Side Diff: media/base/pipeline_unittest.cc

Issue 10831214: Fix Pipeline to properly handle errors during initialization. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Address CR comments Created 8 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « media/base/pipeline.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 <vector> 5 #include <vector>
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/message_loop.h" 8 #include "base/message_loop.h"
9 #include "base/stl_util.h" 9 #include "base/stl_util.h"
10 #include "base/threading/simple_thread.h" 10 #include "base/threading/simple_thread.h"
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 } 128 }
129 129
130 protected: 130 protected:
131 // Sets up expectations to allow the demuxer to initialize. 131 // Sets up expectations to allow the demuxer to initialize.
132 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector; 132 typedef std::vector<MockDemuxerStream*> MockDemuxerStreamVector;
133 void InitializeDemuxer(MockDemuxerStreamVector* streams, 133 void InitializeDemuxer(MockDemuxerStreamVector* streams,
134 const base::TimeDelta& duration) { 134 const base::TimeDelta& duration) {
135 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _)) 135 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _))
136 .WillOnce(DoAll(SetDemuxerProperties(duration), 136 .WillOnce(DoAll(SetDemuxerProperties(duration),
137 RunPipelineStatusCB1())); 137 RunPipelineStatusCB1()));
138 EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(0.0f));
139 138
140 // Configure the demuxer to return the streams. 139 // Configure the demuxer to return the streams.
141 for (size_t i = 0; i < streams->size(); ++i) { 140 for (size_t i = 0; i < streams->size(); ++i) {
142 scoped_refptr<DemuxerStream> stream((*streams)[i]); 141 scoped_refptr<DemuxerStream> stream((*streams)[i]);
143 EXPECT_CALL(*mocks_->demuxer(), GetStream(stream->type())) 142 EXPECT_CALL(*mocks_->demuxer(), GetStream(stream->type()))
144 .WillRepeatedly(Return(stream)); 143 .WillRepeatedly(Return(stream));
145 } 144 }
146 } 145 }
147 146
148 void InitializeDemuxer(MockDemuxerStreamVector* streams) { 147 void InitializeDemuxer(MockDemuxerStreamVector* streams) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 _, _, _, _, _, _)) 194 _, _, _, _, _, _))
196 .WillOnce(DoAll(RunPipelineStatusCB1(), 195 .WillOnce(DoAll(RunPipelineStatusCB1(),
197 WithArg<5>(RunClosure()))); // |disabled_cb|. 196 WithArg<5>(RunClosure()))); // |disabled_cb|.
198 } else { 197 } else {
199 EXPECT_CALL(*mocks_->audio_renderer(), Initialize( 198 EXPECT_CALL(*mocks_->audio_renderer(), Initialize(
200 scoped_refptr<AudioDecoder>(mocks_->audio_decoder()), 199 scoped_refptr<AudioDecoder>(mocks_->audio_decoder()),
201 _, _, _, _, _, _)) 200 _, _, _, _, _, _))
202 .WillOnce(DoAll(SaveArg<3>(&audio_time_cb_), 201 .WillOnce(DoAll(SaveArg<3>(&audio_time_cb_),
203 RunPipelineStatusCB1())); 202 RunPipelineStatusCB1()));
204 } 203 }
205 EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(0.0f));
206 EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(1.0f));
207
208 // Startup sequence.
209 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(base::TimeDelta(), _))
210 .WillOnce(RunPipelineStatusCB1());
211 EXPECT_CALL(*mocks_->audio_renderer(), Play(_))
212 .WillOnce(RunClosure());
213 } 204 }
214 205
215 // Sets up expectations on the callback and initializes the pipeline. Called 206 // Sets up expectations on the callback and initializes the pipeline. Called
216 // after tests have set expectations any filters they wish to use. 207 // after tests have set expectations any filters they wish to use.
217 void InitializePipeline(PipelineStatus start_status) { 208 void InitializePipeline(PipelineStatus start_status) {
218 EXPECT_CALL(callbacks_, OnStart(start_status)); 209 EXPECT_CALL(callbacks_, OnStart(start_status));
219 210
211 if (start_status == PIPELINE_OK) {
212 EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(0.0f));
213
214 if (audio_stream_) {
215 EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(0.0f));
216 EXPECT_CALL(*mocks_->audio_renderer(), SetVolume(1.0f));
217
218 // Startup sequence.
219 EXPECT_CALL(*mocks_->audio_renderer(), Preroll(base::TimeDelta(), _))
220 .WillOnce(RunPipelineStatusCB1());
221 EXPECT_CALL(*mocks_->audio_renderer(), Play(_))
222 .WillOnce(RunClosure());
223 }
224 }
225
220 pipeline_->Start( 226 pipeline_->Start(
221 mocks_->Create().Pass(), 227 mocks_->Create().Pass(),
222 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)), 228 base::Bind(&CallbackHelper::OnEnded, base::Unretained(&callbacks_)),
223 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)), 229 base::Bind(&CallbackHelper::OnError, base::Unretained(&callbacks_)),
224 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_))); 230 base::Bind(&CallbackHelper::OnStart, base::Unretained(&callbacks_)));
225 message_loop_.RunAllPending(); 231 message_loop_.RunAllPending();
226 } 232 }
227 233
228 void CreateAudioStream() { 234 void CreateAudioStream() {
229 audio_stream_ = CreateStream(DemuxerStream::AUDIO); 235 audio_stream_ = CreateStream(DemuxerStream::AUDIO);
(...skipping 478 matching lines...) Expand 10 before | Expand all | Expand 10 after
708 .WillOnce(Return(true)); 714 .WillOnce(Return(true));
709 EXPECT_CALL(callbacks_, OnEnded(PIPELINE_OK)); 715 EXPECT_CALL(callbacks_, OnEnded(PIPELINE_OK));
710 pipeline_->OnRendererEnded(); 716 pipeline_->OnRendererEnded();
711 } 717 }
712 718
713 TEST_F(PipelineTest, ErrorDuringSeek) { 719 TEST_F(PipelineTest, ErrorDuringSeek) {
714 CreateAudioStream(); 720 CreateAudioStream();
715 MockDemuxerStreamVector streams; 721 MockDemuxerStreamVector streams;
716 streams.push_back(audio_stream()); 722 streams.push_back(audio_stream());
717 723
718 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(10)); 724 InitializeDemuxer(&streams);
719 InitializeAudioDecoder(audio_stream()); 725 InitializeAudioDecoder(audio_stream());
720 InitializeAudioRenderer(); 726 InitializeAudioRenderer();
721 InitializePipeline(PIPELINE_OK); 727 InitializePipeline(PIPELINE_OK);
722 728
723 float playback_rate = 1.0f; 729 float playback_rate = 1.0f;
724 EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(playback_rate)); 730 EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(playback_rate));
725 EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(playback_rate)); 731 EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(playback_rate));
726 pipeline_->SetPlaybackRate(playback_rate); 732 pipeline_->SetPlaybackRate(playback_rate);
727 message_loop_.RunAllPending(); 733 message_loop_.RunAllPending();
728 734
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
764 770
765 // No additional tasks should be queued as a result of these calls. 771 // No additional tasks should be queued as a result of these calls.
766 message_loop->AssertIdle(); 772 message_loop->AssertIdle();
767 } 773 }
768 774
769 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) { 775 TEST_F(PipelineTest, NoMessageDuringTearDownFromError) {
770 CreateAudioStream(); 776 CreateAudioStream();
771 MockDemuxerStreamVector streams; 777 MockDemuxerStreamVector streams;
772 streams.push_back(audio_stream()); 778 streams.push_back(audio_stream());
773 779
774 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(10)); 780 InitializeDemuxer(&streams);
775 InitializeAudioDecoder(audio_stream()); 781 InitializeAudioDecoder(audio_stream());
776 InitializeAudioRenderer(); 782 InitializeAudioRenderer();
777 InitializePipeline(PIPELINE_OK); 783 InitializePipeline(PIPELINE_OK);
778 784
779 // Trigger additional requests on the pipeline during tear down from error. 785 // Trigger additional requests on the pipeline during tear down from error.
780 base::Callback<void(PipelineStatus)> cb = base::Bind( 786 base::Callback<void(PipelineStatus)> cb = base::Bind(
781 &TestNoCallsAfterError, pipeline_, &message_loop_); 787 &TestNoCallsAfterError, pipeline_, &message_loop_);
782 ON_CALL(callbacks_, OnError(_)) 788 ON_CALL(callbacks_, OnError(_))
783 .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run)); 789 .WillByDefault(Invoke(&cb, &base::Callback<void(PipelineStatus)>::Run));
784 790
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
849 int max_time_in_ms) { 855 int max_time_in_ms) {
850 time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms), 856 time_cb.Run(base::TimeDelta::FromMilliseconds(time_in_ms),
851 base::TimeDelta::FromMilliseconds(max_time_in_ms)); 857 base::TimeDelta::FromMilliseconds(max_time_in_ms));
852 } 858 }
853 859
854 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) { 860 TEST_F(PipelineTest, AudioTimeUpdateDuringSeek) {
855 CreateAudioStream(); 861 CreateAudioStream();
856 MockDemuxerStreamVector streams; 862 MockDemuxerStreamVector streams;
857 streams.push_back(audio_stream()); 863 streams.push_back(audio_stream());
858 864
859 InitializeDemuxer(&streams, base::TimeDelta::FromSeconds(10)); 865 InitializeDemuxer(&streams);
860 InitializeAudioDecoder(audio_stream()); 866 InitializeAudioDecoder(audio_stream());
861 InitializeAudioRenderer(); 867 InitializeAudioRenderer();
862 InitializePipeline(PIPELINE_OK); 868 InitializePipeline(PIPELINE_OK);
863 869
864 float playback_rate = 1.0f; 870 float playback_rate = 1.0f;
865 EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(playback_rate)); 871 EXPECT_CALL(*mocks_->demuxer(), SetPlaybackRate(playback_rate));
866 EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(playback_rate)); 872 EXPECT_CALL(*mocks_->audio_renderer(), SetPlaybackRate(playback_rate));
867 pipeline_->SetPlaybackRate(playback_rate); 873 pipeline_->SetPlaybackRate(playback_rate);
868 message_loop_.RunAllPending(); 874 message_loop_.RunAllPending();
869 875
(...skipping 27 matching lines...) Expand all
897 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time); 903 EXPECT_EQ(pipeline_->GetMediaTime(), seek_time);
898 904
899 // Now that the seek is complete, verify that time updates advance the current 905 // Now that the seek is complete, verify that time updates advance the current
900 // time. 906 // time.
901 base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100); 907 base::TimeDelta new_time = seek_time + base::TimeDelta::FromMilliseconds(100);
902 audio_time_cb_.Run(new_time, new_time); 908 audio_time_cb_.Run(new_time, new_time);
903 909
904 EXPECT_EQ(pipeline_->GetMediaTime(), new_time); 910 EXPECT_EQ(pipeline_->GetMediaTime(), new_time);
905 } 911 }
906 912
913 TEST_F(PipelineTest, InitFailure_Demuxer) {
914 PipelineStatus expected_status = DEMUXER_ERROR_COULD_NOT_OPEN;
915 EXPECT_CALL(*mocks_->demuxer(), Initialize(_, _))
916 .WillOnce(RunPipelineStatusCB1WithStatus(expected_status));
917 EXPECT_CALL(*mocks_->demuxer(), Stop(_))
918 .WillOnce(RunClosure());
919 InitializePipeline(expected_status);
920 EXPECT_FALSE(pipeline_->IsInitialized());
921 }
922
923 TEST_F(PipelineTest, InitFailure_AudioDecoder) {
924 CreateAudioStream();
925 MockDemuxerStreamVector streams;
926 streams.push_back(audio_stream());
927
928 InitializeDemuxer(&streams);
929
930 PipelineStatus expected_status = PIPELINE_ERROR_DECODE;
931 scoped_refptr<DemuxerStream> stream = streams[0];
932 EXPECT_CALL(*mocks_->audio_decoder(), Initialize(stream, _, _))
933 .WillOnce(RunPipelineStatusCB1WithStatus(expected_status));
934
935 EXPECT_CALL(*mocks_->demuxer(), Stop(_))
936 .WillOnce(RunClosure());
937
938 InitializePipeline(expected_status);
939 EXPECT_FALSE(pipeline_->IsInitialized());
940 EXPECT_FALSE(pipeline_->HasAudio());
941 }
942
943 TEST_F(PipelineTest, InitFailure_AudioRenderer) {
944 CreateAudioStream();
945 MockDemuxerStreamVector streams;
946 streams.push_back(audio_stream());
947
948 InitializeDemuxer(&streams);
949 InitializeAudioDecoder(audio_stream());
950
951 PipelineStatus expected_status = PIPELINE_ERROR_INITIALIZATION_FAILED;
952 EXPECT_CALL(*mocks_->audio_renderer(), Initialize(
953 scoped_refptr<AudioDecoder>(mocks_->audio_decoder()),
954 _, _, _, _, _, _))
955 .WillOnce(RunPipelineStatusCB1WithStatus(expected_status));
956
957 EXPECT_CALL(*mocks_->demuxer(), Stop(_))
958 .WillOnce(RunClosure());
959 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_))
960 .WillOnce(RunClosure());
961
962 InitializePipeline(expected_status);
963 EXPECT_FALSE(pipeline_->IsInitialized());
964 EXPECT_TRUE(pipeline_->HasAudio());
965 }
966
967 TEST_F(PipelineTest, InitFailure_VideoDecoder) {
968 CreateAudioStream();
969 CreateVideoStream();
970 MockDemuxerStreamVector streams;
971 streams.push_back(audio_stream());
972 streams.push_back(video_stream());
973
974 InitializeDemuxer(&streams);
975 InitializeAudioDecoder(audio_stream());
976 InitializeAudioRenderer();
977
978 PipelineStatus expected_status = PIPELINE_ERROR_DECODE;
979 scoped_refptr<DemuxerStream> stream = streams[1];
980 EXPECT_CALL(*mocks_->video_decoder(),
981 Initialize(stream, _, _))
982 .WillOnce(RunPipelineStatusCB1WithStatus(expected_status));
983
984 EXPECT_CALL(*mocks_->demuxer(), Stop(_))
985 .WillOnce(RunClosure());
986 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_))
987 .WillOnce(RunClosure());
988
989 InitializePipeline(expected_status);
990 EXPECT_FALSE(pipeline_->IsInitialized());
991 EXPECT_TRUE(pipeline_->HasAudio());
992 EXPECT_FALSE(pipeline_->HasVideo());
993 }
994
995 TEST_F(PipelineTest, InitFailure_VideoRenderer) {
996 CreateAudioStream();
997 CreateVideoStream();
998 MockDemuxerStreamVector streams;
999 streams.push_back(audio_stream());
1000 streams.push_back(video_stream());
1001
1002 InitializeDemuxer(&streams);
1003 InitializeAudioDecoder(audio_stream());
1004 InitializeAudioRenderer();
1005 InitializeVideoDecoder(video_stream());
1006
1007 PipelineStatus expected_status = PIPELINE_ERROR_INITIALIZATION_FAILED;
1008 EXPECT_CALL(*mocks_->video_renderer(), Initialize(
1009 scoped_refptr<VideoDecoder>(mocks_->video_decoder()),
1010 _, _, _, _, _, _, _, _))
1011 .WillOnce(RunPipelineStatusCB1WithStatus(expected_status));
1012
1013 EXPECT_CALL(*mocks_->demuxer(), Stop(_))
1014 .WillOnce(RunClosure());
1015 EXPECT_CALL(*mocks_->audio_renderer(), Stop(_))
1016 .WillOnce(RunClosure());
1017 EXPECT_CALL(*mocks_->video_renderer(), Stop(_))
1018 .WillOnce(RunClosure());
1019
1020 InitializePipeline(expected_status);
1021 EXPECT_FALSE(pipeline_->IsInitialized());
1022 EXPECT_TRUE(pipeline_->HasAudio());
1023 EXPECT_TRUE(pipeline_->HasVideo());
1024 }
1025
907 class FlexibleCallbackRunner : public base::DelegateSimpleThread::Delegate { 1026 class FlexibleCallbackRunner : public base::DelegateSimpleThread::Delegate {
908 public: 1027 public:
909 FlexibleCallbackRunner(base::TimeDelta delay, PipelineStatus status, 1028 FlexibleCallbackRunner(base::TimeDelta delay, PipelineStatus status,
910 const PipelineStatusCB& status_cb) 1029 const PipelineStatusCB& status_cb)
911 : delay_(delay), 1030 : delay_(delay),
912 status_(status), 1031 status_(status),
913 status_cb_(status_cb) { 1032 status_cb_(status_cb) {
914 if (delay_ < base::TimeDelta()) { 1033 if (delay_ < base::TimeDelta()) {
915 status_cb_.Run(status_); 1034 status_cb_.Run(status_);
916 return; 1035 return;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
951 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(0)); 1070 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(0));
952 } 1071 }
953 1072
954 // Test that different-thread, some-delay callback (the expected common case) 1073 // Test that different-thread, some-delay callback (the expected common case)
955 // works correctly. 1074 // works correctly.
956 TEST(PipelineStatusNotificationTest, DelayedCallback) { 1075 TEST(PipelineStatusNotificationTest, DelayedCallback) {
957 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(20)); 1076 TestPipelineStatusNotification(base::TimeDelta::FromMilliseconds(20));
958 } 1077 }
959 1078
960 } // namespace media 1079 } // namespace media
OLDNEW
« no previous file with comments | « media/base/pipeline.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698