Chromium Code Reviews| Index: media/renderers/renderer_impl.cc |
| diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc |
| index f03b2da865c7f2b02b748b4f9f7f26f2627ebd50..d846df019335c509d1a3e1a96742357c8cfcc147 100644 |
| --- a/media/renderers/renderer_impl.cc |
| +++ b/media/renderers/renderer_impl.cc |
| @@ -80,6 +80,8 @@ RendererImpl::RendererImpl( |
| task_runner_(task_runner), |
| audio_renderer_(std::move(audio_renderer)), |
| video_renderer_(std::move(video_renderer)), |
| + current_audio_stream_(nullptr), |
| + current_video_stream_(nullptr), |
| time_source_(NULL), |
| time_ticking_(false), |
| playback_rate_(0.0), |
| @@ -237,7 +239,10 @@ void RendererImpl::OnStreamStatusChanged(DemuxerStream* stream, |
| DCHECK(video_renderer_); |
| restarting_video_ = true; |
| video_renderer_->Flush( |
| - base::Bind(&RendererImpl::RestartVideoRenderer, weak_this_, time)); |
| + base::Bind((stream == current_video_stream_) |
| + ? &RendererImpl::RestartVideoRenderer |
| + : &RendererImpl::ReinitializeVideoRenderer, |
| + weak_this_, stream, time)); |
| } else if (stream->type() == DemuxerStream::AUDIO) { |
| DCHECK(audio_renderer_); |
| DCHECK(time_source_); |
| @@ -250,25 +255,88 @@ void RendererImpl::OnStreamStatusChanged(DemuxerStream* stream, |
| time_source_->StopTicking(); |
| } |
| audio_renderer_->Flush( |
| - base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time)); |
| + base::Bind((stream == current_audio_stream_) |
| + ? &RendererImpl::RestartAudioRenderer |
| + : &RendererImpl::ReinitializeAudioRenderer, |
| + weak_this_, stream, time)); |
| } |
| } |
| -void RendererImpl::RestartVideoRenderer(base::TimeDelta time) { |
| - DVLOG(3) << __func__; |
| +void RendererImpl::ReinitializeVideoRenderer(DemuxerStream* stream, |
| + base::TimeDelta time) { |
| + DVLOG(3) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); |
|
xhwang
2017/03/29 00:16:47
nit: here and everywhere else, media switching isn
servolk
2017/03/29 01:49:33
Done.
|
| + DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK_NE(stream, current_video_stream_); |
| + |
| + current_video_stream_ = stream; |
| + video_renderer_->OnTimeStopped(); |
| + video_renderer_->Initialize( |
| + stream, cdm_context_, video_renderer_client_.get(), |
| + base::Bind(&RendererImpl::GetWallClockTimes, base::Unretained(this)), |
| + base::Bind(&RendererImpl::OnVideoRendererReinitialized, weak_this_, |
| + stream, time)); |
| +} |
| + |
| +void RendererImpl::OnVideoRendererReinitialized(DemuxerStream* stream, |
|
xhwang
2017/03/29 00:16:47
nit: Why do we need to pass in the |stream| here a
servolk
2017/03/29 01:49:33
Well, we could do without it, but it's just slight
|
| + base::TimeDelta time, |
| + PipelineStatus status) { |
| + DVLOG(3) << __func__ << ": status=" << status; |
| + DCHECK_EQ(stream, current_video_stream_); |
| + |
| + if (status != PIPELINE_OK) { |
| + OnError(status); |
| + return; |
| + } |
| + RestartVideoRenderer(stream, time); |
| +} |
| + |
| +void RendererImpl::RestartVideoRenderer(DemuxerStream* stream, |
| + base::TimeDelta time) { |
| + DVLOG(3) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| DCHECK(video_renderer_); |
| DCHECK_EQ(state_, STATE_PLAYING); |
| + DCHECK_EQ(stream, current_video_stream_); |
| + |
| video_ended_ = false; |
| video_renderer_->StartPlayingFrom(time); |
| } |
| -void RendererImpl::RestartAudioRenderer(base::TimeDelta time) { |
| - DVLOG(3) << __func__; |
| +void RendererImpl::ReinitializeAudioRenderer(DemuxerStream* stream, |
| + base::TimeDelta time) { |
| + DVLOG(3) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); |
| + DCHECK(task_runner_->BelongsToCurrentThread()); |
| + DCHECK_NE(stream, current_audio_stream_); |
| + |
| + current_audio_stream_ = stream; |
| + audio_renderer_->Initialize( |
| + stream, cdm_context_, audio_renderer_client_.get(), |
| + base::Bind(&RendererImpl::OnAudioRendererReinitialized, weak_this_, |
| + stream, time)); |
| +} |
| + |
| +void RendererImpl::OnAudioRendererReinitialized(DemuxerStream* stream, |
| + base::TimeDelta time, |
| + PipelineStatus status) { |
| + DVLOG(3) << __func__ << ": status=" << status; |
| + DCHECK_EQ(stream, current_audio_stream_); |
| + |
| + if (status != PIPELINE_OK) { |
| + OnError(status); |
| + return; |
| + } |
| + RestartAudioRenderer(stream, time); |
| +} |
| + |
| +void RendererImpl::RestartAudioRenderer(DemuxerStream* stream, |
| + base::TimeDelta time) { |
| + DVLOG(3) << __func__ << " stream=" << stream << " time=" << time.InSecondsF(); |
| DCHECK(task_runner_->BelongsToCurrentThread()); |
| DCHECK_EQ(state_, STATE_PLAYING); |
| DCHECK(time_source_); |
| DCHECK(audio_renderer_); |
| + DCHECK_EQ(stream, current_audio_stream_); |
| + |
| audio_ended_ = false; |
| audio_renderer_->StartPlaying(); |
| } |
| @@ -394,6 +462,8 @@ void RendererImpl::InitializeAudioRenderer() { |
| return; |
| } |
| + current_audio_stream_ = audio_stream; |
| + |
| audio_renderer_client_.reset( |
| new RendererClientInternal(DemuxerStream::AUDIO, this)); |
| // Note: After the initialization of a renderer, error events from it may |
| @@ -442,6 +512,8 @@ void RendererImpl::InitializeVideoRenderer() { |
| return; |
| } |
| + current_video_stream_ = video_stream; |
| + |
| video_renderer_client_.reset( |
| new RendererClientInternal(DemuxerStream::VIDEO, this)); |
| video_renderer_->Initialize( |