Index: media/renderers/renderer_impl.cc |
diff --git a/media/renderers/renderer_impl.cc b/media/renderers/renderer_impl.cc |
index f03b2da865c7f2b02b748b4f9f7f26f2627ebd50..f701ba7806386b036721944396a203951df491de 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), |
@@ -236,8 +238,8 @@ void RendererImpl::OnStreamStatusChanged(DemuxerStream* stream, |
if (stream->type() == DemuxerStream::VIDEO) { |
DCHECK(video_renderer_); |
restarting_video_ = true; |
- video_renderer_->Flush( |
- base::Bind(&RendererImpl::RestartVideoRenderer, weak_this_, time)); |
+ video_renderer_->Flush(base::Bind(&RendererImpl::RestartVideoRenderer, |
+ weak_this_, stream, time)); |
} else if (stream->type() == DemuxerStream::AUDIO) { |
DCHECK(audio_renderer_); |
DCHECK(time_source_); |
@@ -249,30 +251,76 @@ void RendererImpl::OnStreamStatusChanged(DemuxerStream* stream, |
time_ticking_ = false; |
time_source_->StopTicking(); |
} |
- audio_renderer_->Flush( |
- base::Bind(&RendererImpl::RestartAudioRenderer, weak_this_, time)); |
+ audio_renderer_->Flush(base::Bind(&RendererImpl::RestartAudioRenderer, |
+ weak_this_, stream, time)); |
} |
} |
-void RendererImpl::RestartVideoRenderer(base::TimeDelta time) { |
- DVLOG(3) << __func__; |
+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); |
+ if (stream != current_video_stream_) { |
+ DVLOG(3) << __func__ << ": detected stream change, reinitializing decoder"; |
+ 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::OnVideoRendererReinitCompleted, weak_this_, |
+ stream, time)); |
+ return; |
+ } |
video_ended_ = false; |
video_renderer_->StartPlayingFrom(time); |
} |
-void RendererImpl::RestartAudioRenderer(base::TimeDelta time) { |
- DVLOG(3) << __func__; |
+void RendererImpl::OnVideoRendererReinitCompleted(DemuxerStream* stream, |
+ base::TimeDelta time, |
+ PipelineStatus status) { |
+ DVLOG(3) << __func__ << ": status=" << status; |
+ if (status != PIPELINE_OK) { |
+ OnError(status); |
+ return; |
+ } |
+ DCHECK_EQ(stream, current_video_stream_); |
+ RestartVideoRenderer(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_); |
+ if (stream != current_audio_stream_) { |
+ DVLOG(3) << __func__ << ": detected stream change, reinitializing decoder"; |
+ current_audio_stream_ = stream; |
+ audio_renderer_->Initialize( |
+ stream, cdm_context_, audio_renderer_client_.get(), |
+ base::Bind(&RendererImpl::OnAudioRendererReinitCompleted, weak_this_, |
+ stream, time)); |
+ return; |
+ } |
audio_ended_ = false; |
audio_renderer_->StartPlaying(); |
} |
+void RendererImpl::OnAudioRendererReinitCompleted(DemuxerStream* stream, |
+ base::TimeDelta time, |
+ PipelineStatus status) { |
+ DVLOG(3) << __func__ << ": status=" << status; |
+ if (status != PIPELINE_OK) { |
+ OnError(status); |
+ return; |
+ } |
+ DCHECK_EQ(stream, current_audio_stream_); |
+ RestartAudioRenderer(stream, time); |
+} |
+ |
void RendererImpl::SetPlaybackRate(double playback_rate) { |
DVLOG(1) << __func__ << "(" << playback_rate << ")"; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
@@ -394,6 +442,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 +492,8 @@ void RendererImpl::InitializeVideoRenderer() { |
return; |
} |
+ current_video_stream_ = video_stream; |
+ |
video_renderer_client_.reset( |
new RendererClientInternal(DemuxerStream::VIDEO, this)); |
video_renderer_->Initialize( |