Index: media/mojo/clients/mojo_renderer_impl.cc |
diff --git a/media/mojo/clients/mojo_renderer_impl.cc b/media/mojo/clients/mojo_renderer_impl.cc |
index f407b89c57c7a98bcfa6b465b0911ad4d7631049..4bdd13a86797d4e15bae652d5213aa54c337cd08 100644 |
--- a/media/mojo/clients/mojo_renderer_impl.cc |
+++ b/media/mojo/clients/mojo_renderer_impl.cc |
@@ -34,6 +34,8 @@ MojoRendererImpl::MojoRendererImpl( |
MojoRendererImpl::~MojoRendererImpl() { |
DVLOG(1) << __FUNCTION__; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
+ |
+ FireAllPendingCallbacks(); |
sandersd (OOO until July 31)
2016/06/16 18:10:06
Why does the destructor need to call this?
xhwang
2016/06/17 06:59:00
The Renderer API says all pending callbacks should
|
} |
void MojoRendererImpl::Initialize( |
@@ -44,8 +46,13 @@ void MojoRendererImpl::Initialize( |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DCHECK(demuxer_stream_provider); |
+ if (encountered_error_) { |
+ task_runner_->PostTask( |
+ FROM_HERE, base::Bind(init_cb, PIPELINE_ERROR_INITIALIZATION_FAILED)); |
+ return; |
+ } |
+ |
demuxer_stream_provider_ = demuxer_stream_provider; |
- client_ = client; |
init_cb_ = init_cb; |
// Create audio and video mojom::DemuxerStream and bind its lifetime to |
@@ -68,10 +75,10 @@ void MojoRendererImpl::Initialize( |
// Using base::Unretained(this) is safe because |this| owns |
// |remote_renderer_|, and the callback won't be dispatched if |
// |remote_renderer_| is destroyed. |
- remote_renderer_->Initialize( |
- binding_.CreateInterfacePtrAndBind(), std::move(audio_stream), |
- std::move(video_stream), |
- base::Bind(&MojoRendererImpl::OnInitialized, base::Unretained(this))); |
+ remote_renderer_->Initialize(binding_.CreateInterfacePtrAndBind(), |
+ std::move(audio_stream), std::move(video_stream), |
+ base::Bind(&MojoRendererImpl::OnInitialized, |
+ base::Unretained(this), client)); |
} |
void MojoRendererImpl::SetCdm(CdmContext* cdm_context, |
@@ -79,24 +86,44 @@ void MojoRendererImpl::SetCdm(CdmContext* cdm_context, |
DVLOG(1) << __FUNCTION__; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DCHECK(cdm_context); |
+ DCHECK(!cdm_attached_cb.is_null()); |
+ DCHECK(cdm_attached_cb_.is_null()); |
+ |
+ if (encountered_error_) { |
+ task_runner_->PostTask(FROM_HERE, base::Bind(cdm_attached_cb, false)); |
+ return; |
+ } |
int32_t cdm_id = cdm_context->GetCdmId(); |
if (cdm_id == CdmContext::kInvalidCdmId) { |
DVLOG(2) << "MojoRendererImpl only works with remote CDMs but the CDM ID " |
"is invalid."; |
- cdm_attached_cb.Run(false); |
+ task_runner_->PostTask(FROM_HERE, base::Bind(cdm_attached_cb, false)); |
return; |
} |
BindRemoteRendererIfNeeded(); |
- remote_renderer_->SetCdm(cdm_id, cdm_attached_cb); |
+ |
+ cdm_attached_cb_ = cdm_attached_cb; |
+ remote_renderer_->SetCdm(cdm_id, base::Bind(&MojoRendererImpl::OnCdmAttached, |
+ base::Unretained(this))); |
} |
void MojoRendererImpl::Flush(const base::Closure& flush_cb) { |
DVLOG(2) << __FUNCTION__; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DCHECK(remote_renderer_.is_bound()); |
- remote_renderer_->Flush(flush_cb); |
+ DCHECK(!flush_cb.is_null()); |
+ DCHECK(flush_cb_.is_null()); |
+ |
+ if (encountered_error_) { |
+ task_runner_->PostTask(FROM_HERE, flush_cb); |
+ return; |
+ } |
+ |
+ flush_cb_ = flush_cb; |
+ remote_renderer_->Flush( |
+ base::Bind(&MojoRendererImpl::OnFlushed, base::Unretained(this))); |
} |
void MojoRendererImpl::StartPlayingFrom(base::TimeDelta time) { |
@@ -116,6 +143,7 @@ void MojoRendererImpl::SetPlaybackRate(double playback_rate) { |
DVLOG(2) << __FUNCTION__; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DCHECK(remote_renderer_.is_bound()); |
+ |
remote_renderer_->SetPlaybackRate(playback_rate); |
} |
@@ -123,6 +151,7 @@ void MojoRendererImpl::SetVolume(float volume) { |
DVLOG(2) << __FUNCTION__; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DCHECK(remote_renderer_.is_bound()); |
+ |
remote_renderer_->SetVolume(volume); |
} |
@@ -135,13 +164,16 @@ base::TimeDelta MojoRendererImpl::GetMediaTime() { |
bool MojoRendererImpl::HasAudio() { |
DVLOG(1) << __FUNCTION__; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
- DCHECK(remote_renderer_.get()); // We always bind the renderer. |
+ DCHECK(remote_renderer_.is_bound()); |
+ |
return !!demuxer_stream_provider_->GetStream(DemuxerStream::AUDIO); |
} |
bool MojoRendererImpl::HasVideo() { |
DVLOG(1) << __FUNCTION__; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(remote_renderer_.is_bound()); |
+ |
return !!demuxer_stream_provider_->GetStream(DemuxerStream::VIDEO); |
} |
@@ -170,6 +202,8 @@ void MojoRendererImpl::OnError() { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DCHECK(init_cb_.is_null()); |
+ encountered_error_ = true; |
+ |
// TODO(tim): Should we plumb error code from remote renderer? |
// http://crbug.com/410451. |
client_->OnError(PIPELINE_ERROR_DECODE); |
@@ -194,12 +228,11 @@ void MojoRendererImpl::OnConnectionError() { |
DVLOG(1) << __FUNCTION__; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
- if (!init_cb_.is_null()) { |
- base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
- return; |
- } |
+ encountered_error_ = true; |
+ FireAllPendingCallbacks(); |
- client_->OnError(PIPELINE_ERROR_DECODE); |
+ if (client_) |
+ client_->OnError(PIPELINE_ERROR_DECODE); |
} |
void MojoRendererImpl::BindRemoteRendererIfNeeded() { |
@@ -207,6 +240,8 @@ void MojoRendererImpl::BindRemoteRendererIfNeeded() { |
DCHECK(task_runner_->BelongsToCurrentThread()); |
// If |remote_renderer_| has already been bound, do nothing. |
+ // Note that after Bind() is called, |remote_renderer_| is always bound even |
+ // after connection error. |
if (remote_renderer_.is_bound()) |
return; |
@@ -221,13 +256,49 @@ void MojoRendererImpl::BindRemoteRendererIfNeeded() { |
base::Bind(&MojoRendererImpl::OnConnectionError, base::Unretained(this))); |
} |
-void MojoRendererImpl::OnInitialized(bool success) { |
+void MojoRendererImpl::OnInitialized(media::RendererClient* client, |
+ bool success) { |
DVLOG(1) << __FUNCTION__; |
DCHECK(task_runner_->BelongsToCurrentThread()); |
DCHECK(!init_cb_.is_null()); |
+ // Only set |client_| after initialization succeeded. No client methods should |
+ // be called before this. |
+ if (success) |
+ client_ = client; |
+ |
base::ResetAndReturn(&init_cb_).Run( |
success ? PIPELINE_OK : PIPELINE_ERROR_INITIALIZATION_FAILED); |
} |
+void MojoRendererImpl::OnFlushed() { |
+ DVLOG(1) << __FUNCTION__; |
+ DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(!flush_cb_.is_null()); |
+ |
+ base::ResetAndReturn(&flush_cb_).Run(); |
+} |
+ |
+void MojoRendererImpl::OnCdmAttached(bool success) { |
+ DVLOG(1) << __FUNCTION__; |
+ DCHECK(task_runner_->BelongsToCurrentThread()); |
+ DCHECK(!cdm_attached_cb_.is_null()); |
+ |
+ base::ResetAndReturn(&cdm_attached_cb_).Run(success); |
+} |
+ |
+void MojoRendererImpl::FireAllPendingCallbacks() { |
sandersd (OOO until July 31)
2016/06/16 18:10:06
This name should probably indicate that the callba
xhwang
2016/06/17 06:59:00
Done.
|
+ DVLOG(1) << __FUNCTION__; |
+ DCHECK(task_runner_->BelongsToCurrentThread()); |
+ |
+ if (!init_cb_.is_null()) |
+ base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED); |
+ |
+ if (!flush_cb_.is_null()) |
+ base::ResetAndReturn(&flush_cb_).Run(); |
+ |
+ if (!cdm_attached_cb_.is_null()) |
+ base::ResetAndReturn(&cdm_attached_cb_).Run(false); |
+} |
+ |
} // namespace media |