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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 renderer_impl_( | 75 renderer_impl_( |
76 new RendererImpl(message_loop_.task_runner(), | 76 new RendererImpl(message_loop_.task_runner(), |
77 std::unique_ptr<AudioRenderer>(audio_renderer_), | 77 std::unique_ptr<AudioRenderer>(audio_renderer_), |
78 std::unique_ptr<VideoRenderer>(video_renderer_))), | 78 std::unique_ptr<VideoRenderer>(video_renderer_))), |
79 cdm_context_(new StrictMock<MockCdmContext>()), | 79 cdm_context_(new StrictMock<MockCdmContext>()), |
80 video_renderer_client_(nullptr), | 80 video_renderer_client_(nullptr), |
81 audio_renderer_client_(nullptr), | 81 audio_renderer_client_(nullptr), |
82 initialization_status_(PIPELINE_OK) { | 82 initialization_status_(PIPELINE_OK) { |
83 // CreateAudioStream() and CreateVideoStream() overrides expectations for | 83 // CreateAudioStream() and CreateVideoStream() overrides expectations for |
84 // expected non-NULL streams. | 84 // expected non-NULL streams. |
85 DemuxerStream* null_pointer = NULL; | 85 EXPECT_CALL(*demuxer_, GetStreams()).WillRepeatedly(Return(streams_)); |
86 EXPECT_CALL(*demuxer_, GetStream(_)) | |
87 .WillRepeatedly(Return(null_pointer)); | |
88 } | 86 } |
89 | 87 |
90 virtual ~RendererImplTest() { Destroy(); } | 88 virtual ~RendererImplTest() { Destroy(); } |
91 | 89 |
92 protected: | 90 protected: |
93 void Destroy() { | 91 void Destroy() { |
94 renderer_impl_.reset(); | 92 renderer_impl_.reset(); |
95 base::RunLoop().RunUntilIdle(); | 93 base::RunLoop().RunUntilIdle(); |
96 } | 94 } |
97 | 95 |
98 std::unique_ptr<StrictMock<MockDemuxerStream>> CreateStream( | 96 std::unique_ptr<StrictMock<MockDemuxerStream>> CreateStream( |
99 DemuxerStream::Type type) { | 97 DemuxerStream::Type type) { |
100 std::unique_ptr<StrictMock<MockDemuxerStream>> stream( | 98 std::unique_ptr<StrictMock<MockDemuxerStream>> stream( |
101 new StrictMock<MockDemuxerStream>(type)); | 99 new StrictMock<MockDemuxerStream>(type)); |
102 EXPECT_CALL(*stream, SetStreamStatusChangeCB(_)) | 100 EXPECT_CALL(*stream, enabled()).WillRepeatedly(Return(true)); |
| 101 EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) |
103 .Times(testing::AnyNumber()); | 102 .Times(testing::AnyNumber()); |
104 return stream; | 103 return stream; |
105 } | 104 } |
106 | 105 |
107 // Sets up expectations to allow the audio renderer to initialize. | 106 // Sets up expectations to allow the audio renderer to initialize. |
108 void SetAudioRendererInitializeExpectations(PipelineStatus status) { | 107 void SetAudioRendererInitializeExpectations(PipelineStatus status) { |
109 EXPECT_CALL(*audio_renderer_, Initialize(audio_stream_.get(), _, _, _)) | 108 EXPECT_CALL(*audio_renderer_, Initialize(audio_stream_.get(), _, _, _)) |
110 .WillOnce( | 109 .WillOnce( |
111 DoAll(SaveArg<2>(&audio_renderer_client_), RunCallback<3>(status))); | 110 DoAll(SaveArg<2>(&audio_renderer_client_), RunCallback<3>(status))); |
112 } | 111 } |
(...skipping 18 matching lines...) Expand all Loading... |
131 } | 130 } |
132 | 131 |
133 renderer_impl_->Initialize(demuxer_.get(), &callbacks_, | 132 renderer_impl_->Initialize(demuxer_.get(), &callbacks_, |
134 base::Bind(&CallbackHelper::OnInitialize, | 133 base::Bind(&CallbackHelper::OnInitialize, |
135 base::Unretained(&callbacks_))); | 134 base::Unretained(&callbacks_))); |
136 base::RunLoop().RunUntilIdle(); | 135 base::RunLoop().RunUntilIdle(); |
137 } | 136 } |
138 | 137 |
139 void CreateAudioStream() { | 138 void CreateAudioStream() { |
140 audio_stream_ = CreateStream(DemuxerStream::AUDIO); | 139 audio_stream_ = CreateStream(DemuxerStream::AUDIO); |
141 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO)) | 140 streams_.push_back(audio_stream_.get()); |
142 .WillRepeatedly(Return(audio_stream_.get())); | 141 EXPECT_CALL(*demuxer_, GetStreams()).WillRepeatedly(Return(streams_)); |
143 } | 142 } |
144 | 143 |
145 void CreateVideoStream(bool is_encrypted = false) { | 144 void CreateVideoStream(bool is_encrypted = false) { |
146 video_stream_ = CreateStream(DemuxerStream::VIDEO); | 145 video_stream_ = CreateStream(DemuxerStream::VIDEO); |
147 video_stream_->set_video_decoder_config( | 146 video_stream_->set_video_decoder_config( |
148 is_encrypted ? TestVideoConfig::NormalEncrypted() | 147 is_encrypted ? TestVideoConfig::NormalEncrypted() |
149 : TestVideoConfig::Normal()); | 148 : TestVideoConfig::Normal()); |
150 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO)) | 149 streams_.push_back(video_stream_.get()); |
151 .WillRepeatedly(Return(video_stream_.get())); | 150 EXPECT_CALL(*demuxer_, GetStreams()).WillRepeatedly(Return(streams_)); |
152 } | 151 } |
153 | 152 |
154 void CreateEncryptedVideoStream() { CreateVideoStream(true); } | 153 void CreateEncryptedVideoStream() { CreateVideoStream(true); } |
155 | 154 |
156 void CreateAudioAndVideoStream() { | 155 void CreateAudioAndVideoStream() { |
157 CreateAudioStream(); | 156 CreateAudioStream(); |
158 CreateVideoStream(); | 157 CreateVideoStream(); |
159 } | 158 } |
160 | 159 |
161 void InitializeWithAudio() { | 160 void InitializeWithAudio() { |
162 CreateAudioStream(); | 161 CreateAudioStream(); |
163 SetAudioRendererInitializeExpectations(PIPELINE_OK); | 162 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
164 // There is a potential race between HTMLMediaElement/WMPI shutdown and | 163 // There is a potential race between HTMLMediaElement/WMPI shutdown and |
165 // renderers being initialized which might result in MediaResource GetStream | 164 // renderers being initialized which might result in MediaResource |
166 // suddenly returning NULL (see crbug.com/668604). So we are going to check | 165 // GetStreams suddenly returning fewer streams than before or even returning |
167 // here that GetStream will be invoked exactly 3 times during RendererImpl | 166 // and empty stream collection (see crbug.com/668604). So we are going to |
168 // initialization to help catch potential issues. Currently the GetStream is | 167 // check here that GetStreams will be invoked exactly 3 times during |
169 // invoked once directly from RendererImpl::Initialize, once indirectly from | 168 // RendererImpl initialization to help catch potential issues. Currently the |
170 // RendererImpl::Initialize via HasEncryptedStream and once from | 169 // GetStreams is invoked once from the RendererImpl::Initialize via |
171 // RendererImpl::InitializeAudioRenderer. | 170 // HasEncryptedStream, once from the RendererImpl::InitializeAudioRenderer |
172 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::AUDIO)) | 171 // and once from the RendererImpl::InitializeVideoRenderer. |
173 .Times(2) | 172 EXPECT_CALL(*demuxer_, GetStreams()) |
174 .WillRepeatedly(Return(audio_stream_.get())); | 173 .Times(3) |
| 174 .WillRepeatedly(Return(streams_)); |
175 InitializeAndExpect(PIPELINE_OK); | 175 InitializeAndExpect(PIPELINE_OK); |
176 } | 176 } |
177 | 177 |
178 void InitializeWithVideo() { | 178 void InitializeWithVideo() { |
179 CreateVideoStream(); | 179 CreateVideoStream(); |
180 SetVideoRendererInitializeExpectations(PIPELINE_OK); | 180 SetVideoRendererInitializeExpectations(PIPELINE_OK); |
181 // There is a potential race between HTMLMediaElement/WMPI shutdown and | 181 // There is a potential race between HTMLMediaElement/WMPI shutdown and |
182 // renderers being initialized which might result in MediaResource GetStream | 182 // renderers being initialized which might result in MediaResource |
183 // suddenly returning NULL (see crbug.com/668604). So we are going to check | 183 // GetStreams suddenly returning fewer streams than before or even returning |
184 // here that GetStream will be invoked exactly 3 times during RendererImpl | 184 // and empty stream collection (see crbug.com/668604). So we are going to |
185 // initialization to help catch potential issues. Currently the GetStream is | 185 // check here that GetStreams will be invoked exactly 3 times during |
186 // invoked once directly from RendererImpl::Initialize, once indirectly from | 186 // RendererImpl initialization to help catch potential issues. Currently the |
187 // RendererImpl::Initialize via HasEncryptedStream and once from | 187 // GetStreams is invoked once from the RendererImpl::Initialize via |
188 // RendererImpl::InitializeVideoRenderer. | 188 // HasEncryptedStream, once from the RendererImpl::InitializeAudioRenderer |
189 EXPECT_CALL(*demuxer_, GetStream(DemuxerStream::VIDEO)) | 189 // and once from the RendererImpl::InitializeVideoRenderer. |
190 .Times(2) | 190 EXPECT_CALL(*demuxer_, GetStreams()) |
191 .WillRepeatedly(Return(video_stream_.get())); | 191 .Times(3) |
| 192 .WillRepeatedly(Return(streams_)); |
192 InitializeAndExpect(PIPELINE_OK); | 193 InitializeAndExpect(PIPELINE_OK); |
193 } | 194 } |
194 | 195 |
195 void InitializeWithAudioAndVideo() { | 196 void InitializeWithAudioAndVideo() { |
196 CreateAudioAndVideoStream(); | 197 CreateAudioAndVideoStream(); |
197 SetAudioRendererInitializeExpectations(PIPELINE_OK); | 198 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
198 SetVideoRendererInitializeExpectations(PIPELINE_OK); | 199 SetVideoRendererInitializeExpectations(PIPELINE_OK); |
199 InitializeAndExpect(PIPELINE_OK); | 200 InitializeAndExpect(PIPELINE_OK); |
200 } | 201 } |
201 | 202 |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
292 | 293 |
293 std::unique_ptr<StrictMock<MockDemuxer>> demuxer_; | 294 std::unique_ptr<StrictMock<MockDemuxer>> demuxer_; |
294 StrictMock<MockVideoRenderer>* video_renderer_; | 295 StrictMock<MockVideoRenderer>* video_renderer_; |
295 StrictMock<MockAudioRenderer>* audio_renderer_; | 296 StrictMock<MockAudioRenderer>* audio_renderer_; |
296 std::unique_ptr<RendererImpl> renderer_impl_; | 297 std::unique_ptr<RendererImpl> renderer_impl_; |
297 std::unique_ptr<StrictMock<MockCdmContext>> cdm_context_; | 298 std::unique_ptr<StrictMock<MockCdmContext>> cdm_context_; |
298 | 299 |
299 StrictMock<MockTimeSource> time_source_; | 300 StrictMock<MockTimeSource> time_source_; |
300 std::unique_ptr<StrictMock<MockDemuxerStream>> audio_stream_; | 301 std::unique_ptr<StrictMock<MockDemuxerStream>> audio_stream_; |
301 std::unique_ptr<StrictMock<MockDemuxerStream>> video_stream_; | 302 std::unique_ptr<StrictMock<MockDemuxerStream>> video_stream_; |
| 303 std::vector<DemuxerStream*> streams_; |
302 RendererClient* video_renderer_client_; | 304 RendererClient* video_renderer_client_; |
303 RendererClient* audio_renderer_client_; | 305 RendererClient* audio_renderer_client_; |
304 VideoDecoderConfig video_decoder_config_; | 306 VideoDecoderConfig video_decoder_config_; |
305 PipelineStatus initialization_status_; | 307 PipelineStatus initialization_status_; |
306 | 308 |
307 private: | 309 private: |
308 DISALLOW_COPY_AND_ASSIGN(RendererImplTest); | 310 DISALLOW_COPY_AND_ASSIGN(RendererImplTest); |
309 }; | 311 }; |
310 | 312 |
311 TEST_F(RendererImplTest, Destroy_BeforeInitialize) { | 313 TEST_F(RendererImplTest, Destroy_BeforeInitialize) { |
(...skipping 432 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
744 EXPECT_CALL(*video_renderer_, StartPlayingFrom(kStartTime)); | 746 EXPECT_CALL(*video_renderer_, StartPlayingFrom(kStartTime)); |
745 renderer_impl_->StartPlayingFrom(kStartTime); | 747 renderer_impl_->StartPlayingFrom(kStartTime); |
746 | 748 |
747 // Nothing else should primed on the message loop. | 749 // Nothing else should primed on the message loop. |
748 base::RunLoop().RunUntilIdle(); | 750 base::RunLoop().RunUntilIdle(); |
749 } | 751 } |
750 | 752 |
751 TEST_F(RendererImplTest, StreamStatusNotificationHandling) { | 753 TEST_F(RendererImplTest, StreamStatusNotificationHandling) { |
752 CreateAudioAndVideoStream(); | 754 CreateAudioAndVideoStream(); |
753 | 755 |
754 DemuxerStream::StreamStatusChangeCB audio_stream_status_change_cb; | 756 StreamStatusChangeCB stream_status_change_cb; |
755 DemuxerStream::StreamStatusChangeCB video_stream_status_change_cb; | 757 EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) |
756 EXPECT_CALL(*audio_stream_, SetStreamStatusChangeCB(_)) | 758 .WillOnce(SaveArg<0>(&stream_status_change_cb)); |
757 .WillOnce(SaveArg<0>(&audio_stream_status_change_cb)); | |
758 EXPECT_CALL(*video_stream_, SetStreamStatusChangeCB(_)) | |
759 .WillOnce(SaveArg<0>(&video_stream_status_change_cb)); | |
760 SetAudioRendererInitializeExpectations(PIPELINE_OK); | 759 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
761 SetVideoRendererInitializeExpectations(PIPELINE_OK); | 760 SetVideoRendererInitializeExpectations(PIPELINE_OK); |
762 InitializeAndExpect(PIPELINE_OK); | 761 InitializeAndExpect(PIPELINE_OK); |
763 Play(); | 762 Play(); |
764 | 763 |
765 // Verify that DemuxerStream status changes cause the corresponding | 764 // Verify that DemuxerStream status changes cause the corresponding |
766 // audio/video renderer to be flushed and restarted. | 765 // audio/video renderer to be flushed and restarted. |
767 EXPECT_CALL(time_source_, StopTicking()); | 766 EXPECT_CALL(time_source_, StopTicking()); |
768 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>()); | 767 EXPECT_CALL(*audio_renderer_, Flush(_)).WillOnce(RunClosure<0>()); |
769 EXPECT_CALL(*audio_renderer_, StartPlaying()) | 768 EXPECT_CALL(*audio_renderer_, StartPlaying()) |
770 .Times(1) | 769 .Times(1) |
771 .WillOnce( | 770 .WillOnce( |
772 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH)); | 771 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH)); |
773 audio_stream_status_change_cb.Run(false, base::TimeDelta()); | 772 stream_status_change_cb.Run(audio_stream_.get(), false, base::TimeDelta()); |
774 | 773 |
775 EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>()); | 774 EXPECT_CALL(*video_renderer_, Flush(_)).WillOnce(RunClosure<0>()); |
776 EXPECT_CALL(*video_renderer_, StartPlayingFrom(_)) | 775 EXPECT_CALL(*video_renderer_, StartPlayingFrom(_)) |
777 .Times(1) | 776 .Times(1) |
778 .WillOnce(DoAll( | 777 .WillOnce(DoAll( |
779 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH), | 778 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH), |
780 PostQuitWhenIdle())); | 779 PostQuitWhenIdle())); |
781 | 780 |
782 video_stream_status_change_cb.Run(false, base::TimeDelta()); | 781 stream_status_change_cb.Run(video_stream_.get(), false, base::TimeDelta()); |
783 base::RunLoop().Run(); | 782 base::RunLoop().Run(); |
784 } | 783 } |
785 | 784 |
786 // Stream status changes are handled asynchronously by the renderer and may take | 785 // Stream status changes are handled asynchronously by the renderer and may take |
787 // some time to process. This test verifies that all status changes are | 786 // some time to process. This test verifies that all status changes are |
788 // processed correctly by the renderer even if status changes of the stream | 787 // processed correctly by the renderer even if status changes of the stream |
789 // happen much faster than the renderer can process them. In that case the | 788 // happen much faster than the renderer can process them. In that case the |
790 // renderer may postpone processing status changes, but still must process all | 789 // renderer may postpone processing status changes, but still must process all |
791 // of them eventually. | 790 // of them eventually. |
792 TEST_F(RendererImplTest, PostponedStreamStatusNotificationHandling) { | 791 TEST_F(RendererImplTest, PostponedStreamStatusNotificationHandling) { |
793 CreateAudioAndVideoStream(); | 792 CreateAudioAndVideoStream(); |
794 | 793 |
795 DemuxerStream::StreamStatusChangeCB audio_stream_status_change_cb; | 794 StreamStatusChangeCB stream_status_change_cb; |
796 DemuxerStream::StreamStatusChangeCB video_stream_status_change_cb; | 795 EXPECT_CALL(*demuxer_, SetStreamStatusChangeCB(_)) |
797 EXPECT_CALL(*audio_stream_, SetStreamStatusChangeCB(_)) | 796 .WillOnce(SaveArg<0>(&stream_status_change_cb)); |
798 .WillOnce(SaveArg<0>(&audio_stream_status_change_cb)); | |
799 EXPECT_CALL(*video_stream_, SetStreamStatusChangeCB(_)) | |
800 .WillOnce(SaveArg<0>(&video_stream_status_change_cb)); | |
801 SetAudioRendererInitializeExpectations(PIPELINE_OK); | 797 SetAudioRendererInitializeExpectations(PIPELINE_OK); |
802 SetVideoRendererInitializeExpectations(PIPELINE_OK); | 798 SetVideoRendererInitializeExpectations(PIPELINE_OK); |
803 InitializeAndExpect(PIPELINE_OK); | 799 InitializeAndExpect(PIPELINE_OK); |
804 Play(); | 800 Play(); |
805 | 801 |
806 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) | 802 EXPECT_CALL(callbacks_, OnBufferingStateChange(BUFFERING_HAVE_ENOUGH)) |
807 .Times(2); | 803 .Times(2); |
808 | 804 |
809 EXPECT_CALL(time_source_, StopTicking()).Times(2); | 805 EXPECT_CALL(time_source_, StopTicking()).Times(2); |
810 EXPECT_CALL(time_source_, StartTicking()).Times(2); | 806 EXPECT_CALL(time_source_, StartTicking()).Times(2); |
811 EXPECT_CALL(*audio_renderer_, Flush(_)) | 807 EXPECT_CALL(*audio_renderer_, Flush(_)) |
812 .Times(2) | 808 .Times(2) |
813 .WillRepeatedly(DoAll( | 809 .WillRepeatedly(DoAll( |
814 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_NOTHING), | 810 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_NOTHING), |
815 WithArg<0>(PostCallback()))); | 811 WithArg<0>(PostCallback()))); |
816 EXPECT_CALL(*audio_renderer_, StartPlaying()) | 812 EXPECT_CALL(*audio_renderer_, StartPlaying()) |
817 .Times(2) | 813 .Times(2) |
818 .WillOnce( | 814 .WillOnce( |
819 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH)) | 815 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH)) |
820 .WillOnce(DoAll( | 816 .WillOnce(DoAll( |
821 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH), | 817 SetBufferingState(&audio_renderer_client_, BUFFERING_HAVE_ENOUGH), |
822 PostQuitWhenIdle())); | 818 PostQuitWhenIdle())); |
823 // The first stream status change will be processed immediately. Each status | 819 // The first stream status change will be processed immediately. Each status |
824 // change processing involves Flush + StartPlaying when the Flush is done. The | 820 // change processing involves Flush + StartPlaying when the Flush is done. The |
825 // Flush operation is async in this case, so the second status change will be | 821 // Flush operation is async in this case, so the second status change will be |
826 // postponed by renderer until after processing the first one is finished. But | 822 // postponed by renderer until after processing the first one is finished. But |
827 // we must still get two pairs of Flush/StartPlaying calls eventually. | 823 // we must still get two pairs of Flush/StartPlaying calls eventually. |
828 audio_stream_status_change_cb.Run(false, base::TimeDelta()); | 824 stream_status_change_cb.Run(audio_stream_.get(), false, base::TimeDelta()); |
829 audio_stream_status_change_cb.Run(true, base::TimeDelta()); | 825 stream_status_change_cb.Run(audio_stream_.get(), true, base::TimeDelta()); |
830 base::RunLoop().Run(); | 826 base::RunLoop().Run(); |
831 | 827 |
832 EXPECT_CALL(*video_renderer_, Flush(_)) | 828 EXPECT_CALL(*video_renderer_, Flush(_)) |
833 .Times(2) | 829 .Times(2) |
834 .WillRepeatedly(DoAll( | 830 .WillRepeatedly(DoAll( |
835 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_NOTHING), | 831 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_NOTHING), |
836 WithArg<0>(PostCallback()))); | 832 WithArg<0>(PostCallback()))); |
837 EXPECT_CALL(*video_renderer_, StartPlayingFrom(base::TimeDelta())) | 833 EXPECT_CALL(*video_renderer_, StartPlayingFrom(base::TimeDelta())) |
838 .Times(2) | 834 .Times(2) |
839 .WillOnce( | 835 .WillOnce( |
840 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH)) | 836 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH)) |
841 .WillOnce(DoAll( | 837 .WillOnce(DoAll( |
842 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH), | 838 SetBufferingState(&video_renderer_client_, BUFFERING_HAVE_ENOUGH), |
843 PostQuitWhenIdle())); | 839 PostQuitWhenIdle())); |
844 // The first stream status change will be processed immediately. Each status | 840 // The first stream status change will be processed immediately. Each status |
845 // change processing involves Flush + StartPlaying when the Flush is done. The | 841 // 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 | 842 // 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 | 843 // postponed by renderer until after processing the first one is finished. But |
848 // we must still get two pairs of Flush/StartPlaying calls eventually. | 844 // we must still get two pairs of Flush/StartPlaying calls eventually. |
849 video_stream_status_change_cb.Run(false, base::TimeDelta()); | 845 stream_status_change_cb.Run(video_stream_.get(), false, base::TimeDelta()); |
850 video_stream_status_change_cb.Run(true, base::TimeDelta()); | 846 stream_status_change_cb.Run(video_stream_.get(), true, base::TimeDelta()); |
851 base::RunLoop().Run(); | 847 base::RunLoop().Run(); |
852 } | 848 } |
853 | 849 |
854 } // namespace media | 850 } // namespace media |
OLD | NEW |