/* 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 "MediaSystemResourceService.h" #include "MediaSystemResourceManagerParent.h" #include "mozilla/layers/CompositorThread.h" using namespace mozilla::layers; namespace mozilla { /* static */ StaticRefPtr MediaSystemResourceService::sSingleton; /* static */ already_AddRefed MediaSystemResourceService::Get() { if (!sSingleton) { Init(); } return do_AddRef(sSingleton); } /* static */ void MediaSystemResourceService::Init() { if (!sSingleton) { sSingleton = new MediaSystemResourceService(); } } /* static */ void MediaSystemResourceService::Shutdown() { MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); if (sSingleton) { sSingleton->Destroy(); sSingleton = nullptr; } } MediaSystemResourceService::MediaSystemResourceService() : mDestroyed(false) { MOZ_ASSERT(CompositorThreadHolder::IsInCompositorThread()); } MediaSystemResourceService::~MediaSystemResourceService() = default; 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(aResourceType)); if (!resource || resource->mResourceCount == 0) { // Resource does not exit // Send fail response (void)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 (void)aParent->SendResponse(aId, true /* success */); return; } if (!aWillWait) { // Resource is not available and do not wait. // Send fail response (void)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(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 (const uint32_t& key : mResources.Keys()) { RemoveRequests(aParent, static_cast(key)); UpdateRequests(static_cast(key)); } } void MediaSystemResourceService::RemoveRequest( media::MediaSystemResourceManagerParent* aParent, uint32_t aId, MediaSystemResourceType aResourceType) { MOZ_ASSERT(aParent); MediaSystemResource* resource = mResources.Get(static_cast(aResourceType)); if (!resource) { return; } std::deque::iterator it; std::deque& acquiredRequests = resource->mAcquiredRequests; for (it = acquiredRequests.begin(); it != acquiredRequests.end(); it++) { if (((*it).mParent == aParent) && ((*it).mId == aId)) { acquiredRequests.erase(it); return; } } std::deque& 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(aResourceType)); if (!resource || resource->mResourceCount == 0) { // Resource does not exit return; } std::deque::iterator it; std::deque& acquiredRequests = resource->mAcquiredRequests; for (it = acquiredRequests.begin(); it != acquiredRequests.end();) { if ((*it).mParent == aParent) { it = acquiredRequests.erase(it); } else { it++; } } std::deque& 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(aResourceType)); if (!resource || resource->mResourceCount == 0) { // Resource does not exit return; } std::deque& acquiredRequests = resource->mAcquiredRequests; std::deque& waitingRequests = resource->mWaitingRequests; while ((acquiredRequests.size() < resource->mResourceCount) && (!waitingRequests.empty())) { MediaSystemResourceRequest& request = waitingRequests.front(); MOZ_ASSERT(request.mParent); // Send response (void)request.mParent->SendResponse(request.mId, true /* success */); // Move request to mAcquiredRequests acquiredRequests.push_back(waitingRequests.front()); waitingRequests.pop_front(); } } } // namespace mozilla