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

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

Issue 2804493002: Introduce a FLUSHED state in media::RendererImpl (Closed)
Patch Set: 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 "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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698