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

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

Issue 1935873002: Implement disabling and enabling media tracks (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@track-control2
Patch Set: rebase Created 4 years, 5 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 12 matching lines...) Expand all
23 #include "media/base/time_source.h" 23 #include "media/base/time_source.h"
24 #include "media/base/video_decoder_config.h" 24 #include "media/base/video_decoder_config.h"
25 #include "media/base/video_renderer.h" 25 #include "media/base/video_renderer.h"
26 #include "media/base/wall_clock_time_source.h" 26 #include "media/base/wall_clock_time_source.h"
27 27
28 namespace media { 28 namespace media {
29 29
30 // See |video_underflow_threshold_|. 30 // See |video_underflow_threshold_|.
31 static const int kDefaultVideoUnderflowThresholdMs = 3000; 31 static const int kDefaultVideoUnderflowThresholdMs = 3000;
32 32
33 static const int kAudioRestartUnderflowThresholdMs = 2000;
34
33 class RendererImpl::RendererClientInternal : public RendererClient { 35 class RendererImpl::RendererClientInternal : public RendererClient {
34 public: 36 public:
35 RendererClientInternal(DemuxerStream::Type type, RendererImpl* renderer) 37 RendererClientInternal(DemuxerStream::Type type, RendererImpl* renderer)
36 : type_(type), renderer_(renderer) { 38 : type_(type), renderer_(renderer) {
37 DCHECK((type_ == DemuxerStream::AUDIO) || (type_ == DemuxerStream::VIDEO)); 39 DCHECK((type_ == DemuxerStream::AUDIO) || (type_ == DemuxerStream::VIDEO));
38 } 40 }
39 41
40 void OnError(PipelineStatus error) override { renderer_->OnError(error); } 42 void OnError(PipelineStatus error) override { renderer_->OnError(error); }
41 void OnEnded() override { renderer_->OnRendererEnded(type_); } 43 void OnEnded() override { renderer_->OnRendererEnded(type_); }
42 void OnStatisticsUpdate(const PipelineStatistics& stats) override { 44 void OnStatisticsUpdate(const PipelineStatistics& stats) override {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
122 DCHECK_EQ(state_, STATE_UNINITIALIZED); 124 DCHECK_EQ(state_, STATE_UNINITIALIZED);
123 DCHECK(!init_cb.is_null()); 125 DCHECK(!init_cb.is_null());
124 DCHECK(client); 126 DCHECK(client);
125 DCHECK(demuxer_stream_provider->GetStream(DemuxerStream::AUDIO) || 127 DCHECK(demuxer_stream_provider->GetStream(DemuxerStream::AUDIO) ||
126 demuxer_stream_provider->GetStream(DemuxerStream::VIDEO)); 128 demuxer_stream_provider->GetStream(DemuxerStream::VIDEO));
127 129
128 client_ = client; 130 client_ = client;
129 demuxer_stream_provider_ = demuxer_stream_provider; 131 demuxer_stream_provider_ = demuxer_stream_provider;
130 init_cb_ = init_cb; 132 init_cb_ = init_cb;
131 133
134 DemuxerStream* audio_stream =
135 demuxer_stream_provider->GetStream(DemuxerStream::AUDIO);
136 if (audio_stream)
137 audio_stream->SetStreamRestartedCB(
138 base::Bind(&RendererImpl::RestartStreamPlayback, weak_this_));
139 DemuxerStream* video_stream =
140 demuxer_stream_provider->GetStream(DemuxerStream::VIDEO);
141 if (video_stream)
142 video_stream->SetStreamRestartedCB(
143 base::Bind(&RendererImpl::RestartStreamPlayback, weak_this_));
144
132 if (HasEncryptedStream() && !cdm_context_) { 145 if (HasEncryptedStream() && !cdm_context_) {
133 state_ = STATE_INIT_PENDING_CDM; 146 state_ = STATE_INIT_PENDING_CDM;
134 return; 147 return;
135 } 148 }
136 149
137 state_ = STATE_INITIALIZING; 150 state_ = STATE_INITIALIZING;
138 InitializeAudioRenderer(); 151 InitializeAudioRenderer();
139 } 152 }
140 153
141 void RendererImpl::SetCdm(CdmContext* cdm_context, 154 void RendererImpl::SetCdm(CdmContext* cdm_context,
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
194 } 207 }
195 208
196 time_source_->SetMediaTime(time); 209 time_source_->SetMediaTime(time);
197 210
198 if (audio_renderer_) 211 if (audio_renderer_)
199 audio_renderer_->StartPlaying(); 212 audio_renderer_->StartPlaying();
200 if (video_renderer_) 213 if (video_renderer_)
201 video_renderer_->StartPlayingFrom(time); 214 video_renderer_->StartPlayingFrom(time);
202 } 215 }
203 216
217 void RendererImpl::RestartStreamPlayback(DemuxerStream* stream,
218 base::TimeDelta time) {
219 DVLOG(1) << __FUNCTION__ << " stream=" << stream
220 << " time=" << time.InSecondsF();
221 DCHECK(task_runner_->BelongsToCurrentThread());
222 if (state_ != STATE_PLAYING)
223 return;
224 if (stream->type() == DemuxerStream::VIDEO) {
225 DCHECK(video_renderer_);
226 if (restarting_video_)
227 return;
228 restarting_video_ = true;
229 video_renderer_->Flush(
230 base::Bind(&RendererImpl::RestartVideoRenderer, weak_this_, time));
231 } else if (stream->type() == DemuxerStream::AUDIO) {
232 DCHECK(audio_renderer_);
233 DCHECK(time_source_);
234 if (restarting_audio_)
235 return;
236 restarting_audio_ = true;
237 // Stop ticking (transition into paused state) in audio renderer before
238 // calling Flush, since after Flush we are going to restart playback by
239 // calling audio renderer StartPlaying which would fail in playing state.
240 if (time_ticking_) {
241 time_ticking_ = false;
242 time_source_->StopTicking();
243 }
244 audio_renderer_->Flush(
245 base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time));
246 }
247 }
248
249 void RendererImpl::RestartVideoRenderer(base::TimeDelta time) {
250 DCHECK(task_runner_->BelongsToCurrentThread());
251 DVLOG(2) << __FUNCTION__;
252 video_ended_ = false;
253 if (state_ == STATE_PLAYING) {
254 DCHECK(video_renderer_);
255 video_renderer_->StartPlayingFrom(time);
256 }
257 }
258
259 void RendererImpl::RestartAudioRenderer(base::TimeDelta time) {
260 DCHECK(task_runner_->BelongsToCurrentThread());
261 DVLOG(2) << __FUNCTION__;
262 audio_ended_ = false;
263 if (state_ == STATE_PLAYING) {
264 DCHECK(time_source_);
265 DCHECK(audio_renderer_);
266 audio_renderer_->StartPlaying();
267 }
268 }
269
204 void RendererImpl::SetPlaybackRate(double playback_rate) { 270 void RendererImpl::SetPlaybackRate(double playback_rate) {
205 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; 271 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")";
206 DCHECK(task_runner_->BelongsToCurrentThread()); 272 DCHECK(task_runner_->BelongsToCurrentThread());
207 273
208 // Playback rate changes are only carried out while playing. 274 // Playback rate changes are only carried out while playing.
209 if (state_ != STATE_PLAYING) 275 if (state_ != STATE_PLAYING)
210 return; 276 return;
211 277
212 time_source_->SetPlaybackRate(playback_rate); 278 time_source_->SetPlaybackRate(playback_rate);
213 279
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
436 if (state_ == STATE_ERROR) { 502 if (state_ == STATE_ERROR) {
437 DCHECK(flush_cb_.is_null()); 503 DCHECK(flush_cb_.is_null());
438 return; 504 return;
439 } 505 }
440 506
441 DCHECK_EQ(state_, STATE_FLUSHING); 507 DCHECK_EQ(state_, STATE_FLUSHING);
442 DCHECK(!flush_cb_.is_null()); 508 DCHECK(!flush_cb_.is_null());
443 509
444 // If we had a deferred video renderer underflow prior to the flush, it should 510 // If we had a deferred video renderer underflow prior to the flush, it should
445 // have been cleared by the audio renderer changing to BUFFERING_HAVE_NOTHING. 511 // have been cleared by the audio renderer changing to BUFFERING_HAVE_NOTHING.
446 DCHECK(deferred_underflow_cb_.IsCancelled()); 512 DCHECK(deferred_video_underflow_cb_.IsCancelled());
447 513
448 DCHECK_EQ(audio_buffering_state_, BUFFERING_HAVE_NOTHING); 514 DCHECK_EQ(audio_buffering_state_, BUFFERING_HAVE_NOTHING);
449 audio_ended_ = false; 515 audio_ended_ = false;
450 FlushVideoRenderer(); 516 FlushVideoRenderer();
451 } 517 }
452 518
453 void RendererImpl::FlushVideoRenderer() { 519 void RendererImpl::FlushVideoRenderer() {
454 DVLOG(1) << __FUNCTION__; 520 DVLOG(1) << __FUNCTION__;
455 DCHECK(task_runner_->BelongsToCurrentThread()); 521 DCHECK(task_runner_->BelongsToCurrentThread());
456 DCHECK_EQ(state_, STATE_FLUSHING); 522 DCHECK_EQ(state_, STATE_FLUSHING);
(...skipping 24 matching lines...) Expand all
481 video_ended_ = false; 547 video_ended_ = false;
482 state_ = STATE_PLAYING; 548 state_ = STATE_PLAYING;
483 base::ResetAndReturn(&flush_cb_).Run(); 549 base::ResetAndReturn(&flush_cb_).Run();
484 } 550 }
485 551
486 void RendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) { 552 void RendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) {
487 DCHECK(task_runner_->BelongsToCurrentThread()); 553 DCHECK(task_runner_->BelongsToCurrentThread());
488 client_->OnStatisticsUpdate(stats); 554 client_->OnStatisticsUpdate(stats);
489 } 555 }
490 556
557 namespace {
558
559 const char* BufferingStateStr(BufferingState state) {
560 switch (state) {
561 case BUFFERING_HAVE_NOTHING:
562 return "HAVE_NOTHING";
563 case BUFFERING_HAVE_ENOUGH:
564 return "HAVE_ENOUGH";
565 }
566 NOTREACHED();
567 return "";
568 }
569 }
570
571 bool RendererImpl::HandleRestartedStreamBufferingChanges(
572 DemuxerStream::Type type,
573 BufferingState new_buffering_state) {
574 // When restarting playback we want to defer the BUFFERING_HAVE_NOTHING for
575 // the stream being restarted, to allow continuing uninterrupted playback on
576 // the other stream.
577 if (type == DemuxerStream::VIDEO && restarting_video_) {
578 if (new_buffering_state == BUFFERING_HAVE_ENOUGH) {
579 DVLOG(1) << __FUNCTION__ << " Got BUFFERING_HAVE_ENOUGH for video stream,"
580 " resuming playback.";
581 restarting_video_ = false;
582 if (state_ == STATE_PLAYING &&
583 !deferred_video_underflow_cb_.IsCancelled()) {
584 // If deferred_video_underflow_cb_ wasn't triggered, then audio should
585 // still be playing, we only need to unpause the video stream.
586 DVLOG(4) << "deferred_video_underflow_cb_.Cancel()";
587 deferred_video_underflow_cb_.Cancel();
588 video_buffering_state_ = new_buffering_state;
589 if (playback_rate_ > 0)
590 video_renderer_->OnTimeStateChanged(true);
591 return true;
592 }
593 }
594 // We don't handle the BUFFERING_HAVE_NOTHING case explicitly here, since
595 // the existing logic for deferring video underflow reporting in
596 // OnBufferingStateChange is exactly what we need. So fall through to the
597 // regular video underflow handling path in OnBufferingStateChange.
598 }
599
600 if (type == DemuxerStream::AUDIO && restarting_audio_) {
601 if (new_buffering_state == BUFFERING_HAVE_NOTHING) {
602 if (deferred_video_underflow_cb_.IsCancelled() &&
603 deferred_audio_restart_underflow_cb_.IsCancelled()) {
604 DVLOG(1) << __FUNCTION__ << " Deferring BUFFERING_HAVE_NOTHING for "
605 "audio stream which is being restarted.";
606 audio_buffering_state_ = new_buffering_state;
607 deferred_audio_restart_underflow_cb_.Reset(
608 base::Bind(&RendererImpl::OnBufferingStateChange, weak_this_, type,
609 new_buffering_state));
610 task_runner_->PostDelayedTask(
611 FROM_HERE, deferred_audio_restart_underflow_cb_.callback(),
612 base::TimeDelta::FromMilliseconds(
613 kAudioRestartUnderflowThresholdMs));
614 return true;
615 }
616 // Cancel the deferred callback and report the underflow immediately.
617 DVLOG(4) << "deferred_audio_restart_underflow_cb_.Cancel()";
618 deferred_audio_restart_underflow_cb_.Cancel();
619 } else if (new_buffering_state == BUFFERING_HAVE_ENOUGH) {
620 DVLOG(1) << __FUNCTION__ << " Got BUFFERING_HAVE_ENOUGH for audio stream,"
621 " resuming playback.";
622 deferred_audio_restart_underflow_cb_.Cancel();
623 // Now that we have decoded enough audio, pause playback momentarily to
624 // ensure video renderer is synchronised with audio.
625 PausePlayback();
626 restarting_audio_ = false;
627 }
628 }
629 return false;
630 }
631
491 void RendererImpl::OnBufferingStateChange(DemuxerStream::Type type, 632 void RendererImpl::OnBufferingStateChange(DemuxerStream::Type type,
492 BufferingState new_buffering_state) { 633 BufferingState new_buffering_state) {
493 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO)); 634 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO));
494 BufferingState* buffering_state = type == DemuxerStream::AUDIO 635 BufferingState* buffering_state = type == DemuxerStream::AUDIO
495 ? &audio_buffering_state_ 636 ? &audio_buffering_state_
496 : &video_buffering_state_; 637 : &video_buffering_state_;
497 638
498 DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", " 639 DVLOG(1) << __FUNCTION__
499 << new_buffering_state << ") " 640 << (type == DemuxerStream::AUDIO ? " audio " : " video ")
500 << (type == DemuxerStream::AUDIO ? "audio" : "video"); 641 << BufferingStateStr(*buffering_state) << " -> "
642 << BufferingStateStr(new_buffering_state);
501 DCHECK(task_runner_->BelongsToCurrentThread()); 643 DCHECK(task_runner_->BelongsToCurrentThread());
502 644
503 bool was_waiting_for_enough_data = WaitingForEnoughData(); 645 bool was_waiting_for_enough_data = WaitingForEnoughData();
504 646
647 if (restarting_audio_ || restarting_video_) {
648 if (HandleRestartedStreamBufferingChanges(type, new_buffering_state))
649 return;
650 }
651
505 // When audio is present and has enough data, defer video underflow callbacks 652 // When audio is present and has enough data, defer video underflow callbacks
506 // for some time to avoid unnecessary glitches in audio; see 653 // for some time to avoid unnecessary glitches in audio; see
507 // http://crbug.com/144683#c53. 654 // http://crbug.com/144683#c53.
508 if (audio_renderer_ && type == DemuxerStream::VIDEO && 655 if (audio_renderer_ && type == DemuxerStream::VIDEO &&
509 state_ == STATE_PLAYING) { 656 state_ == STATE_PLAYING) {
510 if (video_buffering_state_ == BUFFERING_HAVE_ENOUGH && 657 if (video_buffering_state_ == BUFFERING_HAVE_ENOUGH &&
511 audio_buffering_state_ == BUFFERING_HAVE_ENOUGH && 658 audio_buffering_state_ == BUFFERING_HAVE_ENOUGH &&
512 new_buffering_state == BUFFERING_HAVE_NOTHING && 659 new_buffering_state == BUFFERING_HAVE_NOTHING &&
513 deferred_underflow_cb_.IsCancelled()) { 660 deferred_video_underflow_cb_.IsCancelled()) {
514 deferred_underflow_cb_.Reset( 661 DVLOG(4) << __FUNCTION__ << " Deferring HAVE_NOTHING for video stream.";
662 deferred_video_underflow_cb_.Reset(
515 base::Bind(&RendererImpl::OnBufferingStateChange, 663 base::Bind(&RendererImpl::OnBufferingStateChange,
516 weak_factory_.GetWeakPtr(), type, new_buffering_state)); 664 weak_factory_.GetWeakPtr(), type, new_buffering_state));
517 task_runner_->PostDelayedTask(FROM_HERE, 665 task_runner_->PostDelayedTask(FROM_HERE,
518 deferred_underflow_cb_.callback(), 666 deferred_video_underflow_cb_.callback(),
519 video_underflow_threshold_); 667 video_underflow_threshold_);
520 return; 668 return;
521 } 669 }
522 670
523 deferred_underflow_cb_.Cancel(); 671 DVLOG(4) << "deferred_video_underflow_cb_.Cancel()";
524 } else if (!deferred_underflow_cb_.IsCancelled() && 672 deferred_video_underflow_cb_.Cancel();
673 } else if (!deferred_video_underflow_cb_.IsCancelled() &&
525 type == DemuxerStream::AUDIO && 674 type == DemuxerStream::AUDIO &&
526 new_buffering_state == BUFFERING_HAVE_NOTHING) { 675 new_buffering_state == BUFFERING_HAVE_NOTHING) {
527 // If audio underflows while we have a deferred video underflow in progress 676 // If audio underflows while we have a deferred video underflow in progress
528 // we want to mark video as underflowed immediately and cancel the deferral. 677 // we want to mark video as underflowed immediately and cancel the deferral.
529 deferred_underflow_cb_.Cancel(); 678 deferred_video_underflow_cb_.Cancel();
530 video_buffering_state_ = BUFFERING_HAVE_NOTHING; 679 video_buffering_state_ = BUFFERING_HAVE_NOTHING;
531 } 680 }
532 681
533 *buffering_state = new_buffering_state; 682 *buffering_state = new_buffering_state;
534 683
535 // Disable underflow by ignoring updates that renderers have ran out of data. 684 // Disable underflow by ignoring updates that renderers have ran out of data.
536 if (state_ == STATE_PLAYING && underflow_disabled_for_testing_ && 685 if (state_ == STATE_PLAYING && underflow_disabled_for_testing_ &&
537 time_ticking_) { 686 time_ticking_) {
538 DVLOG(1) << "Update ignored because underflow is disabled for testing."; 687 DVLOG(1) << "Update ignored because underflow is disabled for testing.";
539 return; 688 return;
(...skipping 23 matching lines...) Expand all
563 if (audio_renderer_ && audio_buffering_state_ != BUFFERING_HAVE_ENOUGH) 712 if (audio_renderer_ && audio_buffering_state_ != BUFFERING_HAVE_ENOUGH)
564 return true; 713 return true;
565 if (video_renderer_ && video_buffering_state_ != BUFFERING_HAVE_ENOUGH) 714 if (video_renderer_ && video_buffering_state_ != BUFFERING_HAVE_ENOUGH)
566 return true; 715 return true;
567 return false; 716 return false;
568 } 717 }
569 718
570 void RendererImpl::PausePlayback() { 719 void RendererImpl::PausePlayback() {
571 DVLOG(1) << __FUNCTION__; 720 DVLOG(1) << __FUNCTION__;
572 DCHECK(task_runner_->BelongsToCurrentThread()); 721 DCHECK(task_runner_->BelongsToCurrentThread());
573 DCHECK(time_ticking_);
574 switch (state_) { 722 switch (state_) {
575 case STATE_PLAYING: 723 case STATE_PLAYING:
576 DCHECK(PlaybackHasEnded() || WaitingForEnoughData()) 724 DCHECK(PlaybackHasEnded() || WaitingForEnoughData() || restarting_audio_)
577 << "Playback should only pause due to ending or underflowing"; 725 << "Playback should only pause due to ending or underflowing or"
726 " when restarting audio stream";
727
578 break; 728 break;
579 729
580 case STATE_FLUSHING: 730 case STATE_FLUSHING:
581 // It's OK to pause playback when flushing. 731 // It's OK to pause playback when flushing.
582 break; 732 break;
583 733
584 case STATE_UNINITIALIZED: 734 case STATE_UNINITIALIZED:
585 case STATE_INIT_PENDING_CDM: 735 case STATE_INIT_PENDING_CDM:
586 case STATE_INITIALIZING: 736 case STATE_INITIALIZING:
587 NOTREACHED() << "Invalid state: " << state_; 737 NOTREACHED() << "Invalid state: " << state_;
588 break; 738 break;
589 739
590 case STATE_ERROR: 740 case STATE_ERROR:
591 // An error state may occur at any time. 741 // An error state may occur at any time.
592 break; 742 break;
593 } 743 }
594 744
595 time_ticking_ = false; 745 if (time_ticking_) {
596 time_source_->StopTicking(); 746 time_ticking_ = false;
747 time_source_->StopTicking();
748 }
597 if (playback_rate_ > 0 && video_renderer_) 749 if (playback_rate_ > 0 && video_renderer_)
598 video_renderer_->OnTimeStateChanged(false); 750 video_renderer_->OnTimeStateChanged(false);
599 } 751 }
600 752
601 void RendererImpl::StartPlayback() { 753 void RendererImpl::StartPlayback() {
602 DVLOG(1) << __FUNCTION__; 754 DVLOG(1) << __FUNCTION__;
603 DCHECK(task_runner_->BelongsToCurrentThread()); 755 DCHECK(task_runner_->BelongsToCurrentThread());
604 DCHECK_EQ(state_, STATE_PLAYING); 756 DCHECK_EQ(state_, STATE_PLAYING);
605 DCHECK(!time_ticking_); 757 DCHECK(!time_ticking_);
606 DCHECK(!WaitingForEnoughData()); 758 DCHECK(!WaitingForEnoughData());
607 759
608 time_ticking_ = true; 760 time_ticking_ = true;
609 time_source_->StartTicking(); 761 time_source_->StartTicking();
610 if (playback_rate_ > 0 && video_renderer_) 762 if (playback_rate_ > 0 && video_renderer_)
611 video_renderer_->OnTimeStateChanged(true); 763 video_renderer_->OnTimeStateChanged(true);
612 } 764 }
613 765
614 void RendererImpl::OnRendererEnded(DemuxerStream::Type type) { 766 void RendererImpl::OnRendererEnded(DemuxerStream::Type type) {
615 DVLOG(1) << __FUNCTION__; 767 DVLOG(1) << __FUNCTION__
768 << (type == DemuxerStream::AUDIO ? " audio" : " video");
616 DCHECK(task_runner_->BelongsToCurrentThread()); 769 DCHECK(task_runner_->BelongsToCurrentThread());
617 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO)); 770 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO));
618 771
619 if (state_ != STATE_PLAYING) 772 if (state_ != STATE_PLAYING)
620 return; 773 return;
621 774
622 if (type == DemuxerStream::AUDIO) { 775 if (type == DemuxerStream::AUDIO) {
623 DCHECK(!audio_ended_); 776 DCHECK(!audio_ended_);
624 audio_ended_ = true; 777 audio_ended_ = true;
625 } else { 778 } else {
626 DCHECK(!video_ended_); 779 DCHECK(!video_ended_);
627 video_ended_ = true; 780 video_ended_ = true;
781 DCHECK(video_renderer_);
782 video_renderer_->OnTimeStateChanged(false);
628 } 783 }
629 784
630 RunEndedCallbackIfNeeded(); 785 RunEndedCallbackIfNeeded();
631 } 786 }
632 787
633 bool RendererImpl::PlaybackHasEnded() const { 788 bool RendererImpl::PlaybackHasEnded() const {
634 DVLOG(1) << __FUNCTION__;
635 DCHECK(task_runner_->BelongsToCurrentThread()); 789 DCHECK(task_runner_->BelongsToCurrentThread());
636 790
637 if (audio_renderer_ && !audio_ended_) 791 if (audio_renderer_ && !audio_ended_)
638 return false; 792 return false;
639 793
640 if (video_renderer_ && !video_ended_) 794 if (video_renderer_ && !video_ended_)
641 return false; 795 return false;
642 796
643 return true; 797 return true;
644 } 798 }
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
691 DCHECK(task_runner_->BelongsToCurrentThread()); 845 DCHECK(task_runner_->BelongsToCurrentThread());
692 client_->OnVideoNaturalSizeChange(size); 846 client_->OnVideoNaturalSizeChange(size);
693 } 847 }
694 848
695 void RendererImpl::OnVideoOpacityChange(bool opaque) { 849 void RendererImpl::OnVideoOpacityChange(bool opaque) {
696 DCHECK(task_runner_->BelongsToCurrentThread()); 850 DCHECK(task_runner_->BelongsToCurrentThread());
697 client_->OnVideoOpacityChange(opaque); 851 client_->OnVideoOpacityChange(opaque);
698 } 852 }
699 853
700 } // namespace media 854 } // 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