summaryrefslogtreecommitdiffstats
path: root/chromecast
diff options
context:
space:
mode:
authorhalliwell <halliwell@chromium.org>2016-03-24 11:26:58 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-24 18:28:29 +0000
commitb862bc4a9d19233e3876e575c3ca67a28817846c (patch)
treed0560cc3a0e1c607112058341811128b703f7fbc /chromecast
parentbd6dc56899588026a824df756f11303150f02cf3 (diff)
downloadchromium_src-b862bc4a9d19233e3876e575c3ca67a28817846c.zip
chromium_src-b862bc4a9d19233e3876e575c3ca67a28817846c.tar.gz
chromium_src-b862bc4a9d19233e3876e575c3ca67a28817846c.tar.bz2
[Chromecast] Centralise tracking of media resource usage
See linked bug for motivation: new idea is that we will consider CDM instances as potential users of vendor media code (via OEMCrypto APIs) and will also call CastMediaShlib::Finalize when relinquishing media resources (symmetrically, Initialize when acquiring). This means media resource relinquish needs to wait for CDM destruction, similarly to how it waits for CMA pipelines today, so media pipeline client is removed in favour of a more general MediaResourceTracker. All Initialize/Finalize calls should be made from here now in order to keep track of 'initialized' status. Also see internal CL for a complete picture. BUG=internal b/26022500 Review URL: https://codereview.chromium.org/1824583002 Cr-Commit-Position: refs/heads/master@{#383101}
Diffstat (limited to 'chromecast')
-rw-r--r--chromecast/browser/cast_browser_main_parts.cc33
-rw-r--r--chromecast/browser/cast_browser_main_parts.h9
-rw-r--r--chromecast/browser/cast_content_browser_client.cc33
-rw-r--r--chromecast/browser/cast_content_browser_client.h21
-rw-r--r--chromecast/browser/media/BUILD.gn2
-rw-r--r--chromecast/browser/media/cast_browser_cdm_factory.cc8
-rw-r--r--chromecast/browser/media/cast_browser_cdm_factory.h8
-rw-r--r--chromecast/browser/media/cma_media_pipeline_client.cc54
-rw-r--r--chromecast/browser/media/cma_media_pipeline_client.h53
-rw-r--r--chromecast/browser/media/cma_message_filter_host.cc29
-rw-r--r--chromecast/browser/media/cma_message_filter_host.h10
-rw-r--r--chromecast/chromecast.gyp2
-rw-r--r--chromecast/media/base/BUILD.gn3
-rw-r--r--chromecast/media/base/media_resource_tracker.cc168
-rw-r--r--chromecast/media/base/media_resource_tracker.h116
-rw-r--r--chromecast/media/cdm/browser_cdm_cast.cc7
-rw-r--r--chromecast/media/cdm/browser_cdm_cast.h4
-rw-r--r--chromecast/media/media.gyp2
18 files changed, 391 insertions, 171 deletions
diff --git a/chromecast/browser/cast_browser_main_parts.cc b/chromecast/browser/cast_browser_main_parts.cc
index 6251a34..5c3862b 100644
--- a/chromecast/browser/cast_browser_main_parts.cc
+++ b/chromecast/browser/cast_browser_main_parts.cc
@@ -37,7 +37,9 @@
#include "chromecast/media/audio/cast_audio_manager_factory.h"
#include "chromecast/media/base/key_systems_common.h"
#include "chromecast/media/base/media_message_loop.h"
+#include "chromecast/media/base/media_resource_tracker.h"
#include "chromecast/media/base/video_plane_controller.h"
+#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h"
#include "chromecast/net/connectivity_checker.h"
#include "chromecast/public/cast_media_shlib.h"
#include "chromecast/public/cast_sys_info.h"
@@ -246,6 +248,10 @@ CastBrowserMainParts::CastBrowserMainParts(
net_log_(new CastNetLog()) {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
AddDefaultCommandLineSwitches(command_line);
+
+#if !defined(OS_ANDROID)
+ media_resource_tracker_ = nullptr;
+#endif // !defined(OS_ANDROID)
}
CastBrowserMainParts::~CastBrowserMainParts() {
@@ -257,6 +263,16 @@ CastBrowserMainParts::GetMediaTaskRunner() const {
return media::MediaMessageLoop::GetTaskRunner();
}
+#if !defined(OS_ANDROID)
+media::MediaResourceTracker* CastBrowserMainParts::media_resource_tracker() {
+ if (!media_resource_tracker_) {
+ media_resource_tracker_ = new media::MediaResourceTracker(
+ base::ThreadTaskRunnerHandle::Get(), GetMediaTaskRunner());
+ }
+ return media_resource_tracker_;
+}
+#endif
+
void CastBrowserMainParts::PreMainMessageLoopStart() {
// GroupedHistograms needs to be initialized before any threads are created
// to prevent race conditions between calls to Preregister and those threads
@@ -353,7 +369,6 @@ void CastBrowserMainParts::PreMainMessageLoopRun() {
cast_browser_process_->SetPrefService(
PrefServiceHelper::CreatePrefService(pref_registry.get()));
- const base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
#if defined(OS_ANDROID)
::media::SetMediaClientAndroid(new media::CastMediaClientAndroid());
#endif // defined(OS_ANDROID)
@@ -382,9 +397,6 @@ void CastBrowserMainParts::PreMainMessageLoopRun() {
new RemoteDebuggingServer(cast_browser_process_->browser_client()->
EnableRemoteDebuggingImmediately())));
- media::CastMediaShlib::Initialize(cmd_line->argv());
- ::media::InitializeMediaLibrary();
-
#if defined(USE_AURA) && !defined(DISABLE_DISPLAY)
// TODO(halliwell) move audio builds to use ozone_platform_cast, then can
// simplify this by removing DISABLE_DISPLAY condition. Should then also
@@ -407,6 +419,11 @@ void CastBrowserMainParts::PreMainMessageLoopRun() {
video_plane_controller_.get()));
cast_browser_process_->cast_service()->Initialize();
+#if !defined(OS_ANDROID)
+ media_resource_tracker()->InitializeMediaLib();
+#endif
+ ::media::InitializeMediaLibrary();
+
// Initializing metrics service and network delegates must happen after cast
// service is intialized because CastMetricsServiceClient and
// CastNetworkDelegate may use components initialized by cast service.
@@ -465,10 +482,10 @@ void CastBrowserMainParts::PostMainMessageLoopRun() {
}
void CastBrowserMainParts::PostDestroyThreads() {
- // Finalize CastMediaShlib on media thread to ensure it's not accessed
- // after Finalize.
- GetMediaTaskRunner()->PostTask(FROM_HERE,
- base::Bind(&media::CastMediaShlib::Finalize));
+#if !defined(OS_ANDROID)
+ media_resource_tracker_->FinalizeAndDestroy();
+ media_resource_tracker_ = nullptr;
+#endif
}
} // namespace shell
diff --git a/chromecast/browser/cast_browser_main_parts.h b/chromecast/browser/cast_browser_main_parts.h
index 4d7284d..1466b04 100644
--- a/chromecast/browser/cast_browser_main_parts.h
+++ b/chromecast/browser/cast_browser_main_parts.h
@@ -22,6 +22,7 @@ class NetLog;
namespace chromecast {
namespace media {
+class MediaResourceTracker;
class VideoPlaneController;
} // namespace media
@@ -37,6 +38,9 @@ class CastBrowserMainParts : public content::BrowserMainParts {
~CastBrowserMainParts() override;
scoped_refptr<base::SingleThreadTaskRunner> GetMediaTaskRunner() const;
+#if !defined(OS_ANDROID)
+ media::MediaResourceTracker* media_resource_tracker();
+#endif
// content::BrowserMainParts implementation:
void PreMainMessageLoopStart() override;
@@ -55,6 +59,11 @@ class CastBrowserMainParts : public content::BrowserMainParts {
scoped_ptr<net::NetLog> net_log_;
scoped_ptr<media::VideoPlaneController> video_plane_controller_;
+#if !defined(OS_ANDROID)
+ // Tracks usage of media resource by e.g. CMA pipeline, CDM.
+ media::MediaResourceTracker* media_resource_tracker_;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(CastBrowserMainParts);
};
diff --git a/chromecast/browser/cast_content_browser_client.cc b/chromecast/browser/cast_content_browser_client.cc
index ff159cb..00cf5d4 100644
--- a/chromecast/browser/cast_content_browser_client.cc
+++ b/chromecast/browser/cast_content_browser_client.cc
@@ -26,11 +26,11 @@
#include "chromecast/browser/cast_quota_permission_context.h"
#include "chromecast/browser/cast_resource_dispatcher_host_delegate.h"
#include "chromecast/browser/geolocation/cast_access_token_store.h"
-#include "chromecast/browser/media/cma_media_pipeline_client.h"
#include "chromecast/browser/media/cma_message_filter_host.h"
#include "chromecast/browser/service/cast_service_simple.h"
#include "chromecast/browser/url_request_context_factory.h"
#include "chromecast/common/global_descriptors.h"
+#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h"
#include "chromecast/public/media/media_pipeline_backend.h"
#include "components/crash/content/app/breakpad_linux.h"
#include "components/crash/content/browser/crash_handler_host_linux.h"
@@ -105,11 +105,16 @@ scoped_ptr<CastService> CastContentBrowserClient::CreateCastService(
}
#if !defined(OS_ANDROID)
-scoped_refptr<media::CmaMediaPipelineClient>
-CastContentBrowserClient::GetCmaMediaPipelineClient() {
- if (!cma_media_pipeline_client_.get())
- cma_media_pipeline_client_ = CreateCmaMediaPipelineClient();
- return cma_media_pipeline_client_;
+scoped_ptr<media::MediaPipelineBackend>
+CastContentBrowserClient::CreateMediaPipelineBackend(
+ const media::MediaPipelineDeviceParams& params) {
+ return make_scoped_ptr(
+ media::MediaPipelineBackendManager::CreateMediaPipelineBackend(params));
+}
+
+media::MediaResourceTracker*
+CastContentBrowserClient::media_resource_tracker() {
+ return cast_browser_main_parts_->media_resource_tracker();
}
#endif // OS_ANDROID
@@ -139,7 +144,10 @@ void CastContentBrowserClient::RenderProcessWillLaunch(
#if !defined(OS_ANDROID)
scoped_refptr<media::CmaMessageFilterHost> cma_message_filter(
new media::CmaMessageFilterHost(
- host->GetID(), GetCmaMediaPipelineClient(), GetMediaTaskRunner()));
+ host->GetID(),
+ base::Bind(&CastContentBrowserClient::CreateMediaPipelineBackend,
+ base::Unretained(this)),
+ GetMediaTaskRunner(), media_resource_tracker()));
host->AddFilter(cma_message_filter.get());
#endif // !defined(OS_ANDROID)
@@ -160,13 +168,6 @@ CastContentBrowserClient::GetMediaTaskRunner() {
return cast_browser_main_parts_->GetMediaTaskRunner();
}
-#if !defined(OS_ANDROID)
-scoped_refptr<media::CmaMediaPipelineClient>
-CastContentBrowserClient::CreateCmaMediaPipelineClient() {
- return make_scoped_refptr(new media::CmaMediaPipelineClient());
-}
-#endif // OS_ANDROID
-
void CastContentBrowserClient::AddNetworkHintsMessageFilter(
int render_process_id, net::URLRequestContext* context) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -421,8 +422,8 @@ void CastContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
scoped_ptr<::media::CdmFactory> CastContentBrowserClient::CreateCdmFactory() {
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableCmaMediaPipeline)) {
- return make_scoped_ptr(
- new media::CastBrowserCdmFactory(GetMediaTaskRunner()));
+ return make_scoped_ptr(new media::CastBrowserCdmFactory(
+ GetMediaTaskRunner(), media_resource_tracker()));
}
return nullptr;
diff --git a/chromecast/browser/cast_content_browser_client.h b/chromecast/browser/cast_content_browser_client.h
index 9d16a0a..19ccffa 100644
--- a/chromecast/browser/cast_content_browser_client.h
+++ b/chromecast/browser/cast_content_browser_client.h
@@ -32,7 +32,9 @@ namespace chromecast {
class CastService;
namespace media {
-class CmaMediaPipelineClient;
+class MediaPipelineBackend;
+struct MediaPipelineDeviceParams;
+class MediaResourceTracker;
class VideoPlaneController;
}
@@ -65,9 +67,12 @@ class CastContentBrowserClient : public content::ContentBrowserClient {
media::VideoPlaneController* video_plane_controller);
#if !defined(OS_ANDROID)
- // Returns CmaMediaPipelineClient which is responsible to create
- // CMA backend for media playback and watch media pipeline status.
- scoped_refptr<media::CmaMediaPipelineClient> GetCmaMediaPipelineClient();
+ // Creates a MediaPipelineDevice (CMA backend) for media playback, called
+ // once per media player instance.
+ virtual scoped_ptr<media::MediaPipelineBackend> CreateMediaPipelineBackend(
+ const media::MediaPipelineDeviceParams& params);
+
+ media::MediaResourceTracker* media_resource_tracker();
#endif
// Invoked when the metrics client ID changes.
@@ -159,11 +164,6 @@ class CastContentBrowserClient : public content::ContentBrowserClient {
// Returns the task runner that must be used for media IO.
scoped_refptr<base::SingleThreadTaskRunner> GetMediaTaskRunner();
-#if !defined(OS_ANDROID)
- virtual scoped_refptr<media::CmaMediaPipelineClient>
- CreateCmaMediaPipelineClient();
-#endif // !defined(OS_ANDROID)
-
URLRequestContextFactory* url_request_context_factory() const {
return url_request_context_factory_.get();
}
@@ -186,9 +186,6 @@ class CastContentBrowserClient : public content::ContentBrowserClient {
// A static cache to hold crash_handlers for each process_type
std::map<std::string, breakpad::CrashHandlerHostLinux*> crash_handlers_;
-
- // The CmaMediaPipelineClient to pass to all message hosts.
- scoped_refptr<media::CmaMediaPipelineClient> cma_media_pipeline_client_;
#endif // !defined(OS_ANDROID)
// Created by CastContentBrowserClient but owned by BrowserMainLoop.
diff --git a/chromecast/browser/media/BUILD.gn b/chromecast/browser/media/BUILD.gn
index a2d6519..f9dc907 100644
--- a/chromecast/browser/media/BUILD.gn
+++ b/chromecast/browser/media/BUILD.gn
@@ -47,8 +47,6 @@ source_set("media") {
deps += [ "//components/cdm/browser" ]
} else {
sources += [
- "cma_media_pipeline_client.cc",
- "cma_media_pipeline_client.h",
"cma_message_filter_host.cc",
"cma_message_filter_host.h",
]
diff --git a/chromecast/browser/media/cast_browser_cdm_factory.cc b/chromecast/browser/media/cast_browser_cdm_factory.cc
index c04ef522..5393e0a 100644
--- a/chromecast/browser/media/cast_browser_cdm_factory.cc
+++ b/chromecast/browser/media/cast_browser_cdm_factory.cc
@@ -16,10 +16,14 @@ namespace chromecast {
namespace media {
CastBrowserCdmFactory::CastBrowserCdmFactory(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
- : task_runner_(task_runner) {
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ MediaResourceTracker* media_resource_tracker)
+ : media_resource_tracker_(media_resource_tracker),
+ task_runner_(task_runner) {
+ DCHECK(media_resource_tracker_);
DCHECK(task_runner_);
}
+
CastBrowserCdmFactory::~CastBrowserCdmFactory() {}
void CastBrowserCdmFactory::Create(
diff --git a/chromecast/browser/media/cast_browser_cdm_factory.h b/chromecast/browser/media/cast_browser_cdm_factory.h
index 70fd9a4..30d11be 100644
--- a/chromecast/browser/media/cast_browser_cdm_factory.h
+++ b/chromecast/browser/media/cast_browser_cdm_factory.h
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "chromecast/media/base/key_systems_common.h"
+#include "chromecast/media/base/media_resource_tracker.h"
#include "media/base/cdm_factory.h"
#include "media/base/media_keys.h"
@@ -22,8 +23,8 @@ class BrowserCdmCast;
class CastBrowserCdmFactory : public ::media::CdmFactory {
public:
// CDM factory will use |task_runner| to initialize the CDM.
- explicit CastBrowserCdmFactory(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ CastBrowserCdmFactory(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ MediaResourceTracker* media_resource_tracker);
~CastBrowserCdmFactory() override;
// ::media::CdmFactory implementation:
@@ -42,6 +43,9 @@ class CastBrowserCdmFactory : public ::media::CdmFactory {
virtual scoped_refptr<BrowserCdmCast> CreatePlatformBrowserCdm(
const CastKeySystem& cast_key_system);
+ protected:
+ MediaResourceTracker* media_resource_tracker_;
+
private:
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
DISALLOW_COPY_AND_ASSIGN(CastBrowserCdmFactory);
diff --git a/chromecast/browser/media/cma_media_pipeline_client.cc b/chromecast/browser/media/cma_media_pipeline_client.cc
deleted file mode 100644
index e91f513..0000000
--- a/chromecast/browser/media/cma_media_pipeline_client.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chromecast/browser/media/cma_media_pipeline_client.h"
-#include "chromecast/media/cma/backend/media_pipeline_backend_manager.h"
-#include "chromecast/public/cast_media_shlib.h"
-
-namespace chromecast {
-namespace media {
-
-CmaMediaPipelineClient::CmaMediaPipelineClient() : media_pipeline_count_(0) {
- thread_checker_.DetachFromThread();
-}
-
-CmaMediaPipelineClient::~CmaMediaPipelineClient() {}
-
-scoped_ptr<MediaPipelineBackend>
-CmaMediaPipelineClient::CreateMediaPipelineBackend(
- const MediaPipelineDeviceParams& params) {
- return make_scoped_ptr(
- MediaPipelineBackendManager::CreateMediaPipelineBackend(params));
-}
-
-void CmaMediaPipelineClient::OnMediaPipelineBackendCreated() {
- DCHECK(thread_checker_.CalledOnValidThread());
- media_pipeline_count_++;
-
- if (media_pipeline_count_ == 1)
- CastResource::RegisterWithClient();
-}
-
-void CmaMediaPipelineClient::OnMediaPipelineBackendDestroyed() {
- DCHECK(thread_checker_.CalledOnValidThread());
- media_pipeline_count_--;
-
- if (media_pipeline_count_ == 0)
- NotifyResourceReleased(CastResource::kResourceNone);
-}
-
-void CmaMediaPipelineClient::AcquireResource(CastResource::Resource resource) {}
-
-void CmaMediaPipelineClient::ReleaseResource(CastResource::Resource resource) {
- CastResource::Resource audio_video_resource =
- static_cast<CastResource::Resource>(CastResource::kResourceAudio |
- CastResource::kResourceScreenPrimary);
-
- // TODO(yucliu): media pipeline need to stop audio video seperately
- if (!(resource & audio_video_resource))
- NotifyResourceReleased(audio_video_resource);
-}
-
-} // namespace media
-} // namespace chromecast
diff --git a/chromecast/browser/media/cma_media_pipeline_client.h b/chromecast/browser/media/cma_media_pipeline_client.h
deleted file mode 100644
index 0dcf8ba..0000000
--- a/chromecast/browser/media/cma_media_pipeline_client.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef CHROMECAST_BROWSER_MEDIA_CMA_MEDIA_PIPELINE_CLIENT_H_
-#define CHROMECAST_BROWSER_MEDIA_CMA_MEDIA_PIPELINE_CLIENT_H_
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/threading/thread_checker.h"
-#include "chromecast/base/cast_resource.h"
-#include "chromecast/public/media/media_pipeline_backend.h"
-
-namespace chromecast {
-namespace media {
-
-struct MediaPipelineDeviceParams;
-
-// Class to provide media backend and watch media pipeline status.
-class CmaMediaPipelineClient : public base::RefCounted<CmaMediaPipelineClient>,
- public CastResource {
- public:
- CmaMediaPipelineClient();
-
- virtual scoped_ptr<MediaPipelineBackend> CreateMediaPipelineBackend(
- const MediaPipelineDeviceParams& params);
-
- virtual void OnMediaPipelineBackendCreated();
- virtual void OnMediaPipelineBackendDestroyed();
-
- // cast::CastResource implementation:
- void AcquireResource(CastResource::Resource resource) override;
- void ReleaseResource(CastResource::Resource resource) override;
-
- protected:
- ~CmaMediaPipelineClient() override;
-
- private:
- friend class base::RefCounted<CmaMediaPipelineClient>;
-
- // Number of created media pipelines.
- size_t media_pipeline_count_;
- base::ThreadChecker thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(CmaMediaPipelineClient);
-};
-}
-}
-
-#endif
diff --git a/chromecast/browser/media/cma_message_filter_host.cc b/chromecast/browser/media/cma_message_filter_host.cc
index e520e249..018ded0 100644
--- a/chromecast/browser/media/cma_message_filter_host.cc
+++ b/chromecast/browser/media/cma_message_filter_host.cc
@@ -13,7 +13,6 @@
#include "base/memory/shared_memory.h"
#include "base/sync_socket.h"
#include "base/threading/thread_checker.h"
-#include "chromecast/browser/media/cma_media_pipeline_client.h"
#include "chromecast/browser/media/media_pipeline_host.h"
#include "chromecast/common/media/cma_messages.h"
#include "chromecast/media/cdm/browser_cdm_cast.h"
@@ -132,12 +131,14 @@ void SetCdmOnUiThread(
CmaMessageFilterHost::CmaMessageFilterHost(
int render_process_id,
- scoped_refptr<CmaMediaPipelineClient> client,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner)
+ const CreateBackendCB& create_backend_cb,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ MediaResourceTracker* resource_tracker)
: content::BrowserMessageFilter(CastMediaMsgStart),
process_id_(render_process_id),
- client_(client),
+ create_backend_cb_(create_backend_cb),
task_runner_(task_runner),
+ resource_tracker_(resource_tracker),
weak_factory_(this) {
weak_this_ = weak_factory_.GetWeakPtr();
}
@@ -214,21 +215,21 @@ void CmaMessageFilterHost::CreateMedia(int media_id, LoadType load_type) {
client.error_cb = ::media::BindToCurrentLoop(
base::Bind(&CmaMessageFilterHost::OnPlaybackError,
weak_this_, media_id, media::kNoTrackId));
- client.pipeline_backend_created_cb = base::Bind(
- &CmaMediaPipelineClient::OnMediaPipelineBackendCreated, client_);
- client.pipeline_backend_destroyed_cb = base::Bind(
- &CmaMediaPipelineClient::OnMediaPipelineBackendDestroyed, client_);
+ client.pipeline_backend_created_cb =
+ base::Bind(&MediaResourceTracker::IncrementUsageCount,
+ base::Unretained(resource_tracker_));
+ client.pipeline_backend_destroyed_cb =
+ base::Bind(&MediaResourceTracker::DecrementUsageCount,
+ base::Unretained(resource_tracker_));
task_runner_->PostTask(
FROM_HERE, base::Bind(&MediaPipelineCmaMap::SetMediaPipeline,
base::Unretained(g_pipeline_map.Pointer()),
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,
- base::Bind(&CmaMediaPipelineClient::CreateMediaPipelineBackend,
- client_)));
+ task_runner_->PostTask(FROM_HERE,
+ base::Bind(&MediaPipelineHost::Initialize,
+ base::Unretained(media_pipeline_host.get()),
+ load_type, client, create_backend_cb_));
std::pair<MediaPipelineMap::iterator, bool> ret =
media_pipelines_.insert(
std::make_pair(media_id, media_pipeline_host.release()));
diff --git a/chromecast/browser/media/cma_message_filter_host.h b/chromecast/browser/media/cma_message_filter_host.h
index c2b6457..f976ad1 100644
--- a/chromecast/browser/media/cma_message_filter_host.h
+++ b/chromecast/browser/media/cma_message_filter_host.h
@@ -14,6 +14,7 @@
#include "base/memory/shared_memory.h"
#include "base/memory/weak_ptr.h"
#include "chromecast/common/media/cma_ipc_common.h"
+#include "chromecast/media/base/media_resource_tracker.h"
#include "chromecast/media/cma/pipeline/load_type.h"
#include "content/public/browser/browser_message_filter.h"
#include "content/public/browser/browser_thread.h"
@@ -42,7 +43,6 @@ class BrowserCdmCast;
class MediaPipelineBackend;
struct MediaPipelineDeviceParams;
class MediaPipelineHost;
-class CmaMediaPipelineClient;
class CmaMessageFilterHost
: public content::BrowserMessageFilter {
@@ -52,8 +52,9 @@ class CmaMessageFilterHost
const MediaPipelineDeviceParams&)> CreateBackendCB;
CmaMessageFilterHost(int render_process_id,
- scoped_refptr<CmaMediaPipelineClient> client,
- scoped_refptr<base::SingleThreadTaskRunner> task_runner);
+ const CreateBackendCB& create_backend_cb,
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner,
+ MediaResourceTracker* resource_tracker);
// content::BrowserMessageFilter implementation:
void OnChannelClosing() override;
@@ -120,12 +121,13 @@ class CmaMessageFilterHost
// Factory function for media pipeline backend.
CreateBackendCB create_backend_cb_;
- scoped_refptr<CmaMediaPipelineClient> client_;
// List of media pipeline and message loop media pipelines are running on.
MediaPipelineMap media_pipelines_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
+ MediaResourceTracker* resource_tracker_;
+
base::WeakPtr<CmaMessageFilterHost> weak_this_;
base::WeakPtrFactory<CmaMessageFilterHost> weak_factory_;
diff --git a/chromecast/chromecast.gyp b/chromecast/chromecast.gyp
index daab117..060a819 100644
--- a/chromecast/chromecast.gyp
+++ b/chromecast/chromecast.gyp
@@ -732,8 +732,6 @@
'sources': [
'browser/media/cast_browser_cdm_factory.cc',
'browser/media/cast_browser_cdm_factory.h',
- 'browser/media/cma_media_pipeline_client.cc',
- 'browser/media/cma_media_pipeline_client.h',
'browser/media/cma_message_filter_host.cc',
'browser/media/cma_message_filter_host.h',
'browser/media/media_pipeline_host.cc',
diff --git a/chromecast/media/base/BUILD.gn b/chromecast/media/base/BUILD.gn
index 85cfcf3..48a9253 100644
--- a/chromecast/media/base/BUILD.gn
+++ b/chromecast/media/base/BUILD.gn
@@ -51,6 +51,8 @@ source_set("base") {
"media_caps.h",
"media_codec_support.cc",
"media_codec_support.h",
+ "media_resource_tracker.cc",
+ "media_resource_tracker.h",
]
public_deps = [
@@ -62,6 +64,7 @@ source_set("base") {
deps = [
":libcast_media_1.0",
"//base",
+ "//chromecast/base",
"//crypto",
"//crypto:platform",
"//net",
diff --git a/chromecast/media/base/media_resource_tracker.cc b/chromecast/media/base/media_resource_tracker.cc
new file mode 100644
index 0000000..129d2bb
--- /dev/null
+++ b/chromecast/media/base/media_resource_tracker.cc
@@ -0,0 +1,168 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromecast/media/base/media_resource_tracker.h"
+
+#include "base/callback_helpers.h"
+#include "base/command_line.h"
+#include "chromecast/base/bind_to_task_runner.h"
+#include "chromecast/public/cast_media_shlib.h"
+
+namespace chromecast {
+namespace media {
+
+MediaResourceTracker::MediaResourceTracker(
+ const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner)
+ : delegate_(nullptr),
+ media_use_count_(0),
+ media_lib_initialized_(false),
+ delete_on_finalize_(false),
+ ui_task_runner_(ui_task_runner),
+ media_task_runner_(media_task_runner) {
+ DCHECK(ui_task_runner);
+ DCHECK(media_task_runner);
+ DCHECK(ui_task_runner_->BelongsToCurrentThread());
+}
+
+MediaResourceTracker::~MediaResourceTracker() {}
+
+void MediaResourceTracker::SetDelegate(Delegate* delegate) {
+ DCHECK(!delegate_);
+ DCHECK(ui_task_runner_->BelongsToCurrentThread());
+ delegate_ = delegate;
+}
+
+void MediaResourceTracker::InitializeMediaLib() {
+ DCHECK(ui_task_runner_->BelongsToCurrentThread());
+ media_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&MediaResourceTracker::CallInitializeOnMediaThread,
+ base::Unretained(this)));
+}
+
+void MediaResourceTracker::FinalizeMediaLib(
+ const base::Closure& completion_cb) {
+ DCHECK(ui_task_runner_->BelongsToCurrentThread());
+ DCHECK(!completion_cb.is_null());
+
+ media_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaResourceTracker::MaybeCallFinalizeOnMediaThread,
+ base::Unretained(this), completion_cb));
+}
+
+void MediaResourceTracker::FinalizeAndDestroy() {
+ DCHECK(ui_task_runner_->BelongsToCurrentThread());
+ delegate_ = nullptr;
+
+ media_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(
+ &MediaResourceTracker::MaybeCallFinalizeOnMediaThreadAndDeleteSelf,
+ base::Unretained(this)));
+}
+
+void MediaResourceTracker::IncrementUsageCount() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ DCHECK(media_lib_initialized_);
+ DCHECK(finalize_completion_cb_.is_null());
+ media_use_count_++;
+
+ if (media_use_count_ == 1) {
+ ui_task_runner_->PostTask(
+ FROM_HERE,
+ base::Bind(&MediaResourceTracker::CallDelegateStartOnUiThread,
+ base::Unretained(this)));
+ }
+}
+
+void MediaResourceTracker::DecrementUsageCount() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ media_use_count_--;
+
+ if (media_use_count_ == 0) {
+ ui_task_runner_->PostTask(
+ FROM_HERE, base::Bind(&MediaResourceTracker::CallDelegateStopOnUiThread,
+ base::Unretained(this)));
+
+ if (!finalize_completion_cb_.is_null())
+ CallFinalizeOnMediaThread();
+ }
+}
+
+void MediaResourceTracker::CallDelegateStartOnUiThread() {
+ DCHECK(ui_task_runner_->BelongsToCurrentThread());
+ if (delegate_)
+ delegate_->OnStartUsingMedia();
+}
+
+void MediaResourceTracker::CallDelegateStopOnUiThread() {
+ DCHECK(ui_task_runner_->BelongsToCurrentThread());
+ if (delegate_)
+ delegate_->OnStopUsingMedia();
+}
+
+void MediaResourceTracker::CallInitializeOnMediaThread() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ if (media_lib_initialized_)
+ return;
+
+ base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+ media::CastMediaShlib::Initialize(cmd_line->argv());
+ media_lib_initialized_ = true;
+}
+
+void MediaResourceTracker::MaybeCallFinalizeOnMediaThread(
+ const base::Closure& completion_cb) {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ DCHECK(finalize_completion_cb_.is_null());
+
+ finalize_completion_cb_ = BindToTaskRunner(ui_task_runner_, completion_cb);
+ if (!media_lib_initialized_) {
+ if (!finalize_completion_cb_.is_null())
+ base::ResetAndReturn(&finalize_completion_cb_).Run();
+ return;
+ }
+
+ // If there are things using media, we must wait for them to stop.
+ // CallFinalize will get called later from DecrementUsageCount when
+ // usage count drops to 0.
+ if (media_use_count_ == 0)
+ CallFinalizeOnMediaThread();
+}
+
+void MediaResourceTracker::MaybeCallFinalizeOnMediaThreadAndDeleteSelf() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+
+ if (!media_lib_initialized_) {
+ ui_task_runner_->DeleteSoon(FROM_HERE, this);
+ return;
+ }
+
+ delete_on_finalize_ = true;
+
+ // If there are things using media, we must wait for them to stop.
+ // CallFinalize will get called later from DecrementUsageCount when
+ // usage count drops to 0.
+ if (media_use_count_ == 0)
+ CallFinalizeOnMediaThread();
+}
+
+void MediaResourceTracker::CallFinalizeOnMediaThread() {
+ DCHECK(media_task_runner_->BelongsToCurrentThread());
+ DCHECK_EQ(media_use_count_, 0ul);
+ DCHECK(media_lib_initialized_);
+
+ CastMediaShlib::Finalize();
+ media_lib_initialized_ = false;
+
+ if (!finalize_completion_cb_.is_null())
+ base::ResetAndReturn(&finalize_completion_cb_).Run();
+
+ if (delete_on_finalize_)
+ ui_task_runner_->DeleteSoon(FROM_HERE, this);
+}
+
+} // namespace media
+} // namespace chromecast
diff --git a/chromecast/media/base/media_resource_tracker.h b/chromecast/media/base/media_resource_tracker.h
new file mode 100644
index 0000000..68f6992
--- /dev/null
+++ b/chromecast/media/base/media_resource_tracker.h
@@ -0,0 +1,116 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMECAST_MEDIA_BASE_MEDIA_RESOURCE_TRACKER_H_
+#define CHROMECAST_MEDIA_BASE_MEDIA_RESOURCE_TRACKER_H_
+
+#include "base/callback.h"
+#include "base/memory/ref_counted.h"
+#include "base/sequenced_task_runner_helpers.h"
+
+namespace base {
+class SingleThreadTaskRunner;
+}
+
+namespace chromecast {
+namespace media {
+
+// Keeps track of internal usage of resources that need access to underlying
+// media playback hardware. Some example users are the CMA pipeline, and the
+// CDMs. When it's time to release media resources, this class can be used
+// to be wait and receive notification when all such users have stopped.
+//
+// Application should have one MediaResourceTracker instance and perform all
+// CastMediaShlib::Initialize/Finalize through this interface.
+// Threading model and lifetime:
+// * This class interacts on both UI and media threads (task runners required
+// by ctor to perform thread hopping and checks). See function-level comments
+// on which thread to use for which operations.
+// * All interaction with delegate is performed on UI thread.
+// * The application should instantiate a single MediaResourceTracker instance.
+// Destruction should be performed by calling FinalizeAndDestroy from the UI
+// thread.
+class MediaResourceTracker {
+ public:
+ class Delegate {
+ public:
+ // Called on UI thread when media usage starts (i.e. count steps 0->1).
+ // Does not mean Initialize has happened.
+ virtual void OnStartUsingMedia() = 0;
+
+ // Called on UI thread when media usage stops (i.e. count steps 1->0).
+ // Does not mean Finalize has happened.
+ virtual void OnStopUsingMedia() = 0;
+
+ protected:
+ virtual ~Delegate() {}
+ };
+
+ MediaResourceTracker(
+ const scoped_refptr<base::SingleThreadTaskRunner>& ui_task_runner,
+ const scoped_refptr<base::SingleThreadTaskRunner>& media_task_runner);
+
+ // Sets the delegate to receive start/stop media usage notifications. Must
+ // call on UI thread. Set to nullptr to clear existing delegate.
+ void SetDelegate(Delegate* delegate);
+
+ // Media resource acquire implementation. Must call on ui thread; runs
+ // CastMediaShlib::Initialize on media thread. Safe to call even if media lib
+ // already initialized.
+ void InitializeMediaLib();
+
+ // Media resource release implementation:
+ // (1) Waits for usage count to drop to zero
+ // (2) Calls CastMediaShlib::Finalize on media thread
+ // (3) Calls completion_cb
+ // Must be called on UI thread. Only one Finalize request may be in flight
+ // at a time. |completion_cb| must not be null.
+ void FinalizeMediaLib(const base::Closure& completion_cb);
+
+ // Shutdown process:
+ // (1) Waits for usage count to drop to zero
+ // (2) Calls CastMediaShlib::Finalize on media thread
+ // (3) Deletes this object
+ // Must be called on UI thread. No further calls should be made on UI thread
+ // after this. Delegate is implicitly cleared.
+ void FinalizeAndDestroy();
+
+ // Users of media resource (e.g. CMA pipeline) should call these when they
+ // start and stop using media calls (must be called on media thread).
+ void IncrementUsageCount();
+ void DecrementUsageCount();
+
+ private:
+ friend class base::DeleteHelper<MediaResourceTracker>;
+ ~MediaResourceTracker();
+
+ // Tasks posted to UI thread
+ void CallDelegateStartOnUiThread();
+ void CallDelegateStopOnUiThread();
+
+ // Tasks posted to media thread
+ void CallInitializeOnMediaThread();
+ void MaybeCallFinalizeOnMediaThread(const base::Closure& completion_cb);
+ void MaybeCallFinalizeOnMediaThreadAndDeleteSelf();
+ void CallFinalizeOnMediaThread();
+
+ // Accessed on UI thread
+ Delegate* delegate_;
+
+ // Accessed on media thread + ctor
+ size_t media_use_count_;
+ bool media_lib_initialized_;
+ base::Closure finalize_completion_cb_;
+ bool delete_on_finalize_;
+
+ scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
+ scoped_refptr<base::SingleThreadTaskRunner> media_task_runner_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaResourceTracker);
+};
+
+} // namespace media
+} // namespace chromecast
+
+#endif // CHROMECAST_MEDIA_BASE_MEDIA_RESOURCE_TRACKER_H_
diff --git a/chromecast/media/cdm/browser_cdm_cast.cc b/chromecast/media/cdm/browser_cdm_cast.cc
index e5585c5..b617ed6 100644
--- a/chromecast/media/cdm/browser_cdm_cast.cc
+++ b/chromecast/media/cdm/browser_cdm_cast.cc
@@ -10,6 +10,7 @@
#include "base/location.h"
#include "base/single_thread_task_runner.h"
#include "base/thread_task_runner_handle.h"
+#include "chromecast/media/base/media_resource_tracker.h"
#include "media/base/cdm_key_information.h"
#include "media/base/cdm_promise.h"
#include "media/cdm/player_tracker_impl.h"
@@ -77,7 +78,9 @@ scoped_ptr<CdmPromiseInternal<T...>> BindPromiseToCurrentLoop(
} // namespace
-BrowserCdmCast::BrowserCdmCast() {
+BrowserCdmCast::BrowserCdmCast(MediaResourceTracker* media_resource_tracker)
+ : media_resource_tracker_(media_resource_tracker) {
+ DCHECK(media_resource_tracker);
thread_checker_.DetachFromThread();
}
@@ -85,6 +88,7 @@ BrowserCdmCast::~BrowserCdmCast() {
DCHECK(thread_checker_.CalledOnValidThread());
DCHECK(player_tracker_impl_.get());
player_tracker_impl_->NotifyCdmUnset();
+ media_resource_tracker_->DecrementUsageCount();
}
void BrowserCdmCast::Initialize(
@@ -95,6 +99,7 @@ void BrowserCdmCast::Initialize(
const ::media::SessionExpirationUpdateCB& session_expiration_update_cb) {
DCHECK(thread_checker_.CalledOnValidThread());
+ media_resource_tracker_->IncrementUsageCount();
player_tracker_impl_.reset(new ::media::PlayerTrackerImpl());
session_message_cb_ = session_message_cb;
diff --git a/chromecast/media/cdm/browser_cdm_cast.h b/chromecast/media/cdm/browser_cdm_cast.h
index 836b401..bd99958 100644
--- a/chromecast/media/cdm/browser_cdm_cast.h
+++ b/chromecast/media/cdm/browser_cdm_cast.h
@@ -16,6 +16,7 @@
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner_helpers.h"
#include "base/threading/thread_checker.h"
+#include "chromecast/media/base/media_resource_tracker.h"
#include "chromecast/public/media/cast_key_status.h"
#include "media/base/media_keys.h"
#include "media/base/player_tracker.h"
@@ -43,7 +44,7 @@ class DecryptContextImpl;
class BrowserCdmCast : public ::media::MediaKeys,
public ::media::PlayerTracker {
public:
- BrowserCdmCast();
+ explicit BrowserCdmCast(MediaResourceTracker* media_resource_tracker);
void Initialize(
const ::media::SessionMessageCB& session_message_cb,
@@ -97,6 +98,7 @@ class BrowserCdmCast : public ::media::MediaKeys,
::media::SessionKeysChangeCB session_keys_change_cb_;
::media::SessionExpirationUpdateCB session_expiration_update_cb_;
+ MediaResourceTracker* media_resource_tracker_;
scoped_ptr<::media::PlayerTrackerImpl> player_tracker_impl_;
base::ThreadChecker thread_checker_;
diff --git a/chromecast/media/media.gyp b/chromecast/media/media.gyp
index 077ea0c..84af013 100644
--- a/chromecast/media/media.gyp
+++ b/chromecast/media/media.gyp
@@ -68,6 +68,8 @@
'base/media_codec_support.h',
'base/media_message_loop.cc',
'base/media_message_loop.h',
+ 'base/media_resource_tracker.cc',
+ 'base/media_resource_tracker.h',
'base/video_plane_controller.cc',
'base/video_plane_controller.h',
],