Index: chromecast/browser/media/cma_message_filter_host.cc |
diff --git a/chromecast/browser/media/cma_message_filter_host.cc b/chromecast/browser/media/cma_message_filter_host.cc |
index e47cd71bafe539f49d5d44703609fc5fda03871c..899b9ef43f4ba56a855bc638d08320a0d537111a 100644 |
--- a/chromecast/browser/media/cma_message_filter_host.cc |
+++ b/chromecast/browser/media/cma_message_filter_host.cc |
@@ -6,6 +6,7 @@ |
#include <utility> |
+#include "base/lazy_instance.h" |
#include "base/memory/scoped_ptr.h" |
#include "base/memory/shared_memory.h" |
#include "base/sync_socket.h" |
@@ -37,16 +38,91 @@ namespace { |
const size_t kMaxSharedMem = 8 * 1024 * 1024; |
-void DestroyMediaPipelineUi( |
- scoped_refptr<base::SingleThreadTaskRunner> cma_task_runner, |
- scoped_ptr<MediaPipelineHost> media_pipeline) { |
- // Note: the longest path that uses MediaPipelineHost from |
- // CmaMessageFilterHost is the "SetCdm" message, which travels: |
- // IO thread (msg) --> UI thread (get BrowserCdm) --> CMA thread (SetCdm) |
- // Teardown follows the same path to avoid MediaPipelineHost being destroyed |
- // while SetCdm is on/waiting for the UI thread. |
+typedef std::map<uint64_t, MediaPipelineHost*> MediaPipelineCmaMap; |
+ |
+// Map of MediaPipelineHost instances that is accessed only from the CMA thread. |
+// The existence of a MediaPipelineHost* in this map implies that the instance |
+// is still valid. |
+base::LazyInstance<MediaPipelineCmaMap> g_pipeline_map_cma = |
+ LAZY_INSTANCE_INITIALIZER; |
+ |
+uint64_t GetPipelineCmaId(int process_id, int media_id) { |
+ return (static_cast<uint64>(process_id) << 32) + |
+ static_cast<uint64>(media_id); |
+} |
+ |
+MediaPipelineHost* GetMediaPipeline(int process_id, int media_id) { |
+ DCHECK(CmaMessageLoop::GetTaskRunner()->BelongsToCurrentThread()); |
+ MediaPipelineCmaMap::iterator it = |
+ g_pipeline_map_cma.Get().find(GetPipelineCmaId(process_id, media_id)); |
+ if (it == g_pipeline_map_cma.Get().end()) |
+ return nullptr; |
+ return it->second; |
+} |
+ |
+void SetMediaPipeline(int process_id, int media_id, MediaPipelineHost* host) { |
+ DCHECK(CmaMessageLoop::GetTaskRunner()->BelongsToCurrentThread()); |
+ std::pair<MediaPipelineCmaMap::iterator, bool> ret = |
+ g_pipeline_map_cma.Get().insert( |
+ std::make_pair(GetPipelineCmaId(process_id, media_id), host)); |
+ |
+ // Check there is no other entry with the same ID. |
+ DCHECK(ret.second != false); |
+} |
+ |
+void DestroyMediaPipeline(int process_id, |
+ int media_id, |
+ scoped_ptr<MediaPipelineHost> media_pipeline) { |
+ DCHECK(CmaMessageLoop::GetTaskRunner()->BelongsToCurrentThread()); |
+ MediaPipelineCmaMap::iterator it = |
+ g_pipeline_map_cma.Get().find(GetPipelineCmaId(process_id, media_id)); |
+ if (it != g_pipeline_map_cma.Get().end()) |
+ g_pipeline_map_cma.Get().erase(it); |
+} |
+ |
+void SetCdmOnCmaThread(int render_process_id, int media_id, |
+ BrowserCdmCast* cdm) { |
+ MediaPipelineHost* pipeline = GetMediaPipeline(render_process_id, media_id); |
+ if (!pipeline) { |
+ LOG(WARNING) << "MediaPipelineHost not alive: " << render_process_id << "," |
+ << media_id; |
+ return; |
+ } |
+ |
+ pipeline->SetCdm(cdm); |
+} |
+ |
+// BrowserCdm instance must be retrieved/accessed on the UI thread, then |
+// passed to MediaPipelineHost on CMA thread. |
+void SetCdmOnUiThread( |
+ int render_process_id, |
+ int render_frame_id, |
+ int media_id, |
+ int cdm_id) { |
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- cma_task_runner->DeleteSoon(FROM_HERE, media_pipeline.release()); |
+ |
+ content::RenderProcessHost* host = |
+ content::RenderProcessHost::FromID(render_process_id); |
+ if (!host) { |
+ LOG(ERROR) << "RenderProcessHost not alive for ID: " << render_process_id; |
+ return; |
+ } |
+ |
+ ::media::BrowserCdm* cdm = host->GetBrowserCdm(render_frame_id, cdm_id); |
+ if (!cdm) { |
+ LOG(WARNING) << "Could not find BrowserCdm (" << render_frame_id << "," |
+ << cdm_id << ")"; |
+ return; |
+ } |
+ |
+ BrowserCdmCast* browser_cdm_cast = |
+ static_cast<BrowserCdmCastUi*>(cdm)->browser_cdm_cast(); |
+ CmaMessageLoop::GetTaskRunner()->PostTask( |
+ FROM_HERE, |
+ base::Bind(&SetCdmOnCmaThread, |
+ render_process_id, |
+ media_id, |
+ browser_cdm_cast)); |
} |
void UpdateVideoSurfaceHost(int surface_id, const gfx::QuadF& quad) { |
@@ -112,10 +188,9 @@ void CmaMessageFilterHost::DeleteEntries() { |
it != media_pipelines_.end(); ) { |
scoped_ptr<MediaPipelineHost> media_pipeline(it->second); |
media_pipelines_.erase(it++); |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, |
+ task_runner_->PostTask( |
FROM_HERE, |
- base::Bind(&DestroyMediaPipelineUi, task_runner_, |
+ base::Bind(&DestroyMediaPipeline, process_id_, it->first, |
base::Passed(&media_pipeline))); |
} |
} |
@@ -144,6 +219,10 @@ void CmaMessageFilterHost::CreateMedia(int media_id, LoadType load_type) { |
weak_this_, media_id, media::kNoTrackId)); |
task_runner_->PostTask( |
FROM_HERE, |
+ base::Bind(&SetMediaPipeline, |
+ process_id_, media_id, media_pipeline_host.get())); |
+ task_runner_->PostTask( |
+ FROM_HERE, |
base::Bind(&MediaPipelineHost::Initialize, |
base::Unretained(media_pipeline_host.get()), |
load_type, client)); |
@@ -164,10 +243,9 @@ void CmaMessageFilterHost::DestroyMedia(int media_id) { |
scoped_ptr<MediaPipelineHost> media_pipeline(it->second); |
media_pipelines_.erase(it); |
- content::BrowserThread::PostTask( |
- content::BrowserThread::UI, |
+ task_runner_->PostTask( |
FROM_HERE, |
- base::Bind(&DestroyMediaPipelineUi, task_runner_, |
+ base::Bind(&DestroyMediaPipeline, process_id_, media_id, |
base::Passed(&media_pipeline))); |
} |
@@ -181,34 +259,10 @@ void CmaMessageFilterHost::SetCdm(int media_id, |
content::BrowserThread::PostTask( |
content::BrowserThread::UI, FROM_HERE, |
- base::Bind(&CmaMessageFilterHost::SetCdmOnUiThread, |
- this, media_pipeline, render_frame_id, cdm_id)); |
+ base::Bind(&SetCdmOnUiThread, |
+ process_id_, render_frame_id, media_id, cdm_id)); |
} |
-void CmaMessageFilterHost::SetCdmOnUiThread( |
- MediaPipelineHost* media_pipeline, |
- int render_frame_id, |
- int cdm_id) { |
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
- |
- content::RenderProcessHost* host = |
- content::RenderProcessHost::FromID(process_id_); |
- if (!host) { |
- LOG(ERROR) << "RenderProcessHost not alive for ID: " << process_id_; |
- return; |
- } |
- |
- ::media::BrowserCdm* cdm = host->GetBrowserCdm(render_frame_id, cdm_id); |
- if (!cdm) { |
- LOG(ERROR) << "Could not find BrowserCdm (" << render_frame_id << "," |
- << cdm_id << ")"; |
- return; |
- } |
- |
- BrowserCdmCast* browser_cdm_cast = |
- static_cast<BrowserCdmCastUi*>(cdm)->browser_cdm_cast(); |
- FORWARD_CALL(media_pipeline, SetCdm, browser_cdm_cast); |
-} |
void CmaMessageFilterHost::CreateAvPipe( |
int media_id, TrackId track_id, size_t shared_mem_size) { |