Chromium Code Reviews| 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |