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 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 194 } | 194 } |
| 195 | 195 |
| 196 time_source_->SetMediaTime(time); | 196 time_source_->SetMediaTime(time); |
| 197 | 197 |
| 198 if (audio_renderer_) | 198 if (audio_renderer_) |
| 199 audio_renderer_->StartPlaying(); | 199 audio_renderer_->StartPlaying(); |
| 200 if (video_renderer_) | 200 if (video_renderer_) |
| 201 video_renderer_->StartPlayingFrom(time); | 201 video_renderer_->StartPlayingFrom(time); |
| 202 } | 202 } |
| 203 | 203 |
| 204 void RendererImpl::RestartStreamPlayback(DemuxerStream* stream, | |
| 205 base::TimeDelta time) { | |
| 206 DVLOG(1) << __FUNCTION__ << " stream=" << stream | |
| 207 << " time=" << time.InSecondsF(); | |
| 208 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 209 if (stream->type() == DemuxerStream::VIDEO) { | |
| 210 DCHECK(video_renderer_); | |
| 211 DCHECK(video_ended_); | |
| 212 video_ended_ = false; | |
| 213 restarting_video_ = true; | |
| 214 video_renderer_->Flush(base::Bind( | |
| 215 &RendererImpl::OnVideoRendererFlushDone_ForRestart, weak_this_, time)); | |
| 216 } else if (stream->type() == DemuxerStream::AUDIO) { | |
| 217 DCHECK(audio_renderer_); | |
| 218 DCHECK(time_source_); | |
| 219 DCHECK(audio_ended_); | |
| 220 audio_ended_ = false; | |
| 221 restarting_audio_ = true; | |
| 222 // We need to stop ticking (transition into paused state) before calling | |
| 223 // Flush, since after Flush we'll need to restart playback by invoking | |
| 224 // StartPlaying that dchecks we are not in playing state. | |
|
wolenetz
2016/05/27 20:49:42
nit: we usually don't refer to implementation deta
servolk
2016/06/01 17:36:16
Done.
| |
| 225 time_ticking_ = false; | |
| 226 time_source_->StopTicking(); | |
| 227 audio_renderer_->Flush(base::Bind( | |
| 228 &RendererImpl::OnAudioRendererFlushDone_ForRestart, weak_this_, time)); | |
| 229 } | |
| 230 } | |
| 231 | |
| 232 void RendererImpl::OnVideoRendererFlushDone_ForRestart(base::TimeDelta time) { | |
| 233 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 234 if (state_ == STATE_PLAYING) { | |
| 235 DCHECK(video_renderer_); | |
| 236 // TODO(servolk): VideoRenderer should ensure that Flush callback is called | |
| 237 // outside of its internal lock, to allow calling renderer methods directly. | |
| 238 task_runner_->PostTask( | |
| 239 FROM_HERE, base::Bind(&VideoRenderer::StartPlayingFrom, | |
| 240 base::Unretained(video_renderer_.get()), time)); | |
| 241 } | |
| 242 } | |
| 243 | |
| 244 void RendererImpl::OnAudioRendererFlushDone_ForRestart(base::TimeDelta time) { | |
| 245 DCHECK(task_runner_->BelongsToCurrentThread()); | |
| 246 if (state_ == STATE_PLAYING) { | |
| 247 DCHECK(time_source_); | |
| 248 DCHECK(audio_renderer_); | |
| 249 audio_renderer_->StartPlaying(); | |
| 250 } | |
| 251 } | |
| 252 | |
| 204 void RendererImpl::SetPlaybackRate(double playback_rate) { | 253 void RendererImpl::SetPlaybackRate(double playback_rate) { |
| 205 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; | 254 DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; |
| 206 DCHECK(task_runner_->BelongsToCurrentThread()); | 255 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 207 | 256 |
| 208 // Playback rate changes are only carried out while playing. | 257 // Playback rate changes are only carried out while playing. |
| 209 if (state_ != STATE_PLAYING) | 258 if (state_ != STATE_PLAYING) |
| 210 return; | 259 return; |
| 211 | 260 |
| 212 time_source_->SetPlaybackRate(playback_rate); | 261 time_source_->SetPlaybackRate(playback_rate); |
| 213 | 262 |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 495 ? &audio_buffering_state_ | 544 ? &audio_buffering_state_ |
| 496 : &video_buffering_state_; | 545 : &video_buffering_state_; |
| 497 | 546 |
| 498 DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", " | 547 DVLOG(1) << __FUNCTION__ << "(" << *buffering_state << ", " |
| 499 << new_buffering_state << ") " | 548 << new_buffering_state << ") " |
| 500 << (type == DemuxerStream::AUDIO ? "audio" : "video"); | 549 << (type == DemuxerStream::AUDIO ? "audio" : "video"); |
| 501 DCHECK(task_runner_->BelongsToCurrentThread()); | 550 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 502 | 551 |
| 503 bool was_waiting_for_enough_data = WaitingForEnoughData(); | 552 bool was_waiting_for_enough_data = WaitingForEnoughData(); |
| 504 | 553 |
| 554 // When restarting video stream playback we want to ignore the | |
| 555 // BUFFERING_HAVE_NOTHING notification so that audio keeps playing while | |
| 556 // video decoder is catching up. | |
| 557 if (type == DemuxerStream::VIDEO && restarting_video_) { | |
| 558 if (new_buffering_state == BUFFERING_HAVE_NOTHING) { | |
| 559 DVLOG(1) << __FUNCTION__ << " Ignoring BUFFERING_HAVE_NOTHING for video " | |
| 560 "stream which is being restarted."; | |
| 561 } else if (new_buffering_state == BUFFERING_HAVE_ENOUGH) { | |
| 562 DVLOG(1) | |
| 563 << __FUNCTION__ | |
| 564 << " Got BUFFERING_HAVE_ENOUGH for video stream, resuming playback."; | |
| 565 restarting_video_ = false; | |
| 566 if (playback_rate_ > 0) | |
| 567 video_renderer_->OnTimeStateChanged(true); | |
| 568 } | |
| 569 return; | |
| 570 } | |
| 571 | |
| 572 if (type == DemuxerStream::AUDIO && restarting_audio_) { | |
| 573 if (new_buffering_state == BUFFERING_HAVE_NOTHING) { | |
| 574 DVLOG(1) << __FUNCTION__ << " Ignoring BUFFERING_HAVE_NOTHING for " | |
| 575 << (type == DemuxerStream::AUDIO ? "audio" : "video") | |
| 576 << " stream"; | |
| 577 } else if (new_buffering_state == BUFFERING_HAVE_ENOUGH) { | |
| 578 DVLOG(1) << __FUNCTION__ << " Got BUFFERING_HAVE_ENOUGH for " | |
| 579 << (type == DemuxerStream::AUDIO ? "audio" : "video") | |
| 580 << " stream"; | |
| 581 | |
| 582 restarting_audio_ = false; | |
| 583 | |
| 584 // Now that we have decoded enough audio, pause and unpause playback | |
| 585 // momentarily to ensure video renderer is synchronised with audio. | |
| 586 double curr_playback_rate = playback_rate_; | |
| 587 SetPlaybackRate(0); | |
| 588 SetPlaybackRate(curr_playback_rate); | |
| 589 | |
| 590 time_source_->StartTicking(); | |
| 591 } | |
| 592 return; | |
| 593 } | |
| 594 | |
| 505 // When audio is present and has enough data, defer video underflow callbacks | 595 // When audio is present and has enough data, defer video underflow callbacks |
| 506 // for some time to avoid unnecessary glitches in audio; see | 596 // for some time to avoid unnecessary glitches in audio; see |
| 507 // http://crbug.com/144683#c53. | 597 // http://crbug.com/144683#c53. |
| 508 if (audio_renderer_ && type == DemuxerStream::VIDEO && | 598 if (audio_renderer_ && type == DemuxerStream::VIDEO && |
| 509 state_ == STATE_PLAYING) { | 599 state_ == STATE_PLAYING) { |
| 510 if (video_buffering_state_ == BUFFERING_HAVE_ENOUGH && | 600 if (video_buffering_state_ == BUFFERING_HAVE_ENOUGH && |
| 511 audio_buffering_state_ == BUFFERING_HAVE_ENOUGH && | 601 audio_buffering_state_ == BUFFERING_HAVE_ENOUGH && |
| 512 new_buffering_state == BUFFERING_HAVE_NOTHING && | 602 new_buffering_state == BUFFERING_HAVE_NOTHING && |
| 513 deferred_underflow_cb_.IsCancelled()) { | 603 deferred_underflow_cb_.IsCancelled()) { |
| 514 deferred_underflow_cb_.Reset( | 604 deferred_underflow_cb_.Reset( |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 605 DCHECK(!time_ticking_); | 695 DCHECK(!time_ticking_); |
| 606 DCHECK(!WaitingForEnoughData()); | 696 DCHECK(!WaitingForEnoughData()); |
| 607 | 697 |
| 608 time_ticking_ = true; | 698 time_ticking_ = true; |
| 609 time_source_->StartTicking(); | 699 time_source_->StartTicking(); |
| 610 if (playback_rate_ > 0 && video_renderer_) | 700 if (playback_rate_ > 0 && video_renderer_) |
| 611 video_renderer_->OnTimeStateChanged(true); | 701 video_renderer_->OnTimeStateChanged(true); |
| 612 } | 702 } |
| 613 | 703 |
| 614 void RendererImpl::OnRendererEnded(DemuxerStream::Type type) { | 704 void RendererImpl::OnRendererEnded(DemuxerStream::Type type) { |
| 615 DVLOG(1) << __FUNCTION__; | 705 DVLOG(1) << __FUNCTION__ |
| 706 << (type == DemuxerStream::AUDIO ? " audio" : " video"); | |
| 616 DCHECK(task_runner_->BelongsToCurrentThread()); | 707 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 617 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO)); | 708 DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO)); |
| 618 | 709 |
| 619 if (state_ != STATE_PLAYING) | 710 if (state_ != STATE_PLAYING) |
| 620 return; | 711 return; |
| 621 | 712 |
| 622 if (type == DemuxerStream::AUDIO) { | 713 if (type == DemuxerStream::AUDIO) { |
| 623 DCHECK(!audio_ended_); | 714 DCHECK(!audio_ended_); |
| 624 audio_ended_ = true; | 715 audio_ended_ = true; |
| 625 } else { | 716 } else { |
| (...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 691 DCHECK(task_runner_->BelongsToCurrentThread()); | 782 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 692 client_->OnVideoNaturalSizeChange(size); | 783 client_->OnVideoNaturalSizeChange(size); |
| 693 } | 784 } |
| 694 | 785 |
| 695 void RendererImpl::OnVideoOpacityChange(bool opaque) { | 786 void RendererImpl::OnVideoOpacityChange(bool opaque) { |
| 696 DCHECK(task_runner_->BelongsToCurrentThread()); | 787 DCHECK(task_runner_->BelongsToCurrentThread()); |
| 697 client_->OnVideoOpacityChange(opaque); | 788 client_->OnVideoOpacityChange(opaque); |
| 698 } | 789 } |
| 699 | 790 |
| 700 } // namespace media | 791 } // namespace media |
| OLD | NEW |