| Index: chromecast/media/cma/pipeline/av_pipeline_impl.cc
|
| diff --git a/chromecast/media/cma/pipeline/av_pipeline_impl.cc b/chromecast/media/cma/pipeline/av_pipeline_impl.cc
|
| index 2e2da54facea855610ce4925b4979c3927d82fbb..6c415c7fc2e51701458518263fec2a3794a99680 100644
|
| --- a/chromecast/media/cma/pipeline/av_pipeline_impl.cc
|
| +++ b/chromecast/media/cma/pipeline/av_pipeline_impl.cc
|
| @@ -45,10 +45,8 @@ AvPipelineImpl::AvPipelineImpl(
|
| enable_time_update_(false),
|
| pending_time_update_task_(false),
|
| media_keys_(NULL),
|
| - media_keys_callback_id_(kNoCallbackId),
|
| - weak_factory_(this) {
|
| + media_keys_callback_id_(kNoCallbackId) {
|
| DCHECK(media_component_device);
|
| - weak_this_ = weak_factory_.GetWeakPtr();
|
| thread_checker_.DetachFromThread();
|
| }
|
|
|
| @@ -58,8 +56,11 @@ AvPipelineImpl::~AvPipelineImpl() {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| media_component_device_->SetClient(MediaComponentDevice::Client());
|
|
|
| - if (media_keys_ && media_keys_callback_id_ != kNoCallbackId)
|
| - media_keys_->UnregisterPlayer(media_keys_callback_id_);
|
| + {
|
| + base::AutoLock lock(media_keys_lock_);
|
| + if (media_keys_ && media_keys_callback_id_ != kNoCallbackId)
|
| + media_keys_->UnregisterPlayer(media_keys_callback_id_);
|
| + }
|
| }
|
|
|
| void AvPipelineImpl::TransitionToState(State state) {
|
| @@ -80,7 +81,7 @@ void AvPipelineImpl::SetCodedFrameProvider(
|
| frame_provider.Pass(),
|
| max_buffer_size,
|
| max_frame_size,
|
| - base::Bind(&AvPipelineImpl::OnFrameBuffered, weak_this_)));
|
| + base::Bind(&AvPipelineImpl::OnFrameBuffered, this)));
|
| }
|
|
|
| void AvPipelineImpl::SetClient(const AvPipelineClient& client) {
|
| @@ -94,7 +95,7 @@ bool AvPipelineImpl::Initialize() {
|
| DCHECK_EQ(state_, kUninitialized);
|
|
|
| MediaComponentDevice::Client client;
|
| - client.eos_cb = base::Bind(&AvPipelineImpl::OnEos, weak_this_);
|
| + client.eos_cb = base::Bind(&AvPipelineImpl::OnEos, this);
|
| media_component_device_->SetClient(client);
|
| if (!media_component_device_->SetState(MediaComponentDevice::kStateIdle))
|
| return false;
|
| @@ -128,7 +129,7 @@ bool AvPipelineImpl::StartPlayingFrom(
|
| enable_feeding_ = true;
|
| base::MessageLoopProxy::current()->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
|
| + base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, this));
|
|
|
| return true;
|
| }
|
| @@ -183,15 +184,21 @@ void AvPipelineImpl::SetCdm(BrowserCdmCast* media_keys) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| DCHECK(media_keys);
|
|
|
| - if (media_keys_ && media_keys_callback_id_ != kNoCallbackId)
|
| - media_keys_->UnregisterPlayer(media_keys_callback_id_);
|
| -
|
| - media_keys_ = media_keys;
|
| - media_keys_callback_id_ = media_keys_->RegisterPlayer(
|
| - ::media::BindToCurrentLoop(
|
| - base::Bind(&AvPipelineImpl::OnCdmStateChanged, weak_this_)),
|
| - ::media::BindToCurrentLoop(
|
| - base::Bind(&AvPipelineImpl::OnCdmDestroyed, weak_this_)));
|
| + {
|
| + base::AutoLock lock(media_keys_lock_);
|
| + if (media_keys_ && media_keys_callback_id_ != kNoCallbackId)
|
| + media_keys_->UnregisterPlayer(media_keys_callback_id_);
|
| +
|
| + media_keys_ = media_keys;
|
| + media_keys_callback_id_ = media_keys_->RegisterPlayer(
|
| + ::media::BindToCurrentLoop(
|
| + base::Bind(&AvPipelineImpl::OnCdmStateChanged, this)),
|
| + // Note: this callback gets invoked in ~BrowserCdmCast. Posting
|
| + // OnCdmDestroyed to the media thread results in a race condition
|
| + // with media_keys_ accesses. This callback must run synchronously,
|
| + // otherwise media_keys_ access might occur after it is deleted.
|
| + base::Bind(&AvPipelineImpl::OnCdmDestroyed, this));
|
| + }
|
| }
|
|
|
| void AvPipelineImpl::OnEos() {
|
| @@ -214,7 +221,7 @@ void AvPipelineImpl::FetchBufferIfNeeded() {
|
|
|
| pending_read_ = true;
|
| frame_provider_->Read(
|
| - base::Bind(&AvPipelineImpl::OnNewFrame, weak_this_));
|
| + base::Bind(&AvPipelineImpl::OnNewFrame, this));
|
| }
|
|
|
| void AvPipelineImpl::OnNewFrame(
|
| @@ -232,7 +239,7 @@ void AvPipelineImpl::OnNewFrame(
|
|
|
| base::MessageLoopProxy::current()->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
|
| + base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, this));
|
| }
|
|
|
| void AvPipelineImpl::ProcessPendingBuffer() {
|
| @@ -243,7 +250,7 @@ void AvPipelineImpl::ProcessPendingBuffer() {
|
| if (!pending_buffer_.get() && !pending_read_) {
|
| base::MessageLoopProxy::current()->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, weak_this_));
|
| + base::Bind(&AvPipelineImpl::FetchBufferIfNeeded, this));
|
| return;
|
| }
|
|
|
| @@ -262,12 +269,15 @@ void AvPipelineImpl::ProcessPendingBuffer() {
|
| // Verify that CDM has the key ID.
|
| // Should not send the frame if the key ID is not available yet.
|
| std::string key_id(pending_buffer_->decrypt_config()->key_id());
|
| - if (!media_keys_) {
|
| - CMALOG(kLogControl) << "No CDM for frame: pts="
|
| - << pending_buffer_->timestamp().InMilliseconds();
|
| - return;
|
| + {
|
| + base::AutoLock lock(media_keys_lock_);
|
| + if (!media_keys_) {
|
| + CMALOG(kLogControl) << "No CDM for frame: pts="
|
| + << pending_buffer_->timestamp().InMilliseconds();
|
| + return;
|
| + }
|
| + decrypt_context = media_keys_->GetDecryptContext(key_id);
|
| }
|
| - decrypt_context = media_keys_->GetDecryptContext(key_id);
|
| if (!decrypt_context.get()) {
|
| CMALOG(kLogControl) << "frame(pts="
|
| << pending_buffer_->timestamp().InMilliseconds()
|
| @@ -294,7 +304,7 @@ void AvPipelineImpl::ProcessPendingBuffer() {
|
| MediaComponentDevice::FrameStatus status = media_component_device_->PushFrame(
|
| decrypt_context,
|
| pending_buffer_,
|
| - base::Bind(&AvPipelineImpl::OnFramePushed, weak_this_));
|
| + base::Bind(&AvPipelineImpl::OnFramePushed, this));
|
| pending_buffer_ = scoped_refptr<DecoderBufferBase>();
|
|
|
| pending_push_ = (status == MediaComponentDevice::kFramePending);
|
| @@ -313,7 +323,7 @@ void AvPipelineImpl::OnFramePushed(MediaComponentDevice::FrameStatus status) {
|
| }
|
| base::MessageLoopProxy::current()->PostTask(
|
| FROM_HERE,
|
| - base::Bind(&AvPipelineImpl::ProcessPendingBuffer, weak_this_));
|
| + base::Bind(&AvPipelineImpl::ProcessPendingBuffer, this));
|
| }
|
|
|
| void AvPipelineImpl::OnCdmStateChanged() {
|
| @@ -328,7 +338,7 @@ void AvPipelineImpl::OnCdmStateChanged() {
|
| }
|
|
|
| void AvPipelineImpl::OnCdmDestroyed() {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| + base::AutoLock lock(media_keys_lock_);
|
| media_keys_ = NULL;
|
| }
|
|
|
|
|