Chromium Code Reviews| Index: media/renderers/renderer_impl.cc |
| diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc |
| index 6de238c68ce39ea96f3a74813e535b21bb177605..bd46b34e8f72c981c166ff7f56c22fb738aed784 100644 |
| --- a/media/renderers/renderer_impl.cc |
| +++ b/media/renderers/renderer_impl.cc |
| @@ -129,6 +129,17 @@ void RendererImpl::Initialize(DemuxerStreamProvider* demuxer_stream_provider, |
| demuxer_stream_provider_ = demuxer_stream_provider; |
| init_cb_ = init_cb; |
| + DemuxerStream* audio_stream = |
| + demuxer_stream_provider->GetStream(DemuxerStream::AUDIO); |
| + if (audio_stream) |
| + audio_stream->SetStreamRestartedCB( |
| + base::Bind(&RendererImpl::RestartStreamPlayback, weak_this_)); |
| + DemuxerStream* video_stream = |
| + demuxer_stream_provider->GetStream(DemuxerStream::VIDEO); |
| + if (video_stream) |
| + video_stream->SetStreamRestartedCB( |
| + base::Bind(&RendererImpl::RestartStreamPlayback, weak_this_)); |
| + |
| if (HasEncryptedStream() && !cdm_context_) { |
| state_ = STATE_INIT_PENDING_CDM; |
| return; |
| @@ -201,6 +212,51 @@ void RendererImpl::StartPlayingFrom(base::TimeDelta time) { |
| video_renderer_->StartPlayingFrom(time); |
| } |
| +void RendererImpl::RestartStreamPlayback(DemuxerStream* stream, |
| + base::TimeDelta time) { |
| + DVLOG(1) << __FUNCTION__ << " stream=" << stream |
| + << " time=" << time.InSecondsF(); |
| + DCHECK(task_runner_->BelongsToCurrentThread()); |
| + if (stream->type() == DemuxerStream::VIDEO) { |
| + DCHECK(video_renderer_); |
| + DCHECK(video_ended_); |
| + video_ended_ = false; |
| + restarting_video_ = true; |
| + video_renderer_->Flush( |
| + base::Bind(&RendererImpl::RestartVideoRenderer, weak_this_, time)); |
| + } else if (stream->type() == DemuxerStream::AUDIO) { |
| + DCHECK(audio_renderer_); |
| + DCHECK(time_source_); |
| + DCHECK(audio_ended_); |
| + audio_ended_ = false; |
| + restarting_audio_ = true; |
| + // Stop ticking (transition into paused state) in audio renderer before |
| + // calling Flush, since after Flush we are going to restart playback by |
| + // calling audio renderer StartPlaying which would fail in playing state. |
| + time_ticking_ = false; |
| + time_source_->StopTicking(); |
| + audio_renderer_->Flush( |
| + base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time)); |
| + } |
| +} |
| + |
| +void RendererImpl::RestartVideoRenderer(base::TimeDelta time) { |
| + DCHECK(task_runner_->BelongsToCurrentThread()); |
| + if (state_ == STATE_PLAYING) { |
| + DCHECK(video_renderer_); |
| + video_renderer_->StartPlayingFrom(time); |
| + } |
| +} |
| + |
| +void RendererImpl::RestartAudioRenderer(base::TimeDelta time) { |
| + DCHECK(task_runner_->BelongsToCurrentThread()); |
| + if (state_ == STATE_PLAYING) { |
| + DCHECK(time_source_); |
| + DCHECK(audio_renderer_); |
| + audio_renderer_->StartPlaying(); |
| + } |
| +} |
| + |
| void RendererImpl::SetPlaybackRate(double playback_rate) { |
| DVLOG(1) << __FUNCTION__ << "(" << playback_rate << ")"; |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| @@ -502,6 +558,45 @@ void RendererImpl::OnBufferingStateChange(DemuxerStream::Type type, |
| bool was_waiting_for_enough_data = WaitingForEnoughData(); |
| + // When restarting playback we want to ignore the BUFFERING_HAVE_NOTHING for |
| + // the stream being restarted, to allow continuing uninterrupted playback on |
| + // the other stream. |
| + if (type == DemuxerStream::VIDEO && restarting_video_) { |
|
chcunningham
2016/06/24 23:32:55
For both audio and video, my previous comments sti
servolk
2016/06/25 00:36:33
Well, I have looked into this some more after your
chcunningham
2016/06/27 20:31:52
This is true, but its also a bug that I'm soon fix
servolk
2016/06/28 00:15:58
Ok, sure, if you are fixing the delivery of HAVE_N
|
| + if (new_buffering_state == BUFFERING_HAVE_NOTHING) { |
| + DVLOG(1) << __FUNCTION__ << " Ignoring BUFFERING_HAVE_NOTHING for video " |
| + "stream which is being restarted."; |
| + } else if (new_buffering_state == BUFFERING_HAVE_ENOUGH) { |
| + DVLOG(1) << __FUNCTION__ << " Got BUFFERING_HAVE_ENOUGH for video stream," |
| + " resuming playback."; |
| + restarting_video_ = false; |
| + if (playback_rate_ > 0) |
| + video_renderer_->OnTimeStateChanged(true); |
|
chcunningham
2016/06/24 23:32:55
Re-posting discussion from earlier - ping xhwang o
servolk
2016/06/25 00:36:33
Acknowledged. Should we open a separate bug for th
chcunningham
2016/06/27 20:31:52
Since xhwang is AFK and wolenetz is just CC, I rea
servolk
2016/06/28 00:15:58
Done.
|
| + } |
| + return; |
| + } |
| + |
| + if (type == DemuxerStream::AUDIO && restarting_audio_) { |
| + if (new_buffering_state == BUFFERING_HAVE_NOTHING) { |
| + DVLOG(1) << __FUNCTION__ << " Ignoring BUFFERING_HAVE_NOTHING for audio " |
| + "stream which is being restarted."; |
| + } else if (new_buffering_state == BUFFERING_HAVE_ENOUGH) { |
| + DVLOG(1) << __FUNCTION__ << " Got BUFFERING_HAVE_ENOUGH for audio stream," |
| + " resuming playback."; |
| + |
| + restarting_audio_ = false; |
| + |
| + // Now that we have decoded enough audio, pause and unpause playback |
| + // momentarily to ensure video renderer is synchronised with audio. |
| + double curr_playback_rate = playback_rate_; |
| + SetPlaybackRate(0); |
|
chcunningham
2016/06/24 23:32:55
My previous comment is not addressed. Reposting
W
servolk
2016/06/25 00:36:33
Prior to this point only the audio renderer is pau
chcunningham
2016/06/27 20:31:52
Can you instead try to audio_renderer_->SetMediaTi
servolk
2016/06/28 00:15:58
We need to be very careful here. audio_renderer_->
servolk
2016/06/28 02:05:43
Btw, just FYI: When I tried to set audio_renderer_
servolk
2016/06/28 18:51:44
I think we can make this better by allowing PauseP
servolk
2016/06/28 23:03:40
Ok, and patchset #48 implements deferred reporting
|
| + SetPlaybackRate(curr_playback_rate); |
| + |
| + time_ticking_ = true; |
| + time_source_->StartTicking(); |
| + } |
| + return; |
| + } |
| + |
| // When audio is present and has enough data, defer video underflow callbacks |
| // for some time to avoid unnecessary glitches in audio; see |
| // http://crbug.com/144683#c53. |
| @@ -612,7 +707,8 @@ void RendererImpl::StartPlayback() { |
| } |
| void RendererImpl::OnRendererEnded(DemuxerStream::Type type) { |
| - DVLOG(1) << __FUNCTION__; |
| + DVLOG(1) << __FUNCTION__ |
| + << (type == DemuxerStream::AUDIO ? " audio" : " video"); |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| DCHECK((type == DemuxerStream::AUDIO) || (type == DemuxerStream::VIDEO)); |