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

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

Issue 2605473002: Fix processing of multiple stream status changes by renderer (Closed)
Patch Set: CR feedback (use a single unified notification queue) Created 3 years, 11 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
« no previous file with comments | « media/renderers/renderer_impl.h ('k') | media/renderers/renderer_impl_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
201 } 201 }
202 202
203 time_source_->SetMediaTime(time); 203 time_source_->SetMediaTime(time);
204 204
205 if (audio_renderer_) 205 if (audio_renderer_)
206 audio_renderer_->StartPlaying(); 206 audio_renderer_->StartPlaying();
207 if (video_renderer_) 207 if (video_renderer_)
208 video_renderer_->StartPlayingFrom(time); 208 video_renderer_->StartPlayingFrom(time);
209 } 209 }
210 210
211 void RendererImpl::RestartStreamPlayback(DemuxerStream* stream, 211 void RendererImpl::OnStreamStatusChanged(DemuxerStream* stream,
212 bool enabled, 212 bool enabled,
213 base::TimeDelta time) { 213 base::TimeDelta time) {
214 DCHECK(task_runner_->BelongsToCurrentThread()); 214 DCHECK(task_runner_->BelongsToCurrentThread());
215 DCHECK(stream); 215 DCHECK(stream);
216 bool video = (stream->type() == DemuxerStream::VIDEO); 216 bool video = (stream->type() == DemuxerStream::VIDEO);
217 DVLOG(1) << __func__ << (video ? " video" : " audio") << " stream=" << stream 217 DVLOG(1) << __func__ << (video ? " video" : " audio") << " stream=" << stream
218 << " enabled=" << stream->enabled() << " time=" << time.InSecondsF(); 218 << " enabled=" << enabled << " time=" << time.InSecondsF();
219 if ((state_ != STATE_PLAYING) || (audio_ended_ && video_ended_)) 219 if ((state_ != STATE_PLAYING) || (audio_ended_ && video_ended_))
220 return; 220 return;
221 if (restarting_audio_ || restarting_video_) {
222 DVLOG(3) << __func__ << ": postponed stream " << stream
223 << " status change handling.";
224 pending_stream_status_notifications_.push_back(
225 base::Bind(&RendererImpl::OnStreamStatusChanged, weak_this_, stream,
226 enabled, time));
227 return;
228 }
221 if (stream->type() == DemuxerStream::VIDEO) { 229 if (stream->type() == DemuxerStream::VIDEO) {
222 DCHECK(video_renderer_); 230 DCHECK(video_renderer_);
223 if (restarting_video_)
224 return;
225 restarting_video_ = true; 231 restarting_video_ = true;
226 video_renderer_->Flush( 232 video_renderer_->Flush(
227 base::Bind(&RendererImpl::RestartVideoRenderer, weak_this_, time)); 233 base::Bind(&RendererImpl::RestartVideoRenderer, weak_this_, time));
228 } else if (stream->type() == DemuxerStream::AUDIO) { 234 } else if (stream->type() == DemuxerStream::AUDIO) {
229 DCHECK(audio_renderer_); 235 DCHECK(audio_renderer_);
230 DCHECK(time_source_); 236 DCHECK(time_source_);
231 if (restarting_audio_)
232 return;
233 restarting_audio_ = true; 237 restarting_audio_ = true;
234 // Stop ticking (transition into paused state) in audio renderer before 238 // Stop ticking (transition into paused state) in audio renderer before
235 // calling Flush, since after Flush we are going to restart playback by 239 // calling Flush, since after Flush we are going to restart playback by
236 // calling audio renderer StartPlaying which would fail in playing state. 240 // calling audio renderer StartPlaying which would fail in playing state.
237 if (time_ticking_) { 241 if (time_ticking_) {
238 time_ticking_ = false; 242 time_ticking_ = false;
239 time_source_->StopTicking(); 243 time_source_->StopTicking();
240 } 244 }
241 audio_renderer_->Flush( 245 audio_renderer_->Flush(
242 base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time)); 246 base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time));
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
373 377
374 DemuxerStream* audio_stream = 378 DemuxerStream* audio_stream =
375 demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO); 379 demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO);
376 if (!audio_stream) { 380 if (!audio_stream) {
377 audio_renderer_.reset(); 381 audio_renderer_.reset();
378 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); 382 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
379 return; 383 return;
380 } 384 }
381 385
382 audio_stream->SetStreamStatusChangeCB(base::Bind( 386 audio_stream->SetStreamStatusChangeCB(base::Bind(
383 &RendererImpl::RestartStreamPlayback, weak_this_, audio_stream)); 387 &RendererImpl::OnStreamStatusChanged, weak_this_, audio_stream));
384 388
385 audio_renderer_client_.reset( 389 audio_renderer_client_.reset(
386 new RendererClientInternal(DemuxerStream::AUDIO, this)); 390 new RendererClientInternal(DemuxerStream::AUDIO, this));
387 // Note: After the initialization of a renderer, error events from it may 391 // Note: After the initialization of a renderer, error events from it may
388 // happen at any time and all future calls must guard against STATE_ERROR. 392 // happen at any time and all future calls must guard against STATE_ERROR.
389 audio_renderer_->Initialize(audio_stream, cdm_context_, 393 audio_renderer_->Initialize(audio_stream, cdm_context_,
390 audio_renderer_client_.get(), done_cb); 394 audio_renderer_client_.get(), done_cb);
391 } 395 }
392 396
393 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) { 397 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) {
(...skipping 28 matching lines...) Expand all
422 426
423 DemuxerStream* video_stream = 427 DemuxerStream* video_stream =
424 demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO); 428 demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO);
425 if (!video_stream) { 429 if (!video_stream) {
426 video_renderer_.reset(); 430 video_renderer_.reset();
427 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); 431 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
428 return; 432 return;
429 } 433 }
430 434
431 video_stream->SetStreamStatusChangeCB(base::Bind( 435 video_stream->SetStreamStatusChangeCB(base::Bind(
432 &RendererImpl::RestartStreamPlayback, weak_this_, video_stream)); 436 &RendererImpl::OnStreamStatusChanged, weak_this_, video_stream));
433 437
434 video_renderer_client_.reset( 438 video_renderer_client_.reset(
435 new RendererClientInternal(DemuxerStream::VIDEO, this)); 439 new RendererClientInternal(DemuxerStream::VIDEO, this));
436 video_renderer_->Initialize( 440 video_renderer_->Initialize(
437 video_stream, cdm_context_, video_renderer_client_.get(), 441 video_stream, cdm_context_, video_renderer_client_.get(),
438 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)), 442 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)),
439 done_cb); 443 done_cb);
440 } 444 }
441 445
442 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) { 446 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) {
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
557 return "HAVE_ENOUGH"; 561 return "HAVE_ENOUGH";
558 } 562 }
559 NOTREACHED(); 563 NOTREACHED();
560 return ""; 564 return "";
561 } 565 }
562 } 566 }
563 567
564 bool RendererImpl::HandleRestartedStreamBufferingChanges( 568 bool RendererImpl::HandleRestartedStreamBufferingChanges(
565 DemuxerStream::Type type, 569 DemuxerStream::Type type,
566 BufferingState new_buffering_state) { 570 BufferingState new_buffering_state) {
571 DCHECK(task_runner_->BelongsToCurrentThread());
567 // When restarting playback we want to defer the BUFFERING_HAVE_NOTHING for 572 // When restarting playback we want to defer the BUFFERING_HAVE_NOTHING for
568 // the stream being restarted, to allow continuing uninterrupted playback on 573 // the stream being restarted, to allow continuing uninterrupted playback on
569 // the other stream. 574 // the other stream.
570 if (type == DemuxerStream::VIDEO && restarting_video_) { 575 if (type == DemuxerStream::VIDEO && restarting_video_) {
571 if (new_buffering_state == BUFFERING_HAVE_ENOUGH) { 576 if (new_buffering_state == BUFFERING_HAVE_ENOUGH) {
572 DVLOG(1) << __func__ << " Got BUFFERING_HAVE_ENOUGH for video stream," 577 DVLOG(1) << __func__ << " Got BUFFERING_HAVE_ENOUGH for video stream,"
573 " resuming playback."; 578 " resuming playback.";
574 restarting_video_ = false; 579 task_runner_->PostTask(
580 FROM_HERE,
581 base::Bind(&RendererImpl::OnStreamRestartCompleted, weak_this_));
575 if (state_ == STATE_PLAYING && 582 if (state_ == STATE_PLAYING &&
576 !deferred_video_underflow_cb_.IsCancelled()) { 583 !deferred_video_underflow_cb_.IsCancelled()) {
577 // If deferred_video_underflow_cb_ wasn't triggered, then audio should 584 // If deferred_video_underflow_cb_ wasn't triggered, then audio should
578 // still be playing, we only need to unpause the video stream. 585 // still be playing, we only need to unpause the video stream.
579 DVLOG(4) << "deferred_video_underflow_cb_.Cancel()"; 586 DVLOG(4) << "deferred_video_underflow_cb_.Cancel()";
580 deferred_video_underflow_cb_.Cancel(); 587 deferred_video_underflow_cb_.Cancel();
581 video_buffering_state_ = new_buffering_state; 588 video_buffering_state_ = new_buffering_state;
582 if (playback_rate_ > 0) 589 if (playback_rate_ > 0)
583 video_renderer_->OnTimeProgressing(); 590 video_renderer_->OnTimeProgressing();
584 return true; 591 return true;
(...skipping 24 matching lines...) Expand all
609 // Cancel the deferred callback and report the underflow immediately. 616 // Cancel the deferred callback and report the underflow immediately.
610 DVLOG(4) << "deferred_audio_restart_underflow_cb_.Cancel()"; 617 DVLOG(4) << "deferred_audio_restart_underflow_cb_.Cancel()";
611 deferred_audio_restart_underflow_cb_.Cancel(); 618 deferred_audio_restart_underflow_cb_.Cancel();
612 } else if (new_buffering_state == BUFFERING_HAVE_ENOUGH) { 619 } else if (new_buffering_state == BUFFERING_HAVE_ENOUGH) {
613 DVLOG(1) << __func__ << " Got BUFFERING_HAVE_ENOUGH for audio stream," 620 DVLOG(1) << __func__ << " Got BUFFERING_HAVE_ENOUGH for audio stream,"
614 " resuming playback."; 621 " resuming playback.";
615 deferred_audio_restart_underflow_cb_.Cancel(); 622 deferred_audio_restart_underflow_cb_.Cancel();
616 // Now that we have decoded enough audio, pause playback momentarily to 623 // Now that we have decoded enough audio, pause playback momentarily to
617 // ensure video renderer is synchronised with audio. 624 // ensure video renderer is synchronised with audio.
618 PausePlayback(); 625 PausePlayback();
619 restarting_audio_ = false; 626 task_runner_->PostTask(
627 FROM_HERE,
628 base::Bind(&RendererImpl::OnStreamRestartCompleted, weak_this_));
620 } 629 }
621 } 630 }
622 return false; 631 return false;
623 } 632 }
624 633
634 void RendererImpl::OnStreamRestartCompleted() {
635 DCHECK(restarting_audio_ || restarting_video_);
636 restarting_audio_ = false;
637 restarting_video_ = false;
638 if (!pending_stream_status_notifications_.empty()) {
639 pending_stream_status_notifications_.front().Run();
640 pending_stream_status_notifications_.pop_front();
641 }
642 }
643
625 void RendererImpl::OnBufferingStateChange(DemuxerStream::Type type, 644 void RendererImpl::OnBufferingStateChange(DemuxerStream::Type type,
626 BufferingState new_buffering_state) { 645 BufferingState new_buffering_state) {
627 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO)); 646 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO));
628 BufferingState* buffering_state = type == DemuxerStream::AUDIO 647 BufferingState* buffering_state = type == DemuxerStream::AUDIO
629 ? &audio_buffering_state_ 648 ? &audio_buffering_state_
630 : &video_buffering_state_; 649 : &video_buffering_state_;
631 650
632 DVLOG(1) << __func__ << (type == DemuxerStream::AUDIO ? " audio " : " video ") 651 DVLOG(1) << __func__ << (type == DemuxerStream::AUDIO ? " audio " : " video ")
633 << BufferingStateStr(*buffering_state) << " -> " 652 << BufferingStateStr(*buffering_state) << " -> "
634 << BufferingStateStr(new_buffering_state); 653 << BufferingStateStr(new_buffering_state);
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
834 DCHECK(task_runner_->BelongsToCurrentThread()); 853 DCHECK(task_runner_->BelongsToCurrentThread());
835 client_->OnVideoNaturalSizeChange(size); 854 client_->OnVideoNaturalSizeChange(size);
836 } 855 }
837 856
838 void RendererImpl::OnVideoOpacityChange(bool opaque) { 857 void RendererImpl::OnVideoOpacityChange(bool opaque) {
839 DCHECK(task_runner_->BelongsToCurrentThread()); 858 DCHECK(task_runner_->BelongsToCurrentThread());
840 client_->OnVideoOpacityChange(opaque); 859 client_->OnVideoOpacityChange(opaque);
841 } 860 }
842 861
843 } // namespace media 862 } // namespace media
OLDNEW
« no previous file with comments | « media/renderers/renderer_impl.h ('k') | media/renderers/renderer_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698