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 "media/renderers/renderer_impl.h" | 5 #include "media/renderers/renderer_impl.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/callback.h" | 10 #include "base/callback.h" |
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
181 pending_cdm_attached_cb_ = cdm_attached_cb; | 181 pending_cdm_attached_cb_ = cdm_attached_cb; |
182 | 182 |
183 InitializeAudioRenderer(); | 183 InitializeAudioRenderer(); |
184 } | 184 } |
185 | 185 |
186 void RendererImpl::Flush(const base::Closure& flush_cb) { | 186 void RendererImpl::Flush(const base::Closure& flush_cb) { |
187 DVLOG(1) << __func__; | 187 DVLOG(1) << __func__; |
188 DCHECK(task_runner_->BelongsToCurrentThread()); | 188 DCHECK(task_runner_->BelongsToCurrentThread()); |
189 DCHECK(flush_cb_.is_null()); | 189 DCHECK(flush_cb_.is_null()); |
190 | 190 |
191 if (state_ == STATE_FLUSHED) { | |
192 flush_cb.Run(); | |
xhwang
2017/04/06 05:20:28
Directly run the callback could cause reentrancy i
servolk
2017/04/06 17:11:47
Yes, I agree, PostTask should be safer here. Fixed
| |
193 return; | |
194 } | |
195 | |
191 if (state_ != STATE_PLAYING) { | 196 if (state_ != STATE_PLAYING) { |
192 DCHECK_EQ(state_, STATE_ERROR); | 197 DCHECK_EQ(state_, STATE_ERROR); |
193 return; | 198 return; |
194 } | 199 } |
195 | 200 |
196 // If we are currently handling a media stream status change, then postpone | 201 // If we are currently handling a media stream status change, then postpone |
197 // Flush until after that's done (because stream status changes also flush | 202 // Flush until after that's done (because stream status changes also flush |
198 // audio_renderer_/video_renderer_ and they need to be restarted before they | 203 // audio_renderer_/video_renderer_ and they need to be restarted before they |
199 // can be flushed again). OnStreamRestartCompleted will resume Flush | 204 // can be flushed again). OnStreamRestartCompleted will resume Flush |
200 // processing after audio/video restart has completed and there are no other | 205 // processing after audio/video restart has completed and there are no other |
201 // pending stream status changes. | 206 // pending stream status changes. |
202 if (restarting_audio_ || restarting_video_) { | 207 if (restarting_audio_ || restarting_video_) { |
203 DCHECK(!pending_flush_cb_); | 208 DCHECK(!pending_flush_cb_); |
204 pending_flush_cb_ = flush_cb; | 209 pending_flush_cb_ = flush_cb; |
205 pending_actions_.push_back( | 210 pending_actions_.push_back( |
206 base::Bind(&RendererImpl::Flush, weak_this_, pending_flush_cb_)); | 211 base::Bind(&RendererImpl::Flush, weak_this_, pending_flush_cb_)); |
xhwang
2017/04/06 05:20:28
oh, this is based on your other CL? I thought you
servolk
2017/04/06 17:11:47
I have initially create it based on my other CL, t
| |
207 return; | 212 return; |
208 } | 213 } |
209 | 214 |
210 if (pending_flush_cb_) { | 215 if (pending_flush_cb_) { |
211 DCHECK(flush_cb.Equals(pending_flush_cb_)); | 216 DCHECK(flush_cb.Equals(pending_flush_cb_)); |
212 base::ResetAndReturn(&pending_flush_cb_); | 217 base::ResetAndReturn(&pending_flush_cb_); |
213 } | 218 } |
214 | 219 |
215 flush_cb_ = flush_cb; | 220 flush_cb_ = flush_cb; |
216 state_ = STATE_FLUSHING; | 221 state_ = STATE_FLUSHING; |
217 | 222 |
218 if (time_ticking_) | 223 if (time_ticking_) |
219 PausePlayback(); | 224 PausePlayback(); |
220 | 225 |
221 FlushAudioRenderer(); | 226 FlushAudioRenderer(); |
222 } | 227 } |
223 | 228 |
224 void RendererImpl::StartPlayingFrom(base::TimeDelta time) { | 229 void RendererImpl::StartPlayingFrom(base::TimeDelta time) { |
225 DVLOG(1) << __func__; | 230 DVLOG(1) << __func__; |
226 DCHECK(task_runner_->BelongsToCurrentThread()); | 231 DCHECK(task_runner_->BelongsToCurrentThread()); |
227 | 232 |
228 if (state_ != STATE_PLAYING) { | 233 if (state_ != STATE_FLUSHED) { |
229 DCHECK_EQ(state_, STATE_ERROR); | 234 DCHECK_EQ(state_, STATE_ERROR); |
230 return; | 235 return; |
231 } | 236 } |
232 | 237 |
233 time_source_->SetMediaTime(time); | 238 time_source_->SetMediaTime(time); |
234 | 239 |
240 state_ = STATE_PLAYING; | |
235 if (audio_renderer_) | 241 if (audio_renderer_) |
236 audio_renderer_->StartPlaying(); | 242 audio_renderer_->StartPlaying(); |
237 if (video_renderer_) | 243 if (video_renderer_) |
238 video_renderer_->StartPlayingFrom(time); | 244 video_renderer_->StartPlayingFrom(time); |
239 } | 245 } |
240 | 246 |
241 void RendererImpl::SetPlaybackRate(double playback_rate) { | 247 void RendererImpl::SetPlaybackRate(double playback_rate) { |
242 DVLOG(1) << __func__ << "(" << playback_rate << ")"; | 248 DVLOG(1) << __func__ << "(" << playback_rate << ")"; |
243 DCHECK(task_runner_->BelongsToCurrentThread()); | 249 DCHECK(task_runner_->BelongsToCurrentThread()); |
244 | 250 |
245 // Playback rate changes are only carried out while playing. | 251 // Playback rate changes are only carried out while playing. |
246 if (state_ != STATE_PLAYING) | 252 if (state_ != STATE_PLAYING && state_ != STATE_FLUSHED) |
247 return; | 253 return; |
248 | 254 |
249 time_source_->SetPlaybackRate(playback_rate); | 255 time_source_->SetPlaybackRate(playback_rate); |
250 | 256 |
251 const double old_rate = playback_rate_; | 257 const double old_rate = playback_rate_; |
252 playback_rate_ = playback_rate; | 258 playback_rate_ = playback_rate; |
253 if (!time_ticking_ || !video_renderer_) | 259 if (!time_ticking_ || !video_renderer_) |
254 return; | 260 return; |
255 | 261 |
256 if (old_rate == 0 && playback_rate > 0) | 262 if (old_rate == 0 && playback_rate > 0) |
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
442 media_resource_->SetStreamStatusChangeCB( | 448 media_resource_->SetStreamStatusChangeCB( |
443 base::Bind(&RendererImpl::OnStreamStatusChanged, weak_this_)); | 449 base::Bind(&RendererImpl::OnStreamStatusChanged, weak_this_)); |
444 | 450 |
445 if (audio_renderer_) { | 451 if (audio_renderer_) { |
446 time_source_ = audio_renderer_->GetTimeSource(); | 452 time_source_ = audio_renderer_->GetTimeSource(); |
447 } else if (!time_source_) { | 453 } else if (!time_source_) { |
448 wall_clock_time_source_.reset(new WallClockTimeSource()); | 454 wall_clock_time_source_.reset(new WallClockTimeSource()); |
449 time_source_ = wall_clock_time_source_.get(); | 455 time_source_ = wall_clock_time_source_.get(); |
450 } | 456 } |
451 | 457 |
452 state_ = STATE_PLAYING; | 458 state_ = STATE_FLUSHED; |
453 DCHECK(time_source_); | 459 DCHECK(time_source_); |
454 DCHECK(audio_renderer_ || video_renderer_); | 460 DCHECK(audio_renderer_ || video_renderer_); |
455 | 461 |
456 FinishInitialization(PIPELINE_OK); | 462 FinishInitialization(PIPELINE_OK); |
457 } | 463 } |
458 | 464 |
459 void RendererImpl::FlushAudioRenderer() { | 465 void RendererImpl::FlushAudioRenderer() { |
460 DVLOG(1) << __func__; | 466 DVLOG(1) << __func__; |
461 DCHECK(task_runner_->BelongsToCurrentThread()); | 467 DCHECK(task_runner_->BelongsToCurrentThread()); |
462 DCHECK_EQ(state_, STATE_FLUSHING); | 468 DCHECK_EQ(state_, STATE_FLUSHING); |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
514 if (state_ == STATE_ERROR) { | 520 if (state_ == STATE_ERROR) { |
515 DCHECK(flush_cb_.is_null()); | 521 DCHECK(flush_cb_.is_null()); |
516 return; | 522 return; |
517 } | 523 } |
518 | 524 |
519 DCHECK_EQ(state_, STATE_FLUSHING); | 525 DCHECK_EQ(state_, STATE_FLUSHING); |
520 DCHECK(!flush_cb_.is_null()); | 526 DCHECK(!flush_cb_.is_null()); |
521 | 527 |
522 DCHECK_EQ(video_buffering_state_, BUFFERING_HAVE_NOTHING); | 528 DCHECK_EQ(video_buffering_state_, BUFFERING_HAVE_NOTHING); |
523 video_ended_ = false; | 529 video_ended_ = false; |
524 state_ = STATE_PLAYING; | 530 state_ = STATE_FLUSHED; |
525 base::ResetAndReturn(&flush_cb_).Run(); | 531 base::ResetAndReturn(&flush_cb_).Run(); |
526 | 532 |
527 if (!pending_actions_.empty()) { | 533 if (!pending_actions_.empty()) { |
528 base::Closure closure = pending_actions_.front(); | 534 base::Closure closure = pending_actions_.front(); |
529 pending_actions_.pop_front(); | 535 pending_actions_.pop_front(); |
530 closure.Run(); | 536 closure.Run(); |
531 } | 537 } |
532 } | 538 } |
533 | 539 |
534 void RendererImpl::OnStreamStatusChanged(DemuxerStream* stream, | 540 void RendererImpl::OnStreamStatusChanged(DemuxerStream* stream, |
535 bool enabled, | 541 bool enabled, |
536 base::TimeDelta time) { | 542 base::TimeDelta time) { |
537 DCHECK(task_runner_->BelongsToCurrentThread()); | 543 DCHECK(task_runner_->BelongsToCurrentThread()); |
538 DCHECK(stream); | 544 DCHECK(stream); |
539 bool video = (stream->type() == DemuxerStream::VIDEO); | 545 bool video = (stream->type() == DemuxerStream::VIDEO); |
540 DVLOG(1) << __func__ << (video ? " video" : " audio") << " stream=" << stream | 546 DVLOG(1) << __func__ << (video ? " video" : " audio") << " stream=" << stream |
541 << " enabled=" << enabled << " time=" << time.InSecondsF(); | 547 << " enabled=" << enabled << " time=" << time.InSecondsF(); |
542 if ((state_ != STATE_PLAYING && state_ != STATE_FLUSHING) || | 548 |
549 if ((state_ != STATE_PLAYING && state_ != STATE_FLUSHING && | |
550 state_ != STATE_FLUSHED) || | |
543 (audio_ended_ && video_ended_)) | 551 (audio_ended_ && video_ended_)) |
544 return; | 552 return; |
545 if (restarting_audio_ || restarting_video_ || flush_cb_) { | 553 if (restarting_audio_ || restarting_video_ || flush_cb_) { |
546 DVLOG(3) << __func__ << ": postponed stream " << stream | 554 DVLOG(3) << __func__ << ": postponed stream " << stream |
547 << " status change handling."; | 555 << " status change handling."; |
548 pending_actions_.push_back(base::Bind(&RendererImpl::OnStreamStatusChanged, | 556 pending_actions_.push_back(base::Bind(&RendererImpl::OnStreamStatusChanged, |
549 weak_this_, stream, enabled, time)); | 557 weak_this_, stream, enabled, time)); |
550 return; | 558 return; |
551 } | 559 } |
552 if (stream->type() == DemuxerStream::VIDEO) { | 560 if (stream->type() == DemuxerStream::VIDEO) { |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
627 OnError(status); | 635 OnError(status); |
628 return; | 636 return; |
629 } | 637 } |
630 RestartVideoRenderer(stream, time); | 638 RestartVideoRenderer(stream, time); |
631 } | 639 } |
632 | 640 |
633 void RendererImpl::RestartAudioRenderer(DemuxerStream* stream, | 641 void RendererImpl::RestartAudioRenderer(DemuxerStream* stream, |
634 base::TimeDelta time) { | 642 base::TimeDelta time) { |
635 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); | 643 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); |
636 DCHECK(task_runner_->BelongsToCurrentThread()); | 644 DCHECK(task_runner_->BelongsToCurrentThread()); |
637 DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHING); | 645 DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHED); |
638 DCHECK(time_source_); | 646 DCHECK(time_source_); |
639 DCHECK(audio_renderer_); | 647 DCHECK(audio_renderer_); |
640 DCHECK_EQ(stream, current_audio_stream_); | 648 DCHECK_EQ(stream, current_audio_stream_); |
641 | 649 |
642 audio_ended_ = false; | 650 audio_ended_ = false; |
643 audio_renderer_->StartPlaying(); | 651 audio_renderer_->StartPlaying(); |
644 } | 652 } |
645 | 653 |
646 void RendererImpl::RestartVideoRenderer(DemuxerStream* stream, | 654 void RendererImpl::RestartVideoRenderer(DemuxerStream* stream, |
647 base::TimeDelta time) { | 655 base::TimeDelta time) { |
648 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); | 656 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); |
649 DCHECK(task_runner_->BelongsToCurrentThread()); | 657 DCHECK(task_runner_->BelongsToCurrentThread()); |
650 DCHECK(video_renderer_); | 658 DCHECK(video_renderer_); |
651 DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHING); | 659 DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHED); |
652 DCHECK_EQ(stream, current_video_stream_); | 660 DCHECK_EQ(stream, current_video_stream_); |
653 | 661 |
654 video_ended_ = false; | 662 video_ended_ = false; |
655 video_renderer_->StartPlayingFrom(time); | 663 video_renderer_->StartPlayingFrom(time); |
656 } | 664 } |
657 | 665 |
658 void RendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) { | 666 void RendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) { |
659 DCHECK(task_runner_->BelongsToCurrentThread()); | 667 DCHECK(task_runner_->BelongsToCurrentThread()); |
660 client_->OnStatisticsUpdate(stats); | 668 client_->OnStatisticsUpdate(stats); |
661 } | 669 } |
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
828 DCHECK(task_runner_->BelongsToCurrentThread()); | 836 DCHECK(task_runner_->BelongsToCurrentThread()); |
829 switch (state_) { | 837 switch (state_) { |
830 case STATE_PLAYING: | 838 case STATE_PLAYING: |
831 DCHECK(PlaybackHasEnded() || WaitingForEnoughData() || restarting_audio_) | 839 DCHECK(PlaybackHasEnded() || WaitingForEnoughData() || restarting_audio_) |
832 << "Playback should only pause due to ending or underflowing or" | 840 << "Playback should only pause due to ending or underflowing or" |
833 " when restarting audio stream"; | 841 " when restarting audio stream"; |
834 | 842 |
835 break; | 843 break; |
836 | 844 |
837 case STATE_FLUSHING: | 845 case STATE_FLUSHING: |
846 case STATE_FLUSHED: | |
838 // It's OK to pause playback when flushing. | 847 // It's OK to pause playback when flushing. |
839 break; | 848 break; |
840 | 849 |
841 case STATE_UNINITIALIZED: | 850 case STATE_UNINITIALIZED: |
842 case STATE_INIT_PENDING_CDM: | 851 case STATE_INIT_PENDING_CDM: |
843 case STATE_INITIALIZING: | 852 case STATE_INITIALIZING: |
844 NOTREACHED() << "Invalid state: " << state_; | 853 NOTREACHED() << "Invalid state: " << state_; |
845 break; | 854 break; |
846 | 855 |
847 case STATE_ERROR: | 856 case STATE_ERROR: |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
951 DCHECK(task_runner_->BelongsToCurrentThread()); | 960 DCHECK(task_runner_->BelongsToCurrentThread()); |
952 client_->OnVideoNaturalSizeChange(size); | 961 client_->OnVideoNaturalSizeChange(size); |
953 } | 962 } |
954 | 963 |
955 void RendererImpl::OnVideoOpacityChange(bool opaque) { | 964 void RendererImpl::OnVideoOpacityChange(bool opaque) { |
956 DCHECK(task_runner_->BelongsToCurrentThread()); | 965 DCHECK(task_runner_->BelongsToCurrentThread()); |
957 client_->OnVideoOpacityChange(opaque); | 966 client_->OnVideoOpacityChange(opaque); |
958 } | 967 } |
959 | 968 |
960 } // namespace media | 969 } // namespace media |
OLD | NEW |