/* -*- 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/. */ #ifndef mozilla_dom_GMPVideoDecoderTrialCreator_h #define mozilla_dom_GMPVideoDecoderTrialCreator_h #include "mozilla/dom/MediaKeySystemAccess.h" #include "nsIObserver.h" #include "nsCycleCollectionParticipant.h" #include "nsISupportsImpl.h" #include "nsITimer.h" #include "nsClassHashtable.h" #include "mozilla/dom/MediaKeys.h" #include "GMPVideoDecoderProxy.h" namespace mozilla { namespace dom { class TestGMPVideoDecoder; class GMPVideoDecoderTrialCreator { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPVideoDecoderTrialCreator); void TrialCreateGMPVideoDecoderFailed(const nsAString& aKeySystem, const nsACString& aReason); void TrialCreateGMPVideoDecoderSucceeded(const nsAString& aKeySystem); template void MaybeAwaitTrialCreate(const nsAString& aKeySystem, MediaKeySystemAccess* aAccess, T* aPromiseLike, nsPIDOMWindow* aParent) { RefPtr> p(new PromiseLike(aPromiseLike, aAccess)); MaybeAwaitTrialCreate(aKeySystem, p, aParent); } static void UpdateTrialCreateState(const nsAString& aKeySystem, uint32_t aState); private: class AbstractPromiseLike { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AbstractPromiseLike); virtual void Resolve() = 0; virtual void Reject(nsresult aResult, const nsACString& aMessage) = 0; protected: virtual ~AbstractPromiseLike() {} }; template class PromiseLike : public AbstractPromiseLike { public: explicit PromiseLike(T* aPromiseLike, MediaKeySystemAccess* aAccess) : mPromiseLike(aPromiseLike) , mAccess(aAccess) { } void Resolve() override { MOZ_ASSERT(NS_IsMainThread()); mPromiseLike->MaybeResolve(mAccess); } void Reject(nsresult aResult, const nsACString& aMessage) override { MOZ_ASSERT(NS_IsMainThread()); mPromiseLike->MaybeReject(aResult, aMessage); } protected: ~PromiseLike() {} RefPtr mPromiseLike; RefPtr mAccess; }; void MaybeAwaitTrialCreate(const nsAString& aKeySystem, AbstractPromiseLike* aPromisey, nsPIDOMWindow* aParent); ~GMPVideoDecoderTrialCreator() {} // Note: Keep this in sync with GetCreateTrialState. enum TrialCreateState { Pending = 0, Succeeded = 1, Failed = 2, }; static TrialCreateState GetCreateTrialState(const nsAString& aKeySystem); static void UpdateTrialCreateState(const nsAString& aKeySystem, TrialCreateState aState); struct TrialCreateData { explicit TrialCreateData(const nsAString& aKeySystem) : mKeySystem(aKeySystem) , mStatus(GetCreateTrialState(aKeySystem)) {} ~TrialCreateData() {} const nsString mKeySystem; RefPtr mTest; nsTArray> mPending; TrialCreateState mStatus; private: TrialCreateData(const TrialCreateData& aOther) = delete; TrialCreateData() = delete; TrialCreateData& operator =(const TrialCreateData&) = delete; }; nsClassHashtable mTestCreate; }; class TestGMPVideoDecoder : public GMPVideoDecoderCallbackProxy { public: NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestGMPVideoDecoder); TestGMPVideoDecoder(GMPVideoDecoderTrialCreator* aInstance, const nsAString& aKeySystem, nsPIDOMWindow* aParent) : mKeySystem(aKeySystem) , mInstance(aInstance) , mWindow(aParent) , mGMP(nullptr) , mHost(nullptr) , mReceivedDecoded(false) {} nsresult Start(); // GMPVideoDecoderCallbackProxy virtual void Decoded(GMPVideoi420Frame* aDecodedFrame) override; virtual void ReceivedDecodedReferenceFrame(const uint64_t aPictureId) override {} virtual void ReceivedDecodedFrame(const uint64_t aPictureId) override {} virtual void InputDataExhausted() override {} virtual void DrainComplete() override; virtual void ResetComplete() override {} virtual void Error(GMPErr aErr) override; virtual void Terminated() override; void ActorCreated(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost); // Main thread. class Callback : public GetGMPVideoDecoderCallback { public: explicit Callback(TestGMPVideoDecoder* aInstance) : mInstance(aInstance) {} ~Callback() {} void Done(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost) override; private: RefPtr mInstance; }; private: void InitGMPDone(GMPVideoDecoderProxy* aGMP, GMPVideoHost* aHost); // GMP thread. void CreateGMPVideoDecoder(); ~TestGMPVideoDecoder() {} void ReportFailure(const nsACString& aReason); void ReportSuccess(); const nsString mKeySystem; nsCOMPtr mGMPService; RefPtr mInstance; nsCOMPtr mWindow; GMPVideoDecoderProxy* mGMP; GMPVideoHost* mHost; bool mReceivedDecoded; }; } // namespace dom } // namespace mozilla #endif