mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-17 07:15:46 +00:00
Bug 1312337. Part 2 - implement a policy object to control the number of decoders to be created concurrently. r=gerald
MozReview-Commit-ID: 7D4PXedDC3D --HG-- extra : rebase_source : 93f977f6543423eac79a2330d51e27aea2dfa6ee extra : intermediate-source : 782d9f42291f3d089e5046a593d07f5073dc8830 extra : source : 421fdc7d95fcdd99d9d18dda4ab38568da7e2043
This commit is contained in:
parent
0a2d601dc2
commit
d7adc92e17
@ -5,6 +5,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/CDMProxy.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/dom/HTMLMediaElement.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/Telemetry.h"
|
||||
@ -15,6 +16,7 @@
|
||||
#include "MediaData.h"
|
||||
#include "MediaInfo.h"
|
||||
#include "MediaFormatReader.h"
|
||||
#include "MediaPrefs.h"
|
||||
#include "MediaResource.h"
|
||||
#include "mozilla/SharedThreadPool.h"
|
||||
#include "VideoUtils.h"
|
||||
@ -22,6 +24,7 @@
|
||||
#include "mozilla/layers/ShadowLayers.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <queue>
|
||||
|
||||
using namespace mozilla::media;
|
||||
|
||||
@ -37,6 +40,129 @@ mozilla::LazyLogModule gMediaDemuxerLog("MediaDemuxer");
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
/**
|
||||
* This is a singleton which controls the number of decoders that can be
|
||||
* created concurrently. Before calling PDMFactory::CreateDecoder(), Alloc()
|
||||
* must be called to get a token object as a permission to create a decoder.
|
||||
* The token should stay alive until Shutdown() is called on the decoder.
|
||||
* The destructor of the token will restore the decoder count so it is available
|
||||
* for next calls of Alloc().
|
||||
*/
|
||||
class DecoderAllocPolicy
|
||||
{
|
||||
using TrackType = TrackInfo::TrackType;
|
||||
|
||||
public:
|
||||
class Token
|
||||
{
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Token)
|
||||
protected:
|
||||
virtual ~Token() {}
|
||||
};
|
||||
|
||||
using Promise = MozPromise<RefPtr<Token>, bool, true>;
|
||||
|
||||
// Acquire a token for decoder creation. Thread-safe.
|
||||
auto Alloc(TrackType aTrack) -> RefPtr<Promise>;
|
||||
|
||||
// Called by ClearOnShutdown() to delete the singleton.
|
||||
void operator=(decltype(nullptr));
|
||||
|
||||
// Get the singleton. Thread-safe.
|
||||
static DecoderAllocPolicy& Instance();
|
||||
|
||||
private:
|
||||
class AutoDeallocToken;
|
||||
using PromisePrivate = Promise::Private;
|
||||
DecoderAllocPolicy();
|
||||
~DecoderAllocPolicy();
|
||||
// Called by the destructor of TokenImpl to restore the decoder limit.
|
||||
void Dealloc();
|
||||
// Decrement the decoder limit and resolve a promise if available.
|
||||
void ResolvePromise(ReentrantMonitorAutoEnter& aProofOfLock);
|
||||
|
||||
ReentrantMonitor mMonitor;
|
||||
// The number of decoders available for creation.
|
||||
int mDecoderLimit;
|
||||
// Requests to acquire tokens.
|
||||
std::queue<RefPtr<PromisePrivate>> mPromises;
|
||||
};
|
||||
|
||||
class DecoderAllocPolicy::AutoDeallocToken : public Token
|
||||
{
|
||||
private:
|
||||
~AutoDeallocToken() { DecoderAllocPolicy::Instance().Dealloc(); }
|
||||
};
|
||||
|
||||
DecoderAllocPolicy::DecoderAllocPolicy()
|
||||
: mMonitor("DecoderAllocPolicy::mMonitor")
|
||||
, mDecoderLimit(MediaPrefs::MediaDecoderLimit())
|
||||
{
|
||||
AbstractThread::MainThread()->Dispatch(NS_NewRunnableFunction([this] () {
|
||||
ClearOnShutdown(this, ShutdownPhase::ShutdownThreads);
|
||||
}));
|
||||
}
|
||||
|
||||
DecoderAllocPolicy::~DecoderAllocPolicy()
|
||||
{
|
||||
while (!mPromises.empty()) {
|
||||
RefPtr<PromisePrivate> p = mPromises.front().forget();
|
||||
mPromises.pop();
|
||||
p->Reject(true, __func__);
|
||||
}
|
||||
}
|
||||
|
||||
DecoderAllocPolicy&
|
||||
DecoderAllocPolicy::Instance()
|
||||
{
|
||||
// Note: Function-static initialization is not thread-safe in VS 2013.
|
||||
// Don't uplift this code to 45esr.
|
||||
static auto sPolicy = new DecoderAllocPolicy();
|
||||
return *sPolicy;
|
||||
}
|
||||
|
||||
auto
|
||||
DecoderAllocPolicy::Alloc(TrackType aTrack) -> RefPtr<Promise>
|
||||
{
|
||||
// No limit for audio decoders or a negative number.
|
||||
if (aTrack == TrackInfo::kAudioTrack || mDecoderLimit < 0) {
|
||||
return Promise::CreateAndResolve(new Token(), __func__);
|
||||
}
|
||||
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
RefPtr<PromisePrivate> p = new PromisePrivate(__func__);
|
||||
mPromises.push(p);
|
||||
ResolvePromise(mon);
|
||||
return p.forget();
|
||||
}
|
||||
|
||||
void
|
||||
DecoderAllocPolicy::Dealloc()
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(mMonitor);
|
||||
++mDecoderLimit;
|
||||
ResolvePromise(mon);
|
||||
}
|
||||
|
||||
void
|
||||
DecoderAllocPolicy::ResolvePromise(ReentrantMonitorAutoEnter& aProofOfLock)
|
||||
{
|
||||
MOZ_ASSERT(mDecoderLimit >= 0);
|
||||
|
||||
if (mDecoderLimit > 0 && !mPromises.empty()) {
|
||||
--mDecoderLimit;
|
||||
RefPtr<PromisePrivate> p = mPromises.front().forget();
|
||||
mPromises.pop();
|
||||
p->Resolve(new AutoDeallocToken(), __func__);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DecoderAllocPolicy::operator=(std::nullptr_t)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
class MediaFormatReader::DecoderFactory
|
||||
{
|
||||
using InitPromise = MediaDataDecoder::InitPromise;
|
||||
|
Loading…
Reference in New Issue
Block a user