summaryrefslogtreecommitdiffstats
path: root/dom/media/systemservices/MediaSystemResourceService.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dom/media/systemservices/MediaSystemResourceService.cpp')
-rw-r--r--dom/media/systemservices/MediaSystemResourceService.cpp256
1 files changed, 256 insertions, 0 deletions
diff --git a/dom/media/systemservices/MediaSystemResourceService.cpp b/dom/media/systemservices/MediaSystemResourceService.cpp
new file mode 100644
index 000000000..0e5d6a50c
--- /dev/null
+++ b/dom/media/systemservices/MediaSystemResourceService.cpp
@@ -0,0 +1,256 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "MediaSystemResourceManagerParent.h"
+#include "mozilla/layers/CompositorThread.h"
+#include "mozilla/Unused.h"
+
+#include "MediaSystemResourceService.h"
+
+using namespace mozilla::layers;
+
+namespace mozilla {
+
+/* static */ StaticRefPtr<MediaSystemResourceService> MediaSystemResourceService::sSingleton;
+
+/* static */ MediaSystemResourceService*
+MediaSystemResourceService::Get()
+{
+ if (sSingleton) {
+ return sSingleton;
+ }
+ Init();
+ return sSingleton;
+}
+
+/* static */ void
+MediaSystemResourceService::Init()
+{
+ if (!sSingleton) {
+ sSingleton = new MediaSystemResourceService();
+ }
+}
+
+/* static */ void
+MediaSystemResourceService::Shutdown()
+{
+ if (sSingleton) {
+ sSingleton->Destroy();
+ sSingleton = nullptr;
+ }
+}
+
+MediaSystemResourceService::MediaSystemResourceService()
+ : mDestroyed(false)
+{
+ MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+#ifdef MOZ_WIDGET_GONK
+ // The maximum number of hardware resoureces available.
+ // XXX need to hange to a dynamic way.
+ enum
+ {
+ VIDEO_DECODER_COUNT = 1,
+ VIDEO_ENCODER_COUNT = 1
+ };
+
+ MediaSystemResource* resource;
+
+ resource = new MediaSystemResource(VIDEO_DECODER_COUNT);
+ mResources.Put(static_cast<uint32_t>(MediaSystemResourceType::VIDEO_DECODER), resource);
+
+ resource = new MediaSystemResource(VIDEO_ENCODER_COUNT);
+ mResources.Put(static_cast<uint32_t>(MediaSystemResourceType::VIDEO_ENCODER), resource);
+#endif
+}
+
+MediaSystemResourceService::~MediaSystemResourceService()
+{
+}
+
+void
+MediaSystemResourceService::Destroy()
+{
+ mDestroyed = true;
+}
+
+void
+MediaSystemResourceService::Acquire(media::MediaSystemResourceManagerParent* aParent,
+ uint32_t aId,
+ MediaSystemResourceType aResourceType,
+ bool aWillWait)
+{
+ MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+ MOZ_ASSERT(aParent);
+
+ if (mDestroyed) {
+ return;
+ }
+
+ MediaSystemResource* resource = mResources.Get(static_cast<uint32_t>(aResourceType));
+
+ if (!resource ||
+ resource->mResourceCount == 0) {
+ // Resource does not exit
+ // Send fail response
+ mozilla::Unused << aParent->SendResponse(aId, false /* fail */);
+ return;
+ }
+
+ // Try to acquire a resource
+ if (resource->mAcquiredRequests.size() < resource->mResourceCount) {
+ // Resource is available
+ resource->mAcquiredRequests.push_back(
+ MediaSystemResourceRequest(aParent, aId));
+ // Send success response
+ mozilla::Unused << aParent->SendResponse(aId, true /* success */);
+ return;
+ } else if (!aWillWait) {
+ // Resource is not available and do not wait.
+ // Send fail response
+ mozilla::Unused << aParent->SendResponse(aId, false /* fail */);
+ return;
+ }
+ // Wait until acquire.
+ resource->mWaitingRequests.push_back(
+ MediaSystemResourceRequest(aParent, aId));
+}
+
+void
+MediaSystemResourceService::ReleaseResource(media::MediaSystemResourceManagerParent* aParent,
+ uint32_t aId,
+ MediaSystemResourceType aResourceType)
+{
+ MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread());
+ MOZ_ASSERT(aParent);
+
+ if (mDestroyed) {
+ return;
+ }
+
+ MediaSystemResource* resource = mResources.Get(static_cast<uint32_t>(aResourceType));
+
+ if (!resource ||
+ resource->mResourceCount == 0) {
+ // Resource does not exit
+ return;
+ }
+ RemoveRequest(aParent, aId, aResourceType);
+ UpdateRequests(aResourceType);
+}
+
+void
+MediaSystemResourceService::ReleaseResource(media::MediaSystemResourceManagerParent* aParent)
+{
+ MOZ_ASSERT(aParent);
+
+ if (mDestroyed) {
+ return;
+ }
+
+ for (auto iter = mResources.Iter(); !iter.Done(); iter.Next()) {
+ const uint32_t& key = iter.Key();
+ RemoveRequests(aParent, static_cast<MediaSystemResourceType>(key));
+ UpdateRequests(static_cast<MediaSystemResourceType>(key));
+ }
+}
+
+void
+MediaSystemResourceService::RemoveRequest(media::MediaSystemResourceManagerParent* aParent,
+ uint32_t aId,
+ MediaSystemResourceType aResourceType)
+{
+ MOZ_ASSERT(aParent);
+
+ MediaSystemResource* resource = mResources.Get(static_cast<uint32_t>(aResourceType));
+ if (!resource) {
+ return;
+ }
+
+ std::deque<MediaSystemResourceRequest>::iterator it;
+ std::deque<MediaSystemResourceRequest>& acquiredRequests =
+ resource->mAcquiredRequests;
+ for (it = acquiredRequests.begin(); it != acquiredRequests.end(); it++) {
+ if (((*it).mParent == aParent) && ((*it).mId == aId)) {
+ acquiredRequests.erase(it);
+ return;
+ }
+ }
+
+ std::deque<MediaSystemResourceRequest>& waitingRequests =
+ resource->mWaitingRequests;
+ for (it = waitingRequests.begin(); it != waitingRequests.end(); it++) {
+ if (((*it).mParent == aParent) && ((*it).mId == aId)) {
+ waitingRequests.erase(it);
+ return;
+ }
+ }
+}
+
+void
+MediaSystemResourceService::RemoveRequests(media::MediaSystemResourceManagerParent* aParent,
+ MediaSystemResourceType aResourceType)
+{
+ MOZ_ASSERT(aParent);
+
+ MediaSystemResource* resource = mResources.Get(static_cast<uint32_t>(aResourceType));
+
+ if (!resource ||
+ resource->mResourceCount == 0) {
+ // Resource does not exit
+ return;
+ }
+
+ std::deque<MediaSystemResourceRequest>::iterator it;
+ std::deque<MediaSystemResourceRequest>& acquiredRequests =
+ resource->mAcquiredRequests;
+ for (it = acquiredRequests.begin(); it != acquiredRequests.end();) {
+ if ((*it).mParent == aParent) {
+ it = acquiredRequests.erase(it);
+ } else {
+ it++;
+ }
+ }
+
+ std::deque<MediaSystemResourceRequest>& waitingRequests =
+ resource->mWaitingRequests;
+ for (it = waitingRequests.begin(); it != waitingRequests.end();) {
+ if ((*it).mParent == aParent) {
+ it = waitingRequests.erase(it);
+ } else {
+ it++;
+ }
+ }
+}
+
+void
+MediaSystemResourceService::UpdateRequests(MediaSystemResourceType aResourceType)
+{
+ MediaSystemResource* resource = mResources.Get(static_cast<uint32_t>(aResourceType));
+
+ if (!resource ||
+ resource->mResourceCount == 0) {
+ // Resource does not exit
+ return;
+ }
+
+ std::deque<MediaSystemResourceRequest>& acquiredRequests =
+ resource->mAcquiredRequests;
+ std::deque<MediaSystemResourceRequest>& waitingRequests =
+ resource->mWaitingRequests;
+
+ while ((acquiredRequests.size() < resource->mResourceCount) &&
+ (waitingRequests.size() > 0)) {
+ MediaSystemResourceRequest& request = waitingRequests.front();
+ MOZ_ASSERT(request.mParent);
+ // Send response
+ mozilla::Unused << request.mParent->SendResponse(request.mId, true /* success */);
+ // Move request to mAcquiredRequests
+ acquiredRequests.push_back(waitingRequests.front());
+ waitingRequests.pop_front();
+ }
+}
+
+} // namespace mozilla