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

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

Issue 2684103005: Allow media track switching. (Closed)
Patch Set: Properly handle track status changes in FLUSHED state 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 }; 73 };
74 74
75 RendererImpl::RendererImpl( 75 RendererImpl::RendererImpl(
76 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 76 const scoped_refptr<base::SingleThreadTaskRunner>& 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 : state_(STATE_UNINITIALIZED), 79 : state_(STATE_UNINITIALIZED),
80 task_runner_(task_runner), 80 task_runner_(task_runner),
81 audio_renderer_(std::move(audio_renderer)), 81 audio_renderer_(std::move(audio_renderer)),
82 video_renderer_(std::move(video_renderer)), 82 video_renderer_(std::move(video_renderer)),
83 current_audio_stream_(nullptr),
84 current_video_stream_(nullptr),
83 time_source_(NULL), 85 time_source_(NULL),
84 time_ticking_(false), 86 time_ticking_(false),
85 playback_rate_(0.0), 87 playback_rate_(0.0),
86 audio_buffering_state_(BUFFERING_HAVE_NOTHING), 88 audio_buffering_state_(BUFFERING_HAVE_NOTHING),
87 video_buffering_state_(BUFFERING_HAVE_NOTHING), 89 video_buffering_state_(BUFFERING_HAVE_NOTHING),
88 audio_ended_(false), 90 audio_ended_(false),
89 video_ended_(false), 91 video_ended_(false),
90 cdm_context_(nullptr), 92 cdm_context_(nullptr),
91 underflow_disabled_for_testing_(false), 93 underflow_disabled_for_testing_(false),
92 clockless_video_playback_enabled_for_testing_(false), 94 clockless_video_playback_enabled_for_testing_(false),
(...skipping 26 matching lines...) Expand all
119 121
120 // Tear down in opposite order of construction as |video_renderer_| can still 122 // Tear down in opposite order of construction as |video_renderer_| can still
121 // need |time_source_| (which can be |audio_renderer_|) to be alive. 123 // need |time_source_| (which can be |audio_renderer_|) to be alive.
122 video_renderer_.reset(); 124 video_renderer_.reset();
123 audio_renderer_.reset(); 125 audio_renderer_.reset();
124 126
125 if (!init_cb_.is_null()) { 127 if (!init_cb_.is_null()) {
126 FinishInitialization(PIPELINE_ERROR_ABORT); 128 FinishInitialization(PIPELINE_ERROR_ABORT);
127 } else if (!flush_cb_.is_null()) { 129 } else if (!flush_cb_.is_null()) {
128 base::ResetAndReturn(&flush_cb_).Run(); 130 base::ResetAndReturn(&flush_cb_).Run();
131 } else if (pending_flush_cb_) {
132 base::ResetAndReturn(&pending_flush_cb_).Run();
129 } 133 }
130 } 134 }
131 135
132 void RendererImpl::Initialize(MediaResource* media_resource, 136 void RendererImpl::Initialize(MediaResource* media_resource,
133 RendererClient* client, 137 RendererClient* client,
134 const PipelineStatusCB& init_cb) { 138 const PipelineStatusCB& init_cb) {
135 DVLOG(1) << __func__; 139 DVLOG(1) << __func__;
136 DCHECK(task_runner_->BelongsToCurrentThread()); 140 DCHECK(task_runner_->BelongsToCurrentThread());
137 DCHECK_EQ(state_, STATE_UNINITIALIZED); 141 DCHECK_EQ(state_, STATE_UNINITIALIZED);
138 DCHECK(!init_cb.is_null()); 142 DCHECK(!init_cb.is_null());
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 if (state_ == STATE_FLUSHED) { 191 if (state_ == STATE_FLUSHED) {
188 task_runner_->PostTask(FROM_HERE, flush_cb); 192 task_runner_->PostTask(FROM_HERE, flush_cb);
189 return; 193 return;
190 } 194 }
191 195
192 if (state_ != STATE_PLAYING) { 196 if (state_ != STATE_PLAYING) {
193 DCHECK_EQ(state_, STATE_ERROR); 197 DCHECK_EQ(state_, STATE_ERROR);
194 return; 198 return;
195 } 199 }
196 200
201 // If we are currently handling a media stream status change, then postpone
202 // Flush until after that's done (because stream status changes also flush
203 // audio_renderer_/video_renderer_ and they need to be restarted before they
204 // can be flushed again). OnStreamRestartCompleted will resume Flush
205 // processing after audio/video restart has completed and there are no other
206 // pending stream status changes.
207 if (restarting_audio_ || restarting_video_) {
208 DCHECK(!pending_flush_cb_);
209 pending_flush_cb_ = flush_cb;
210 pending_actions_.push_back(
211 base::Bind(&RendererImpl::Flush, weak_this_, pending_flush_cb_));
xhwang 2017/04/10 18:57:30 Can you just use base::Bind(&RendererImpl::Flush
servolk 2017/04/10 20:21:22 We could remove the |pending_flush_cb_| and use |f
servolk 2017/04/10 20:29:53 Actually, let me expand a bit more. The main reaso
xhwang 2017/04/11 00:29:41 I am confused. We are not setting the |flush_cb_|
servolk 2017/04/11 01:14:05 Well, yes, if we do it like that (by setting state
212 return;
213 }
214
215 if (pending_flush_cb_) {
216 DCHECK(flush_cb.Equals(pending_flush_cb_));
217 base::ResetAndReturn(&pending_flush_cb_);
218 }
219
197 flush_cb_ = flush_cb; 220 flush_cb_ = flush_cb;
198 state_ = STATE_FLUSHING; 221 state_ = STATE_FLUSHING;
199 222
200 if (time_ticking_) 223 if (time_ticking_)
201 PausePlayback(); 224 PausePlayback();
202 225
203 FlushAudioRenderer(); 226 FlushAudioRenderer();
204 } 227 }
205 228
206 void RendererImpl::StartPlayingFrom(base::TimeDelta time) { 229 void RendererImpl::StartPlayingFrom(base::TimeDelta time) {
207 DVLOG(1) << __func__; 230 DVLOG(1) << __func__;
208 DCHECK(task_runner_->BelongsToCurrentThread()); 231 DCHECK(task_runner_->BelongsToCurrentThread());
209 232
210 if (state_ != STATE_FLUSHED) { 233 if (state_ != STATE_FLUSHED) {
211 DCHECK_EQ(state_, STATE_ERROR); 234 DCHECK_EQ(state_, STATE_ERROR);
212 return; 235 return;
213 } 236 }
214 237
215 time_source_->SetMediaTime(time); 238 time_source_->SetMediaTime(time);
216 239
217 state_ = STATE_PLAYING; 240 state_ = STATE_PLAYING;
218 if (audio_renderer_) 241 if (audio_renderer_)
219 audio_renderer_->StartPlaying(); 242 audio_renderer_->StartPlaying();
220 if (video_renderer_) 243 if (video_renderer_)
221 video_renderer_->StartPlayingFrom(time); 244 video_renderer_->StartPlayingFrom(time);
222 } 245 }
223 246
224 void RendererImpl::OnStreamStatusChanged(DemuxerStream* stream,
225 bool enabled,
226 base::TimeDelta time) {
227 DCHECK(task_runner_->BelongsToCurrentThread());
228 DCHECK(stream);
229 bool video = (stream->type() == DemuxerStream::VIDEO);
230 DVLOG(1) << __func__ << (video ? " video" : " audio") << " stream=" << stream
231 << " enabled=" << enabled << " time=" << time.InSecondsF();
232 if ((state_ != STATE_PLAYING) || (audio_ended_ && video_ended_))
233 return;
234 if (restarting_audio_ || restarting_video_) {
235 DVLOG(3) << __func__ << ": postponed stream " << stream
236 << " status change handling.";
237 pending_stream_status_notifications_.push_back(
238 base::Bind(&RendererImpl::OnStreamStatusChanged, weak_this_, stream,
239 enabled, time));
240 return;
241 }
242 if (stream->type() == DemuxerStream::VIDEO) {
243 DCHECK(video_renderer_);
244 restarting_video_ = true;
245 video_renderer_->Flush(
246 base::Bind(&RendererImpl::RestartVideoRenderer, weak_this_, time));
247 } else if (stream->type() == DemuxerStream::AUDIO) {
248 DCHECK(audio_renderer_);
249 DCHECK(time_source_);
250 restarting_audio_ = true;
251 // Stop ticking (transition into paused state) in audio renderer before
252 // calling Flush, since after Flush we are going to restart playback by
253 // calling audio renderer StartPlaying which would fail in playing state.
254 if (time_ticking_) {
255 time_ticking_ = false;
256 time_source_->StopTicking();
257 }
258 audio_renderer_->Flush(
259 base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time));
260 }
261 }
262
263 void RendererImpl::RestartVideoRenderer(base::TimeDelta time) {
264 DVLOG(3) << __func__;
265 DCHECK(task_runner_->BelongsToCurrentThread());
266 DCHECK(video_renderer_);
267 DCHECK_EQ(state_, STATE_PLAYING);
268 video_ended_ = false;
269 video_renderer_->StartPlayingFrom(time);
270 }
271
272 void RendererImpl::RestartAudioRenderer(base::TimeDelta time) {
273 DVLOG(3) << __func__;
274 DCHECK(task_runner_->BelongsToCurrentThread());
275 DCHECK_EQ(state_, STATE_PLAYING);
276 DCHECK(time_source_);
277 DCHECK(audio_renderer_);
278 audio_ended_ = false;
279 audio_renderer_->StartPlaying();
280 }
281
282 void RendererImpl::SetPlaybackRate(double playback_rate) { 247 void RendererImpl::SetPlaybackRate(double playback_rate) {
283 DVLOG(1) << __func__ << "(" << playback_rate << ")"; 248 DVLOG(1) << __func__ << "(" << playback_rate << ")";
284 DCHECK(task_runner_->BelongsToCurrentThread()); 249 DCHECK(task_runner_->BelongsToCurrentThread());
285 250
286 // Playback rate changes are only carried out while playing. 251 // Playback rate changes are only carried out while playing.
287 if (state_ != STATE_PLAYING && state_ != STATE_FLUSHED) 252 if (state_ != STATE_PLAYING && state_ != STATE_FLUSHED)
288 return; 253 return;
289 254
290 time_source_->SetPlaybackRate(playback_rate); 255 time_source_->SetPlaybackRate(playback_rate);
291 256
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 // TODO(servolk): Implement proper support for multiple streams. But for now 358 // TODO(servolk): Implement proper support for multiple streams. But for now
394 // pick the first enabled stream to preserve the existing behavior. 359 // pick the first enabled stream to preserve the existing behavior.
395 DemuxerStream* audio_stream = 360 DemuxerStream* audio_stream =
396 media_resource_->GetFirstStream(DemuxerStream::AUDIO); 361 media_resource_->GetFirstStream(DemuxerStream::AUDIO);
397 if (!audio_stream) { 362 if (!audio_stream) {
398 audio_renderer_.reset(); 363 audio_renderer_.reset();
399 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); 364 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
400 return; 365 return;
401 } 366 }
402 367
368 current_audio_stream_ = audio_stream;
369
403 audio_renderer_client_.reset( 370 audio_renderer_client_.reset(
404 new RendererClientInternal(DemuxerStream::AUDIO, this)); 371 new RendererClientInternal(DemuxerStream::AUDIO, this));
405 // Note: After the initialization of a renderer, error events from it may 372 // Note: After the initialization of a renderer, error events from it may
406 // happen at any time and all future calls must guard against STATE_ERROR. 373 // happen at any time and all future calls must guard against STATE_ERROR.
407 audio_renderer_->Initialize(audio_stream, cdm_context_, 374 audio_renderer_->Initialize(audio_stream, cdm_context_,
408 audio_renderer_client_.get(), done_cb); 375 audio_renderer_client_.get(), done_cb);
409 } 376 }
410 377
411 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) { 378 void RendererImpl::OnAudioRendererInitializeDone(PipelineStatus status) {
412 DVLOG(1) << __func__ << ": " << status; 379 DVLOG(1) << __func__ << ": " << status;
(...skipping 28 matching lines...) Expand all
441 // TODO(servolk): Implement proper support for multiple streams. But for now 408 // TODO(servolk): Implement proper support for multiple streams. But for now
442 // pick the first enabled stream to preserve the existing behavior. 409 // pick the first enabled stream to preserve the existing behavior.
443 DemuxerStream* video_stream = 410 DemuxerStream* video_stream =
444 media_resource_->GetFirstStream(DemuxerStream::VIDEO); 411 media_resource_->GetFirstStream(DemuxerStream::VIDEO);
445 if (!video_stream) { 412 if (!video_stream) {
446 video_renderer_.reset(); 413 video_renderer_.reset();
447 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK)); 414 task_runner_->PostTask(FROM_HERE, base::Bind(done_cb, PIPELINE_OK));
448 return; 415 return;
449 } 416 }
450 417
418 current_video_stream_ = video_stream;
419
451 video_renderer_client_.reset( 420 video_renderer_client_.reset(
452 new RendererClientInternal(DemuxerStream::VIDEO, this)); 421 new RendererClientInternal(DemuxerStream::VIDEO, this));
453 video_renderer_->Initialize( 422 video_renderer_->Initialize(
454 video_stream, cdm_context_, video_renderer_client_.get(), 423 video_stream, cdm_context_, video_renderer_client_.get(),
455 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)), 424 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)),
456 done_cb); 425 done_cb);
457 } 426 }
458 427
459 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) { 428 void RendererImpl::OnVideoRendererInitializeDone(PipelineStatus status) {
460 DVLOG(1) << __func__ << ": " << status; 429 DVLOG(1) << __func__ << ": " << status;
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 return; 522 return;
554 } 523 }
555 524
556 DCHECK_EQ(state_, STATE_FLUSHING); 525 DCHECK_EQ(state_, STATE_FLUSHING);
557 DCHECK(!flush_cb_.is_null()); 526 DCHECK(!flush_cb_.is_null());
558 527
559 DCHECK_EQ(video_buffering_state_, BUFFERING_HAVE_NOTHING); 528 DCHECK_EQ(video_buffering_state_, BUFFERING_HAVE_NOTHING);
560 video_ended_ = false; 529 video_ended_ = false;
561 state_ = STATE_FLUSHED; 530 state_ = STATE_FLUSHED;
562 base::ResetAndReturn(&flush_cb_).Run(); 531 base::ResetAndReturn(&flush_cb_).Run();
532
533 if (!pending_actions_.empty()) {
534 base::Closure closure = pending_actions_.front();
535 pending_actions_.pop_front();
536 closure.Run();
537 }
538 }
539
540 void RendererImpl::OnStreamStatusChanged(DemuxerStream* stream,
541 bool enabled,
542 base::TimeDelta time) {
543 DCHECK(task_runner_->BelongsToCurrentThread());
544 DCHECK(stream);
545 bool video = (stream->type() == DemuxerStream::VIDEO);
546 DVLOG(1) << __func__ << (video ? " video" : " audio") << " stream=" << stream
547 << " enabled=" << enabled << " time=" << time.InSecondsF();
548
549 if ((state_ != STATE_PLAYING && state_ != STATE_FLUSHING &&
550 state_ != STATE_FLUSHED) ||
551 (audio_ended_ && video_ended_))
552 return;
553
554 if (restarting_audio_ || restarting_video_ || state_ == STATE_FLUSHING) {
555 DVLOG(3) << __func__ << ": postponed stream " << stream
556 << " status change handling.";
557 pending_actions_.push_back(base::Bind(&RendererImpl::OnStreamStatusChanged,
558 weak_this_, stream, enabled, time));
559 return;
560 }
561
562 DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHED);
563 if (stream->type() == DemuxerStream::VIDEO) {
564 DCHECK(video_renderer_);
565 restarting_video_ = true;
566 base::Closure handle_track_status_cb =
567 base::Bind(stream == current_video_stream_
568 ? &RendererImpl::RestartVideoRenderer
569 : &RendererImpl::ReinitializeVideoRenderer,
570 weak_this_, stream, time);
571 if (state_ == STATE_FLUSHED)
572 handle_track_status_cb.Run();
573 else
574 video_renderer_->Flush(handle_track_status_cb);
575 } else if (stream->type() == DemuxerStream::AUDIO) {
576 DCHECK(audio_renderer_);
577 DCHECK(time_source_);
578 restarting_audio_ = true;
579 base::Closure handle_track_status_cb =
580 base::Bind(stream == current_audio_stream_
581 ? &RendererImpl::RestartAudioRenderer
582 : &RendererImpl::ReinitializeAudioRenderer,
583 weak_this_, stream, time);
584 if (state_ == STATE_FLUSHED) {
585 handle_track_status_cb.Run();
586 return;
587 }
588 // Stop ticking (transition into paused state) in audio renderer before
589 // calling Flush, since after Flush we are going to restart playback by
590 // calling audio renderer StartPlaying which would fail in playing state.
591 if (time_ticking_) {
592 time_ticking_ = false;
593 time_source_->StopTicking();
594 }
595 audio_renderer_->Flush(handle_track_status_cb);
596 }
597 }
598
599 void RendererImpl::ReinitializeAudioRenderer(DemuxerStream* stream,
600 base::TimeDelta time) {
601 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
602 DCHECK(task_runner_->BelongsToCurrentThread());
603 DCHECK_NE(stream, current_audio_stream_);
604
605 current_audio_stream_ = stream;
606 audio_renderer_->Initialize(
607 stream, cdm_context_, audio_renderer_client_.get(),
608 base::Bind(&RendererImpl::OnAudioRendererReinitialized, weak_this_,
609 stream, time));
610 }
611
612 void RendererImpl::OnAudioRendererReinitialized(DemuxerStream* stream,
613 base::TimeDelta time,
614 PipelineStatus status) {
615 DVLOG(2) << __func__ << ": status=" << status;
616 DCHECK_EQ(stream, current_audio_stream_);
617
618 if (status != PIPELINE_OK) {
619 OnError(status);
620 return;
621 }
622 RestartAudioRenderer(stream, time);
623 }
624
625 void RendererImpl::ReinitializeVideoRenderer(DemuxerStream* stream,
626 base::TimeDelta time) {
627 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
628 DCHECK(task_runner_->BelongsToCurrentThread());
629 DCHECK_NE(stream, current_video_stream_);
630
631 current_video_stream_ = stream;
632 video_renderer_->OnTimeStopped();
633 video_renderer_->Initialize(
634 stream, cdm_context_, video_renderer_client_.get(),
635 base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)),
636 base::Bind(&RendererImpl::OnVideoRendererReinitialized, weak_this_,
637 stream, time));
638 }
639
640 void RendererImpl::OnVideoRendererReinitialized(DemuxerStream* stream,
641 base::TimeDelta time,
642 PipelineStatus status) {
643 DVLOG(2) << __func__ << ": status=" << status;
644 DCHECK_EQ(stream, current_video_stream_);
645
646 if (status != PIPELINE_OK) {
647 OnError(status);
648 return;
649 }
650 RestartVideoRenderer(stream, time);
651 }
652
653 void RendererImpl::RestartAudioRenderer(DemuxerStream* stream,
654 base::TimeDelta time) {
655 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
656 DCHECK(task_runner_->BelongsToCurrentThread());
657 DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHED);
658 DCHECK(time_source_);
659 DCHECK(audio_renderer_);
660 DCHECK_EQ(stream, current_audio_stream_);
661
662 audio_ended_ = false;
663 if (state_ == STATE_PLAYING)
664 audio_renderer_->StartPlaying();
xhwang 2017/04/10 18:57:30 nit: add a comment when stream restart will be fin
servolk 2017/04/10 20:21:22 Done.
665 else
666 OnStreamRestartCompleted();
667 }
668
669 void RendererImpl::RestartVideoRenderer(DemuxerStream* stream,
670 base::TimeDelta time) {
671 DVLOG(2) << __func__ << " stream=" << stream << " time=" << time.InSecondsF();
672 DCHECK(task_runner_->BelongsToCurrentThread());
673 DCHECK(video_renderer_);
674 DCHECK(state_ == STATE_PLAYING || state_ == STATE_FLUSHED);
675 DCHECK_EQ(stream, current_video_stream_);
676
677 video_ended_ = false;
678 if (state_ == STATE_PLAYING)
679 video_renderer_->StartPlayingFrom(time);
680 else
681 OnStreamRestartCompleted();
563 } 682 }
564 683
565 void RendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) { 684 void RendererImpl::OnStatisticsUpdate(const PipelineStatistics& stats) {
566 DCHECK(task_runner_->BelongsToCurrentThread()); 685 DCHECK(task_runner_->BelongsToCurrentThread());
567 client_->OnStatisticsUpdate(stats); 686 client_->OnStatisticsUpdate(stats);
568 } 687 }
569 688
570 bool RendererImpl::HandleRestartedStreamBufferingChanges( 689 bool RendererImpl::HandleRestartedStreamBufferingChanges(
571 DemuxerStream::Type type, 690 DemuxerStream::Type type,
572 BufferingState new_buffering_state) { 691 BufferingState new_buffering_state) {
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
627 PausePlayback(); 746 PausePlayback();
628 task_runner_->PostTask( 747 task_runner_->PostTask(
629 FROM_HERE, 748 FROM_HERE,
630 base::Bind(&RendererImpl::OnStreamRestartCompleted, weak_this_)); 749 base::Bind(&RendererImpl::OnStreamRestartCompleted, weak_this_));
631 } 750 }
632 } 751 }
633 return false; 752 return false;
634 } 753 }
635 754
636 void RendererImpl::OnStreamRestartCompleted() { 755 void RendererImpl::OnStreamRestartCompleted() {
756 DVLOG(3) << __func__ << " restarting_audio_=" << restarting_audio_
757 << " restarting_video_=" << restarting_video_;
758 DCHECK(task_runner_->BelongsToCurrentThread());
637 DCHECK(restarting_audio_ || restarting_video_); 759 DCHECK(restarting_audio_ || restarting_video_);
638 restarting_audio_ = false; 760 restarting_audio_ = false;
639 restarting_video_ = false; 761 restarting_video_ = false;
640 if (!pending_stream_status_notifications_.empty()) { 762 if (!pending_actions_.empty()) {
641 pending_stream_status_notifications_.front().Run(); 763 base::Closure closure = pending_actions_.front();
642 pending_stream_status_notifications_.pop_front(); 764 pending_actions_.pop_front();
765 closure.Run();
643 } 766 }
644 } 767 }
645 768
646 void RendererImpl::OnBufferingStateChange(DemuxerStream::Type type, 769 void RendererImpl::OnBufferingStateChange(DemuxerStream::Type type,
647 BufferingState new_buffering_state) { 770 BufferingState new_buffering_state) {
648 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO)); 771 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO));
649 BufferingState* buffering_state = type == DemuxerStream::AUDIO 772 BufferingState* buffering_state = type == DemuxerStream::AUDIO
650 ? &audio_buffering_state_ 773 ? &audio_buffering_state_
651 : &video_buffering_state_; 774 : &video_buffering_state_;
652 775
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 DCHECK(task_runner_->BelongsToCurrentThread()); 979 DCHECK(task_runner_->BelongsToCurrentThread());
857 client_->OnVideoNaturalSizeChange(size); 980 client_->OnVideoNaturalSizeChange(size);
858 } 981 }
859 982
860 void RendererImpl::OnVideoOpacityChange(bool opaque) { 983 void RendererImpl::OnVideoOpacityChange(bool opaque) {
861 DCHECK(task_runner_->BelongsToCurrentThread()); 984 DCHECK(task_runner_->BelongsToCurrentThread());
862 client_->OnVideoOpacityChange(opaque); 985 client_->OnVideoOpacityChange(opaque);
863 } 986 }
864 987
865 } // namespace media 988 } // namespace media
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698