From e80bbcfe915e1f6c64a8b44a2e501f8fedfcf659 Mon Sep 17 00:00:00 2001 From: Moonchild Date: Tue, 17 Oct 2023 12:59:49 +0200 Subject: Issue #2346 - Remove unused EME components This removes: dom/media/eme code GMP CDM proxies GMP WideVine adapter code EME media platform code GMP clearkey module --- dom/media/eme/CDMCaps.cpp | 169 -- dom/media/eme/CDMCaps.h | 112 -- dom/media/eme/CDMProxy.h | 278 --- dom/media/eme/DecryptorProxyCallback.h | 54 - dom/media/eme/DetailedPromise.cpp | 57 - dom/media/eme/DetailedPromise.h | 57 - dom/media/eme/EMEUtils.cpp | 86 - dom/media/eme/EMEUtils.h | 104 -- dom/media/eme/MediaEncryptedEvent.cpp | 128 -- dom/media/eme/MediaEncryptedEvent.h | 66 - dom/media/eme/MediaKeyError.cpp | 38 - dom/media/eme/MediaKeyError.h | 37 - dom/media/eme/MediaKeyMessageEvent.cpp | 122 -- dom/media/eme/MediaKeyMessageEvent.h | 66 - dom/media/eme/MediaKeySession.cpp | 670 ------- dom/media/eme/MediaKeySession.h | 136 -- dom/media/eme/MediaKeyStatusMap.cpp | 120 -- dom/media/eme/MediaKeyStatusMap.h | 96 - dom/media/eme/MediaKeySystemAccess.cpp | 1041 ----------- dom/media/eme/MediaKeySystemAccess.h | 80 - dom/media/eme/MediaKeySystemAccessManager.cpp | 339 ---- dom/media/eme/MediaKeySystemAccessManager.h | 83 - dom/media/eme/MediaKeys.cpp | 579 ------ dom/media/eme/MediaKeys.h | 167 -- dom/media/eme/moz.build | 41 - dom/media/gmp/GMPCDMCallbackProxy.cpp | 250 --- dom/media/gmp/GMPCDMCallbackProxy.h | 71 - dom/media/gmp/GMPCDMProxy.cpp | 798 -------- dom/media/gmp/GMPCDMProxy.h | 265 --- dom/media/gmp/widevine-adapter/WidevineAdapter.cpp | 168 -- dom/media/gmp/widevine-adapter/WidevineAdapter.h | 59 - .../gmp/widevine-adapter/WidevineDecryptor.cpp | 554 ------ dom/media/gmp/widevine-adapter/WidevineDecryptor.h | 132 -- dom/media/gmp/widevine-adapter/WidevineFileIO.cpp | 97 - dom/media/gmp/widevine-adapter/WidevineFileIO.h | 46 - dom/media/gmp/widevine-adapter/WidevineUtils.cpp | 95 - dom/media/gmp/widevine-adapter/WidevineUtils.h | 73 - .../gmp/widevine-adapter/WidevineVideoDecoder.cpp | 400 ---- .../gmp/widevine-adapter/WidevineVideoDecoder.h | 80 - .../gmp/widevine-adapter/WidevineVideoFrame.cpp | 126 -- .../gmp/widevine-adapter/WidevineVideoFrame.h | 50 - .../widevine-adapter/content_decryption_module.h | 1278 ------------- .../content_decryption_module_export.h | 22 - .../content_decryption_module_ext.h | 64 - dom/media/gmp/widevine-adapter/moz.build | 24 - .../platforms/agnostic/eme/EMEAudioDecoder.cpp | 43 - dom/media/platforms/agnostic/eme/EMEAudioDecoder.h | 36 - .../platforms/agnostic/eme/EMEDecoderModule.cpp | 306 ---- .../platforms/agnostic/eme/EMEDecoderModule.h | 51 - .../platforms/agnostic/eme/EMEVideoDecoder.cpp | 67 - dom/media/platforms/agnostic/eme/EMEVideoDecoder.h | 44 - .../agnostic/eme/SamplesWaitingForKey.cpp | 85 - .../platforms/agnostic/eme/SamplesWaitingForKey.h | 57 - dom/media/platforms/agnostic/eme/moz.build | 22 - media/gmp-clearkey/0.1/AnnexB.cpp | 79 - media/gmp-clearkey/0.1/AnnexB.h | 32 - media/gmp-clearkey/0.1/ArrayUtils.h | 23 - media/gmp-clearkey/0.1/AudioDecoder.cpp | 312 ---- media/gmp-clearkey/0.1/AudioDecoder.h | 73 - media/gmp-clearkey/0.1/BigEndian.h | 68 - media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp | 45 - media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h | 37 - media/gmp-clearkey/0.1/ClearKeyBase64.cpp | 99 - media/gmp-clearkey/0.1/ClearKeyBase64.h | 28 - .../gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp | 241 --- media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h | 101 - media/gmp-clearkey/0.1/ClearKeyPersistence.cpp | 260 --- media/gmp-clearkey/0.1/ClearKeyPersistence.h | 53 - media/gmp-clearkey/0.1/ClearKeySession.cpp | 94 - media/gmp-clearkey/0.1/ClearKeySession.h | 58 - media/gmp-clearkey/0.1/ClearKeySessionManager.cpp | 418 ----- media/gmp-clearkey/0.1/ClearKeySessionManager.h | 100 - media/gmp-clearkey/0.1/ClearKeyStorage.cpp | 194 -- media/gmp-clearkey/0.1/ClearKeyStorage.h | 48 - media/gmp-clearkey/0.1/ClearKeyUtils.cpp | 541 ------ media/gmp-clearkey/0.1/ClearKeyUtils.h | 114 -- media/gmp-clearkey/0.1/RefCounted.h | 116 -- media/gmp-clearkey/0.1/VideoDecoder.cpp | 455 ----- media/gmp-clearkey/0.1/VideoDecoder.h | 110 -- media/gmp-clearkey/0.1/WMFAACDecoder.cpp | 366 ---- media/gmp-clearkey/0.1/WMFAACDecoder.h | 74 - media/gmp-clearkey/0.1/WMFH264Decoder.cpp | 365 ---- media/gmp-clearkey/0.1/WMFH264Decoder.h | 78 - media/gmp-clearkey/0.1/WMFSymbols.h | 20 - media/gmp-clearkey/0.1/WMFUtils.cpp | 276 --- media/gmp-clearkey/0.1/WMFUtils.h | 269 --- media/gmp-clearkey/0.1/clearkey.info.in | 10 - media/gmp-clearkey/0.1/gmp-clearkey.cpp | 89 - media/gmp-clearkey/0.1/gmp-task-utils-generated.h | 1938 -------------------- media/gmp-clearkey/0.1/gmp-task-utils.h | 47 - media/gmp-clearkey/0.1/gtest/TestClearKeyUtils.cpp | 92 - media/gmp-clearkey/0.1/gtest/moz.build | 14 - media/gmp-clearkey/0.1/moz.build | 74 - media/gmp-clearkey/0.1/openaes/LICENSE | 27 - media/gmp-clearkey/0.1/openaes/oaes_common.h | 77 - media/gmp-clearkey/0.1/openaes/oaes_config.h | 46 - media/gmp-clearkey/0.1/openaes/oaes_lib.c | 1393 -------------- media/gmp-clearkey/0.1/openaes/oaes_lib.h | 168 -- media/gmp-clearkey/0.1/openaes/standard.h | 57 - 99 files changed, 19268 deletions(-) delete mode 100644 dom/media/eme/CDMCaps.cpp delete mode 100644 dom/media/eme/CDMCaps.h delete mode 100644 dom/media/eme/CDMProxy.h delete mode 100644 dom/media/eme/DecryptorProxyCallback.h delete mode 100644 dom/media/eme/DetailedPromise.cpp delete mode 100644 dom/media/eme/DetailedPromise.h delete mode 100644 dom/media/eme/EMEUtils.cpp delete mode 100644 dom/media/eme/EMEUtils.h delete mode 100644 dom/media/eme/MediaEncryptedEvent.cpp delete mode 100644 dom/media/eme/MediaEncryptedEvent.h delete mode 100644 dom/media/eme/MediaKeyError.cpp delete mode 100644 dom/media/eme/MediaKeyError.h delete mode 100644 dom/media/eme/MediaKeyMessageEvent.cpp delete mode 100644 dom/media/eme/MediaKeyMessageEvent.h delete mode 100644 dom/media/eme/MediaKeySession.cpp delete mode 100644 dom/media/eme/MediaKeySession.h delete mode 100644 dom/media/eme/MediaKeyStatusMap.cpp delete mode 100644 dom/media/eme/MediaKeyStatusMap.h delete mode 100644 dom/media/eme/MediaKeySystemAccess.cpp delete mode 100644 dom/media/eme/MediaKeySystemAccess.h delete mode 100644 dom/media/eme/MediaKeySystemAccessManager.cpp delete mode 100644 dom/media/eme/MediaKeySystemAccessManager.h delete mode 100644 dom/media/eme/MediaKeys.cpp delete mode 100644 dom/media/eme/MediaKeys.h delete mode 100644 dom/media/eme/moz.build delete mode 100644 dom/media/gmp/GMPCDMCallbackProxy.cpp delete mode 100644 dom/media/gmp/GMPCDMCallbackProxy.h delete mode 100644 dom/media/gmp/GMPCDMProxy.cpp delete mode 100644 dom/media/gmp/GMPCDMProxy.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineAdapter.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineAdapter.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineDecryptor.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineFileIO.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineFileIO.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineUtils.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineUtils.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineVideoDecoder.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h delete mode 100644 dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp delete mode 100644 dom/media/gmp/widevine-adapter/WidevineVideoFrame.h delete mode 100644 dom/media/gmp/widevine-adapter/content_decryption_module.h delete mode 100644 dom/media/gmp/widevine-adapter/content_decryption_module_export.h delete mode 100644 dom/media/gmp/widevine-adapter/content_decryption_module_ext.h delete mode 100644 dom/media/gmp/widevine-adapter/moz.build delete mode 100644 dom/media/platforms/agnostic/eme/EMEAudioDecoder.cpp delete mode 100644 dom/media/platforms/agnostic/eme/EMEAudioDecoder.h delete mode 100644 dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp delete mode 100644 dom/media/platforms/agnostic/eme/EMEDecoderModule.h delete mode 100644 dom/media/platforms/agnostic/eme/EMEVideoDecoder.cpp delete mode 100644 dom/media/platforms/agnostic/eme/EMEVideoDecoder.h delete mode 100644 dom/media/platforms/agnostic/eme/SamplesWaitingForKey.cpp delete mode 100644 dom/media/platforms/agnostic/eme/SamplesWaitingForKey.h delete mode 100644 dom/media/platforms/agnostic/eme/moz.build delete mode 100644 media/gmp-clearkey/0.1/AnnexB.cpp delete mode 100644 media/gmp-clearkey/0.1/AnnexB.h delete mode 100644 media/gmp-clearkey/0.1/ArrayUtils.h delete mode 100644 media/gmp-clearkey/0.1/AudioDecoder.cpp delete mode 100644 media/gmp-clearkey/0.1/AudioDecoder.h delete mode 100644 media/gmp-clearkey/0.1/BigEndian.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyBase64.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyBase64.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyPersistence.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyPersistence.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeySession.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeySession.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeySessionManager.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeySessionManager.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyStorage.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyStorage.h delete mode 100644 media/gmp-clearkey/0.1/ClearKeyUtils.cpp delete mode 100644 media/gmp-clearkey/0.1/ClearKeyUtils.h delete mode 100644 media/gmp-clearkey/0.1/RefCounted.h delete mode 100644 media/gmp-clearkey/0.1/VideoDecoder.cpp delete mode 100644 media/gmp-clearkey/0.1/VideoDecoder.h delete mode 100644 media/gmp-clearkey/0.1/WMFAACDecoder.cpp delete mode 100644 media/gmp-clearkey/0.1/WMFAACDecoder.h delete mode 100644 media/gmp-clearkey/0.1/WMFH264Decoder.cpp delete mode 100644 media/gmp-clearkey/0.1/WMFH264Decoder.h delete mode 100644 media/gmp-clearkey/0.1/WMFSymbols.h delete mode 100644 media/gmp-clearkey/0.1/WMFUtils.cpp delete mode 100644 media/gmp-clearkey/0.1/WMFUtils.h delete mode 100644 media/gmp-clearkey/0.1/clearkey.info.in delete mode 100644 media/gmp-clearkey/0.1/gmp-clearkey.cpp delete mode 100644 media/gmp-clearkey/0.1/gmp-task-utils-generated.h delete mode 100644 media/gmp-clearkey/0.1/gmp-task-utils.h delete mode 100644 media/gmp-clearkey/0.1/gtest/TestClearKeyUtils.cpp delete mode 100644 media/gmp-clearkey/0.1/gtest/moz.build delete mode 100644 media/gmp-clearkey/0.1/moz.build delete mode 100644 media/gmp-clearkey/0.1/openaes/LICENSE delete mode 100644 media/gmp-clearkey/0.1/openaes/oaes_common.h delete mode 100644 media/gmp-clearkey/0.1/openaes/oaes_config.h delete mode 100644 media/gmp-clearkey/0.1/openaes/oaes_lib.c delete mode 100644 media/gmp-clearkey/0.1/openaes/oaes_lib.h delete mode 100644 media/gmp-clearkey/0.1/openaes/standard.h diff --git a/dom/media/eme/CDMCaps.cpp b/dom/media/eme/CDMCaps.cpp deleted file mode 100644 index a30fb59ac8..0000000000 --- a/dom/media/eme/CDMCaps.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "mozilla/CDMCaps.h" -#include "mozilla/EMEUtils.h" -#include "nsThreadUtils.h" -#include "SamplesWaitingForKey.h" - -namespace mozilla { - -CDMCaps::CDMCaps() - : mMonitor("CDMCaps") -{ -} - -CDMCaps::~CDMCaps() -{ -} - -void -CDMCaps::Lock() -{ - mMonitor.Lock(); -} - -void -CDMCaps::Unlock() -{ - mMonitor.Unlock(); -} - -CDMCaps::AutoLock::AutoLock(CDMCaps& aInstance) - : mData(aInstance) -{ - mData.Lock(); -} - -CDMCaps::AutoLock::~AutoLock() -{ - mData.Unlock(); -} - -// Keys with MediaKeyStatus::Usable, MediaKeyStatus::Output_downscaled, -// or MediaKeyStatus::Output_restricted status can be used by the CDM -// to decrypt or decrypt-and-decode samples. -static bool -IsUsableStatus(dom::MediaKeyStatus aStatus) -{ - return aStatus == dom::MediaKeyStatus::Usable || - aStatus == dom::MediaKeyStatus::Output_restricted || - aStatus == dom::MediaKeyStatus::Output_downscaled; -} - -bool -CDMCaps::AutoLock::IsKeyUsable(const CencKeyId& aKeyId) -{ - mData.mMonitor.AssertCurrentThreadOwns(); - for (const KeyStatus& keyStatus : mData.mKeyStatuses) { - if (keyStatus.mId == aKeyId) { - return IsUsableStatus(keyStatus.mStatus); - } - } - return false; -} - -bool -CDMCaps::AutoLock::SetKeyStatus(const CencKeyId& aKeyId, - const nsString& aSessionId, - const dom::Optional& aStatus) -{ - mData.mMonitor.AssertCurrentThreadOwns(); - - if (!aStatus.WasPassed()) { - // Called from ForgetKeyStatus. - // Return true if the element is found to notify key changes. - return mData.mKeyStatuses.RemoveElement(KeyStatus(aKeyId, - aSessionId, - dom::MediaKeyStatus::Internal_error)); - } - - KeyStatus key(aKeyId, aSessionId, aStatus.Value()); - auto index = mData.mKeyStatuses.IndexOf(key); - if (index != mData.mKeyStatuses.NoIndex) { - if (mData.mKeyStatuses[index].mStatus == aStatus.Value()) { - // No change. - return false; - } - auto oldStatus = mData.mKeyStatuses[index].mStatus; - mData.mKeyStatuses[index].mStatus = aStatus.Value(); - // The old key status was one for which we can decrypt media. We don't - // need to do the "notify usable" step below, as it should be impossible - // for us to have anything waiting on this key to become usable, since it - // was already usable. - if (IsUsableStatus(oldStatus)) { - return true; - } - } else { - mData.mKeyStatuses.AppendElement(key); - } - - // Only call NotifyUsable() for a key when we are going from non-usable - // to usable state. - if (!IsUsableStatus(aStatus.Value())) { - return true; - } - - auto& waiters = mData.mWaitForKeys; - size_t i = 0; - while (i < waiters.Length()) { - auto& w = waiters[i]; - if (w.mKeyId == aKeyId) { - w.mListener->NotifyUsable(aKeyId); - waiters.RemoveElementAt(i); - } else { - i++; - } - } - return true; -} - -void -CDMCaps::AutoLock::NotifyWhenKeyIdUsable(const CencKeyId& aKey, - SamplesWaitingForKey* aListener) -{ - mData.mMonitor.AssertCurrentThreadOwns(); - MOZ_ASSERT(!IsKeyUsable(aKey)); - MOZ_ASSERT(aListener); - mData.mWaitForKeys.AppendElement(WaitForKeys(aKey, aListener)); -} - -void -CDMCaps::AutoLock::GetKeyStatusesForSession(const nsAString& aSessionId, - nsTArray& aOutKeyStatuses) -{ - for (const KeyStatus& keyStatus : mData.mKeyStatuses) { - if (keyStatus.mSessionId.Equals(aSessionId)) { - aOutKeyStatuses.AppendElement(keyStatus); - } - } -} - -void -CDMCaps::AutoLock::GetSessionIdsForKeyId(const CencKeyId& aKeyId, - nsTArray& aOutSessionIds) -{ - for (const KeyStatus& keyStatus : mData.mKeyStatuses) { - if (keyStatus.mId == aKeyId) { - aOutSessionIds.AppendElement(NS_ConvertUTF16toUTF8(keyStatus.mSessionId)); - } - } -} - -bool -CDMCaps::AutoLock::RemoveKeysForSession(const nsString& aSessionId) -{ - bool changed = false; - nsTArray statuses; - GetKeyStatusesForSession(aSessionId, statuses); - for (const KeyStatus& status : statuses) { - changed |= SetKeyStatus(status.mId, - aSessionId, - dom::Optional()); - } - return changed; -} - -} // namespace mozilla diff --git a/dom/media/eme/CDMCaps.h b/dom/media/eme/CDMCaps.h deleted file mode 100644 index cb4b5e2910..0000000000 --- a/dom/media/eme/CDMCaps.h +++ /dev/null @@ -1,112 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 CDMCaps_h_ -#define CDMCaps_h_ - -#include "gmp-decryption.h" -#include "nsIThread.h" -#include "nsTArray.h" -#include "nsString.h" -#include "SamplesWaitingForKey.h" - -#include "mozilla/Monitor.h" -#include "mozilla/Attributes.h" -#include "mozilla/dom/MediaKeyStatusMapBinding.h" // For MediaKeyStatus -#include "mozilla/dom/BindingDeclarations.h" // For Optional - -namespace mozilla { - -// CDM capabilities; what keys a CDMProxy can use. -// Must be locked to access state. -class CDMCaps { -public: - CDMCaps(); - ~CDMCaps(); - - struct KeyStatus { - KeyStatus(const CencKeyId& aId, - const nsString& aSessionId, - dom::MediaKeyStatus aStatus) - : mId(aId) - , mSessionId(aSessionId) - , mStatus(aStatus) - {} - KeyStatus(const KeyStatus& aOther) - : mId(aOther.mId) - , mSessionId(aOther.mSessionId) - , mStatus(aOther.mStatus) - {} - bool operator==(const KeyStatus& aOther) const { - return mId == aOther.mId && - mSessionId == aOther.mSessionId; - }; - - CencKeyId mId; - nsString mSessionId; - dom::MediaKeyStatus mStatus; - }; - - // Locks the CDMCaps. It must be locked to access its shared state. - // Threadsafe when locked. - class MOZ_STACK_CLASS AutoLock { - public: - explicit AutoLock(CDMCaps& aKeyCaps); - ~AutoLock(); - - bool IsKeyUsable(const CencKeyId& aKeyId); - - // Returns true if key status changed, - // i.e. the key status changed from usable to expired. - bool SetKeyStatus(const CencKeyId& aKeyId, - const nsString& aSessionId, - const dom::Optional& aStatus); - - void GetKeyStatusesForSession(const nsAString& aSessionId, - nsTArray& aOutKeyStatuses); - - void GetSessionIdsForKeyId(const CencKeyId& aKeyId, - nsTArray& aOutSessionIds); - - // Ensures all keys for a session are marked as 'unknown', i.e. removed. - // Returns true if a key status was changed. - bool RemoveKeysForSession(const nsString& aSessionId); - - // Notifies the SamplesWaitingForKey when key become usable. - void NotifyWhenKeyIdUsable(const CencKeyId& aKey, - SamplesWaitingForKey* aSamplesWaiting); - private: - // Not taking a strong ref, since this should be allocated on the stack. - CDMCaps& mData; - }; - -private: - void Lock(); - void Unlock(); - - struct WaitForKeys { - WaitForKeys(const CencKeyId& aKeyId, - SamplesWaitingForKey* aListener) - : mKeyId(aKeyId) - , mListener(aListener) - {} - CencKeyId mKeyId; - RefPtr mListener; - }; - - Monitor mMonitor; - - nsTArray mKeyStatuses; - - nsTArray mWaitForKeys; - - // It is not safe to copy this object. - CDMCaps(const CDMCaps&) = delete; - CDMCaps& operator=(const CDMCaps&) = delete; -}; - -} // namespace mozilla - -#endif diff --git a/dom/media/eme/CDMProxy.h b/dom/media/eme/CDMProxy.h deleted file mode 100644 index a9e783f506..0000000000 --- a/dom/media/eme/CDMProxy.h +++ /dev/null @@ -1,278 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 CDMProxy_h_ -#define CDMProxy_h_ - -#include "mozilla/CDMCaps.h" -#include "mozilla/MozPromise.h" - -#include "mozilla/dom/MediaKeyMessageEvent.h" -#include "mozilla/dom/MediaKeys.h" - -#include "nsIThread.h" - -namespace mozilla { -class MediaRawData; - -enum DecryptStatus { - Ok = 0, - GenericErr = 1, - NoKeyErr = 2, - AbortedErr = 3, -}; - -struct DecryptResult { - DecryptResult(DecryptStatus aStatus, MediaRawData* aSample) - : mStatus(aStatus) - , mSample(aSample) - {} - DecryptStatus mStatus; - RefPtr mSample; -}; - -class CDMKeyInfo { -public: - explicit CDMKeyInfo(const nsTArray& aKeyId) - : mKeyId(aKeyId) - , mStatus() - {} - - CDMKeyInfo(const nsTArray& aKeyId, - const dom::Optional& aStatus) - : mKeyId(aKeyId) - , mStatus(aStatus.Value()) - {} - - // The copy-ctor and copy-assignment operator for Optional are declared as - // delete, so override CDMKeyInfo copy-ctor for nsTArray operations. - CDMKeyInfo(const CDMKeyInfo& aKeyInfo) - { - mKeyId = aKeyInfo.mKeyId; - if (aKeyInfo.mStatus.WasPassed()) { - mStatus.Construct(aKeyInfo.mStatus.Value()); - } - } - - nsTArray mKeyId; - dom::Optional mStatus; -}; - -typedef int64_t UnixTime; - -// Proxies calls CDM, and proxies calls back. -// Note: Promises are passed in via a PromiseId, so that the ID can be -// passed via IPC to the CDM, which can then signal when to reject or -// resolve the promise using its PromiseId. -class CDMProxy { -protected: - typedef dom::PromiseId PromiseId; - typedef dom::MediaKeySessionType MediaKeySessionType; -public: - - NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; - NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; - - typedef MozPromise DecryptPromise; - - // Main thread only. - CDMProxy(dom::MediaKeys* aKeys, - const nsAString& aKeySystem, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) - : mKeys(aKeys) - , mKeySystem(aKeySystem) - , mDistinctiveIdentifierRequired(aDistinctiveIdentifierRequired) - , mPersistentStateRequired(aPersistentStateRequired) - {} - - // Main thread only. - // Loads the CDM corresponding to mKeySystem. - // Calls MediaKeys::OnCDMCreated() when the CDM is created. - virtual void Init(PromiseId aPromiseId, - const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - const nsAString& aName, - bool aInPrivateBrowsing) = 0; - - virtual void OnSetDecryptorId(uint32_t aId) {} - - // Main thread only. - // Uses the CDM to create a key session. - // Calls MediaKeys::OnSessionActivated() when session is created. - // Assumes ownership of (Move()s) aInitData's contents. - virtual void CreateSession(uint32_t aCreateSessionToken, - MediaKeySessionType aSessionType, - PromiseId aPromiseId, - const nsAString& aInitDataType, - nsTArray& aInitData) = 0; - - // Main thread only. - // Uses the CDM to load a presistent session stored on disk. - // Calls MediaKeys::OnSessionActivated() when session is loaded. - virtual void LoadSession(PromiseId aPromiseId, - const nsAString& aSessionId) = 0; - - // Main thread only. - // Sends a new certificate to the CDM. - // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has - // processed the request. - // Assumes ownership of (Move()s) aCert's contents. - virtual void SetServerCertificate(PromiseId aPromiseId, - nsTArray& aCert) = 0; - - // Main thread only. - // Sends an update to the CDM. - // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has - // processed the request. - // Assumes ownership of (Move()s) aResponse's contents. - virtual void UpdateSession(const nsAString& aSessionId, - PromiseId aPromiseId, - nsTArray& aResponse) = 0; - - // Main thread only. - // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has - // processed the request. - // If processing this operation results in the session actually closing, - // we also call MediaKeySession::OnClosed(), which in turn calls - // MediaKeys::OnSessionClosed(). - virtual void CloseSession(const nsAString& aSessionId, - PromiseId aPromiseId) = 0; - - // Main thread only. - // Removes all data for a persisent session. - // Calls MediaKeys->ResolvePromise(aPromiseId) after the CDM has - // processed the request. - virtual void RemoveSession(const nsAString& aSessionId, - PromiseId aPromiseId) = 0; - - // Main thread only. - virtual void Shutdown() = 0; - - // Main thread only. - virtual void Terminated() = 0; - - // Threadsafe. - virtual const nsCString& GetNodeId() const = 0; - - // Main thread only. - virtual void OnSetSessionId(uint32_t aCreateSessionToken, - const nsAString& aSessionId) = 0; - - // Main thread only. - virtual void OnResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) = 0; - - // Main thread only. - virtual void OnSessionMessage(const nsAString& aSessionId, - dom::MediaKeyMessageType aMessageType, - nsTArray& aMessage) = 0; - - // Main thread only. - virtual void OnExpirationChange(const nsAString& aSessionId, - UnixTime aExpiryTime) = 0; - - // Main thread only. - virtual void OnSessionClosed(const nsAString& aSessionId) = 0; - - // Main thread only. - virtual void OnSessionError(const nsAString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsAString& aMsg) = 0; - - // Main thread only. - virtual void OnRejectPromise(uint32_t aPromiseId, - nsresult aDOMException, - const nsCString& aMsg) = 0; - - virtual RefPtr Decrypt(MediaRawData* aSample) = 0; - - // Owner thread only. - virtual void OnDecrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray& aDecryptedData) = 0; - - // Reject promise with DOMException corresponding to aExceptionCode. - // Can be called from any thread. - virtual void RejectPromise(PromiseId aId, - nsresult aExceptionCode, - const nsCString& aReason) = 0; - - // Resolves promise with "undefined". - // Can be called from any thread. - virtual void ResolvePromise(PromiseId aId) = 0; - - // Threadsafe. - virtual const nsString& KeySystem() const = 0; - - virtual CDMCaps& Capabilites() = 0; - - // Main thread only. - virtual void OnKeyStatusesChange(const nsAString& aSessionId) = 0; - - virtual void GetSessionIdsForKeyId(const nsTArray& aKeyId, - nsTArray& aSessionIds) = 0; - -#ifdef DEBUG - virtual bool IsOnOwnerThread() = 0; -#endif - - virtual uint32_t GetDecryptorId() { return 0; } - -protected: - virtual ~CDMProxy() {} - - // Helper to enforce that a raw pointer is only accessed on the main thread. - template - class MainThreadOnlyRawPtr { - public: - explicit MainThreadOnlyRawPtr(Type* aPtr) - : mPtr(aPtr) - { - MOZ_ASSERT(NS_IsMainThread()); - } - - bool IsNull() const { - MOZ_ASSERT(NS_IsMainThread()); - return !mPtr; - } - - void Clear() { - MOZ_ASSERT(NS_IsMainThread()); - mPtr = nullptr; - } - - Type* operator->() const MOZ_NO_ADDREF_RELEASE_ON_RETURN { - MOZ_ASSERT(NS_IsMainThread()); - return mPtr; - } - private: - Type* mPtr; - }; - - // Our reference back to the MediaKeys object. - // WARNING: This is a non-owning reference that is cleared by MediaKeys - // destructor. only use on main thread, and always nullcheck before using! - MainThreadOnlyRawPtr mKeys; - - const nsString mKeySystem; - - // Onwer specified thread. e.g. Gecko Media Plugin thread. - // All interactions with the out-of-process EME plugin must come from this thread. - RefPtr mOwnerThread; - - nsCString mNodeId; - - CDMCaps mCapabilites; - - const bool mDistinctiveIdentifierRequired; - const bool mPersistentStateRequired; -}; - - -} // namespace mozilla - -#endif // CDMProxy_h_ diff --git a/dom/media/eme/DecryptorProxyCallback.h b/dom/media/eme/DecryptorProxyCallback.h deleted file mode 100644 index c1fcb49a4f..0000000000 --- a/dom/media/eme/DecryptorProxyCallback.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 DecryptorProxyCallback_h_ -#define DecryptorProxyCallback_h_ - -#include "mozilla/dom/MediaKeyStatusMapBinding.h" // For MediaKeyStatus -#include "mozilla/dom/MediaKeyMessageEventBinding.h" // For MediaKeyMessageType -#include "mozilla/CDMProxy.h" - -class DecryptorProxyCallback { -public: - - virtual ~DecryptorProxyCallback() {} - - virtual void SetDecryptorId(uint32_t aId) = 0; - - virtual void SetSessionId(uint32_t aCreateSessionId, - const nsCString& aSessionId) = 0; - - virtual void ResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) = 0; - - virtual void ResolvePromise(uint32_t aPromiseId) = 0; - - virtual void RejectPromise(uint32_t aPromiseId, - nsresult aException, - const nsCString& aSessionId) = 0; - - virtual void SessionMessage(const nsCString& aSessionId, - mozilla::dom::MediaKeyMessageType aMessageType, - const nsTArray& aMessage) = 0; - - virtual void ExpirationChange(const nsCString& aSessionId, - mozilla::UnixTime aExpiryTime) = 0; - - virtual void SessionClosed(const nsCString& aSessionId) = 0; - - virtual void SessionError(const nsCString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsCString& aMessage) = 0; - - virtual void Decrypted(uint32_t aId, - mozilla::DecryptStatus aResult, - const nsTArray& aDecryptedData) = 0; - - virtual void BatchedKeyStatusChanged(const nsCString& aSessionId, - const nsTArray& aKeyInfos) = 0; -}; - -#endif diff --git a/dom/media/eme/DetailedPromise.cpp b/dom/media/eme/DetailedPromise.cpp deleted file mode 100644 index 1aa83bef5d..0000000000 --- a/dom/media/eme/DetailedPromise.cpp +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "DetailedPromise.h" -#include "mozilla/dom/DOMException.h" -#include "nsPrintfCString.h" - -namespace mozilla { -namespace dom { - -DetailedPromise::DetailedPromise(nsIGlobalObject* aGlobal, - const nsACString& aName) - : Promise(aGlobal) - , mName(aName) - , mResponded(false) - , mStartTime(TimeStamp::Now()) -{ -} - -DetailedPromise::~DetailedPromise() -{ -} - -void -DetailedPromise::MaybeReject(nsresult aArg, const nsACString& aReason) -{ - nsPrintfCString msg("%s promise rejected 0x%x '%s'", mName.get(), aArg, - PromiseFlatCString(aReason).get()); - EME_LOG(msg.get()); - - LogToBrowserConsole(NS_ConvertUTF8toUTF16(msg)); - - ErrorResult rv; - rv.ThrowDOMException(aArg, aReason); - Promise::MaybeReject(rv); -} - -void -DetailedPromise::MaybeReject(ErrorResult&, const nsACString& aReason) -{ - NS_NOTREACHED("nsresult expected in MaybeReject()"); -} - -/* static */ already_AddRefed -DetailedPromise::Create(nsIGlobalObject* aGlobal, - ErrorResult& aRv, - const nsACString& aName) -{ - RefPtr promise = new DetailedPromise(aGlobal, aName); - promise->CreateWrapper(nullptr, aRv); - return aRv.Failed() ? nullptr : promise.forget(); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/DetailedPromise.h b/dom/media/eme/DetailedPromise.h deleted file mode 100644 index f7f10aa403..0000000000 --- a/dom/media/eme/DetailedPromise.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 __DetailedPromise_h__ -#define __DetailedPromise_h__ - -#include "mozilla/dom/Promise.h" -#include "EMEUtils.h" - -namespace mozilla { -namespace dom { - -/* - * This is pretty horrible; bug 1160445. - * Extend Promise to add custom DOMException messages on rejection. - * Get rid of this once we've ironed out EME errors in the wild. - */ -class DetailedPromise : public Promise -{ -public: - static already_AddRefed - Create(nsIGlobalObject* aGlobal, - ErrorResult& aRv, - const nsACString& aName); - - template - void MaybeResolve(const T& aArg) - { - EME_LOG("%s promise resolved", mName.get()); - Promise::MaybeResolve(aArg); - } - - void MaybeReject(nsresult aArg) = delete; - void MaybeReject(nsresult aArg, const nsACString& aReason); - - void MaybeReject(ErrorResult& aArg) = delete; - void MaybeReject(ErrorResult&, const nsACString& aReason); - -private: - explicit DetailedPromise(nsIGlobalObject* aGlobal, - const nsACString& aName); - - virtual ~DetailedPromise(); - - enum Status { Succeeded, Failed }; - - nsCString mName; - bool mResponded; - TimeStamp mStartTime; -}; - -} // namespace dom -} // namespace mozilla - -#endif // __DetailedPromise_h__ diff --git a/dom/media/eme/EMEUtils.cpp b/dom/media/eme/EMEUtils.cpp deleted file mode 100644 index 68ef52d83e..0000000000 --- a/dom/media/eme/EMEUtils.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "mozilla/EMEUtils.h" - -#include "jsfriendapi.h" // for AutoCheckCannotGC -#include "mozilla/dom/UnionTypes.h" - -namespace mozilla { - -LogModule* GetEMELog() { - static LazyLogModule log("EME"); - return log; -} - -LogModule* GetEMEVerboseLog() { - static LazyLogModule log("EMEV"); - return log; -} - -ArrayData -GetArrayBufferViewOrArrayBufferData(const dom::ArrayBufferViewOrArrayBuffer& aBufferOrView) -{ - MOZ_ASSERT(aBufferOrView.IsArrayBuffer() || aBufferOrView.IsArrayBufferView()); - JS::AutoCheckCannotGC nogc; - if (aBufferOrView.IsArrayBuffer()) { - const dom::ArrayBuffer& buffer = aBufferOrView.GetAsArrayBuffer(); - buffer.ComputeLengthAndData(); - return ArrayData(buffer.Data(), buffer.Length()); - } else if (aBufferOrView.IsArrayBufferView()) { - const dom::ArrayBufferView& bufferview = aBufferOrView.GetAsArrayBufferView(); - bufferview.ComputeLengthAndData(); - return ArrayData(bufferview.Data(), bufferview.Length()); - } - return ArrayData(nullptr, 0); -} - -void -CopyArrayBufferViewOrArrayBufferData(const dom::ArrayBufferViewOrArrayBuffer& aBufferOrView, - nsTArray& aOutData) -{ - JS::AutoCheckCannotGC nogc; - ArrayData data = GetArrayBufferViewOrArrayBufferData(aBufferOrView); - aOutData.Clear(); - if (!data.IsValid()) { - return; - } - aOutData.AppendElements(data.mData, data.mLength); -} - -void CopyArrayBufferViewOrArrayBufferData(const dom::ArrayBuffer& aBuffer, - nsTArray& aOutData) { - JS::AutoCheckCannotGC nogc; - aBuffer.ComputeLengthAndData(); - aOutData.Clear(); - aOutData.AppendElements(aBuffer.Data(), aBuffer.Length()); -} - -bool -IsClearkeyKeySystem(const nsAString& aKeySystem) -{ - return !CompareUTF8toUTF16(kEMEKeySystemClearkey, aKeySystem); -} - -bool -IsWidevineKeySystem(const nsAString& aKeySystem) -{ - return !CompareUTF8toUTF16(kEMEKeySystemWidevine, aKeySystem); -} - -nsString -KeySystemToGMPName(const nsAString& aKeySystem) -{ - if (IsClearkeyKeySystem(aKeySystem)) { - return NS_LITERAL_STRING("gmp-clearkey"); - } - if (IsWidevineKeySystem(aKeySystem)) { - return NS_LITERAL_STRING("gmp-widevinecdm"); - } - MOZ_ASSERT(false, "We should only call this for known GMPs"); - return EmptyString(); -} - -} // namespace mozilla diff --git a/dom/media/eme/EMEUtils.h b/dom/media/eme/EMEUtils.h deleted file mode 100644 index aef1574829..0000000000 --- a/dom/media/eme/EMEUtils.h +++ /dev/null @@ -1,104 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 EME_LOG_H_ -#define EME_LOG_H_ - -#include "VideoUtils.h" -#include "mozilla/Logging.h" -#include "nsString.h" -#include "nsTArray.h" -#include "mozilla/dom/TypedArray.h" - -namespace mozilla { - -namespace dom { -class ArrayBufferViewOrArrayBuffer; -} - -#ifndef EME_LOG - LogModule* GetEMELog(); - #define EME_LOG(...) MOZ_LOG(GetEMELog(), mozilla::LogLevel::Debug, (__VA_ARGS__)) - #define EME_LOG_ENABLED() MOZ_LOG_TEST(GetEMELog(), mozilla::LogLevel::Debug) -#endif - -#ifndef EME_VERBOSE_LOG - LogModule* GetEMEVerboseLog(); - #define EME_VERBOSE_LOG(...) MOZ_LOG(GetEMEVerboseLog(), mozilla::LogLevel::Debug, (__VA_ARGS__)) -#else - #ifndef EME_LOG - #define EME_LOG(...) - #endif - - #ifndef EME_VERBOSE_LOG - #define EME_VERBOSE_LOG(...) - #endif -#endif - -// Helper function to extract a copy of data coming in from JS in an -// (ArrayBuffer or ArrayBufferView) IDL typed function argument. -// -// Only call this on a properly initialized ArrayBufferViewOrArrayBuffer. -void -CopyArrayBufferViewOrArrayBufferData(const dom::ArrayBufferViewOrArrayBuffer& aBufferOrView, - nsTArray& aOutData); - -// Overload for ArrayBuffer -void CopyArrayBufferViewOrArrayBufferData(const dom::ArrayBuffer& aBufferOrView, - nsTArray& aOutData); - -struct ArrayData { - explicit ArrayData(const uint8_t* aData, size_t aLength) - : mData(aData) - , mLength(aLength) - { - } - const uint8_t* mData; - const size_t mLength; - bool IsValid() const { - return mData != nullptr && mLength != 0; - } - bool operator== (const nsTArray& aOther) const { - return mLength == aOther.Length() && - memcmp(mData, aOther.Elements(), mLength) == 0; - } -}; - -// Helper function to extract data coming in from JS in an -// (ArrayBuffer or ArrayBufferView) IDL typed function argument. -// -// Be *very* careful with this! -// -// Only use returned ArrayData inside the lifetime of the -// ArrayBufferViewOrArrayBuffer; the ArrayData struct does not contain -// a copy of the data! -// -// And do *not* call out to anything that could call into JavaScript, -// while the ArrayData is live, as then all bets about the data not changing -// are off! No calls into JS, no calls into JS-implemented WebIDL or XPIDL, -// nothing. Beware! -// -// Only call this on a properly initialized ArrayBufferViewOrArrayBuffer. -ArrayData -GetArrayBufferViewOrArrayBufferData(const dom::ArrayBufferViewOrArrayBuffer& aBufferOrView); - -nsString -KeySystemToGMPName(const nsAString& aKeySystem); - -bool -IsClearkeyKeySystem(const nsAString& aKeySystem); - -bool -IsWidevineKeySystem(const nsAString& aKeySystem); - -enum CDMType { - eClearKey = 0, - eWidevine = 2, - eUnknown = 3 -}; - -} // namespace mozilla - -#endif // EME_LOG_H_ diff --git a/dom/media/eme/MediaEncryptedEvent.cpp b/dom/media/eme/MediaEncryptedEvent.cpp deleted file mode 100644 index a9c83291e9..0000000000 --- a/dom/media/eme/MediaEncryptedEvent.cpp +++ /dev/null @@ -1,128 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "MediaEncryptedEvent.h" -#include "mozilla/dom/MediaEncryptedEventBinding.h" -#include "nsContentUtils.h" -#include "jsfriendapi.h" -#include "nsINode.h" -#include "mozilla/dom/MediaKeys.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_CLASS(MediaEncryptedEvent) - -NS_IMPL_ADDREF_INHERITED(MediaEncryptedEvent, Event) -NS_IMPL_RELEASE_INHERITED(MediaEncryptedEvent, Event) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaEncryptedEvent, Event) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MediaEncryptedEvent, Event) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mInitData) -NS_IMPL_CYCLE_COLLECTION_TRACE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaEncryptedEvent, Event) - tmp->mInitData = nullptr; - mozilla::DropJSObjects(this); -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaEncryptedEvent) -NS_INTERFACE_MAP_END_INHERITING(Event) - -MediaEncryptedEvent::MediaEncryptedEvent(EventTarget* aOwner) - : Event(aOwner, nullptr, nullptr) -{ - mozilla::HoldJSObjects(this); -} - -MediaEncryptedEvent::~MediaEncryptedEvent() -{ - mInitData = nullptr; - mozilla::DropJSObjects(this); -} - -JSObject* -MediaEncryptedEvent::WrapObjectInternal(JSContext* aCx, JS::Handle aGivenProto) -{ - return MediaEncryptedEventBinding::Wrap(aCx, this, aGivenProto); -} - -already_AddRefed -MediaEncryptedEvent::Constructor(EventTarget* aOwner) -{ - RefPtr e = new MediaEncryptedEvent(aOwner); - e->InitEvent(NS_LITERAL_STRING("encrypted"), false, false); - e->SetTrusted(true); - return e.forget(); -} - -already_AddRefed -MediaEncryptedEvent::Constructor(EventTarget* aOwner, - const nsAString& aInitDataType, - const nsTArray& aInitData) -{ - RefPtr e = new MediaEncryptedEvent(aOwner); - e->InitEvent(NS_LITERAL_STRING("encrypted"), false, false); - e->mInitDataType = aInitDataType; - e->mRawInitData = aInitData; - e->SetTrusted(true); - return e.forget(); -} - -already_AddRefed -MediaEncryptedEvent::Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyNeededEventInit& aEventInitDict, - ErrorResult& aRv) -{ - nsCOMPtr owner = do_QueryInterface(aGlobal.GetAsSupports()); - RefPtr e = new MediaEncryptedEvent(owner); - bool trusted = e->Init(owner); - e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable); - e->mInitDataType = aEventInitDict.mInitDataType; - if (!aEventInitDict.mInitData.IsNull()) { - const auto& a = aEventInitDict.mInitData.Value(); - nsTArray initData; - CopyArrayBufferViewOrArrayBufferData(a, initData); - e->mInitData = ArrayBuffer::Create(aGlobal.Context(), initData.Length(), - initData.Elements()); - if (!e->mInitData) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return nullptr; - } - } - e->SetTrusted(trusted); - return e.forget(); -} - -void -MediaEncryptedEvent::GetInitDataType(nsString& aRetVal) const -{ - aRetVal = mInitDataType; -} - -void -MediaEncryptedEvent::GetInitData(JSContext* cx, - JS::MutableHandle aData, - ErrorResult& aRv) -{ - if (mRawInitData.Length()) { - mInitData = ArrayBuffer::Create(cx, - this, - mRawInitData.Length(), - mRawInitData.Elements()); - if (!mInitData) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } - mRawInitData.Clear(); - } - aData.set(mInitData); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaEncryptedEvent.h b/dom/media/eme/MediaEncryptedEvent.h deleted file mode 100644 index c2ac560612..0000000000 --- a/dom/media/eme/MediaEncryptedEvent.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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_MediaKeyNeededEvent_h__ -#define mozilla_dom_MediaKeyNeededEvent_h__ - -#include "mozilla/dom/MediaEncryptedEventBinding.h" -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "nsCycleCollectionParticipant.h" -#include "nsWrapperCache.h" -#include "nsCOMPtr.h" -#include "mozilla/dom/Event.h" -#include "mozilla/dom/TypedArray.h" -#include "mozilla/Attributes.h" -#include "mozilla/dom/BindingUtils.h" -#include "js/TypeDecls.h" - -namespace mozilla { -namespace dom { - -class MediaEncryptedEvent final : public Event -{ -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MediaEncryptedEvent, Event) -protected: - virtual ~MediaEncryptedEvent(); - explicit MediaEncryptedEvent(EventTarget* aOwner); - - nsString mInitDataType; - JS::Heap mInitData; - -public: - - JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle aGivenProto) override; - - static already_AddRefed - Constructor(EventTarget* aOwner); - - static already_AddRefed - Constructor(EventTarget* aOwner, - const nsAString& aInitDataType, - const nsTArray& aInitData); - - static already_AddRefed - Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyNeededEventInit& aEventInitDict, - ErrorResult& aRv); - - void GetInitDataType(nsString& aRetVal) const; - - void GetInitData(JSContext* cx, - JS::MutableHandle aData, - ErrorResult& aRv); -private: - nsTArray mRawInitData; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_MediaKeyNeededEvent_h__ diff --git a/dom/media/eme/MediaKeyError.cpp b/dom/media/eme/MediaKeyError.cpp deleted file mode 100644 index 95e544fe76..0000000000 --- a/dom/media/eme/MediaKeyError.cpp +++ /dev/null @@ -1,38 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "MediaKeyError.h" -#include "mozilla/dom/MediaKeyErrorBinding.h" -#include "nsContentUtils.h" - -namespace mozilla { -namespace dom { - -MediaKeyError::MediaKeyError(EventTarget* aOwner, uint32_t aSystemCode) - : Event(aOwner, nullptr, nullptr) - , mSystemCode(aSystemCode) -{ - InitEvent(NS_LITERAL_STRING("error"), false, false); -} - -MediaKeyError::~MediaKeyError() -{ -} - -uint32_t -MediaKeyError::SystemCode() const -{ - return mSystemCode; -} - -JSObject* -MediaKeyError::WrapObjectInternal(JSContext* aCx, JS::Handle aGivenProto) -{ - return MediaKeyErrorBinding::Wrap(aCx, this, aGivenProto); -} - - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeyError.h b/dom/media/eme/MediaKeyError.h deleted file mode 100644 index b1e7aad3ee..0000000000 --- a/dom/media/eme/MediaKeyError.h +++ /dev/null @@ -1,37 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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_MediaKeyError_h -#define mozilla_dom_MediaKeyError_h - -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "nsWrapperCache.h" -#include "mozilla/dom/Event.h" -#include "js/TypeDecls.h" - -namespace mozilla { -namespace dom { - -class MediaKeyError final : public Event -{ -public: - NS_FORWARD_TO_EVENT - - MediaKeyError(EventTarget* aOwner, uint32_t aSystemCode); - ~MediaKeyError(); - - JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle aGivenProto) override; - - uint32_t SystemCode() const; - -private: - uint32_t mSystemCode; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/media/eme/MediaKeyMessageEvent.cpp b/dom/media/eme/MediaKeyMessageEvent.cpp deleted file mode 100644 index ee13f8d26f..0000000000 --- a/dom/media/eme/MediaKeyMessageEvent.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "mozilla/dom/MediaKeyMessageEvent.h" -#include "mozilla/dom/MediaKeyMessageEventBinding.h" -#include "js/GCAPI.h" -#include "jsfriendapi.h" -#include "mozilla/dom/Nullable.h" -#include "mozilla/dom/PrimitiveConversions.h" -#include "mozilla/HoldDropJSObjects.h" -#include "mozilla/dom/TypedArray.h" -#include "nsContentUtils.h" -#include "mozilla/dom/MediaKeys.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_CLASS(MediaKeyMessageEvent) - -NS_IMPL_ADDREF_INHERITED(MediaKeyMessageEvent, Event) -NS_IMPL_RELEASE_INHERITED(MediaKeyMessageEvent, Event) - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(MediaKeyMessageEvent, Event) -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -NS_IMPL_CYCLE_COLLECTION_TRACE_BEGIN_INHERITED(MediaKeyMessageEvent, Event) - NS_IMPL_CYCLE_COLLECTION_TRACE_JS_MEMBER_CALLBACK(mMessage) -NS_IMPL_CYCLE_COLLECTION_TRACE_END - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(MediaKeyMessageEvent, Event) - tmp->mMessage = nullptr; - mozilla::DropJSObjects(this); -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaKeyMessageEvent) -NS_INTERFACE_MAP_END_INHERITING(Event) - -MediaKeyMessageEvent::MediaKeyMessageEvent(EventTarget* aOwner) - : Event(aOwner, nullptr, nullptr) -{ - mozilla::HoldJSObjects(this); -} - -MediaKeyMessageEvent::~MediaKeyMessageEvent() -{ - mMessage = nullptr; - mozilla::DropJSObjects(this); -} - -MediaKeyMessageEvent* -MediaKeyMessageEvent::AsMediaKeyMessageEvent() -{ - return this; -} - -JSObject* -MediaKeyMessageEvent::WrapObjectInternal(JSContext* aCx, JS::Handle aGivenProto) -{ - return MediaKeyMessageEventBinding::Wrap(aCx, this, aGivenProto); -} - -already_AddRefed -MediaKeyMessageEvent::Constructor(EventTarget* aOwner, - MediaKeyMessageType aMessageType, - const nsTArray& aMessage) -{ - RefPtr e = new MediaKeyMessageEvent(aOwner); - e->InitEvent(NS_LITERAL_STRING("message"), false, false); - e->mMessageType = aMessageType; - e->mRawMessage = aMessage; - e->SetTrusted(true); - return e.forget(); -} - -already_AddRefed -MediaKeyMessageEvent::Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyMessageEventInit& aEventInitDict, - ErrorResult& aRv) -{ - nsCOMPtr owner = do_QueryInterface(aGlobal.GetAsSupports()); - RefPtr e = new MediaKeyMessageEvent(owner); - bool trusted = e->Init(owner); - e->InitEvent(aType, aEventInitDict.mBubbles, aEventInitDict.mCancelable); - nsTArray initData; - CopyArrayBufferViewOrArrayBufferData(aEventInitDict.mMessage, initData); - e->mMessage = ArrayBuffer::Create(aGlobal.Context(), - initData.Length(), - initData.Elements()); - if (!e->mMessage) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return nullptr; - } - e->mMessageType = aEventInitDict.mMessageType; - e->SetTrusted(trusted); - e->SetComposed(aEventInitDict.mComposed); - return e.forget(); -} - -void -MediaKeyMessageEvent::GetMessage(JSContext* cx, - JS::MutableHandle aMessage, - ErrorResult& aRv) -{ - if (!mMessage) { - mMessage = ArrayBuffer::Create(cx, - this, - mRawMessage.Length(), - mRawMessage.Elements()); - if (!mMessage) { - aRv.Throw(NS_ERROR_OUT_OF_MEMORY); - return; - } - mRawMessage.Clear(); - } - aMessage.set(mMessage); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeyMessageEvent.h b/dom/media/eme/MediaKeyMessageEvent.h deleted file mode 100644 index 2ec50f4f07..0000000000 --- a/dom/media/eme/MediaKeyMessageEvent.h +++ /dev/null @@ -1,66 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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_MediaKeyMessageEvent_h__ -#define mozilla_dom_MediaKeyMessageEvent_h__ - -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "nsCycleCollectionParticipant.h" -#include "nsWrapperCache.h" -#include "nsCOMPtr.h" -#include "mozilla/dom/Event.h" -#include "mozilla/dom/TypedArray.h" -#include "js/TypeDecls.h" -#include "mozilla/dom/MediaKeyMessageEventBinding.h" - -namespace mozilla { -namespace dom { - -struct MediaKeyMessageEventInit; - -class MediaKeyMessageEvent final : public Event -{ -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(MediaKeyMessageEvent, Event) -protected: - virtual ~MediaKeyMessageEvent(); - explicit MediaKeyMessageEvent(EventTarget* aOwner); - - MediaKeyMessageType mMessageType; - JS::Heap mMessage; - -public: - virtual MediaKeyMessageEvent* AsMediaKeyMessageEvent(); - - JSObject* WrapObjectInternal(JSContext* aCx, JS::Handle aGivenProto) override; - - static already_AddRefed - Constructor(EventTarget* aOwner, - MediaKeyMessageType aMessageType, - const nsTArray& aMessage); - - static already_AddRefed - Constructor(const GlobalObject& aGlobal, - const nsAString& aType, - const MediaKeyMessageEventInit& aEventInitDict, - ErrorResult& aRv); - - MediaKeyMessageType MessageType() const { return mMessageType; } - - void GetMessage(JSContext* cx, - JS::MutableHandle aMessage, - ErrorResult& aRv); - -private: - nsTArray mRawMessage; -}; - - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_MediaKeyMessageEvent_h__ diff --git a/dom/media/eme/MediaKeySession.cpp b/dom/media/eme/MediaKeySession.cpp deleted file mode 100644 index b5f3fe498b..0000000000 --- a/dom/media/eme/MediaKeySession.cpp +++ /dev/null @@ -1,670 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "mozilla/dom/HTMLMediaElement.h" -#include "mozilla/dom/MediaKeySession.h" -#include "mozilla/dom/MediaKeyError.h" -#include "mozilla/dom/MediaKeyMessageEvent.h" -#include "mozilla/dom/MediaEncryptedEvent.h" -#include "mozilla/dom/MediaKeyStatusMap.h" -#include "mozilla/dom/MediaKeySystemAccess.h" -#include "mozilla/dom/KeyIdsInitDataBinding.h" -#include "nsCycleCollectionParticipant.h" -#include "mozilla/CDMProxy.h" -#include "mozilla/AsyncEventDispatcher.h" -#include "mozilla/Move.h" -#include "nsContentUtils.h" -#include "mozilla/EMEUtils.h" -#include "GMPUtils.h" -#include "nsPrintfCString.h" -#include "psshparser/PsshParser.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_INHERITED(MediaKeySession, - DOMEventTargetHelper, - mMediaKeyError, - mKeys, - mKeyStatusMap, - mClosed) - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(MediaKeySession) -NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper) - -NS_IMPL_ADDREF_INHERITED(MediaKeySession, DOMEventTargetHelper) -NS_IMPL_RELEASE_INHERITED(MediaKeySession, DOMEventTargetHelper) - -// Count of number of instances. Used to give each instance a -// unique token. -static uint32_t sMediaKeySessionNum = 0; - -// Max length of keyId in EME "keyIds" or WebM init data format, as enforced -// by web platform tests. -static const uint32_t MAX_KEY_ID_LENGTH = 512; - -// Max length of CENC PSSH init data tolerated, as enforced by web -// platform tests. -static const uint32_t MAX_CENC_INIT_DATA_LENGTH = 64 * 1024; - - -MediaKeySession::MediaKeySession(JSContext* aCx, - nsPIDOMWindowInner* aParent, - MediaKeys* aKeys, - const nsAString& aKeySystem, - MediaKeySessionType aSessionType, - ErrorResult& aRv) - : DOMEventTargetHelper(aParent) - , mKeys(aKeys) - , mKeySystem(aKeySystem) - , mSessionType(aSessionType) - , mToken(sMediaKeySessionNum++) - , mIsClosed(false) - , mUninitialized(true) - , mKeyStatusMap(new MediaKeyStatusMap(aParent)) - , mExpiration(JS::GenericNaN()) -{ - EME_LOG("MediaKeySession[%p,''] ctor", this); - - MOZ_ASSERT(aParent); - if (aRv.Failed()) { - return; - } - mClosed = MakePromise(aRv, NS_LITERAL_CSTRING("MediaKeys.createSession")); -} - -void MediaKeySession::SetSessionId(const nsAString& aSessionId) -{ - EME_LOG("MediaKeySession[%p,'%s'] session Id set", - this, NS_ConvertUTF16toUTF8(aSessionId).get()); - - if (NS_WARN_IF(!mSessionId.IsEmpty())) { - return; - } - mSessionId = aSessionId; - mKeys->OnSessionIdReady(this); -} - -MediaKeySession::~MediaKeySession() -{ -} - -MediaKeyError* -MediaKeySession::GetError() const -{ - return mMediaKeyError; -} - -void -MediaKeySession::GetKeySystem(nsString& aOutKeySystem) const -{ - aOutKeySystem.Assign(mKeySystem); -} - -void -MediaKeySession::GetSessionId(nsString& aSessionId) const -{ - aSessionId = GetSessionId(); -} - -const nsString& -MediaKeySession::GetSessionId() const -{ - return mSessionId; -} - -JSObject* -MediaKeySession::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return MediaKeySessionBinding::Wrap(aCx, this, aGivenProto); -} - -double -MediaKeySession::Expiration() const -{ - return mExpiration; -} - -Promise* -MediaKeySession::Closed() const -{ - return mClosed; -} - -void -MediaKeySession::UpdateKeyStatusMap() -{ - MOZ_ASSERT(!IsClosed()); - if (!mKeys->GetCDMProxy()) { - return; - } - - nsTArray keyStatuses; - { - CDMCaps::AutoLock caps(mKeys->GetCDMProxy()->Capabilites()); - caps.GetKeyStatusesForSession(mSessionId, keyStatuses); - } - - mKeyStatusMap->Update(keyStatuses); - - if (EME_LOG_ENABLED()) { - nsAutoCString message( - nsPrintfCString("MediaKeySession[%p,'%s'] key statuses change {", - this, NS_ConvertUTF16toUTF8(mSessionId).get())); - using IntegerType = typename std::underlying_type::type; - for (const CDMCaps::KeyStatus& status : keyStatuses) { - message.Append(nsPrintfCString(" (%s,%s)", ToBase64(status.mId).get(), - MediaKeyStatusValues::strings[static_cast(status.mStatus)].value)); - } - message.Append(" }"); - EME_LOG(message.get()); - } -} - -MediaKeyStatusMap* -MediaKeySession::KeyStatuses() const -{ - return mKeyStatusMap; -} - -// The user agent MUST thoroughly validate the Initialization Data before -// passing it to the CDM. This includes verifying that the length and -// values of fields are reasonable, verifying that values are within -// reasonable limits, and stripping irrelevant, unsupported, or unknown -// data or fields. It is RECOMMENDED that user agents pre-parse, sanitize, -// and/or generate a fully sanitized version of the Initialization Data. -// If the Initialization Data format specified by initDataType supports -// multiple entries, the user agent SHOULD remove entries that are not -// needed by the CDM. The user agent MUST NOT re-order entries within -// the Initialization Data. -static bool -ValidateInitData(const nsTArray& aInitData, const nsAString& aInitDataType) -{ - if (aInitDataType.LowerCaseEqualsLiteral("webm")) { - // WebM initData consists of a single keyId. Ensure it's of reasonable length. - return aInitData.Length() <= MAX_KEY_ID_LENGTH; - } else if (aInitDataType.LowerCaseEqualsLiteral("cenc")) { - // Limit initData to less than 64KB. - if (aInitData.Length() > MAX_CENC_INIT_DATA_LENGTH) { - return false; - } - std::vector> keyIds; - return ParseCENCInitData(aInitData.Elements(), aInitData.Length(), keyIds); - } else if (aInitDataType.LowerCaseEqualsLiteral("keyids")) { - if (aInitData.Length() > MAX_KEY_ID_LENGTH) { - return false; - } - // Ensure that init data matches the expected JSON format. - mozilla::dom::KeyIdsInitData keyIds; - nsString json; - nsDependentCSubstring raw(reinterpret_cast(aInitData.Elements()), aInitData.Length()); - if (NS_FAILED(nsContentUtils::ConvertStringFromEncoding(NS_LITERAL_CSTRING("UTF-8"), raw, json))) { - return false; - } - if (!keyIds.Init(json)) { - return false; - } - if (keyIds.mKids.Length() == 0) { - return false; - } - for (const auto& kid : keyIds.mKids) { - if (kid.IsEmpty()) { - return false; - } - } - } - return true; -} - -// Generates a license request based on the initData. A message of type -// "license-request" or "individualization-request" will always be queued -// if the algorithm succeeds and the promise is resolved. -already_AddRefed -MediaKeySession::GenerateRequest(const nsAString& aInitDataType, - const ArrayBufferViewOrArrayBuffer& aInitData, - ErrorResult& aRv) -{ - RefPtr promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeySession.generateRequest"))); - if (aRv.Failed()) { - return nullptr; - } - - // If this object is closed, return a promise rejected with an InvalidStateError. - if (IsClosed()) { - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, closed", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Session is closed in MediaKeySession.generateRequest()")); - return promise.forget(); - } - - // If this object's uninitialized value is false, return a promise rejected - // with an InvalidStateError. - if (!mUninitialized) { - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, uninitialized", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Session is already initialized in MediaKeySession.generateRequest()")); - return promise.forget(); - } - - // Let this object's uninitialized value be false. - mUninitialized = false; - - // If initDataType is the empty string, return a promise rejected - // with a newly created TypeError. - if (aInitDataType.IsEmpty()) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Empty initDataType passed to MediaKeySession.generateRequest()")); - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, empty initDataType", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - - // If initData is an empty array, return a promise rejected with - // a newly created TypeError. - nsTArray data; - CopyArrayBufferViewOrArrayBufferData(aInitData, data); - if (data.IsEmpty()) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Empty initData passed to MediaKeySession.generateRequest()")); - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, empty initData", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - - // If the Key System implementation represented by this object's - // cdm implementation value does not support initDataType as an - // Initialization Data Type, return a promise rejected with a - // NotSupportedError. String comparison is case-sensitive. - if (!MediaKeySystemAccess::KeySystemSupportsInitDataType(mKeySystem, aInitDataType)) { - promise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, - NS_LITERAL_CSTRING("Unsupported initDataType passed to MediaKeySession.generateRequest()")); - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() failed, unsupported initDataType", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - - // Let init data be a copy of the contents of the initData parameter. - // Note: Handled by the CopyArrayBufferViewOrArrayBufferData call above. - - // Let session type be this object's session type. - - // Let promise be a new promise. - - // Run the following steps in parallel: - - // If the init data is not valid for initDataType, reject promise with - // a newly created TypeError. - if (!ValidateInitData(data, aInitDataType)) { - // If the preceding step failed, reject promise with a newly created TypeError. - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("initData sanitization failed in MediaKeySession.generateRequest()")); - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() initData sanitization failed", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - - // Let sanitized init data be a validated and sanitized version of init data. - - // If sanitized init data is empty, reject promise with a NotSupportedError. - - // Note: Remaining steps of generateRequest method continue in CDM. - - // Convert initData to base64 for easier logging. - // Note: CreateSession() Move()s the data out of the array, so we have - // to copy it here. - nsAutoCString base64InitData(ToBase64(data)); - PromiseId pid = mKeys->StorePromise(promise); - mKeys->ConnectPendingPromiseIdWithToken(pid, Token()); - mKeys->GetCDMProxy()->CreateSession(Token(), - mSessionType, - pid, - aInitDataType, data); - - EME_LOG("MediaKeySession[%p,'%s'] GenerateRequest() sent, " - "promiseId=%d initData(base64)='%s' initDataType='%s'", - this, - NS_ConvertUTF16toUTF8(mSessionId).get(), - pid, - base64InitData.get(), - NS_ConvertUTF16toUTF8(aInitDataType).get()); - - return promise.forget(); -} - -already_AddRefed -MediaKeySession::Load(const nsAString& aSessionId, ErrorResult& aRv) -{ - RefPtr promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeySession.load"))); - if (aRv.Failed()) { - return nullptr; - } - - // 1. If this object is closed, return a promise rejected with an InvalidStateError. - if (IsClosed()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Session is closed in MediaKeySession.load()")); - EME_LOG("MediaKeySession[%p,'%s'] Load() failed, closed", - this, NS_ConvertUTF16toUTF8(aSessionId).get()); - return promise.forget(); - } - - // 2.If this object's uninitialized value is false, return a promise rejected - // with an InvalidStateError. - if (!mUninitialized) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Session is already initialized in MediaKeySession.load()")); - EME_LOG("MediaKeySession[%p,'%s'] Load() failed, uninitialized", - this, NS_ConvertUTF16toUTF8(aSessionId).get()); - return promise.forget(); - } - - // 3.Let this object's uninitialized value be false. - mUninitialized = false; - - // 4. If sessionId is the empty string, return a promise rejected with a newly created TypeError. - if (aSessionId.IsEmpty()) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Trying to load a session with empty session ID")); - // "The sessionId parameter is empty." - EME_LOG("MediaKeySession[%p,''] Load() failed, no sessionId", this); - return promise.forget(); - } - - // 5. If the result of running the Is persistent session type? algorithm - // on this object's session type is false, return a promise rejected with - // a newly created TypeError. - if (mSessionType == MediaKeySessionType::Temporary) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Trying to load() into a non-persistent session")); - EME_LOG("MediaKeySession[%p,''] Load() failed, can't load in a non-persistent session", this); - return promise.forget(); - } - - // Note: We don't support persistent sessions in any keysystem, so all calls - // to Load() should reject with a TypeError in the preceding check. Omitting - // implementing the rest of the specified MediaKeySession::Load() algorithm. - - // We now know the sessionId being loaded into this session. Remove the - // session from its owning MediaKey's set of sessions awaiting a sessionId. - RefPtr session(mKeys->GetPendingSession(Token())); - MOZ_ASSERT(session == this, "Session should be awaiting id on its own token"); - - // Associate with the known sessionId. - SetSessionId(aSessionId); - - PromiseId pid = mKeys->StorePromise(promise); - mKeys->GetCDMProxy()->LoadSession(pid, aSessionId); - - EME_LOG("MediaKeySession[%p,'%s'] Load() sent to CDM, promiseId=%d", - this, NS_ConvertUTF16toUTF8(mSessionId).get(), pid); - - return promise.forget(); -} - -already_AddRefed -MediaKeySession::Update(const ArrayBufferViewOrArrayBuffer& aResponse, ErrorResult& aRv) -{ - RefPtr promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeySession.update"))); - if (aRv.Failed()) { - return nullptr; - } - - if (!IsCallable()) { - // If this object's callable value is false, return a promise rejected - // with a new DOMException whose name is InvalidStateError. - EME_LOG("MediaKeySession[%p,''] Update() called before sessionId set by CDM", this); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("MediaKeySession.Update() called before sessionId set by CDM")); - return promise.forget(); - } - - nsTArray data; - if (IsClosed() || !mKeys->GetCDMProxy()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Session is closed or was not properly initialized")); - EME_LOG("MediaKeySession[%p,'%s'] Update() failed, session is closed or was not properly initialised.", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - CopyArrayBufferViewOrArrayBufferData(aResponse, data); - if (data.IsEmpty()) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Empty response buffer passed to MediaKeySession.update()")); - EME_LOG("MediaKeySession[%p,'%s'] Update() failed, empty response buffer", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - - - // Convert response to base64 for easier logging. - // Note: UpdateSession() Move()s the data out of the array, so we have - // to copy it here. - nsAutoCString base64Response(ToBase64(data)); - - PromiseId pid = mKeys->StorePromise(promise); - mKeys->GetCDMProxy()->UpdateSession(mSessionId, - pid, - data); - - EME_LOG("MediaKeySession[%p,'%s'] Update() sent to CDM, " - "promiseId=%d Response(base64)='%s'", - this, - NS_ConvertUTF16toUTF8(mSessionId).get(), - pid, - base64Response.get()); - - return promise.forget(); -} - -already_AddRefed -MediaKeySession::Close(ErrorResult& aRv) -{ - RefPtr promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeySession.close"))); - if (aRv.Failed()) { - return nullptr; - } - // 1. Let session be the associated MediaKeySession object. - // 2. If session is closed, return a resolved promise. - if (IsClosed()) { - EME_LOG("MediaKeySession[%p,'%s'] Close() already closed", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - promise->MaybeResolveWithUndefined(); - return promise.forget(); - } - // 3. If session's callable value is false, return a promise rejected - // with an InvalidStateError. - if (!IsCallable()) { - EME_LOG("MediaKeySession[%p,''] Close() called before sessionId set by CDM", this); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("MediaKeySession.Close() called before sessionId set by CDM")); - return promise.forget(); - } - if (!mKeys->GetCDMProxy()) { - EME_LOG("MediaKeySession[%p,'%s'] Close() null CDMProxy", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("MediaKeySession.Close() lost reference to CDM")); - return promise.forget(); - } - // 4. Let promise be a new promise. - PromiseId pid = mKeys->StorePromise(promise); - // 5. Run the following steps in parallel: - // 5.1 Let cdm be the CDM instance represented by session's cdm instance value. - // 5.2 Use cdm to close the session associated with session. - mKeys->GetCDMProxy()->CloseSession(mSessionId, pid); - - EME_LOG("MediaKeySession[%p,'%s'] Close() sent to CDM, promiseId=%d", - this, NS_ConvertUTF16toUTF8(mSessionId).get(), pid); - - // Session Closed algorithm is run when CDM causes us to run OnSessionClosed(). - - // 6. Return promise. - return promise.forget(); -} - -void -MediaKeySession::OnClosed() -{ - if (IsClosed()) { - return; - } - EME_LOG("MediaKeySession[%p,'%s'] session close operation complete.", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - mIsClosed = true; - mKeys->OnSessionClosed(this); - mKeys = nullptr; - mClosed->MaybeResolveWithUndefined(); -} - -bool -MediaKeySession::IsClosed() const -{ - return mIsClosed; -} - -already_AddRefed -MediaKeySession::Remove(ErrorResult& aRv) -{ - RefPtr promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeySession.remove"))); - if (aRv.Failed()) { - return nullptr; - } - if (!IsCallable()) { - // If this object's callable value is false, return a promise rejected - // with a new DOMException whose name is InvalidStateError. - EME_LOG("MediaKeySession[%p,''] Remove() called before sessionId set by CDM", this); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("MediaKeySession.Remove() called before sessionId set by CDM")); - return promise.forget(); - } - if (mSessionType != MediaKeySessionType::Persistent_license) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR, - NS_LITERAL_CSTRING("Calling MediaKeySession.remove() on non-persistent session")); - // "The operation is not supported on session type sessions." - EME_LOG("MediaKeySession[%p,'%s'] Remove() failed, sesion not persisrtent.", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - if (IsClosed() || !mKeys->GetCDMProxy()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("MediaKeySesison.remove() called but session is not active")); - // "The session is closed." - EME_LOG("MediaKeySession[%p,'%s'] Remove() failed, already session closed.", - this, NS_ConvertUTF16toUTF8(mSessionId).get()); - return promise.forget(); - } - PromiseId pid = mKeys->StorePromise(promise); - mKeys->GetCDMProxy()->RemoveSession(mSessionId, pid); - EME_LOG("MediaKeySession[%p,'%s'] Remove() sent to CDM, promiseId=%d.", - this, NS_ConvertUTF16toUTF8(mSessionId).get(), pid); - - return promise.forget(); -} - -void -MediaKeySession::DispatchKeyMessage(MediaKeyMessageType aMessageType, - const nsTArray& aMessage) -{ - if (EME_LOG_ENABLED()) { - EME_LOG("MediaKeySession[%p,'%s'] DispatchKeyMessage() type=%s message(base64)='%s'", - this, NS_ConvertUTF16toUTF8(mSessionId).get(), - MediaKeyMessageTypeValues::strings[uint32_t(aMessageType)].value, - ToBase64(aMessage).get()); - } - - RefPtr event( - MediaKeyMessageEvent::Constructor(this, aMessageType, aMessage)); - RefPtr asyncDispatcher = - new AsyncEventDispatcher(this, event); - asyncDispatcher->PostDOMEvent(); -} - -void -MediaKeySession::DispatchKeyError(uint32_t aSystemCode) -{ - EME_LOG("MediaKeySession[%p,'%s'] DispatchKeyError() systemCode=%u.", - this, NS_ConvertUTF16toUTF8(mSessionId).get(), aSystemCode); - - RefPtr event(new MediaKeyError(this, aSystemCode)); - RefPtr asyncDispatcher = - new AsyncEventDispatcher(this, event); - asyncDispatcher->PostDOMEvent(); -} - -void -MediaKeySession::DispatchKeyStatusesChange() -{ - if (IsClosed()) { - return; - } - - UpdateKeyStatusMap(); - - RefPtr asyncDispatcher = - new AsyncEventDispatcher(this, NS_LITERAL_STRING("keystatuseschange"), false); - asyncDispatcher->PostDOMEvent(); -} - -uint32_t -MediaKeySession::Token() const -{ - return mToken; -} - -already_AddRefed -MediaKeySession::MakePromise(ErrorResult& aRv, const nsACString& aName) -{ - nsCOMPtr global = do_QueryInterface(GetParentObject()); - if (!global) { - NS_WARNING("Passed non-global to MediaKeys ctor!"); - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - return DetailedPromise::Create(global, aRv, aName); -} - -void -MediaKeySession::SetExpiration(double aExpiration) -{ - EME_LOG("MediaKeySession[%p,'%s'] SetExpiry(%lf)", - this, - NS_ConvertUTF16toUTF8(mSessionId).get(), - aExpiration); - mExpiration = aExpiration; -} - -EventHandlerNonNull* -MediaKeySession::GetOnkeystatuseschange() -{ - return GetEventHandler(nsGkAtoms::onkeystatuseschange, EmptyString()); -} - -void -MediaKeySession::SetOnkeystatuseschange(EventHandlerNonNull* aCallback) -{ - SetEventHandler(nsGkAtoms::onkeystatuseschange, EmptyString(), aCallback); -} - -EventHandlerNonNull* -MediaKeySession::GetOnmessage() -{ - return GetEventHandler(nsGkAtoms::onmessage, EmptyString()); -} - -void -MediaKeySession::SetOnmessage(EventHandlerNonNull* aCallback) -{ - SetEventHandler(nsGkAtoms::onmessage, EmptyString(), aCallback); -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeySession.h b/dom/media/eme/MediaKeySession.h deleted file mode 100644 index 6b71370469..0000000000 --- a/dom/media/eme/MediaKeySession.h +++ /dev/null @@ -1,136 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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_MediaKeySession_h -#define mozilla_dom_MediaKeySession_h - -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "nsCycleCollectionParticipant.h" -#include "mozilla/DOMEventTargetHelper.h" -#include "nsCOMPtr.h" -#include "mozilla/dom/TypedArray.h" -#include "mozilla/Mutex.h" -#include "mozilla/dom/Date.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/DetailedPromise.h" -#include "mozilla/dom/MediaKeySessionBinding.h" -#include "mozilla/dom/MediaKeysBinding.h" -#include "mozilla/dom/MediaKeyMessageEventBinding.h" - -struct JSContext; - -namespace mozilla { -namespace dom { - -class ArrayBufferViewOrArrayBuffer; -class MediaKeyError; -class MediaKeyStatusMap; - -class MediaKeySession final : public DOMEventTargetHelper -{ -public: - NS_DECL_ISUPPORTS_INHERITED - NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(MediaKeySession, - DOMEventTargetHelper) -public: - MediaKeySession(JSContext* aCx, - nsPIDOMWindowInner* aParent, - MediaKeys* aKeys, - const nsAString& aKeySystem, - MediaKeySessionType aSessionType, - ErrorResult& aRv); - - void SetSessionId(const nsAString& aSessionId); - - JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - // Mark this as resultNotAddRefed to return raw pointers - MediaKeyError* GetError() const; - - MediaKeyStatusMap* KeyStatuses() const; - - void GetKeySystem(nsString& aRetval) const; - - void GetSessionId(nsString& aRetval) const; - - const nsString& GetSessionId() const; - - // Number of ms since epoch at which expiration occurs, or NaN if unknown. - // TODO: The type of this attribute is still under contention. - // https://www.w3.org/Bugs/Public/show_bug.cgi?id=25902 - double Expiration() const; - - Promise* Closed() const; - - already_AddRefed GenerateRequest(const nsAString& aInitDataType, - const ArrayBufferViewOrArrayBuffer& aInitData, - ErrorResult& aRv); - - already_AddRefed Load(const nsAString& aSessionId, - ErrorResult& aRv); - - already_AddRefed Update(const ArrayBufferViewOrArrayBuffer& response, - ErrorResult& aRv); - - already_AddRefed Close(ErrorResult& aRv); - - already_AddRefed Remove(ErrorResult& aRv); - - void DispatchKeyMessage(MediaKeyMessageType aMessageType, - const nsTArray& aMessage); - - void DispatchKeyError(uint32_t system_code); - - void DispatchKeyStatusesChange(); - - void OnClosed(); - - bool IsClosed() const; - - void SetExpiration(double aExpiry); - - mozilla::dom::EventHandlerNonNull* GetOnkeystatuseschange(); - void SetOnkeystatuseschange(mozilla::dom::EventHandlerNonNull* aCallback); - - mozilla::dom::EventHandlerNonNull* GetOnmessage(); - void SetOnmessage(mozilla::dom::EventHandlerNonNull* aCallback); - - // Process-unique identifier. - uint32_t Token() const; - -private: - ~MediaKeySession(); - - void UpdateKeyStatusMap(); - - bool IsCallable() const { - // The EME spec sets the "callable value" to true whenever the CDM sets - // the sessionId. When the session is initialized, sessionId is empty and - // callable is thus false. - return !mSessionId.IsEmpty(); - } - - already_AddRefed MakePromise(ErrorResult& aRv, - const nsACString& aName); - - RefPtr mClosed; - - RefPtr mMediaKeyError; - RefPtr mKeys; - const nsString mKeySystem; - nsString mSessionId; - const MediaKeySessionType mSessionType; - const uint32_t mToken; - bool mIsClosed; - bool mUninitialized; - RefPtr mKeyStatusMap; - double mExpiration; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/media/eme/MediaKeyStatusMap.cpp b/dom/media/eme/MediaKeyStatusMap.cpp deleted file mode 100644 index 677fd0db2e..0000000000 --- a/dom/media/eme/MediaKeyStatusMap.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "mozilla/dom/MediaKeyStatusMap.h" -#include "nsPIDOMWindow.h" -#include "mozilla/dom/UnionTypes.h" -#include "mozilla/dom/ToJSValue.h" -#include "mozilla/EMEUtils.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeyStatusMap) -NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeyStatusMap) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeyStatusMap) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeyStatusMap, mParent) - -MediaKeyStatusMap::MediaKeyStatusMap(nsPIDOMWindowInner* aParent) - : mParent(aParent) -{ -} - -MediaKeyStatusMap::~MediaKeyStatusMap() -{ -} - -JSObject* -MediaKeyStatusMap::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return MediaKeyStatusMapBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -MediaKeyStatusMap::GetParentObject() const -{ - return mParent; -} - -void -MediaKeyStatusMap::Get(JSContext* aCx, - const ArrayBufferViewOrArrayBuffer& aKey, - JS::MutableHandle aOutValue, - ErrorResult& aOutRv) const -{ - ArrayData keyId = GetArrayBufferViewOrArrayBufferData(aKey); - if (!keyId.IsValid()) { - aOutValue.setUndefined(); - return; - } - for (const KeyStatus& status : mStatuses) { - if (keyId == status.mKeyId) { - bool ok = ToJSValue(aCx, status.mStatus, aOutValue); - if (!ok) { - aOutRv.NoteJSContextException(aCx); - } - return; - } - } - aOutValue.setUndefined(); -} - -bool -MediaKeyStatusMap::Has(const ArrayBufferViewOrArrayBuffer& aKey) const -{ - ArrayData keyId = GetArrayBufferViewOrArrayBufferData(aKey); - if (!keyId.IsValid()) { - return false; - } - - for (const KeyStatus& status : mStatuses) { - if (keyId == status.mKeyId) { - return true; - } - } - - return false; -} - -uint32_t -MediaKeyStatusMap::GetIterableLength() const -{ - return mStatuses.Length(); -} - -TypedArrayCreator -MediaKeyStatusMap::GetKeyAtIndex(uint32_t aIndex) const -{ - MOZ_ASSERT(aIndex < GetIterableLength()); - return TypedArrayCreator(mStatuses[aIndex].mKeyId); -} - -MediaKeyStatus -MediaKeyStatusMap::GetValueAtIndex(uint32_t aIndex) const -{ - MOZ_ASSERT(aIndex < GetIterableLength()); - return mStatuses[aIndex].mStatus; -} - -uint32_t -MediaKeyStatusMap::Size() const -{ - return mStatuses.Length(); -} - -void -MediaKeyStatusMap::Update(const nsTArray& aKeys) -{ - mStatuses.Clear(); - for (const auto& key : aKeys) { - mStatuses.InsertElementSorted(KeyStatus(key.mId, key.mStatus)); - } -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeyStatusMap.h b/dom/media/eme/MediaKeyStatusMap.h deleted file mode 100644 index 8bfbd4d07c..0000000000 --- a/dom/media/eme/MediaKeyStatusMap.h +++ /dev/null @@ -1,96 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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_MediaKeyStatuses_h -#define mozilla_dom_MediaKeyStatuses_h - -#include "mozilla/ErrorResult.h" -#include "mozilla/Attributes.h" -#include "nsCycleCollectionParticipant.h" -#include "nsWrapperCache.h" - -#include "mozilla/dom/TypedArray.h" -#include "mozilla/dom/MediaKeyStatusMapBinding.h" -#include "mozilla/CDMCaps.h" - -class nsPIDOMWindowInner; - -namespace mozilla { -namespace dom { - -class ArrayBufferViewOrArrayBuffer; - -// The MediaKeyStatusMap WebIDL interface; maps a keyId to its status. -// Note that the underlying "map" is stored in an array, since we assume -// that a MediaKeySession won't have many key statuses to report. -class MediaKeyStatusMap final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeyStatusMap) - -public: - explicit MediaKeyStatusMap(nsPIDOMWindowInner* aParent); - -protected: - ~MediaKeyStatusMap(); - -public: - nsPIDOMWindowInner* GetParentObject() const; - - JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - void Get(JSContext* aCx, - const ArrayBufferViewOrArrayBuffer& aKey, - JS::MutableHandle aOutValue, - ErrorResult& aOutRv) const; - bool Has(const ArrayBufferViewOrArrayBuffer& aKey) const; - uint32_t Size() const; - - uint32_t GetIterableLength() const; - TypedArrayCreator GetKeyAtIndex(uint32_t aIndex) const; - MediaKeyStatus GetValueAtIndex(uint32_t aIndex) const; - - void Update(const nsTArray& keys); - -private: - - nsCOMPtr mParent; - - struct KeyStatus { - KeyStatus(const nsTArray& aKeyId, - MediaKeyStatus aStatus) - : mKeyId(aKeyId) - , mStatus(aStatus) - { - } - bool operator== (const KeyStatus& aOther) const { - return aOther.mKeyId == mKeyId; - } - bool operator<(const KeyStatus& aOther) const { - // Copy chromium and compare keys' bytes. - // Update once https://github.com/w3c/encrypted-media/issues/69 - // is resolved. - const nsTArray& other = aOther.mKeyId; - const nsTArray& self = mKeyId; - size_t length = std::min(other.Length(), self.Length()); - int cmp = memcmp(self.Elements(), other.Elements(), length); - if (cmp != 0) { - return cmp < 0; - } - return self.Length() <= other.Length(); - } - nsTArray mKeyId; - MediaKeyStatus mStatus; - }; - - nsTArray mStatuses; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/media/eme/MediaKeySystemAccess.cpp b/dom/media/eme/MediaKeySystemAccess.cpp deleted file mode 100644 index 3c594f9191..0000000000 --- a/dom/media/eme/MediaKeySystemAccess.cpp +++ /dev/null @@ -1,1041 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "mozilla/dom/MediaKeySystemAccess.h" -#include "mozilla/dom/MediaKeySystemAccessBinding.h" -#include "mozilla/Preferences.h" -#include "MediaPrefs.h" -#include "nsContentTypeParser.h" -#ifdef MOZ_FMP4 -#include "MP4Decoder.h" -#endif -#ifdef XP_WIN -#include "mozilla/WindowsVersion.h" -#include "WMFDecoderModule.h" -#endif -#include "nsContentCID.h" -#include "nsServiceManagerUtils.h" -#include "mozIGeckoMediaPluginService.h" -#include "VideoUtils.h" -#include "mozilla/Services.h" -#include "nsIObserverService.h" -#include "mozilla/EMEUtils.h" -#include "GMPUtils.h" -#include "nsAppDirectoryServiceDefs.h" -#include "nsDirectoryServiceUtils.h" -#include "nsDirectoryServiceDefs.h" -#include "nsXULAppAPI.h" -#include "gmp-audio-decode.h" -#include "gmp-video-decode.h" -#include "DecoderDoctorDiagnostics.h" -#include "WebMDecoder.h" -#include "mozilla/StaticPtr.h" -#include "mozilla/ClearOnShutdown.h" -#include "nsUnicharUtils.h" -#include "mozilla/dom/MediaSource.h" -#include "DecoderTraits.h" - -namespace mozilla { -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeySystemAccess, - mParent) -NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeySystemAccess) -NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeySystemAccess) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeySystemAccess) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -MediaKeySystemAccess::MediaKeySystemAccess(nsPIDOMWindowInner* aParent, - const nsAString& aKeySystem, - const MediaKeySystemConfiguration& aConfig) - : mParent(aParent) - , mKeySystem(aKeySystem) - , mConfig(aConfig) -{ -} - -MediaKeySystemAccess::~MediaKeySystemAccess() -{ -} - -JSObject* -MediaKeySystemAccess::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return MediaKeySystemAccessBinding::Wrap(aCx, this, aGivenProto); -} - -nsPIDOMWindowInner* -MediaKeySystemAccess::GetParentObject() const -{ - return mParent; -} - -void -MediaKeySystemAccess::GetKeySystem(nsString& aOutKeySystem) const -{ - aOutKeySystem.Assign(mKeySystem); -} - -void -MediaKeySystemAccess::GetConfiguration(MediaKeySystemConfiguration& aConfig) -{ - aConfig = mConfig; -} - -already_AddRefed -MediaKeySystemAccess::CreateMediaKeys(ErrorResult& aRv) -{ - RefPtr keys(new MediaKeys(mParent, - mKeySystem, - mConfig)); - return keys->Init(aRv); -} - -static bool -HavePluginForKeySystem(const nsCString& aKeySystem) -{ - bool havePlugin = HaveGMPFor(NS_LITERAL_CSTRING(GMP_API_DECRYPTOR), - { aKeySystem }); - return havePlugin; -} - -static MediaKeySystemStatus -EnsureCDMInstalled(const nsAString& aKeySystem, - nsACString& aOutMessage) -{ - if (!HavePluginForKeySystem(NS_ConvertUTF16toUTF8(aKeySystem))) { - aOutMessage = NS_LITERAL_CSTRING("CDM is not installed"); - return MediaKeySystemStatus::Cdm_not_installed; - } - - return MediaKeySystemStatus::Available; -} - -/* static */ -MediaKeySystemStatus -MediaKeySystemAccess::GetKeySystemStatus(const nsAString& aKeySystem, - nsACString& aOutMessage) -{ - MOZ_ASSERT(MediaPrefs::EMEEnabled() || IsClearkeyKeySystem(aKeySystem)); - - if (IsClearkeyKeySystem(aKeySystem)) { - return EnsureCDMInstalled(aKeySystem, aOutMessage); - } - - if (IsWidevineKeySystem(aKeySystem)) { - if (Preferences::GetBool("media.gmp-widevinecdm.visible", false)) { - if (!Preferences::GetBool("media.gmp-widevinecdm.enabled", false)) { - aOutMessage = NS_LITERAL_CSTRING("Widevine EME disabled"); - return MediaKeySystemStatus::Cdm_disabled; - } - return EnsureCDMInstalled(aKeySystem, aOutMessage); - } - } - - return MediaKeySystemStatus::Cdm_not_supported; -} - -typedef nsCString EMECodecString; - -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_AAC, "aac"); -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_OPUS, "opus"); -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_VORBIS, "vorbis"); -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_H264, "h264"); -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_VP8, "vp8"); -static NS_NAMED_LITERAL_CSTRING(EME_CODEC_VP9, "vp9"); - -EMECodecString -ToEMEAPICodecString(const nsString& aCodec) -{ - if (IsAACCodecString(aCodec)) { - return EME_CODEC_AAC; - } - if (aCodec.EqualsLiteral("opus")) { - return EME_CODEC_OPUS; - } - if (aCodec.EqualsLiteral("vorbis")) { - return EME_CODEC_VORBIS; - } - if (IsH264CodecString(aCodec)) { - return EME_CODEC_H264; - } - if (IsVP8CodecString(aCodec)) { - return EME_CODEC_VP8; - } - if (IsVP9CodecString(aCodec)) { - return EME_CODEC_VP9; - } - return EmptyCString(); -} - -// A codec can be decrypted-and-decoded by the CDM, or only decrypted -// by the CDM and decoded by Gecko. Not both. -struct KeySystemContainerSupport -{ - bool IsSupported() const - { - return !mCodecsDecoded.IsEmpty() || !mCodecsDecrypted.IsEmpty(); - } - - // CDM decrypts and decodes using a DRM robust decoder, and passes decoded - // samples back to Gecko for rendering. - bool DecryptsAndDecodes(EMECodecString aCodec) const - { - return mCodecsDecoded.Contains(aCodec); - } - - // CDM decrypts and passes the decrypted samples back to Gecko for decoding. - bool Decrypts(EMECodecString aCodec) const - { - return mCodecsDecrypted.Contains(aCodec); - } - - void SetCanDecryptAndDecode(EMECodecString aCodec) - { - // Can't both decrypt and decrypt-and-decode a codec. - MOZ_ASSERT(!Decrypts(aCodec)); - // Prevent duplicates. - MOZ_ASSERT(!DecryptsAndDecodes(aCodec)); - mCodecsDecoded.AppendElement(aCodec); - } - - void SetCanDecrypt(EMECodecString aCodec) - { - // Prevent duplicates. - MOZ_ASSERT(!Decrypts(aCodec)); - // Can't both decrypt and decrypt-and-decode a codec. - MOZ_ASSERT(!DecryptsAndDecodes(aCodec)); - mCodecsDecrypted.AppendElement(aCodec); - } - -private: - nsTArray mCodecsDecoded; - nsTArray mCodecsDecrypted; -}; - -enum class KeySystemFeatureSupport -{ - Prohibited = 1, - Requestable = 2, - Required = 3, -}; - -struct KeySystemConfig -{ - nsString mKeySystem; - nsTArray mInitDataTypes; - KeySystemFeatureSupport mPersistentState = KeySystemFeatureSupport::Prohibited; - KeySystemFeatureSupport mDistinctiveIdentifier = KeySystemFeatureSupport::Prohibited; - nsTArray mSessionTypes; - nsTArray mVideoRobustness; - nsTArray mAudioRobustness; - KeySystemContainerSupport mMP4; - KeySystemContainerSupport mWebM; -}; - -static nsTArray -GetSupportedKeySystems() -{ - nsTArray keySystemConfigs; - - { - if (HavePluginForKeySystem(kEMEKeySystemClearkey)) { - KeySystemConfig clearkey; - clearkey.mKeySystem = NS_ConvertUTF8toUTF16(kEMEKeySystemClearkey); - clearkey.mInitDataTypes.AppendElement(NS_LITERAL_STRING("cenc")); - clearkey.mInitDataTypes.AppendElement(NS_LITERAL_STRING("keyids")); - clearkey.mInitDataTypes.AppendElement(NS_LITERAL_STRING("webm")); - clearkey.mPersistentState = KeySystemFeatureSupport::Requestable; - clearkey.mDistinctiveIdentifier = KeySystemFeatureSupport::Prohibited; - clearkey.mSessionTypes.AppendElement(MediaKeySessionType::Temporary); - if (MediaPrefs::ClearKeyPersistentLicenseEnabled()) { - clearkey.mSessionTypes.AppendElement(MediaKeySessionType::Persistent_license); - } -#if defined(XP_WIN) - // Clearkey CDM uses WMF decoders on Windows. - if (WMFDecoderModule::HasAAC()) { - clearkey.mMP4.SetCanDecryptAndDecode(EME_CODEC_AAC); - } else { - clearkey.mMP4.SetCanDecrypt(EME_CODEC_AAC); - } - if (WMFDecoderModule::HasH264()) { - clearkey.mMP4.SetCanDecryptAndDecode(EME_CODEC_H264); - } else { - clearkey.mMP4.SetCanDecrypt(EME_CODEC_H264); - } -#else - clearkey.mMP4.SetCanDecrypt(EME_CODEC_AAC); - clearkey.mMP4.SetCanDecrypt(EME_CODEC_H264); -#endif - clearkey.mWebM.SetCanDecrypt(EME_CODEC_VORBIS); - clearkey.mWebM.SetCanDecrypt(EME_CODEC_OPUS); - clearkey.mWebM.SetCanDecrypt(EME_CODEC_VP8); - clearkey.mWebM.SetCanDecrypt(EME_CODEC_VP9); - keySystemConfigs.AppendElement(Move(clearkey)); - } - } - { - if (HavePluginForKeySystem(kEMEKeySystemWidevine)) { - KeySystemConfig widevine; - widevine.mKeySystem = NS_ConvertUTF8toUTF16(kEMEKeySystemWidevine); - widevine.mInitDataTypes.AppendElement(NS_LITERAL_STRING("cenc")); - widevine.mInitDataTypes.AppendElement(NS_LITERAL_STRING("keyids")); - widevine.mInitDataTypes.AppendElement(NS_LITERAL_STRING("webm")); - widevine.mPersistentState = KeySystemFeatureSupport::Requestable; - widevine.mDistinctiveIdentifier = KeySystemFeatureSupport::Prohibited; - widevine.mSessionTypes.AppendElement(MediaKeySessionType::Temporary); - widevine.mAudioRobustness.AppendElement(NS_LITERAL_STRING("SW_SECURE_CRYPTO")); - widevine.mVideoRobustness.AppendElement(NS_LITERAL_STRING("SW_SECURE_DECODE")); -#if defined(XP_WIN) - // Widevine CDM doesn't include an AAC decoder. So if WMF can't - // decode AAC, and a codec wasn't specified, be conservative - // and reject the MediaKeys request, since our policy is to prevent - // the Adobe GMP's unencrypted AAC decoding path being used to - // decode content decrypted by the Widevine CDM. - if (WMFDecoderModule::HasAAC()) { - widevine.mMP4.SetCanDecrypt(EME_CODEC_AAC); - } -#endif - - widevine.mMP4.SetCanDecryptAndDecode(EME_CODEC_H264); - widevine.mWebM.SetCanDecrypt(EME_CODEC_VORBIS); - widevine.mWebM.SetCanDecrypt(EME_CODEC_OPUS); - widevine.mWebM.SetCanDecryptAndDecode(EME_CODEC_VP8); - widevine.mWebM.SetCanDecryptAndDecode(EME_CODEC_VP9); - keySystemConfigs.AppendElement(Move(widevine)); - } - } - - return keySystemConfigs; -} - -static bool -GetKeySystemConfig(const nsAString& aKeySystem, KeySystemConfig& aOutKeySystemConfig) -{ - for (auto&& config : GetSupportedKeySystems()) { - if (config.mKeySystem.Equals(aKeySystem)) { - aOutKeySystemConfig = mozilla::Move(config); - return true; - } - } - // No matching key system found. - return false; -} - -/* static */ -bool -MediaKeySystemAccess::KeySystemSupportsInitDataType(const nsAString& aKeySystem, - const nsAString& aInitDataType) -{ - KeySystemConfig implementation; - return GetKeySystemConfig(aKeySystem, implementation) && - implementation.mInitDataTypes.Contains(aInitDataType); -} - -enum CodecType -{ - Audio, - Video, - Invalid -}; - -static bool -CanDecryptAndDecode(const nsString& aKeySystem, - const nsString& aContentType, - CodecType aCodecType, - const KeySystemContainerSupport& aContainerSupport, - const nsTArray& aCodecs, - DecoderDoctorDiagnostics* aDiagnostics) -{ - MOZ_ASSERT(aCodecType != Invalid); - for (const EMECodecString& codec : aCodecs) { - MOZ_ASSERT(!codec.IsEmpty()); - - if (aContainerSupport.DecryptsAndDecodes(codec)) { - // GMP can decrypt-and-decode this codec. - continue; - } - - if (aContainerSupport.Decrypts(codec) && - NS_SUCCEEDED(MediaSource::IsTypeSupported(aContentType, aDiagnostics))) { - // GMP can decrypt and is allowed to return compressed samples to - // Gecko to decode, and Gecko has a decoder. - continue; - } - - // Neither the GMP nor Gecko can both decrypt and decode. We don't - // support this codec. - -#if defined(XP_WIN) - // Widevine CDM doesn't include an AAC decoder. So if WMF can't - // decode AAC, and a codec wasn't specified, be conservative - // and reject the MediaKeys request, since our policy is to prevent - // the Adobe GMP's unencrypted AAC decoding path being used to - // decode content decrypted by the Widevine CDM. - if (codec == EME_CODEC_AAC && - IsWidevineKeySystem(aKeySystem) && - !WMFDecoderModule::HasAAC()) { - if (aDiagnostics) { - aDiagnostics->SetKeySystemIssue( - DecoderDoctorDiagnostics::eWidevineWithNoWMF); - } - } -#endif - return false; - } - return true; -} - -static bool -ToSessionType(const nsAString& aSessionType, MediaKeySessionType& aOutType) -{ - using MediaKeySessionTypeValues::strings; - const char* temporary = - strings[static_cast(MediaKeySessionType::Temporary)].value; - if (aSessionType.EqualsASCII(temporary)) { - aOutType = MediaKeySessionType::Temporary; - return true; - } - const char* persistentLicense = - strings[static_cast(MediaKeySessionType::Persistent_license)].value; - if (aSessionType.EqualsASCII(persistentLicense)) { - aOutType = MediaKeySessionType::Persistent_license; - return true; - } - return false; -} - -// 5.2.1 Is persistent session type? -static bool -IsPersistentSessionType(MediaKeySessionType aSessionType) -{ - return aSessionType == MediaKeySessionType::Persistent_license; -} - -CodecType -GetMajorType(const nsAString& aContentType) -{ - if (CaseInsensitiveFindInReadable(NS_LITERAL_STRING("audio/"), aContentType)) { - return Audio; - } - if (CaseInsensitiveFindInReadable(NS_LITERAL_STRING("video/"), aContentType)) { - return Video; - } - return Invalid; -} - -static CodecType -GetCodecType(const EMECodecString& aCodec) -{ - if (aCodec.Equals(EME_CODEC_AAC) || - aCodec.Equals(EME_CODEC_OPUS) || - aCodec.Equals(EME_CODEC_VORBIS)) { - return Audio; - } - if (aCodec.Equals(EME_CODEC_H264) || - aCodec.Equals(EME_CODEC_VP8) || - aCodec.Equals(EME_CODEC_VP9)) { - return Video; - } - return Invalid; -} - -static bool -AllCodecsOfType(const nsTArray& aCodecs, const CodecType aCodecType) -{ - for (const EMECodecString& codec : aCodecs) { - if (GetCodecType(codec) != aCodecType) { - return false; - } - } - return true; -} - -static bool -IsParameterUnrecognized(const nsAString& aContentType) -{ - nsAutoString contentType(aContentType); - contentType.StripWhitespace(); - - nsTArray params; - nsAString::const_iterator start, end, semicolon, equalSign; - contentType.BeginReading(start); - contentType.EndReading(end); - semicolon = start; - // Find any substring between ';' & '='. - while (semicolon != end) { - if (FindCharInReadable(';', semicolon, end)) { - equalSign = ++semicolon; - if (FindCharInReadable('=', equalSign, end)) { - params.AppendElement(Substring(semicolon, equalSign)); - semicolon = equalSign; - } - } - } - - for (auto param : params) { - if (!param.LowerCaseEqualsLiteral("codecs") && - !param.LowerCaseEqualsLiteral("profiles")) { - return true; - } - } - return false; -} - -// 3.1.2.3 Get Supported Capabilities for Audio/Video Type -static Sequence -GetSupportedCapabilities(const CodecType aCodecType, - const nsTArray& aRequestedCapabilities, - const MediaKeySystemConfiguration& aPartialConfig, - const KeySystemConfig& aKeySystem, - DecoderDoctorDiagnostics* aDiagnostics) -{ - // Let local accumulated configuration be a local copy of partial configuration. - // (Note: It's not necessary for us to maintain a local copy, as we don't need - // to test whether capabilites from previous calls to this algorithm work with - // the capabilities currently being considered in this call. ) - - // Let supported media capabilities be an empty sequence of - // MediaKeySystemMediaCapability dictionaries. - Sequence supportedCapabilities; - - // For each requested media capability in requested media capabilities: - for (const MediaKeySystemMediaCapability& capabilities : aRequestedCapabilities) { - // Let content type be requested media capability's contentType member. - const nsString& contentType = capabilities.mContentType; - // Let robustness be requested media capability's robustness member. - const nsString& robustness = capabilities.mRobustness; - // If content type is the empty string, return null. - if (contentType.IsEmpty()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') rejected; " - "audio or video capability has empty contentType.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - return Sequence(); - } - // If content type is an invalid or unrecognized MIME type, continue - // to the next iteration. - nsAutoString container; - nsTArray codecStrings; - if (!ParseMIMETypeString(contentType, container, codecStrings)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "failed to parse contentType as MIME type.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - bool invalid = false; - nsTArray codecs; - for (const nsString& codecString : codecStrings) { - EMECodecString emeCodec = ToEMEAPICodecString(codecString); - if (emeCodec.IsEmpty()) { - invalid = true; - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "'%s' is an invalid codec string.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get(), - NS_ConvertUTF16toUTF8(codecString).get()); - break; - } - codecs.AppendElement(emeCodec); - } - if (invalid) { - continue; - } - - // If the user agent does not support container, continue to the next iteration. - // The case-sensitivity of string comparisons is determined by the appropriate RFC. - // (Note: Per RFC 6838 [RFC6838], "Both top-level type and subtype names are - // case-insensitive."'. We're using nsContentTypeParser and that is - // case-insensitive and converts all its parameter outputs to lower case.) - NS_ConvertUTF16toUTF8 container_utf8(container); - const bool isMP4 = DecoderTraits::IsMP4TypeAndEnabled(container_utf8, aDiagnostics); - if (isMP4 && !aKeySystem.mMP4.IsSupported()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "MP4 requested but unsupported.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - const bool isWebM = DecoderTraits::IsWebMTypeAndEnabled(container_utf8); - if (isWebM && !aKeySystem.mWebM.IsSupported()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "WebM requested but unsupported.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - if (!isMP4 && !isWebM) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "Unsupported or unrecognized container requested.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - - // Let parameters be the RFC 6381[RFC6381] parameters, if any, specified by - // content type. - // If the user agent does not recognize one or more parameters, continue to - // the next iteration. - if (IsParameterUnrecognized(contentType)) { - continue; - } - - // Let media types be the set of codecs and codec constraints specified by - // parameters. The case-sensitivity of string comparisons is determined by - // the appropriate RFC or other specification. - // (Note: codecs array is 'parameter'). - - // If media types is empty: - if (codecs.IsEmpty()) { - // If container normatively implies a specific set of codecs and codec constraints: - // Let parameters be that set. - if (isMP4) { - if (aCodecType == Audio) { - codecs.AppendElement(EME_CODEC_AAC); - } else if (aCodecType == Video) { - codecs.AppendElement(EME_CODEC_H264); - } - } else if (isWebM) { - if (aCodecType == Audio) { - codecs.AppendElement(EME_CODEC_VORBIS); - } else if (aCodecType == Video) { - codecs.AppendElement(EME_CODEC_VP8); - } - } - // Otherwise: Continue to the next iteration. - // (Note: all containers we support have implied codecs, so don't continue here.) - } - - // If content type is not strictly a audio/video type, continue to the next iteration. - const auto majorType = GetMajorType(container); - if (majorType == Invalid) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "MIME type is not an audio or video MIME type.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - if (majorType != aCodecType || !AllCodecsOfType(codecs, aCodecType)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "MIME type mixes audio codecs in video capabilities " - "or video codecs in audio capabilities.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - // If robustness is not the empty string and contains an unrecognized - // value or a value not supported by implementation, continue to the - // next iteration. String comparison is case-sensitive. - if (!robustness.IsEmpty()) { - if (majorType == Audio && !aKeySystem.mAudioRobustness.Contains(robustness)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "unsupported robustness string.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - if (majorType == Video && !aKeySystem.mVideoRobustness.Contains(robustness)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "unsupported robustness string.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - // Note: specified robustness requirements are satisfied. - } - - // If the user agent and implementation definitely support playback of - // encrypted media data for the combination of container, media types, - // robustness and local accumulated configuration in combination with - // restrictions... - const auto& containerSupport = isMP4 ? aKeySystem.mMP4 : aKeySystem.mWebM; - if (!CanDecryptAndDecode(aKeySystem.mKeySystem, - contentType, - majorType, - containerSupport, - codecs, - aDiagnostics)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') " - "MediaKeySystemMediaCapability('%s','%s') unsupported; " - "codec unsupported by CDM requested.", - NS_ConvertUTF16toUTF8(aPartialConfig.mLabel).get(), - NS_ConvertUTF16toUTF8(contentType).get(), - NS_ConvertUTF16toUTF8(robustness).get()); - continue; - } - - // ... add requested media capability to supported media capabilities. - if (!supportedCapabilities.AppendElement(capabilities, mozilla::fallible)) { - NS_WARNING("GetSupportedCapabilities: Malloc failure"); - return Sequence(); - } - - // Note: omitting steps 3.13.2, our robustness is not sophisticated enough - // to require considering all requirements together. - } - return Move(supportedCapabilities); -} - -// "Get Supported Configuration and Consent" algorithm, steps 4-7 for -// distinctive identifier, and steps 8-11 for persistent state. The steps -// are the same for both requirements/features, so we factor them out into -// a single function. -static bool -CheckRequirement(const MediaKeysRequirement aRequirement, - const KeySystemFeatureSupport aFeatureSupport, - MediaKeysRequirement& aOutRequirement) -{ - // Let requirement be the value of candidate configuration's member. - MediaKeysRequirement requirement = aRequirement; - // If requirement is "optional" and feature is not allowed according to - // restrictions, set requirement to "not-allowed". - if (aRequirement == MediaKeysRequirement::Optional && - aFeatureSupport == KeySystemFeatureSupport::Prohibited) { - requirement = MediaKeysRequirement::Not_allowed; - } - - // Follow the steps for requirement from the following list: - switch (requirement) { - case MediaKeysRequirement::Required: { - // If the implementation does not support use of requirement in combination - // with accumulated configuration and restrictions, return NotSupported. - if (aFeatureSupport == KeySystemFeatureSupport::Prohibited) { - return false; - } - break; - } - case MediaKeysRequirement::Optional: { - // Continue with the following steps. - break; - } - case MediaKeysRequirement::Not_allowed: { - // If the implementation requires use of feature in combination with - // accumulated configuration and restrictions, return NotSupported. - if (aFeatureSupport == KeySystemFeatureSupport::Required) { - return false; - } - break; - } - default: { - return false; - } - } - - // Set the requirement member of accumulated configuration to equal - // calculated requirement. - aOutRequirement = requirement; - - return true; -} - -// 3.1.2.2, step 12 -// Follow the steps for the first matching condition from the following list: -// If the sessionTypes member is present in candidate configuration. -// Let session types be candidate configuration's sessionTypes member. -// Otherwise let session types be ["temporary"]. -// Note: This returns an empty array on malloc failure. -static Sequence -UnboxSessionTypes(const Optional>& aSessionTypes) -{ - Sequence sessionTypes; - if (aSessionTypes.WasPassed()) { - sessionTypes = aSessionTypes.Value(); - } else { - using MediaKeySessionTypeValues::strings; - const char* temporary = strings[static_cast(MediaKeySessionType::Temporary)].value; - // Note: fallible. Results in an empty array. - sessionTypes.AppendElement(NS_ConvertUTF8toUTF16(nsDependentCString(temporary)), mozilla::fallible); - } - return sessionTypes; -} - -// 3.1.2.2 Get Supported Configuration and Consent -static bool -GetSupportedConfig(const KeySystemConfig& aKeySystem, - const MediaKeySystemConfiguration& aCandidate, - MediaKeySystemConfiguration& aOutConfig, - DecoderDoctorDiagnostics* aDiagnostics) -{ - // Let accumulated configuration be a new MediaKeySystemConfiguration dictionary. - MediaKeySystemConfiguration config; - // Set the label member of accumulated configuration to equal the label member of - // candidate configuration. - config.mLabel = aCandidate.mLabel; - // If the initDataTypes member of candidate configuration is non-empty, run the - // following steps: - if (!aCandidate.mInitDataTypes.IsEmpty()) { - // Let supported types be an empty sequence of DOMStrings. - nsTArray supportedTypes; - // For each value in candidate configuration's initDataTypes member: - for (const nsString& initDataType : aCandidate.mInitDataTypes) { - // Let initDataType be the value. - // If the implementation supports generating requests based on initDataType, - // add initDataType to supported types. String comparison is case-sensitive. - // The empty string is never supported. - if (aKeySystem.mInitDataTypes.Contains(initDataType)) { - supportedTypes.AppendElement(initDataType); - } - } - // If supported types is empty, return NotSupported. - if (supportedTypes.IsEmpty()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "no supported initDataTypes provided.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - // Set the initDataTypes member of accumulated configuration to supported types. - if (!config.mInitDataTypes.Assign(supportedTypes)) { - return false; - } - } - - if (!CheckRequirement(aCandidate.mDistinctiveIdentifier, - aKeySystem.mDistinctiveIdentifier, - config.mDistinctiveIdentifier)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "distinctiveIdentifier requirement not satisfied.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - - if (!CheckRequirement(aCandidate.mPersistentState, - aKeySystem.mPersistentState, - config.mPersistentState)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "persistentState requirement not satisfied.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - - Sequence sessionTypes(UnboxSessionTypes(aCandidate.mSessionTypes)); - if (sessionTypes.IsEmpty()) { - // Malloc failure. - return false; - } - - // For each value in session types: - for (const auto& sessionTypeString : sessionTypes) { - // Let session type be the value. - MediaKeySessionType sessionType; - if (!ToSessionType(sessionTypeString, sessionType)) { - // (Assume invalid sessionType is unsupported as per steps below). - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "invalid session type specified.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - // If accumulated configuration's persistentState value is "not-allowed" - // and the Is persistent session type? algorithm returns true for session - // type return NotSupported. - if (config.mPersistentState == MediaKeysRequirement::Not_allowed && - IsPersistentSessionType(sessionType)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "persistent session requested but keysystem doesn't" - "support persistent state.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - // If the implementation does not support session type in combination - // with accumulated configuration and restrictions for other reasons, - // return NotSupported. - if (!aKeySystem.mSessionTypes.Contains(sessionType)) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "session type '%s' unsupported by keySystem.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get(), - NS_ConvertUTF16toUTF8(sessionTypeString).get()); - return false; - } - // If accumulated configuration's persistentState value is "optional" - // and the result of running the Is persistent session type? algorithm - // on session type is true, change accumulated configuration's - // persistentState value to "required". - if (config.mPersistentState == MediaKeysRequirement::Optional && - IsPersistentSessionType(sessionType)) { - config.mPersistentState = MediaKeysRequirement::Required; - } - } - // Set the sessionTypes member of accumulated configuration to session types. - config.mSessionTypes.Construct(Move(sessionTypes)); - - // If the videoCapabilities and audioCapabilities members in candidate - // configuration are both empty, return NotSupported. - // TODO: Most sites using EME still don't pass capabilities, so we - // can't reject on it yet without breaking them. So add this later. - - // If the videoCapabilities member in candidate configuration is non-empty: - if (!aCandidate.mVideoCapabilities.IsEmpty()) { - // Let video capabilities be the result of executing the Get Supported - // Capabilities for Audio/Video Type algorithm on Video, candidate - // configuration's videoCapabilities member, accumulated configuration, - // and restrictions. - Sequence caps = - GetSupportedCapabilities(Video, - aCandidate.mVideoCapabilities, - config, - aKeySystem, - aDiagnostics); - // If video capabilities is null, return NotSupported. - if (caps.IsEmpty()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "no supported video capabilities.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - // Set the videoCapabilities member of accumulated configuration to video capabilities. - config.mVideoCapabilities = Move(caps); - } else { - // Otherwise: - // Set the videoCapabilities member of accumulated configuration to an empty sequence. - } - - // If the audioCapabilities member in candidate configuration is non-empty: - if (!aCandidate.mAudioCapabilities.IsEmpty()) { - // Let audio capabilities be the result of executing the Get Supported Capabilities - // for Audio/Video Type algorithm on Audio, candidate configuration's audioCapabilities - // member, accumulated configuration, and restrictions. - Sequence caps = - GetSupportedCapabilities(Audio, - aCandidate.mAudioCapabilities, - config, - aKeySystem, - aDiagnostics); - // If audio capabilities is null, return NotSupported. - if (caps.IsEmpty()) { - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "no supported audio capabilities.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } - // Set the audioCapabilities member of accumulated configuration to audio capabilities. - config.mAudioCapabilities = Move(caps); - } else { - // Otherwise: - // Set the audioCapabilities member of accumulated configuration to an empty sequence. - } - - // If accumulated configuration's distinctiveIdentifier value is "optional", follow the - // steps for the first matching condition from the following list: - if (config.mDistinctiveIdentifier == MediaKeysRequirement::Optional) { - // If the implementation requires use Distinctive Identifier(s) or - // Distinctive Permanent Identifier(s) for any of the combinations - // in accumulated configuration - if (aKeySystem.mDistinctiveIdentifier == KeySystemFeatureSupport::Required) { - // Change accumulated configuration's distinctiveIdentifier value to "required". - config.mDistinctiveIdentifier = MediaKeysRequirement::Required; - } else { - // Otherwise, change accumulated configuration's distinctiveIdentifier - // value to "not-allowed". - config.mDistinctiveIdentifier = MediaKeysRequirement::Not_allowed; - } - } - - // If accumulated configuration's persistentState value is "optional", follow the - // steps for the first matching condition from the following list: - if (config.mPersistentState == MediaKeysRequirement::Optional) { - // If the implementation requires persisting state for any of the combinations - // in accumulated configuration - if (aKeySystem.mPersistentState == KeySystemFeatureSupport::Required) { - // Change accumulated configuration's persistentState value to "required". - config.mPersistentState = MediaKeysRequirement::Required; - } else { - // Otherwise, change accumulated configuration's persistentState - // value to "not-allowed". - config.mPersistentState = MediaKeysRequirement::Not_allowed; - } - } - - // Note: Omitting steps 20-22. We don't ask for consent. - -#if defined(XP_WIN) - // Widevine CDM doesn't include an AAC decoder. So if WMF can't decode AAC, - // and a codec wasn't specified, be conservative and reject the MediaKeys request. - if (IsWidevineKeySystem(aKeySystem.mKeySystem) && - (aCandidate.mAudioCapabilities.IsEmpty() || - aCandidate.mVideoCapabilities.IsEmpty()) && - !WMFDecoderModule::HasAAC()) { - if (aDiagnostics) { - aDiagnostics->SetKeySystemIssue( - DecoderDoctorDiagnostics::eWidevineWithNoWMF); - } - EME_LOG("MediaKeySystemConfiguration (label='%s') rejected; " - "WMF required for Widevine decoding, but it's not available.", - NS_ConvertUTF16toUTF8(aCandidate.mLabel).get()); - return false; - } -#endif - - // Return accumulated configuration. - aOutConfig = config; - - return true; -} - -/* static */ -bool -MediaKeySystemAccess::GetSupportedConfig(const nsAString& aKeySystem, - const Sequence& aConfigs, - MediaKeySystemConfiguration& aOutConfig, - DecoderDoctorDiagnostics* aDiagnostics) -{ - KeySystemConfig implementation; - if (!GetKeySystemConfig(aKeySystem, implementation)) { - return false; - } - for (const MediaKeySystemConfiguration& candidate : aConfigs) { - if (mozilla::dom::GetSupportedConfig(implementation, - candidate, - aOutConfig, - aDiagnostics)) { - return true; - } - } - - return false; -} - - -/* static */ -void -MediaKeySystemAccess::NotifyObservers(nsPIDOMWindowInner* aWindow, - const nsAString& aKeySystem, - MediaKeySystemStatus aStatus) -{ - RequestMediaKeySystemAccessNotification data; - data.mKeySystem = aKeySystem; - data.mStatus = aStatus; - nsAutoString json; - data.ToJSON(json); - EME_LOG("MediaKeySystemAccess::NotifyObservers() %s", NS_ConvertUTF16toUTF8(json).get()); - nsCOMPtr obs = services::GetObserverService(); - if (obs) { - obs->NotifyObservers(aWindow, "mediakeys-request", json.get()); - } -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeySystemAccess.h b/dom/media/eme/MediaKeySystemAccess.h deleted file mode 100644 index c260e92b5c..0000000000 --- a/dom/media/eme/MediaKeySystemAccess.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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_MediaKeySystemAccess_h -#define mozilla_dom_MediaKeySystemAccess_h - -#include "mozilla/Attributes.h" -#include "mozilla/ErrorResult.h" -#include "nsCycleCollectionParticipant.h" -#include "nsWrapperCache.h" - -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/MediaKeySystemAccessBinding.h" -#include "mozilla/dom/MediaKeysRequestStatusBinding.h" - -#include "js/TypeDecls.h" - -namespace mozilla { - -class DecoderDoctorDiagnostics; - -namespace dom { - -class MediaKeySystemAccess final : public nsISupports, - public nsWrapperCache -{ -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeySystemAccess) - -public: - explicit MediaKeySystemAccess(nsPIDOMWindowInner* aParent, - const nsAString& aKeySystem, - const MediaKeySystemConfiguration& aConfig); - -protected: - ~MediaKeySystemAccess(); - -public: - nsPIDOMWindowInner* GetParentObject() const; - - JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - void GetKeySystem(nsString& aRetVal) const; - - void GetConfiguration(MediaKeySystemConfiguration& aConfig); - - already_AddRefed CreateMediaKeys(ErrorResult& aRv); - - static MediaKeySystemStatus GetKeySystemStatus(const nsAString& aKeySystem, - nsACString& aOutExceptionMessage); - - static bool IsSupported(const nsAString& aKeySystem, - const Sequence& aConfigs, - DecoderDoctorDiagnostics* aDiagnostics); - - static void NotifyObservers(nsPIDOMWindowInner* aWindow, - const nsAString& aKeySystem, - MediaKeySystemStatus aStatus); - - static bool GetSupportedConfig(const nsAString& aKeySystem, - const Sequence& aConfigs, - MediaKeySystemConfiguration& aOutConfig, - DecoderDoctorDiagnostics* aDiagnostics); - - static bool KeySystemSupportsInitDataType(const nsAString& aKeySystem, - const nsAString& aInitDataType); - -private: - nsCOMPtr mParent; - const nsString mKeySystem; - const MediaKeySystemConfiguration mConfig; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_MediaKeySystemAccess_h diff --git a/dom/media/eme/MediaKeySystemAccessManager.cpp b/dom/media/eme/MediaKeySystemAccessManager.cpp deleted file mode 100644 index ed31059e22..0000000000 --- a/dom/media/eme/MediaKeySystemAccessManager.cpp +++ /dev/null @@ -1,339 +0,0 @@ -/* 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 "MediaKeySystemAccessManager.h" -#include "DecoderDoctorDiagnostics.h" -#include "MediaPrefs.h" -#include "mozilla/EMEUtils.h" -#include "nsServiceManagerUtils.h" -#include "nsComponentManagerUtils.h" -#include "nsIObserverService.h" -#include "mozilla/Services.h" -#include "mozilla/DetailedPromise.h" -#ifdef XP_WIN -#include "mozilla/WindowsVersion.h" -#endif -#ifdef XP_MACOSX -#include "nsCocoaFeatures.h" -#endif -#include "nsPrintfCString.h" - -namespace mozilla { -namespace dom { - -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeySystemAccessManager) - NS_INTERFACE_MAP_ENTRY(nsISupports) - NS_INTERFACE_MAP_ENTRY(nsIObserver) -NS_INTERFACE_MAP_END - -NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeySystemAccessManager) -NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeySystemAccessManager) - -NS_IMPL_CYCLE_COLLECTION_CLASS(MediaKeySystemAccessManager) - -NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(MediaKeySystemAccessManager) - NS_IMPL_CYCLE_COLLECTION_UNLINK(mWindow) - for (size_t i = 0; i < tmp->mRequests.Length(); i++) { - tmp->mRequests[i].RejectPromise(NS_LITERAL_CSTRING("Promise still outstanding at MediaKeySystemAccessManager GC")); - tmp->mRequests[i].CancelTimer(); - NS_IMPL_CYCLE_COLLECTION_UNLINK(mRequests[i].mPromise) - } - tmp->mRequests.Clear(); -NS_IMPL_CYCLE_COLLECTION_UNLINK_END - -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(MediaKeySystemAccessManager) - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mWindow) - for (size_t i = 0; i < tmp->mRequests.Length(); i++) { - NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mRequests[i].mPromise) - } -NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END - -MediaKeySystemAccessManager::MediaKeySystemAccessManager(nsPIDOMWindowInner* aWindow) - : mWindow(aWindow) - , mAddedObservers(false) -{ -} - -MediaKeySystemAccessManager::~MediaKeySystemAccessManager() -{ - Shutdown(); -} - -void -MediaKeySystemAccessManager::Request(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& aConfigs) -{ - Request(aPromise, aKeySystem, aConfigs, RequestType::Initial); -} - -void -MediaKeySystemAccessManager::Request(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& aConfigs, - RequestType aType) -{ - EME_LOG("MediaKeySystemAccessManager::Request %s", NS_ConvertUTF16toUTF8(aKeySystem).get()); - - if (aKeySystem.IsEmpty()) { - aPromise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Key system string is empty")); - // Don't notify DecoderDoctor, as there's nothing we or the user can - // do to fix this situation; the site is using the API wrong. - return; - } - if (aConfigs.IsEmpty()) { - aPromise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Candidate MediaKeySystemConfigs is empty")); - // Don't notify DecoderDoctor, as there's nothing we or the user can - // do to fix this situation; the site is using the API wrong. - return; - } - - DecoderDoctorDiagnostics diagnostics; - - // Ensure keysystem is supported. - if (!IsWidevineKeySystem(aKeySystem) && - !IsClearkeyKeySystem(aKeySystem)) { - // Not to inform user, because nothing to do if the keySystem is not - // supported. - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, - NS_LITERAL_CSTRING("Key system is unsupported")); - diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(), - aKeySystem, false, __func__); - return; - } - - if (!MediaPrefs::EMEEnabled() && !IsClearkeyKeySystem(aKeySystem)) { - // EME disabled by user, send notification to chrome so UI can inform user. - // Clearkey is allowed even when EME is disabled because we want the pref - // "media.eme.enabled" only taking effect on proprietary DRMs. - MediaKeySystemAccess::NotifyObservers(mWindow, - aKeySystem, - MediaKeySystemStatus::Api_disabled); - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, - NS_LITERAL_CSTRING("EME has been preffed off")); - diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(), - aKeySystem, false, __func__); - return; - } - - nsAutoCString message; - MediaKeySystemStatus status = - MediaKeySystemAccess::GetKeySystemStatus(aKeySystem, message); - - nsPrintfCString msg("MediaKeySystemAccess::GetKeySystemStatus(%s) " - "result=%s msg='%s'", - NS_ConvertUTF16toUTF8(aKeySystem).get(), - MediaKeySystemStatusValues::strings[(size_t)status].value, - message.get()); - LogToBrowserConsole(NS_ConvertUTF8toUTF16(msg)); - - if (status == MediaKeySystemStatus::Cdm_not_installed && - IsWidevineKeySystem(aKeySystem)) { - // These are cases which could be resolved by downloading a new(er) CDM. - // When we send the status to chrome, chrome's GMPProvider will attempt to - // download or update the CDM. In AwaitInstall() we add listeners to wait - // for the update to complete, and we'll call this function again with - // aType==Subsequent once the download has completed and the GMPService - // has had a new plugin added. AwaitInstall() sets a timer to fail if the - // update/download takes too long or fails. - if (aType == RequestType::Initial && - AwaitInstall(aPromise, aKeySystem, aConfigs)) { - // Notify chrome that we're going to wait for the CDM to download/update. - // Note: If we're re-trying, we don't re-send the notification, - // as chrome is already displaying the "we can't play, updating" - // notification. - MediaKeySystemAccess::NotifyObservers(mWindow, aKeySystem, status); - } else { - // We waited or can't wait for an update and we still can't service - // the request. Give up. Chrome will still be showing a "I can't play, - // updating" notification. - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, - NS_LITERAL_CSTRING("Gave up while waiting for a CDM update")); - } - diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(), - aKeySystem, false, __func__); - return; - } - if (status != MediaKeySystemStatus::Available) { - // Failed due to user disabling something, send a notification to - // chrome, so we can show some UI to explain how the user can rectify - // the situation. - MediaKeySystemAccess::NotifyObservers(mWindow, aKeySystem, status); - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, message); - return; - } - - MediaKeySystemConfiguration config; - if (MediaKeySystemAccess::GetSupportedConfig(aKeySystem, aConfigs, config, &diagnostics)) { - RefPtr access( - new MediaKeySystemAccess(mWindow, aKeySystem, config)); - aPromise->MaybeResolve(access); - diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(), - aKeySystem, true, __func__); - return; - } - // Not to inform user, because nothing to do if the corresponding keySystem - // configuration is not supported. - aPromise->MaybeReject(NS_ERROR_DOM_NOT_SUPPORTED_ERR, - NS_LITERAL_CSTRING("Key system configuration is not supported")); - diagnostics.StoreMediaKeySystemAccess(mWindow->GetExtantDoc(), - aKeySystem, false, __func__); -} - -MediaKeySystemAccessManager::PendingRequest::PendingRequest(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& aConfigs, - nsITimer* aTimer) - : mPromise(aPromise) - , mKeySystem(aKeySystem) - , mConfigs(aConfigs) - , mTimer(aTimer) -{ - MOZ_COUNT_CTOR(MediaKeySystemAccessManager::PendingRequest); -} - -MediaKeySystemAccessManager::PendingRequest::PendingRequest(const PendingRequest& aOther) - : mPromise(aOther.mPromise) - , mKeySystem(aOther.mKeySystem) - , mConfigs(aOther.mConfigs) - , mTimer(aOther.mTimer) -{ - MOZ_COUNT_CTOR(MediaKeySystemAccessManager::PendingRequest); -} - -MediaKeySystemAccessManager::PendingRequest::~PendingRequest() -{ - MOZ_COUNT_DTOR(MediaKeySystemAccessManager::PendingRequest); -} - -void -MediaKeySystemAccessManager::PendingRequest::CancelTimer() -{ - if (mTimer) { - mTimer->Cancel(); - } -} - -void -MediaKeySystemAccessManager::PendingRequest::RejectPromise(const nsCString& aReason) -{ - if (mPromise) { - mPromise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR, aReason); - } -} - -bool -MediaKeySystemAccessManager::AwaitInstall(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& aConfigs) -{ - EME_LOG("MediaKeySystemAccessManager::AwaitInstall %s", NS_ConvertUTF16toUTF8(aKeySystem).get()); - - if (!EnsureObserversAdded()) { - NS_WARNING("Failed to add pref observer"); - return false; - } - - nsCOMPtr timer(do_CreateInstance("@mozilla.org/timer;1")); - if (!timer || NS_FAILED(timer->Init(this, 60 * 1000, nsITimer::TYPE_ONE_SHOT))) { - NS_WARNING("Failed to create timer to await CDM install."); - return false; - } - - mRequests.AppendElement(PendingRequest(aPromise, aKeySystem, aConfigs, timer)); - return true; -} - -void -MediaKeySystemAccessManager::RetryRequest(PendingRequest& aRequest) -{ - aRequest.CancelTimer(); - Request(aRequest.mPromise, aRequest.mKeySystem, aRequest.mConfigs, RequestType::Subsequent); -} - -nsresult -MediaKeySystemAccessManager::Observe(nsISupports* aSubject, - const char* aTopic, - const char16_t* aData) -{ - EME_LOG("MediaKeySystemAccessManager::Observe %s", aTopic); - - if (!strcmp(aTopic, "gmp-changed")) { - // Filter out the requests where the CDM's install-status is no longer - // "unavailable". This will be the CDMs which have downloaded since the - // initial request. - // Note: We don't have a way to communicate from chrome that the CDM has - // failed to download, so we'll just let the timeout fail us in that case. - nsTArray requests; - for (size_t i = mRequests.Length(); i-- > 0; ) { - PendingRequest& request = mRequests[i]; - nsAutoCString message; - MediaKeySystemStatus status = - MediaKeySystemAccess::GetKeySystemStatus(request.mKeySystem, message); - if (status == MediaKeySystemStatus::Cdm_not_installed) { - // Not yet installed, don't retry. Keep waiting until timeout. - continue; - } - // Status has changed, retry request. - requests.AppendElement(Move(request)); - mRequests.RemoveElementAt(i); - } - // Retry all pending requests, but this time fail if the CDM is not installed. - for (PendingRequest& request : requests) { - RetryRequest(request); - } - } else if (!strcmp(aTopic, "timer-callback")) { - // Find the timer that expired and re-run the request for it. - nsCOMPtr timer(do_QueryInterface(aSubject)); - for (size_t i = 0; i < mRequests.Length(); i++) { - if (mRequests[i].mTimer == timer) { - EME_LOG("MediaKeySystemAccessManager::AwaitInstall resuming request"); - PendingRequest request = mRequests[i]; - mRequests.RemoveElementAt(i); - RetryRequest(request); - break; - } - } - } - return NS_OK; -} - -bool -MediaKeySystemAccessManager::EnsureObserversAdded() -{ - if (mAddedObservers) { - return true; - } - - nsCOMPtr obsService = mozilla::services::GetObserverService(); - if (NS_WARN_IF(!obsService)) { - return false; - } - mAddedObservers = NS_SUCCEEDED(obsService->AddObserver(this, "gmp-changed", false)); - return mAddedObservers; -} - -void -MediaKeySystemAccessManager::Shutdown() -{ - EME_LOG("MediaKeySystemAccessManager::Shutdown"); - nsTArray requests(Move(mRequests)); - for (PendingRequest& request : requests) { - // Cancel all requests; we're shutting down. - request.CancelTimer(); - request.RejectPromise(NS_LITERAL_CSTRING("Promise still outstanding at MediaKeySystemAccessManager shutdown")); - } - if (mAddedObservers) { - nsCOMPtr obsService = mozilla::services::GetObserverService(); - if (obsService) { - obsService->RemoveObserver(this, "gmp-changed"); - mAddedObservers = false; - } - } -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeySystemAccessManager.h b/dom/media/eme/MediaKeySystemAccessManager.h deleted file mode 100644 index 9c092248e2..0000000000 --- a/dom/media/eme/MediaKeySystemAccessManager.h +++ /dev/null @@ -1,83 +0,0 @@ -/* 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_MediaKeySystemAccessManager_h -#define mozilla_dom_MediaKeySystemAccessManager_h - -#include "mozilla/dom/MediaKeySystemAccess.h" -#include "nsIObserver.h" -#include "nsCycleCollectionParticipant.h" -#include "nsISupportsImpl.h" -#include "nsITimer.h" - -namespace mozilla { -namespace dom { - -class DetailedPromise; -class TestGMPVideoDecoder; - -class MediaKeySystemAccessManager final : public nsIObserver -{ -public: - - explicit MediaKeySystemAccessManager(nsPIDOMWindowInner* aWindow); - - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_CLASS_AMBIGUOUS(MediaKeySystemAccessManager, nsIObserver) - NS_DECL_NSIOBSERVER - - void Request(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& aConfig); - - void Shutdown(); - - struct PendingRequest { - PendingRequest(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& aConfig, - nsITimer* aTimer); - PendingRequest(const PendingRequest& aOther); - ~PendingRequest(); - void CancelTimer(); - void RejectPromise(const nsCString& aReason); - - RefPtr mPromise; - const nsString mKeySystem; - const Sequence mConfigs; - nsCOMPtr mTimer; - }; - -private: - - enum RequestType { - Initial, - Subsequent - }; - - void Request(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& aConfig, - RequestType aType); - - ~MediaKeySystemAccessManager(); - - bool EnsureObserversAdded(); - - bool AwaitInstall(DetailedPromise* aPromise, - const nsAString& aKeySystem, - const Sequence& aConfig); - - void RetryRequest(PendingRequest& aRequest); - - nsTArray mRequests; - - nsCOMPtr mWindow; - bool mAddedObservers; -}; - -} // namespace dom -} // namespace mozilla - -#endif diff --git a/dom/media/eme/MediaKeys.cpp b/dom/media/eme/MediaKeys.cpp deleted file mode 100644 index 8621007579..0000000000 --- a/dom/media/eme/MediaKeys.cpp +++ /dev/null @@ -1,579 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "mozilla/dom/MediaKeys.h" -#include "GMPService.h" -#include "mozilla/dom/HTMLMediaElement.h" -#include "mozilla/dom/MediaKeysBinding.h" -#include "mozilla/dom/MediaKeyMessageEvent.h" -#include "mozilla/dom/MediaKeyError.h" -#include "mozilla/dom/MediaKeySession.h" -#include "mozilla/dom/DOMException.h" -#include "mozilla/dom/UnionTypes.h" -#include "GMPCDMProxy.h" -#include "mozilla/EMEUtils.h" -#include "nsContentUtils.h" -#include "nsIScriptObjectPrincipal.h" -#include "nsContentTypeParser.h" -#ifdef MOZ_FMP4 -#include "MP4Decoder.h" -#endif -#ifdef XP_WIN -#include "mozilla/WindowsVersion.h" -#endif -#include "nsContentCID.h" -#include "nsServiceManagerUtils.h" -#include "mozilla/dom/MediaKeySystemAccess.h" -#include "nsPrintfCString.h" - -namespace mozilla { - -namespace dom { - -NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(MediaKeys, - mElement, - mParent, - mKeySessions, - mPromises, - mPendingSessions); -NS_IMPL_CYCLE_COLLECTING_ADDREF(MediaKeys) -NS_IMPL_CYCLE_COLLECTING_RELEASE(MediaKeys) -NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(MediaKeys) - NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY - NS_INTERFACE_MAP_ENTRY(nsISupports) -NS_INTERFACE_MAP_END - -MediaKeys::MediaKeys(nsPIDOMWindowInner* aParent, - const nsAString& aKeySystem, - const MediaKeySystemConfiguration& aConfig) - : mParent(aParent) - , mKeySystem(aKeySystem) - , mCreatePromiseId(0) - , mConfig(aConfig) -{ - EME_LOG("MediaKeys[%p] constructed keySystem=%s", - this, NS_ConvertUTF16toUTF8(mKeySystem).get()); -} - -MediaKeys::~MediaKeys() -{ - Shutdown(); - EME_LOG("MediaKeys[%p] destroyed", this); -} - -void -MediaKeys::Terminated() -{ - EME_LOG("MediaKeys[%p] CDM crashed unexpectedly", this); - - KeySessionHashMap keySessions; - // Remove entries during iteration will screw it. Make a copy first. - for (auto iter = mKeySessions.Iter(); !iter.Done(); iter.Next()) { - RefPtr& session = iter.Data(); - keySessions.Put(session->GetSessionId(), session); - } - for (auto iter = keySessions.Iter(); !iter.Done(); iter.Next()) { - RefPtr& session = iter.Data(); - session->OnClosed(); - } - keySessions.Clear(); - MOZ_ASSERT(mKeySessions.Count() == 0); - - // Notify the element about that CDM has terminated. - if (mElement) { - mElement->DecodeError(NS_ERROR_DOM_MEDIA_CDM_ERR); - } - - Shutdown(); -} - -void -MediaKeys::Shutdown() -{ - if (mProxy) { - mProxy->Shutdown(); - mProxy = nullptr; - } - - RefPtr kungFuDeathGrip = this; - - for (auto iter = mPromises.Iter(); !iter.Done(); iter.Next()) { - RefPtr& promise = iter.Data(); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Promise still outstanding at MediaKeys shutdown")); - Release(); - } - mPromises.Clear(); -} - -nsPIDOMWindowInner* -MediaKeys::GetParentObject() const -{ - return mParent; -} - -JSObject* -MediaKeys::WrapObject(JSContext* aCx, JS::Handle aGivenProto) -{ - return MediaKeysBinding::Wrap(aCx, this, aGivenProto); -} - -void -MediaKeys::GetKeySystem(nsString& aOutKeySystem) const -{ - aOutKeySystem.Assign(mKeySystem); -} - -already_AddRefed -MediaKeys::SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aCert, ErrorResult& aRv) -{ - RefPtr promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeys.setServerCertificate"))); - if (aRv.Failed()) { - return nullptr; - } - - if (!mProxy) { - NS_WARNING("Tried to use a MediaKeys without a CDM"); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in MediaKeys.setServerCertificate()")); - return promise.forget(); - } - - nsTArray data; - CopyArrayBufferViewOrArrayBufferData(aCert, data); - if (data.IsEmpty()) { - promise->MaybeReject(NS_ERROR_DOM_TYPE_ERR, - NS_LITERAL_CSTRING("Empty certificate passed to MediaKeys.setServerCertificate()")); - return promise.forget(); - } - - mProxy->SetServerCertificate(StorePromise(promise), data); - return promise.forget(); -} - -already_AddRefed -MediaKeys::MakePromise(ErrorResult& aRv, const nsACString& aName) -{ - nsCOMPtr global = do_QueryInterface(GetParentObject()); - if (!global) { - NS_WARNING("Passed non-global to MediaKeys ctor!"); - aRv.Throw(NS_ERROR_UNEXPECTED); - return nullptr; - } - return DetailedPromise::Create(global, aRv, aName); -} - -PromiseId -MediaKeys::StorePromise(DetailedPromise* aPromise) -{ - static uint32_t sEMEPromiseCount = 1; - MOZ_ASSERT(aPromise); - uint32_t id = sEMEPromiseCount++; - - EME_LOG("MediaKeys[%p]::StorePromise() id=%d", this, id); - - // Keep MediaKeys alive for the lifetime of its promises. Any still-pending - // promises are rejected in Shutdown(). - AddRef(); - -#ifdef DEBUG - // We should not have already stored this promise! - for (auto iter = mPromises.ConstIter(); !iter.Done(); iter.Next()) { - MOZ_ASSERT(iter.Data() != aPromise); - } -#endif - - mPromises.Put(id, aPromise); - return id; -} - -void -MediaKeys::ConnectPendingPromiseIdWithToken(PromiseId aId, uint32_t aToken) -{ - // Should only be called from MediaKeySession::GenerateRequest. - mPromiseIdToken.Put(aId, aToken); - EME_LOG("MediaKeys[%p]::ConnectPendingPromiseIdWithToken() id=%u => token(%u)", - this, aId, aToken); -} - -already_AddRefed -MediaKeys::RetrievePromise(PromiseId aId) -{ - if (!mPromises.Contains(aId)) { - NS_WARNING(nsPrintfCString("Tried to retrieve a non-existent promise id=%d", aId).get()); - return nullptr; - } - RefPtr promise; - mPromises.Remove(aId, getter_AddRefs(promise)); - Release(); - return promise.forget(); -} - -void -MediaKeys::RejectPromise(PromiseId aId, nsresult aExceptionCode, - const nsCString& aReason) -{ - EME_LOG("MediaKeys[%p]::RejectPromise(%d, 0x%x)", this, aId, aExceptionCode); - - RefPtr promise(RetrievePromise(aId)); - if (!promise) { - return; - } - - // This promise could be a createSession or loadSession promise, - // so we might have a pending session waiting to be resolved into - // the promise on success. We've been directed to reject to promise, - // so we can throw away the corresponding session object. - uint32_t token = 0; - if (mPromiseIdToken.Get(aId, &token)) { - MOZ_ASSERT(mPendingSessions.Contains(token)); - mPendingSessions.Remove(token); - mPromiseIdToken.Remove(aId); - } - - MOZ_ASSERT(NS_FAILED(aExceptionCode)); - promise->MaybeReject(aExceptionCode, aReason); - - if (mCreatePromiseId == aId) { - // Note: This will probably destroy the MediaKeys object! - Release(); - } -} - -void -MediaKeys::OnSessionIdReady(MediaKeySession* aSession) -{ - if (!aSession) { - NS_WARNING("Invalid MediaKeySession passed to OnSessionIdReady()"); - return; - } - if (mKeySessions.Contains(aSession->GetSessionId())) { - NS_WARNING("MediaKeySession's made ready multiple times!"); - return; - } - if (mPendingSessions.Contains(aSession->Token())) { - NS_WARNING("MediaKeySession made ready when it wasn't waiting to be ready!"); - return; - } - if (aSession->GetSessionId().IsEmpty()) { - NS_WARNING("MediaKeySession with invalid sessionId passed to OnSessionIdReady()"); - return; - } - mKeySessions.Put(aSession->GetSessionId(), aSession); -} - -void -MediaKeys::ResolvePromise(PromiseId aId) -{ - EME_LOG("MediaKeys[%p]::ResolvePromise(%d)", this, aId); - - RefPtr promise(RetrievePromise(aId)); - MOZ_ASSERT(!mPromises.Contains(aId)); - if (!promise) { - return; - } - - uint32_t token = 0; - if (!mPromiseIdToken.Get(aId, &token)) { - promise->MaybeResolveWithUndefined(); - return; - } else if (!mPendingSessions.Contains(token)) { - // Pending session for CreateSession() should be removed when sessionId - // is ready. - promise->MaybeResolveWithUndefined(); - mPromiseIdToken.Remove(aId); - return; - } - mPromiseIdToken.Remove(aId); - - // We should only resolve LoadSession calls via this path, - // not CreateSession() promises. - RefPtr session; - mPendingSessions.Remove(token, getter_AddRefs(session)); - if (!session || session->GetSessionId().IsEmpty()) { - NS_WARNING("Received activation for non-existent session!"); - promise->MaybeReject(NS_ERROR_DOM_INVALID_ACCESS_ERR, - NS_LITERAL_CSTRING("CDM LoadSession() returned a different session ID than requested")); - return; - } - mKeySessions.Put(session->GetSessionId(), session); - promise->MaybeResolve(session); -} - -class MediaKeysGMPCrashHelper : public GMPCrashHelper -{ -public: - explicit MediaKeysGMPCrashHelper(MediaKeys* aMediaKeys) - : mMediaKeys(aMediaKeys) - { - MOZ_ASSERT(NS_IsMainThread()); // WeakPtr isn't thread safe. - } - already_AddRefed - GetPluginCrashedEventTarget() override - { - MOZ_ASSERT(NS_IsMainThread()); // WeakPtr isn't thread safe. - EME_LOG("MediaKeysGMPCrashHelper::GetPluginCrashedEventTarget()"); - return (mMediaKeys && mMediaKeys->GetParentObject()) ? - do_AddRef(mMediaKeys->GetParentObject()) : nullptr; - } -private: - WeakPtr mMediaKeys; -}; - -already_AddRefed -MediaKeys::CreateCDMProxy() -{ - RefPtr proxy; - { - proxy = new GMPCDMProxy(this, - mKeySystem, - new MediaKeysGMPCrashHelper(this), - mConfig.mDistinctiveIdentifier == MediaKeysRequirement::Required, - mConfig.mPersistentState == MediaKeysRequirement::Required); - } - return proxy.forget(); -} - -already_AddRefed -MediaKeys::Init(ErrorResult& aRv) -{ - RefPtr promise(MakePromise(aRv, - NS_LITERAL_CSTRING("MediaKeys::Init()"))); - if (aRv.Failed()) { - return nullptr; - } - - mProxy = CreateCDMProxy(); - - // Determine principal (at creation time) of the MediaKeys object. - nsCOMPtr sop = do_QueryInterface(GetParentObject()); - if (!sop) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get script principal in MediaKeys::Init")); - return promise.forget(); - } - mPrincipal = sop->GetPrincipal(); - - // Determine principal of the "top-level" window; the principal of the - // page that will display in the URL bar. - nsCOMPtr window = GetParentObject(); - if (!window) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get top-level window in MediaKeys::Init")); - return promise.forget(); - } - nsCOMPtr top = window->GetOuterWindow()->GetTop(); - if (!top || !top->GetExtantDoc()) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get document in MediaKeys::Init")); - return promise.forget(); - } - - mTopLevelPrincipal = top->GetExtantDoc()->NodePrincipal(); - - if (!mPrincipal || !mTopLevelPrincipal) { - NS_WARNING("Failed to get principals when creating MediaKeys"); - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get principal(s) in MediaKeys::Init")); - return promise.forget(); - } - - nsAutoCString origin; - nsresult rv = mPrincipal->GetOrigin(origin); - if (NS_FAILED(rv)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get principal origin string in MediaKeys::Init")); - return promise.forget(); - } - nsAutoCString topLevelOrigin; - rv = mTopLevelPrincipal->GetOrigin(topLevelOrigin); - if (NS_FAILED(rv)) { - promise->MaybeReject(NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get top-level principal origin string in MediaKeys::Init")); - return promise.forget(); - } - - nsIDocument* doc = window->GetExtantDoc(); - const bool inPrivateBrowsing = nsContentUtils::IsInPrivateBrowsing(doc); - - EME_LOG("MediaKeys[%p]::Create() (%s, %s), %s", - this, - origin.get(), - topLevelOrigin.get(), - (inPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing")); - - // The CDMProxy's initialization is asynchronous. The MediaKeys is - // refcounted, and its instance is returned to JS by promise once - // it's been initialized. No external refs exist to the MediaKeys while - // we're waiting for the promise to be resolved, so we must hold a - // reference to the new MediaKeys object until it's been created, - // or its creation has failed. Store the id of the promise returned - // here, and hold a self-reference until that promise is resolved or - // rejected. - MOZ_ASSERT(!mCreatePromiseId, "Should only be created once!"); - mCreatePromiseId = StorePromise(promise); - AddRef(); - mProxy->Init(mCreatePromiseId, - NS_ConvertUTF8toUTF16(origin), - NS_ConvertUTF8toUTF16(topLevelOrigin), - KeySystemToGMPName(mKeySystem), - inPrivateBrowsing); - - return promise.forget(); -} - -void -MediaKeys::OnCDMCreated(PromiseId aId, const nsACString& aNodeId, const uint32_t aPluginId) -{ - RefPtr promise(RetrievePromise(aId)); - if (!promise) { - return; - } - mNodeId = aNodeId; - RefPtr keys(this); - EME_LOG("MediaKeys[%p]::OnCDMCreated() resolve promise id=%d", this, aId); - promise->MaybeResolve(keys); - if (mCreatePromiseId == aId) { - Release(); - } - - MediaKeySystemAccess::NotifyObservers(mParent, - mKeySystem, - MediaKeySystemStatus::Cdm_created); - -} - -static bool -IsSessionTypeSupported(const MediaKeySessionType aSessionType, - const MediaKeySystemConfiguration& aConfig) -{ - if (aSessionType == MediaKeySessionType::Temporary) { - // Temporary is always supported. - return true; - } - if (!aConfig.mSessionTypes.WasPassed()) { - // No other session types supported. - return false; - } - using MediaKeySessionTypeValues::strings; - const char* sessionType = strings[static_cast(aSessionType)].value; - for (const nsString& s : aConfig.mSessionTypes.Value()) { - if (s.EqualsASCII(sessionType)) { - return true; - } - } - return false; -} - -already_AddRefed -MediaKeys::CreateSession(JSContext* aCx, - MediaKeySessionType aSessionType, - ErrorResult& aRv) -{ - if (!IsSessionTypeSupported(aSessionType, mConfig)) { - EME_LOG("MediaKeys[%p,'%s'] CreateSession() failed, unsupported session type", this); - aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR); - return nullptr; - } - - if (!mProxy) { - NS_WARNING("Tried to use a MediaKeys which lost its CDM"); - aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR); - return nullptr; - } - - EME_LOG("MediaKeys[%p] Creating session", this); - - RefPtr session = new MediaKeySession(aCx, - GetParentObject(), - this, - mKeySystem, - aSessionType, - aRv); - - if (aRv.Failed()) { - return nullptr; - } - - // Add session to the set of sessions awaiting their sessionId being ready. - mPendingSessions.Put(session->Token(), session); - - return session.forget(); -} - -void -MediaKeys::OnSessionLoaded(PromiseId aId, bool aSuccess) -{ - RefPtr promise(RetrievePromise(aId)); - if (!promise) { - return; - } - EME_LOG("MediaKeys[%p]::OnSessionLoaded() resolve promise id=%d", this, aId); - - promise->MaybeResolve(aSuccess); -} - -void -MediaKeys::OnSessionClosed(MediaKeySession* aSession) -{ - nsAutoString id; - aSession->GetSessionId(id); - mKeySessions.Remove(id); -} - -already_AddRefed -MediaKeys::GetSession(const nsAString& aSessionId) -{ - RefPtr session; - mKeySessions.Get(aSessionId, getter_AddRefs(session)); - return session.forget(); -} - -already_AddRefed -MediaKeys::GetPendingSession(uint32_t aToken) -{ - RefPtr session; - mPendingSessions.Get(aToken, getter_AddRefs(session)); - mPendingSessions.Remove(aToken); - return session.forget(); -} - -const nsCString& -MediaKeys::GetNodeId() const -{ - MOZ_ASSERT(NS_IsMainThread()); - return mNodeId; -} - -bool -MediaKeys::IsBoundToMediaElement() const -{ - MOZ_ASSERT(NS_IsMainThread()); - return mElement != nullptr; -} - -nsresult -MediaKeys::Bind(HTMLMediaElement* aElement) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (IsBoundToMediaElement()) { - return NS_ERROR_FAILURE; - } - - mElement = aElement; - - return NS_OK; -} - -void -MediaKeys::Unbind() -{ - MOZ_ASSERT(NS_IsMainThread()); - mElement = nullptr; -} - -} // namespace dom -} // namespace mozilla diff --git a/dom/media/eme/MediaKeys.h b/dom/media/eme/MediaKeys.h deleted file mode 100644 index 4919639342..0000000000 --- a/dom/media/eme/MediaKeys.h +++ /dev/null @@ -1,167 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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_mediakeys_h__ -#define mozilla_dom_mediakeys_h__ - -#include "nsWrapperCache.h" -#include "nsISupports.h" -#include "mozilla/Attributes.h" -#include "mozilla/RefPtr.h" -#include "nsCOMPtr.h" -#include "nsCycleCollectionParticipant.h" -#include "nsRefPtrHashtable.h" -#include "mozilla/dom/Promise.h" -#include "mozilla/dom/MediaKeysBinding.h" -#include "mozilla/dom/MediaKeySystemAccessBinding.h" -#include "mozIGeckoMediaPluginService.h" -#include "mozilla/DetailedPromise.h" -#include "mozilla/WeakPtr.h" - -namespace mozilla { - -class CDMProxy; - -namespace dom { - -class ArrayBufferViewOrArrayBuffer; -class MediaKeySession; -class HTMLMediaElement; - -typedef nsRefPtrHashtable KeySessionHashMap; -typedef nsRefPtrHashtable PromiseHashMap; -typedef nsRefPtrHashtable PendingKeySessionsHashMap; -typedef nsDataHashtable PendingPromiseIdTokenHashMap; -typedef uint32_t PromiseId; - -// This class is used on the main thread only. -// Note: its addref/release is not (and can't be) thread safe! -class MediaKeys final : public nsISupports, - public nsWrapperCache, - public SupportsWeakPtr -{ - ~MediaKeys(); - -public: - NS_DECL_CYCLE_COLLECTING_ISUPPORTS - NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(MediaKeys) - MOZ_DECLARE_WEAKREFERENCE_TYPENAME(MediaKeys) - - MediaKeys(nsPIDOMWindowInner* aParentWindow, - const nsAString& aKeySystem, - const MediaKeySystemConfiguration& aConfig); - - already_AddRefed Init(ErrorResult& aRv); - - nsPIDOMWindowInner* GetParentObject() const; - - JSObject* WrapObject(JSContext* aCx, JS::Handle aGivenProto) override; - - nsresult Bind(HTMLMediaElement* aElement); - void Unbind(); - - // Javascript: readonly attribute DOMString keySystem; - void GetKeySystem(nsString& retval) const; - - // JavaScript: MediaKeys.createSession() - already_AddRefed CreateSession(JSContext* aCx, - MediaKeySessionType aSessionType, - ErrorResult& aRv); - - // JavaScript: MediaKeys.SetServerCertificate() - already_AddRefed - SetServerCertificate(const ArrayBufferViewOrArrayBuffer& aServerCertificate, - ErrorResult& aRv); - - already_AddRefed GetSession(const nsAString& aSessionId); - - // Removes and returns MediaKeySession from the set of sessions awaiting - // their sessionId to be assigned. - already_AddRefed GetPendingSession(uint32_t aToken); - - // Called once a Init() operation succeeds. - void OnCDMCreated(PromiseId aId, - const nsACString& aNodeId, const uint32_t aPluginId); - - // Called once the CDM generates a sessionId while servicing a - // MediaKeySession.generateRequest() or MediaKeySession.load() call, - // once the sessionId of a MediaKeySession is known. - void OnSessionIdReady(MediaKeySession* aSession); - - // Called once a LoadSession succeeds. - void OnSessionLoaded(PromiseId aId, bool aSuccess); - - // Called once a session has closed. - void OnSessionClosed(MediaKeySession* aSession); - - CDMProxy* GetCDMProxy() { return mProxy; } - - // Makes a new promise, or nullptr on failure. - already_AddRefed MakePromise(ErrorResult& aRv, - const nsACString& aName); - // Stores promise in mPromises, returning an ID that can be used to retrieve - // it later. The ID is passed to the CDM, so that it can signal specific - // promises to be resolved. - PromiseId StorePromise(DetailedPromise* aPromise); - - // Stores a map from promise id to pending session token. Using this - // mapping, when a promise is rejected via its ID, we can check if the - // promise corresponds to a pending session and retrieve that session - // via the mapped-to token, and remove the pending session from the - // list of sessions awaiting a session id. - void ConnectPendingPromiseIdWithToken(PromiseId aId, uint32_t aToken); - - // Reject promise with DOMException corresponding to aExceptionCode. - void RejectPromise(PromiseId aId, nsresult aExceptionCode, - const nsCString& aReason); - // Resolves promise with "undefined". - void ResolvePromise(PromiseId aId); - - const nsCString& GetNodeId() const; - - void Shutdown(); - - // Called by CDMProxy when CDM crashes or shuts down. It is different from - // Shutdown which is called from the script/dom side. - void Terminated(); - - // Returns true if this MediaKeys has been bound to a media element. - bool IsBoundToMediaElement() const; - -private: - - // Instantiate CDMProxy instance. - // It could be MediaDrmCDMProxy (Widevine on Fennec) or GMPCDMProxy (the rest). - already_AddRefed CreateCDMProxy(); - - // Removes promise from mPromises, and returns it. - already_AddRefed RetrievePromise(PromiseId aId); - - // Owning ref to proxy. The proxy has a weak reference back to the MediaKeys, - // and the MediaKeys destructor clears the proxy's reference to the MediaKeys. - RefPtr mProxy; - - RefPtr mElement; - - nsCOMPtr mParent; - const nsString mKeySystem; - nsCString mNodeId; - KeySessionHashMap mKeySessions; - PromiseHashMap mPromises; - PendingKeySessionsHashMap mPendingSessions; - PromiseId mCreatePromiseId; - - RefPtr mPrincipal; - RefPtr mTopLevelPrincipal; - - const MediaKeySystemConfiguration mConfig; - - PendingPromiseIdTokenHashMap mPromiseIdToken; -}; - -} // namespace dom -} // namespace mozilla - -#endif // mozilla_dom_mediakeys_h__ diff --git a/dom/media/eme/moz.build b/dom/media/eme/moz.build deleted file mode 100644 index 31ab9ffd87..0000000000 --- a/dom/media/eme/moz.build +++ /dev/null @@ -1,41 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -EXPORTS.mozilla.dom += [ - 'MediaEncryptedEvent.h', - 'MediaKeyError.h', - 'MediaKeyMessageEvent.h', - 'MediaKeys.h', - 'MediaKeySession.h', - 'MediaKeyStatusMap.h', - 'MediaKeySystemAccess.h', - 'MediaKeySystemAccessManager.h', -] - -EXPORTS.mozilla += [ - 'CDMCaps.h', - 'CDMProxy.h', - 'DecryptorProxyCallback.h', - 'DetailedPromise.h', - 'EMEUtils.h', -] - -UNIFIED_SOURCES += [ - 'CDMCaps.cpp', - 'DetailedPromise.cpp', - 'EMEUtils.cpp', - 'MediaEncryptedEvent.cpp', - 'MediaKeyError.cpp', - 'MediaKeyMessageEvent.cpp', - 'MediaKeys.cpp', - 'MediaKeySession.cpp', - 'MediaKeyStatusMap.cpp', - 'MediaKeySystemAccess.cpp', - 'MediaKeySystemAccessManager.cpp', -] - -include('/ipc/chromium/chromium-config.mozbuild') - -FINAL_LIBRARY = 'xul' diff --git a/dom/media/gmp/GMPCDMCallbackProxy.cpp b/dom/media/gmp/GMPCDMCallbackProxy.cpp deleted file mode 100644 index a0b490849a..0000000000 --- a/dom/media/gmp/GMPCDMCallbackProxy.cpp +++ /dev/null @@ -1,250 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "GMPCDMCallbackProxy.h" -#include "mozilla/CDMProxy.h" -#include "nsString.h" -#include "mozilla/dom/MediaKeys.h" -#include "mozilla/dom/MediaKeySession.h" -#include "mozIGeckoMediaPluginService.h" -#include "nsContentCID.h" -#include "nsServiceManagerUtils.h" -#include "MainThreadUtils.h" -#include "mozilla/EMEUtils.h" - -namespace mozilla { - -GMPCDMCallbackProxy::GMPCDMCallbackProxy(CDMProxy* aProxy) - : mProxy(aProxy) -{} - -void -GMPCDMCallbackProxy::SetDecryptorId(uint32_t aId) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, aId] () - { - proxy->OnSetDecryptorId(aId); - }) - );} - -void -GMPCDMCallbackProxy::SetSessionId(uint32_t aToken, - const nsCString& aSessionId) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr proxy = mProxy; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, - aToken, - sid] () - { - proxy->OnSetSessionId(aToken, sid); - }) - ); -} - -void -GMPCDMCallbackProxy::ResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, aPromiseId, aSuccess] () - { - proxy->OnResolveLoadSessionPromise(aPromiseId, aSuccess); - }) - ); -} - -void -GMPCDMCallbackProxy::ResolvePromise(uint32_t aPromiseId) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - // Note: CDMProxy proxies this from non-main threads to main thread. - mProxy->ResolvePromise(aPromiseId); -} - -void -GMPCDMCallbackProxy::RejectPromise(uint32_t aPromiseId, - nsresult aException, - const nsCString& aMessage) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, - aPromiseId, - aException, - aMessage] () - { - proxy->OnRejectPromise(aPromiseId, aException, aMessage); - }) - ); -} - -void -GMPCDMCallbackProxy::SessionMessage(const nsCString& aSessionId, - dom::MediaKeyMessageType aMessageType, - const nsTArray& aMessage) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr proxy = mProxy; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - nsTArray msg(aMessage); - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, - sid, - aMessageType, - msg] () mutable - { - proxy->OnSessionMessage(sid, aMessageType, msg); - }) - ); -} - -void -GMPCDMCallbackProxy::ExpirationChange(const nsCString& aSessionId, - GMPTimestamp aExpiryTime) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr proxy = mProxy; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, - sid, - aExpiryTime] () - { - proxy->OnExpirationChange(sid, aExpiryTime); - }) - ); -} - -void -GMPCDMCallbackProxy::SessionClosed(const nsCString& aSessionId) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - bool keyStatusesChange = false; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - { - CDMCaps::AutoLock caps(mProxy->Capabilites()); - keyStatusesChange = caps.RemoveKeysForSession(NS_ConvertUTF8toUTF16(aSessionId)); - } - if (keyStatusesChange) { - RefPtr proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, sid] () - { - proxy->OnKeyStatusesChange(sid); - }) - ); - } - - RefPtr proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, sid] () - { - proxy->OnSessionClosed(sid); - }) - ); -} - -void -GMPCDMCallbackProxy::SessionError(const nsCString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsCString& aMessage) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr proxy = mProxy; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - auto msg = NS_ConvertUTF8toUTF16(aMessage); - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, - sid, - aException, - aSystemCode, - msg] () - { - proxy->OnSessionError(sid, - aException, - aSystemCode, - msg); - }) - ); -} - -void -GMPCDMCallbackProxy::BatchedKeyStatusChanged(const nsCString& aSessionId, - const nsTArray& aKeyInfos) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - BatchedKeyStatusChangedInternal(aSessionId, aKeyInfos); -} - -void -GMPCDMCallbackProxy::BatchedKeyStatusChangedInternal(const nsCString& aSessionId, - const nsTArray& aKeyInfos) -{ - bool keyStatusesChange = false; - { - CDMCaps::AutoLock caps(mProxy->Capabilites()); - for (size_t i = 0; i < aKeyInfos.Length(); i++) { - keyStatusesChange |= - caps.SetKeyStatus(aKeyInfos[i].mKeyId, - NS_ConvertUTF8toUTF16(aSessionId), - aKeyInfos[i].mStatus); - } - } - if (keyStatusesChange) { - RefPtr proxy = mProxy; - auto sid = NS_ConvertUTF8toUTF16(aSessionId); - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy, sid] () - { - proxy->OnKeyStatusesChange(sid); - }) - ); - } -} - -void -GMPCDMCallbackProxy::Decrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray& aDecryptedData) -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - mProxy->OnDecrypted(aId, aResult, aDecryptedData); -} - -void -GMPCDMCallbackProxy::Terminated() -{ - MOZ_ASSERT(mProxy->IsOnOwnerThread()); - - RefPtr proxy = mProxy; - NS_DispatchToMainThread( - NS_NewRunnableFunction([proxy] () - { - proxy->Terminated(); - }) - ); -} - -} // namespace mozilla diff --git a/dom/media/gmp/GMPCDMCallbackProxy.h b/dom/media/gmp/GMPCDMCallbackProxy.h deleted file mode 100644 index d2cc806825..0000000000 --- a/dom/media/gmp/GMPCDMCallbackProxy.h +++ /dev/null @@ -1,71 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 GMPCDMCallbackProxy_h_ -#define GMPCDMCallbackProxy_h_ - -#include "mozilla/CDMProxy.h" -#include "gmp-decryption.h" -#include "GMPDecryptorProxy.h" - -namespace mozilla { - -// Proxies call backs from the CDM on the GMP thread back to the MediaKeys -// object on the main thread. -class GMPCDMCallbackProxy : public GMPDecryptorProxyCallback { -public: - - void SetDecryptorId(uint32_t aId) override; - - void SetSessionId(uint32_t aCreateSessionToken, - const nsCString& aSessionId) override; - - void ResolveLoadSessionPromise(uint32_t aPromiseId, - bool aSuccess) override; - - void ResolvePromise(uint32_t aPromiseId) override; - - void RejectPromise(uint32_t aPromiseId, - nsresult aException, - const nsCString& aSessionId) override; - - void SessionMessage(const nsCString& aSessionId, - dom::MediaKeyMessageType aMessageType, - const nsTArray& aMessage) override; - - void ExpirationChange(const nsCString& aSessionId, - UnixTime aExpiryTime) override; - - void SessionClosed(const nsCString& aSessionId) override; - - void SessionError(const nsCString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsCString& aMessage) override; - - void Decrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray& aDecryptedData) override; - - void BatchedKeyStatusChanged(const nsCString& aSessionId, - const nsTArray& aKeyInfos) override; - - void Terminated() override; - - ~GMPCDMCallbackProxy() {} - -private: - friend class GMPCDMProxy; - explicit GMPCDMCallbackProxy(CDMProxy* aProxy); - - void BatchedKeyStatusChangedInternal(const nsCString& aSessionId, - const nsTArray& aKeyInfos); - // Warning: Weak ref. - CDMProxy* mProxy; -}; - -} // namespace mozilla - -#endif // GMPCDMCallbackProxy_h_ diff --git a/dom/media/gmp/GMPCDMProxy.cpp b/dom/media/gmp/GMPCDMProxy.cpp deleted file mode 100644 index 0f19586321..0000000000 --- a/dom/media/gmp/GMPCDMProxy.cpp +++ /dev/null @@ -1,798 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "GMPCDMProxy.h" -#include "mozilla/EMEUtils.h" -#include "mozilla/PodOperations.h" - -#include "mozilla/dom/MediaKeys.h" -#include "mozilla/dom/MediaKeySession.h" - -#include "mozIGeckoMediaPluginService.h" -#include "nsContentCID.h" -#include "nsIConsoleService.h" -#include "nsPrintfCString.h" -#include "nsServiceManagerUtils.h" -#include "nsString.h" -#include "prenv.h" -#include "GMPCDMCallbackProxy.h" -#include "GMPService.h" -#include "MainThreadUtils.h" -#include "MediaData.h" - -namespace mozilla { - -GMPCDMProxy::GMPCDMProxy(dom::MediaKeys* aKeys, - const nsAString& aKeySystem, - GMPCrashHelper* aCrashHelper, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) - : CDMProxy(aKeys, - aKeySystem, - aDistinctiveIdentifierRequired, - aPersistentStateRequired) - , mCrashHelper(aCrashHelper) - , mCDM(nullptr) - , mDecryptionJobCount(0) - , mShutdownCalled(false) - , mDecryptorId(0) - , mCreatePromiseId(0) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_COUNT_CTOR(GMPCDMProxy); -} - -GMPCDMProxy::~GMPCDMProxy() -{ - MOZ_COUNT_DTOR(GMPCDMProxy); -} - -void -GMPCDMProxy::Init(PromiseId aPromiseId, - const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsing) -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - EME_LOG("GMPCDMProxy::Init (%s, %s) %s", - NS_ConvertUTF16toUTF8(aOrigin).get(), - NS_ConvertUTF16toUTF8(aTopLevelOrigin).get(), - (aInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing")); - - nsCString pluginVersion; - if (!mOwnerThread) { - nsCOMPtr mps = - do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - if (!mps) { - RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::Init")); - return; - } - mps->GetThread(getter_AddRefs(mOwnerThread)); - if (!mOwnerThread) { - RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get GMP thread GMPCDMProxy::Init")); - return; - } - } - - if (aGMPName.IsEmpty()) { - RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - nsPrintfCString("Unknown GMP for keysystem '%s'", NS_ConvertUTF16toUTF8(mKeySystem).get())); - return; - } - - nsAutoPtr data(new InitData()); - data->mPromiseId = aPromiseId; - data->mOrigin = aOrigin; - data->mTopLevelOrigin = aTopLevelOrigin; - data->mGMPName = aGMPName; - data->mInPrivateBrowsing = aInPrivateBrowsing; - data->mCrashHelper = mCrashHelper; - nsCOMPtr task( - NewRunnableMethod>(this, - &GMPCDMProxy::gmp_Init, - Move(data))); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -#ifdef DEBUG -bool -GMPCDMProxy::IsOnOwnerThread() -{ - return NS_GetCurrentThread() == mOwnerThread; -} -#endif - -void -GMPCDMProxy::gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr&& aData) -{ - EME_LOG("GMPCDMProxy::gmp_InitDone"); - if (mShutdownCalled) { - if (aCDM) { - aCDM->Close(); - } - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("GMPCDMProxy was shut down before init could complete")); - return; - } - if (!aCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("GetGMPDecryptor failed to return a CDM")); - return; - } - - mCDM = aCDM; - mCallback = new GMPCDMCallbackProxy(this); - mCDM->Init(mCallback, - mDistinctiveIdentifierRequired, - mPersistentStateRequired); - - // Await the OnSetDecryptorId callback. - mCreatePromiseId = aData->mPromiseId; -} - -void GMPCDMProxy::OnSetDecryptorId(uint32_t aId) -{ - MOZ_ASSERT(mCreatePromiseId); - mDecryptorId = aId; - nsCOMPtr task( - NewRunnableMethod(this, - &GMPCDMProxy::OnCDMCreated, - mCreatePromiseId)); - NS_DispatchToMainThread(task); -} - -class gmp_InitDoneCallback : public GetGMPDecryptorCallback -{ -public: - gmp_InitDoneCallback(GMPCDMProxy* aGMPCDMProxy, - nsAutoPtr&& aData) - : mGMPCDMProxy(aGMPCDMProxy), - mData(Move(aData)) - { - } - - void Done(GMPDecryptorProxy* aCDM) - { - mGMPCDMProxy->gmp_InitDone(aCDM, Move(mData)); - } - -private: - RefPtr mGMPCDMProxy; - nsAutoPtr mData; -}; - -class gmp_InitGetGMPDecryptorCallback : public GetNodeIdCallback -{ -public: - gmp_InitGetGMPDecryptorCallback(GMPCDMProxy* aGMPCDMProxy, - nsAutoPtr&& aData) - : mGMPCDMProxy(aGMPCDMProxy), - mData(aData) - { - } - - void Done(nsresult aResult, const nsACString& aNodeId) - { - mGMPCDMProxy->gmp_InitGetGMPDecryptor(aResult, aNodeId, Move(mData)); - } - -private: - RefPtr mGMPCDMProxy; - nsAutoPtr mData; -}; - -void -GMPCDMProxy::gmp_Init(nsAutoPtr&& aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - - nsCOMPtr mps = - do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - if (!mps) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::gmp_Init")); - return; - } - - // Make a copy before we transfer ownership of aData to the - // gmp_InitGetGMPDecryptorCallback. - InitData data(*aData); - UniquePtr callback( - new gmp_InitGetGMPDecryptorCallback(this, Move(aData))); - nsresult rv = mps->GetNodeId(data.mOrigin, - data.mTopLevelOrigin, - data.mGMPName, - data.mInPrivateBrowsing, - Move(callback)); - if (NS_FAILED(rv)) { - RejectPromise(data.mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Call to GetNodeId() failed early")); - } -} - -void -GMPCDMProxy::gmp_InitGetGMPDecryptor(nsresult aResult, - const nsACString& aNodeId, - nsAutoPtr&& aData) -{ - uint32_t promiseID = aData->mPromiseId; - if (NS_FAILED(aResult)) { - RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("GetNodeId() called back, but with a failure result")); - return; - } - - mNodeId = aNodeId; - MOZ_ASSERT(!GetNodeId().IsEmpty()); - - nsCOMPtr mps = - do_GetService("@mozilla.org/gecko-media-plugin-service;1"); - if (!mps) { - RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Couldn't get MediaPluginService in GMPCDMProxy::gmp_InitGetGMPDecryptor")); - return; - } - - EME_LOG("GMPCDMProxy::gmp_Init (%s, %s) %s NodeId=%s", - NS_ConvertUTF16toUTF8(aData->mOrigin).get(), - NS_ConvertUTF16toUTF8(aData->mTopLevelOrigin).get(), - (aData->mInPrivateBrowsing ? "PrivateBrowsing" : "NonPrivateBrowsing"), - GetNodeId().get()); - - nsTArray tags; - tags.AppendElement(NS_ConvertUTF16toUTF8(mKeySystem)); - - // Note: must capture helper refptr here, before the Move() - // when we create the GetGMPDecryptorCallback below. - RefPtr crashHelper = Move(aData->mCrashHelper); - UniquePtr callback(new gmp_InitDoneCallback(this, - Move(aData))); - nsresult rv = mps->GetGMPDecryptor(crashHelper, - &tags, - GetNodeId(), - Move(callback)); - if (NS_FAILED(rv)) { - RejectPromise(promiseID, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Call to GetGMPDecryptor() failed early")); - } -} - -void -GMPCDMProxy::OnCDMCreated(uint32_t aPromiseId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - MOZ_ASSERT(!GetNodeId().IsEmpty()); - if (mCDM) { - mKeys->OnCDMCreated(aPromiseId, GetNodeId(), mCDM->GetPluginId()); - } else { - // No CDM? Just reject the promise. - mKeys->RejectPromise(aPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in OnCDMCreated()")); - } -} - -void -GMPCDMProxy::CreateSession(uint32_t aCreateSessionToken, - dom::MediaKeySessionType aSessionType, - PromiseId aPromiseId, - const nsAString& aInitDataType, - nsTArray& aInitData) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOwnerThread); - - nsAutoPtr data(new CreateSessionData()); - data->mSessionType = aSessionType; - data->mCreateSessionToken = aCreateSessionToken; - data->mPromiseId = aPromiseId; - data->mInitDataType = NS_ConvertUTF16toUTF8(aInitDataType); - data->mInitData = Move(aInitData); - - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_CreateSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -GMPSessionType -ToGMPSessionType(dom::MediaKeySessionType aSessionType) { - switch (aSessionType) { - case dom::MediaKeySessionType::Temporary: return kGMPTemporySession; - case dom::MediaKeySessionType::Persistent_license: return kGMPPersistentSession; - default: return kGMPTemporySession; - }; -}; - -void -GMPCDMProxy::gmp_CreateSession(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_CreateSession")); - return; - } - mCDM->CreateSession(aData->mCreateSessionToken, - aData->mPromiseId, - aData->mInitDataType, - aData->mInitData, - ToGMPSessionType(aData->mSessionType)); -} - -void -GMPCDMProxy::LoadSession(PromiseId aPromiseId, - const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOwnerThread); - - nsAutoPtr data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_LoadSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_LoadSession(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_LoadSession")); - return; - } - mCDM->LoadSession(aData->mPromiseId, aData->mSessionId); -} - -void -GMPCDMProxy::SetServerCertificate(PromiseId aPromiseId, - nsTArray& aCert) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOwnerThread); - - nsAutoPtr data(new SetServerCertificateData()); - data->mPromiseId = aPromiseId; - data->mCert = Move(aCert); - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_SetServerCertificate, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_SetServerCertificate(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_SetServerCertificate")); - return; - } - mCDM->SetServerCertificate(aData->mPromiseId, aData->mCert); -} - -void -GMPCDMProxy::UpdateSession(const nsAString& aSessionId, - PromiseId aPromiseId, - nsTArray& aResponse) -{ - MOZ_ASSERT(NS_IsMainThread()); - MOZ_ASSERT(mOwnerThread); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - nsAutoPtr data(new UpdateSessionData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - data->mResponse = Move(aResponse); - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_UpdateSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_UpdateSession(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_UpdateSession")); - return; - } - mCDM->UpdateSession(aData->mPromiseId, - aData->mSessionId, - aData->mResponse); -} - -void -GMPCDMProxy::CloseSession(const nsAString& aSessionId, - PromiseId aPromiseId) -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - nsAutoPtr data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_CloseSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_CloseSession(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_CloseSession")); - return; - } - mCDM->CloseSession(aData->mPromiseId, aData->mSessionId); -} - -void -GMPCDMProxy::RemoveSession(const nsAString& aSessionId, - PromiseId aPromiseId) -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_ENSURE_TRUE_VOID(!mKeys.IsNull()); - - nsAutoPtr data(new SessionOpData()); - data->mPromiseId = aPromiseId; - data->mSessionId = NS_ConvertUTF16toUTF8(aSessionId); - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_RemoveSession, data)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); -} - -void -GMPCDMProxy::gmp_RemoveSession(nsAutoPtr aData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - if (!mCDM) { - RejectPromise(aData->mPromiseId, NS_ERROR_DOM_INVALID_STATE_ERR, - NS_LITERAL_CSTRING("Null CDM in gmp_RemoveSession")); - return; - } - mCDM->RemoveSession(aData->mPromiseId, aData->mSessionId); -} - -void -GMPCDMProxy::Shutdown() -{ - MOZ_ASSERT(NS_IsMainThread()); - mKeys.Clear(); - // Note: This may end up being the last owning reference to the GMPCDMProxy. - nsCOMPtr task(NewRunnableMethod(this, &GMPCDMProxy::gmp_Shutdown)); - if (mOwnerThread) { - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); - } -} - -void -GMPCDMProxy::gmp_Shutdown() -{ - MOZ_ASSERT(IsOnOwnerThread()); - - mShutdownCalled = true; - - // Abort any pending decrypt jobs, to awaken any clients waiting on a job. - for (size_t i = 0; i < mDecryptionJobs.Length(); i++) { - DecryptJob* job = mDecryptionJobs[i]; - job->PostResult(AbortedErr); - } - mDecryptionJobs.Clear(); - - if (mCDM) { - mCDM->Close(); - mCDM = nullptr; - } -} - -void -GMPCDMProxy::RejectPromise(PromiseId aId, nsresult aCode, - const nsCString& aReason) -{ - if (NS_IsMainThread()) { - if (!mKeys.IsNull()) { - mKeys->RejectPromise(aId, aCode, aReason); - } - } else { - nsCOMPtr task(new RejectPromiseTask(this, aId, aCode, - aReason)); - NS_DispatchToMainThread(task); - } -} - -void -GMPCDMProxy::ResolvePromise(PromiseId aId) -{ - if (NS_IsMainThread()) { - if (!mKeys.IsNull()) { - mKeys->ResolvePromise(aId); - } else { - NS_WARNING("GMPCDMProxy unable to resolve promise!"); - } - } else { - nsCOMPtr task; - task = NewRunnableMethod(this, - &GMPCDMProxy::ResolvePromise, - aId); - NS_DispatchToMainThread(task); - } -} - -const nsCString& -GMPCDMProxy::GetNodeId() const -{ - return mNodeId; -} - -void -GMPCDMProxy::OnSetSessionId(uint32_t aCreateSessionToken, - const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - - RefPtr session(mKeys->GetPendingSession(aCreateSessionToken)); - if (session) { - session->SetSessionId(aSessionId); - } -} - -void -GMPCDMProxy::OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - mKeys->OnSessionLoaded(aPromiseId, aSuccess); -} - -void -GMPCDMProxy::OnSessionMessage(const nsAString& aSessionId, - dom::MediaKeyMessageType aMessageType, - nsTArray& aMessage) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr session(mKeys->GetSession(aSessionId)); - if (session) { - session->DispatchKeyMessage(aMessageType, aMessage); - } -} - -void -GMPCDMProxy::OnKeyStatusesChange(const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr session(mKeys->GetSession(aSessionId)); - if (session) { - session->DispatchKeyStatusesChange(); - } -} - -void -GMPCDMProxy::OnExpirationChange(const nsAString& aSessionId, - GMPTimestamp aExpiryTime) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr session(mKeys->GetSession(aSessionId)); - if (session) { - session->SetExpiration(static_cast(aExpiryTime)); - } -} - -void -GMPCDMProxy::OnSessionClosed(const nsAString& aSessionId) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr session(mKeys->GetSession(aSessionId)); - if (session) { - session->OnClosed(); - } -} - -void -GMPCDMProxy::OnDecrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray& aDecryptedData) -{ - MOZ_ASSERT(IsOnOwnerThread()); - gmp_Decrypted(aId, aResult, aDecryptedData); -} - -static void -LogToConsole(const nsAString& aMsg) -{ - nsCOMPtr console( - do_GetService("@mozilla.org/consoleservice;1")); - if (!console) { - NS_WARNING("Failed to log message to console."); - return; - } - nsAutoString msg(aMsg); - console->LogStringMessage(msg.get()); -} - -void -GMPCDMProxy::OnSessionError(const nsAString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsAString& aMsg) -{ - MOZ_ASSERT(NS_IsMainThread()); - if (mKeys.IsNull()) { - return; - } - RefPtr session(mKeys->GetSession(aSessionId)); - if (session) { - session->DispatchKeyError(aSystemCode); - } - LogToConsole(aMsg); -} - -void -GMPCDMProxy::OnRejectPromise(uint32_t aPromiseId, - nsresult aDOMException, - const nsCString& aMsg) -{ - MOZ_ASSERT(NS_IsMainThread()); - RejectPromise(aPromiseId, aDOMException, aMsg); -} - -const nsString& -GMPCDMProxy::KeySystem() const -{ - return mKeySystem; -} - -CDMCaps& -GMPCDMProxy::Capabilites() { - return mCapabilites; -} - -RefPtr -GMPCDMProxy::Decrypt(MediaRawData* aSample) -{ - RefPtr job(new DecryptJob(aSample)); - RefPtr promise(job->Ensure()); - - nsCOMPtr task( - NewRunnableMethod>(this, &GMPCDMProxy::gmp_Decrypt, job)); - mOwnerThread->Dispatch(task, NS_DISPATCH_NORMAL); - return promise; -} - -void -GMPCDMProxy::gmp_Decrypt(RefPtr aJob) -{ - MOZ_ASSERT(IsOnOwnerThread()); - - if (!mCDM) { - aJob->PostResult(AbortedErr); - return; - } - - aJob->mId = ++mDecryptionJobCount; - nsTArray data; - data.AppendElements(aJob->mSample->Data(), aJob->mSample->Size()); - mCDM->Decrypt(aJob->mId, aJob->mSample->mCrypto, data); - mDecryptionJobs.AppendElement(aJob.forget()); -} - -void -GMPCDMProxy::gmp_Decrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray& aDecryptedData) -{ - MOZ_ASSERT(IsOnOwnerThread()); -#ifdef DEBUG - bool jobIdFound = false; -#endif - for (size_t i = 0; i < mDecryptionJobs.Length(); i++) { - DecryptJob* job = mDecryptionJobs[i]; - if (job->mId == aId) { -#ifdef DEBUG - jobIdFound = true; -#endif - job->PostResult(aResult, aDecryptedData); - mDecryptionJobs.RemoveElementAt(i); - } - } -#ifdef DEBUG - if (!jobIdFound) { - NS_WARNING("GMPDecryptorChild returned incorrect job ID"); - } -#endif -} - -void -GMPCDMProxy::DecryptJob::PostResult(DecryptStatus aResult) -{ - nsTArray empty; - PostResult(aResult, empty); -} - -void -GMPCDMProxy::DecryptJob::PostResult(DecryptStatus aResult, - const nsTArray& aDecryptedData) -{ - if (aDecryptedData.Length() != mSample->Size()) { - NS_WARNING("CDM returned incorrect number of decrypted bytes"); - } - if (aResult == Ok) { - nsAutoPtr writer(mSample->CreateWriter()); - PodCopy(writer->Data(), - aDecryptedData.Elements(), - std::min(aDecryptedData.Length(), mSample->Size())); - } else if (aResult == NoKeyErr) { - NS_WARNING("CDM returned NoKeyErr"); - // We still have the encrypted sample, so we can re-enqueue it to be - // decrypted again once the key is usable again. - } else { - nsAutoCString str("CDM returned decode failure DecryptStatus="); - str.AppendInt(aResult); - NS_WARNING(str.get()); - } - mPromise.Resolve(DecryptResult(aResult, mSample), __func__); -} - -void -GMPCDMProxy::GetSessionIdsForKeyId(const nsTArray& aKeyId, - nsTArray& aSessionIds) -{ - CDMCaps::AutoLock caps(Capabilites()); - caps.GetSessionIdsForKeyId(aKeyId, aSessionIds); -} - -void -GMPCDMProxy::Terminated() -{ - MOZ_ASSERT(NS_IsMainThread()); - NS_WARNING("CDM terminated"); - if (mCreatePromiseId) { - RejectPromise(mCreatePromiseId, - NS_ERROR_DOM_MEDIA_FATAL_ERR, - NS_LITERAL_CSTRING("Crashed waiting for CDM to initialize")); - mCreatePromiseId = 0; - } - if (!mKeys.IsNull()) { - mKeys->Terminated(); - } -} - -uint32_t -GMPCDMProxy::GetDecryptorId() -{ - return mDecryptorId; -} - -} // namespace mozilla diff --git a/dom/media/gmp/GMPCDMProxy.h b/dom/media/gmp/GMPCDMProxy.h deleted file mode 100644 index a7fae235b6..0000000000 --- a/dom/media/gmp/GMPCDMProxy.h +++ /dev/null @@ -1,265 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 GMPCDMProxy_h_ -#define GMPCDMProxy_h_ - -#include "mozilla/CDMProxy.h" -#include "GMPCDMCallbackProxy.h" -#include "GMPDecryptorProxy.h" - -namespace mozilla { -class MediaRawData; - -// Implementation of CDMProxy which is based on GMP architecture. -class GMPCDMProxy : public CDMProxy { -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(GMPCDMProxy, override) - - typedef MozPromise DecryptPromise; - - GMPCDMProxy(dom::MediaKeys* aKeys, - const nsAString& aKeySystem, - GMPCrashHelper* aCrashHelper, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired); - - void Init(PromiseId aPromiseId, - const nsAString& aOrigin, - const nsAString& aTopLevelOrigin, - const nsAString& aGMPName, - bool aInPrivateBrowsing) override; - - void OnSetDecryptorId(uint32_t aId) override; - - void CreateSession(uint32_t aCreateSessionToken, - dom::MediaKeySessionType aSessionType, - PromiseId aPromiseId, - const nsAString& aInitDataType, - nsTArray& aInitData) override; - - void LoadSession(PromiseId aPromiseId, - const nsAString& aSessionId) override; - - void SetServerCertificate(PromiseId aPromiseId, - nsTArray& aCert) override; - - void UpdateSession(const nsAString& aSessionId, - PromiseId aPromiseId, - nsTArray& aResponse) override; - - void CloseSession(const nsAString& aSessionId, - PromiseId aPromiseId) override; - - void RemoveSession(const nsAString& aSessionId, - PromiseId aPromiseId) override; - - void Shutdown() override; - - void Terminated() override; - - const nsCString& GetNodeId() const override; - - void OnSetSessionId(uint32_t aCreateSessionToken, - const nsAString& aSessionId) override; - - void OnResolveLoadSessionPromise(uint32_t aPromiseId, bool aSuccess) override; - - void OnSessionMessage(const nsAString& aSessionId, - dom::MediaKeyMessageType aMessageType, - nsTArray& aMessage) override; - - void OnExpirationChange(const nsAString& aSessionId, - GMPTimestamp aExpiryTime) override; - - void OnSessionClosed(const nsAString& aSessionId) override; - - void OnSessionError(const nsAString& aSessionId, - nsresult aException, - uint32_t aSystemCode, - const nsAString& aMsg) override; - - void OnRejectPromise(uint32_t aPromiseId, - nsresult aDOMException, - const nsCString& aMsg) override; - - RefPtr Decrypt(MediaRawData* aSample) override; - - void OnDecrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray& aDecryptedData) override; - - void RejectPromise(PromiseId aId, nsresult aExceptionCode, - const nsCString& aReason) override; - - void ResolvePromise(PromiseId aId) override; - - const nsString& KeySystem() const override; - - CDMCaps& Capabilites() override; - - void OnKeyStatusesChange(const nsAString& aSessionId) override; - - void GetSessionIdsForKeyId(const nsTArray& aKeyId, - nsTArray& aSessionIds) override; - -#ifdef DEBUG - bool IsOnOwnerThread() override; -#endif - - uint32_t GetDecryptorId() override; - -private: - friend class gmp_InitDoneCallback; - friend class gmp_InitGetGMPDecryptorCallback; - - struct InitData { - uint32_t mPromiseId; - nsString mOrigin; - nsString mTopLevelOrigin; - nsString mGMPName; - RefPtr mCrashHelper; - bool mInPrivateBrowsing; - }; - - // GMP thread only. - void gmp_Init(nsAutoPtr&& aData); - void gmp_InitDone(GMPDecryptorProxy* aCDM, nsAutoPtr&& aData); - void gmp_InitGetGMPDecryptor(nsresult aResult, - const nsACString& aNodeId, - nsAutoPtr&& aData); - - // GMP thread only. - void gmp_Shutdown(); - - // Main thread only. - void OnCDMCreated(uint32_t aPromiseId); - - struct CreateSessionData { - dom::MediaKeySessionType mSessionType; - uint32_t mCreateSessionToken; - PromiseId mPromiseId; - nsCString mInitDataType; - nsTArray mInitData; - }; - // GMP thread only. - void gmp_CreateSession(nsAutoPtr aData); - - struct SessionOpData { - PromiseId mPromiseId; - nsCString mSessionId; - }; - // GMP thread only. - void gmp_LoadSession(nsAutoPtr aData); - - struct SetServerCertificateData { - PromiseId mPromiseId; - nsTArray mCert; - }; - // GMP thread only. - void gmp_SetServerCertificate(nsAutoPtr aData); - - struct UpdateSessionData { - PromiseId mPromiseId; - nsCString mSessionId; - nsTArray mResponse; - }; - // GMP thread only. - void gmp_UpdateSession(nsAutoPtr aData); - - // GMP thread only. - void gmp_CloseSession(nsAutoPtr aData); - - // GMP thread only. - void gmp_RemoveSession(nsAutoPtr aData); - - class DecryptJob { - public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(DecryptJob) - - explicit DecryptJob(MediaRawData* aSample) - : mId(0) - , mSample(aSample) - { - } - - void PostResult(DecryptStatus aResult, - const nsTArray& aDecryptedData); - void PostResult(DecryptStatus aResult); - - RefPtr Ensure() { - return mPromise.Ensure(__func__); - } - - uint32_t mId; - RefPtr mSample; - private: - ~DecryptJob() {} - MozPromiseHolder mPromise; - }; - // GMP thread only. - void gmp_Decrypt(RefPtr aJob); - - // GMP thread only. - void gmp_Decrypted(uint32_t aId, - DecryptStatus aResult, - const nsTArray& aDecryptedData); - - class RejectPromiseTask : public Runnable { - public: - RejectPromiseTask(GMPCDMProxy* aProxy, - PromiseId aId, - nsresult aCode, - const nsCString& aReason) - : mProxy(aProxy) - , mId(aId) - , mCode(aCode) - , mReason(aReason) - { - } - NS_IMETHOD Run() override { - mProxy->RejectPromise(mId, mCode, mReason); - return NS_OK; - } - private: - RefPtr mProxy; - PromiseId mId; - nsresult mCode; - nsCString mReason; - }; - - ~GMPCDMProxy(); - - GMPCrashHelper* mCrashHelper; - - GMPDecryptorProxy* mCDM; - - nsAutoPtr mCallback; - - // Decryption jobs sent to CDM, awaiting result. - // GMP thread only. - nsTArray> mDecryptionJobs; - - // Number of buffers we've decrypted. Used to uniquely identify - // decryption jobs sent to CDM. Note we can't just use the length of - // mDecryptionJobs as that shrinks as jobs are completed and removed - // from it. - // GMP thread only. - uint32_t mDecryptionJobCount; - - // True if GMPCDMProxy::gmp_Shutdown was called. - // GMP thread only. - bool mShutdownCalled; - - uint32_t mDecryptorId; - - PromiseId mCreatePromiseId; -}; - - -} // namespace mozilla - -#endif // GMPCDMProxy_h_ diff --git a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp b/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp deleted file mode 100644 index 57d4ecec27..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineAdapter.cpp +++ /dev/null @@ -1,168 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "WidevineAdapter.h" -#include "content_decryption_module.h" -#include "VideoUtils.h" -#include "WidevineDecryptor.h" -#include "WidevineUtils.h" -#include "WidevineVideoDecoder.h" -#include "gmp-api/gmp-entrypoints.h" -#include "gmp-api/gmp-decryption.h" -#include "gmp-api/gmp-video-codec.h" -#include "gmp-api/gmp-platform.h" - -static const GMPPlatformAPI* sPlatform = nullptr; - -namespace mozilla { - -GMPErr GMPGetCurrentTime(GMPTimestamp* aOutTime) { - return sPlatform->getcurrenttime(aOutTime); -} - -// Call on main thread only. -GMPErr GMPSetTimerOnMainThread(GMPTask* aTask, int64_t aTimeoutMS) { - return sPlatform->settimer(aTask, aTimeoutMS); -} - -GMPErr GMPCreateRecord(const char* aRecordName, - uint32_t aRecordNameSize, - GMPRecord** aOutRecord, - GMPRecordClient* aClient) -{ - return sPlatform->createrecord(aRecordName, aRecordNameSize, aOutRecord, aClient); -} - -void -WidevineAdapter::SetAdaptee(PRLibrary* aLib) -{ - mLib = aLib; -} - -void* GetCdmHost(int aHostInterfaceVersion, void* aUserData) -{ - Log("GetCdmHostFunc(%d, %p)", aHostInterfaceVersion, aUserData); - WidevineDecryptor* decryptor = reinterpret_cast(aUserData); - MOZ_ASSERT(decryptor); - return static_cast(decryptor); -} - -#define STRINGIFY(s) _STRINGIFY(s) -#define _STRINGIFY(s) #s - -GMPErr -WidevineAdapter::GMPInit(const GMPPlatformAPI* aPlatformAPI) -{ -#ifdef ENABLE_WIDEVINE_LOG - if (getenv("GMP_LOG_FILE")) { - // Clear log file. - FILE* f = fopen(getenv("GMP_LOG_FILE"), "w"); - if (f) { - fclose(f); - } - } -#endif - - sPlatform = aPlatformAPI; - if (!mLib) { - return GMPGenericErr; - } - - auto init = reinterpret_cast( - PR_FindFunctionSymbol(mLib, STRINGIFY(INITIALIZE_CDM_MODULE))); - if (!init) { - return GMPGenericErr; - } - - Log(STRINGIFY(INITIALIZE_CDM_MODULE)"()"); - init(); - - return GMPNoErr; -} - -GMPErr -WidevineAdapter::GMPGetAPI(const char* aAPIName, - void* aHostAPI, - void** aPluginAPI, - uint32_t aDecryptorId) -{ - Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p", - aAPIName, aHostAPI, aPluginAPI, this, aDecryptorId); - if (!strcmp(aAPIName, GMP_API_DECRYPTOR)) { - if (WidevineDecryptor::GetInstance(aDecryptorId)) { - // We only support one CDM instance per PGMPDecryptor. Fail! - Log("WidevineAdapter::GMPGetAPI() Tried to create more than once CDM per IPDL actor! FAIL!"); - return GMPQuotaExceededErr; - } - auto create = reinterpret_cast( - PR_FindFunctionSymbol(mLib, "CreateCdmInstance")); - if (!create) { - Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p FAILED to find CreateCdmInstance", - aAPIName, aHostAPI, aPluginAPI, this, aDecryptorId); - return GMPGenericErr; - } - - WidevineDecryptor* decryptor = new WidevineDecryptor(); - - auto cdm = reinterpret_cast( - create(cdm::ContentDecryptionModule_9::kVersion, - kEMEKeySystemWidevine.get(), - kEMEKeySystemWidevine.Length(), - &GetCdmHost, - decryptor)); - if (!cdm) { - Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p FAILED to create cdm", - aAPIName, aHostAPI, aPluginAPI, this, aDecryptorId); - return GMPGenericErr; - } - Log("cdm: 0x%x", cdm); - RefPtr wrapper(new CDMWrapper(cdm, decryptor)); - decryptor->SetCDM(wrapper, aDecryptorId); - *aPluginAPI = decryptor; - - } else if (!strcmp(aAPIName, GMP_API_VIDEO_DECODER)) { - RefPtr wrapper = WidevineDecryptor::GetInstance(aDecryptorId); - if (!wrapper) { - Log("WidevineAdapter::GMPGetAPI(%s, 0x%p, 0x%p, %u) this=0x%p No cdm for video decoder", - aAPIName, aHostAPI, aPluginAPI, thiss, aDecryptorId); - return GMPGenericErr; - } - *aPluginAPI = new WidevineVideoDecoder(static_cast(aHostAPI), - wrapper); - } - return *aPluginAPI ? GMPNoErr : GMPNotImplementedErr; -} - -void -WidevineAdapter::GMPShutdown() -{ - Log("WidevineAdapter::GMPShutdown()"); - - decltype(::DeinitializeCdmModule)* deinit; - deinit = (decltype(deinit))(PR_FindFunctionSymbol(mLib, "DeinitializeCdmModule")); - if (deinit) { - Log("DeinitializeCdmModule()"); - deinit(); - } -} - -void -WidevineAdapter::GMPSetNodeId(const char* aNodeId, uint32_t aLength) -{ - -} - -/* static */ -bool -WidevineAdapter::Supports(int32_t aModuleVersion, - int32_t aInterfaceVersion, - int32_t aHostVersion) -{ - return aModuleVersion == CDM_MODULE_VERSION && - aInterfaceVersion == cdm::ContentDecryptionModule_9::kVersion && - aHostVersion == cdm::Host_9::kVersion; -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineAdapter.h b/dom/media/gmp/widevine-adapter/WidevineAdapter.h deleted file mode 100644 index 714e041bef..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineAdapter.h +++ /dev/null @@ -1,59 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 WidevineAdapter_h_ -#define WidevineAdapter_h_ - -#include "GMPLoader.h" -#include "prlink.h" -#include "GMPUtils.h" - -struct GMPPlatformAPI; - -namespace mozilla { - -class WidevineAdapter : public gmp::GMPAdapter { -public: - - void SetAdaptee(PRLibrary* aLib) override; - - // These are called in place of the corresponding GMP API functions. - GMPErr GMPInit(const GMPPlatformAPI* aPlatformAPI) override; - GMPErr GMPGetAPI(const char* aAPIName, - void* aHostAPI, - void** aPluginAPI, - uint32_t aDecryptorId) override; - void GMPShutdown() override; - void GMPSetNodeId(const char* aNodeId, uint32_t aLength) override; - - static bool Supports(int32_t aModuleVersion, - int32_t aInterfaceVersion, - int32_t aHostVersion); - -private: - PRLibrary* mLib = nullptr; -}; - -GMPErr GMPCreateThread(GMPThread** aThread); -GMPErr GMPRunOnMainThread(GMPTask* aTask); -GMPErr GMPCreateMutex(GMPMutex** aMutex); - -// Call on main thread only. -GMPErr GMPCreateRecord(const char* aRecordName, - uint32_t aRecordNameSize, - GMPRecord** aOutRecord, - GMPRecordClient* aClient); - -// Call on main thread only. -GMPErr GMPSetTimerOnMainThread(GMPTask* aTask, int64_t aTimeoutMS); - -GMPErr GMPGetCurrentTime(GMPTimestamp* aOutTime); - -GMPErr GMPCreateRecordIterator(RecvGMPRecordIteratorPtr aRecvIteratorFunc, - void* aUserArg); - -} // namespace mozilla - -#endif // WidevineAdapter_h_ diff --git a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp b/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp deleted file mode 100644 index 4d3408804f..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.cpp +++ /dev/null @@ -1,554 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "WidevineDecryptor.h" - -#include "WidevineAdapter.h" -#include "WidevineUtils.h" -#include "WidevineFileIO.h" -#include -#include -#include "base/time.h" - -using namespace cdm; -using namespace std; - -namespace mozilla { - -static map> sDecryptors; - -/* static */ -RefPtr -WidevineDecryptor::GetInstance(uint32_t aInstanceId) -{ - auto itr = sDecryptors.find(aInstanceId); - if (itr != sDecryptors.end()) { - return itr->second; - } - return nullptr; -} - - -WidevineDecryptor::WidevineDecryptor() - : mCallback(nullptr) -{ - Log("WidevineDecryptor created this=%p", this); - AddRef(); // Released in DecryptingComplete(). -} - -WidevineDecryptor::~WidevineDecryptor() -{ - Log("WidevineDecryptor destroyed this=%p", this); -} - -void -WidevineDecryptor::SetCDM(RefPtr aCDM, uint32_t aInstanceId) -{ - mCDM = aCDM; - mInstanceId = aInstanceId; - sDecryptors[mInstanceId] = aCDM; -} - -void -WidevineDecryptor::Init(GMPDecryptorCallback* aCallback, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) -{ - Log("WidevineDecryptor::Init() this=%p distinctiveId=%d persistentState=%d", - this, aDistinctiveIdentifierRequired, aPersistentStateRequired); - MOZ_ASSERT(aCallback); - mCallback = aCallback; - MOZ_ASSERT(mCDM); - mDistinctiveIdentifierRequired = aDistinctiveIdentifierRequired; - mPersistentStateRequired = aPersistentStateRequired; - if (CDM()) { - CDM()->Initialize(aDistinctiveIdentifierRequired, - aPersistentStateRequired); - } -} - -static SessionType -ToCDMSessionType(GMPSessionType aSessionType) -{ - switch (aSessionType) { - case kGMPTemporySession: return kTemporary; - case kGMPPersistentSession: return kPersistentLicense; - case kGMPSessionInvalid: return kTemporary; - // TODO: kPersistentKeyRelease - } - MOZ_ASSERT(false); // Not supposed to get here. - return kTemporary; -} - -void -WidevineDecryptor::CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const char* aInitDataType, - uint32_t aInitDataTypeSize, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) -{ - Log("Decryptor::CreateSession(token=%d, pid=%d)", aCreateSessionToken, aPromiseId); - InitDataType initDataType; - if (!strcmp(aInitDataType, "cenc")) { - initDataType = kCenc; - } else if (!strcmp(aInitDataType, "webm")) { - initDataType = kWebM; - } else if (!strcmp(aInitDataType, "keyids")) { - initDataType = kKeyIds; - } else { - // Invalid init data type - const char* errorMsg = "Invalid init data type when creating session."; - OnRejectPromise(aPromiseId, kExceptionNotSupportedError, 0, errorMsg, sizeof(errorMsg)); - return; - } - mPromiseIdToNewSessionTokens[aPromiseId] = aCreateSessionToken; - CDM()->CreateSessionAndGenerateRequest(aPromiseId, - ToCDMSessionType(aSessionType), - initDataType, - aInitData, aInitDataSize); -} - -void -WidevineDecryptor::LoadSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - Log("Decryptor::LoadSession(pid=%d, %s)", aPromiseId, aSessionId); - // TODO: session type?? - CDM()->LoadSession(aPromiseId, kPersistentLicense, aSessionId, aSessionIdLength); -} - -void -WidevineDecryptor::UpdateSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aResponse, - uint32_t aResponseSize) -{ - Log("Decryptor::UpdateSession(pid=%d, session=%s)", aPromiseId, aSessionId); - CDM()->UpdateSession(aPromiseId, aSessionId, aSessionIdLength, aResponse, aResponseSize); -} - -void -WidevineDecryptor::CloseSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - Log("Decryptor::CloseSession(pid=%d, session=%s)", aPromiseId, aSessionId); - CDM()->CloseSession(aPromiseId, aSessionId, aSessionIdLength); -} - -void -WidevineDecryptor::RemoveSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - Log("Decryptor::RemoveSession(%s)", aSessionId); - CDM()->RemoveSession(aPromiseId, aSessionId, aSessionIdLength); -} - -void -WidevineDecryptor::SetServerCertificate(uint32_t aPromiseId, - const uint8_t* aServerCert, - uint32_t aServerCertSize) -{ - Log("Decryptor::SetServerCertificate()"); - CDM()->SetServerCertificate(aPromiseId, aServerCert, aServerCertSize); -} - -class WidevineDecryptedBlock : public cdm::DecryptedBlock { -public: - - WidevineDecryptedBlock() - : mBuffer(nullptr) - , mTimestamp(0) - { - } - - ~WidevineDecryptedBlock() { - if (mBuffer) { - mBuffer->Destroy(); - mBuffer = nullptr; - } - } - - void SetDecryptedBuffer(cdm::Buffer* aBuffer) override { - mBuffer = aBuffer; - } - - cdm::Buffer* DecryptedBuffer() override { - return mBuffer; - } - - void SetTimestamp(int64_t aTimestamp) override { - mTimestamp = aTimestamp; - } - - int64_t Timestamp() const override { - return mTimestamp; - } - -private: - cdm::Buffer* mBuffer; - int64_t mTimestamp; -}; - -void -WidevineDecryptor::Decrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) -{ - if (!mCallback) { - Log("WidevineDecryptor::Decrypt() this=%p FAIL; !mCallback", this); - return; - } - const GMPEncryptedBufferMetadata* crypto = aMetadata; - InputBuffer sample; - nsTArray subsamples; - InitInputBuffer(crypto, aBuffer->Id(), aBuffer->Data(), aBuffer->Size(), sample, subsamples); - WidevineDecryptedBlock decrypted; - Status rv = CDM()->Decrypt(sample, &decrypted); - Log("Decryptor::Decrypt(timestamp=%lld) rv=%d sz=%d", - sample.timestamp, rv, decrypted.DecryptedBuffer()->Size()); - if (rv == kSuccess) { - aBuffer->Resize(decrypted.DecryptedBuffer()->Size()); - memcpy(aBuffer->Data(), - decrypted.DecryptedBuffer()->Data(), - decrypted.DecryptedBuffer()->Size()); - } - mCallback->Decrypted(aBuffer, ToGMPErr(rv)); -} - -void -WidevineDecryptor::DecryptingComplete() -{ - Log("WidevineDecryptor::DecryptingComplete() this=%p", this); - // Drop our references to the CDMWrapper. When any other references - // held elsewhere are dropped (for example references held by a - // WidevineVideoDecoder, or a runnable), the CDMWrapper destroys - // the CDM. - mCDM = nullptr; - sDecryptors.erase(mInstanceId); - mCallback = nullptr; - Release(); -} - -class WidevineBuffer : public cdm::Buffer { -public: - explicit WidevineBuffer(size_t aSize) { - Log("WidevineBuffer(size=" PRIuSIZE ") created", aSize); - mBuffer.SetLength(aSize); - } - ~WidevineBuffer() { - Log("WidevineBuffer(size=" PRIuSIZE ") destroyed", Size()); - } - void Destroy() override { delete this; } - uint32_t Capacity() const override { return mBuffer.Length(); }; - uint8_t* Data() override { return mBuffer.Elements(); } - void SetSize(uint32_t aSize) override { mBuffer.SetLength(aSize); } - uint32_t Size() const override { return mBuffer.Length(); } - -private: - WidevineBuffer(const WidevineBuffer&); - void operator=(const WidevineBuffer&); - - nsTArray mBuffer; -}; - -Buffer* -WidevineDecryptor::Allocate(uint32_t aCapacity) -{ - Log("Decryptor::Allocate(capacity=%u)", aCapacity); - return new WidevineBuffer(aCapacity); -} - -class TimerTask : public GMPTask { -public: - TimerTask(WidevineDecryptor* aDecryptor, - RefPtr aCDM, - void* aContext) - : mDecryptor(aDecryptor) - , mCDM(aCDM) - , mContext(aContext) - { - } - ~TimerTask() override {} - void Run() override { - mCDM->GetCDM()->TimerExpired(mContext); - } - void Destroy() override { delete this; } -private: - RefPtr mDecryptor; - RefPtr mCDM; - void* mContext; -}; - -void -WidevineDecryptor::SetTimer(int64_t aDelayMs, void* aContext) -{ - Log("Decryptor::SetTimer(delay_ms=%lld, context=0x%x)", aDelayMs, aContext); - if (mCDM) { - GMPSetTimerOnMainThread(new TimerTask(this, mCDM, aContext), aDelayMs); - } -} - -Time -WidevineDecryptor::GetCurrentWallTime() -{ - return base::Time::Now().ToDoubleT(); -} - -void -WidevineDecryptor::OnResolveKeyStatusPromise(uint32_t aPromiseId, - cdm::KeyStatus aKeyStatus) { - //TODO: The callback of GetStatusForPolicy. See Mozilla bug 1404230. -} - -void -WidevineDecryptor::OnResolveNewSessionPromise(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdSize) -{ - if (!mCallback) { - Log("Decryptor::OnResolveNewSessionPromise(aPromiseId=0x%d) FAIL; !mCallback", aPromiseId); - return; - } - Log("Decryptor::OnResolveNewSessionPromise(aPromiseId=0x%d)", aPromiseId); - auto iter = mPromiseIdToNewSessionTokens.find(aPromiseId); - if (iter == mPromiseIdToNewSessionTokens.end()) { - Log("FAIL: Decryptor::OnResolveNewSessionPromise(aPromiseId=%d) unknown aPromiseId", aPromiseId); - return; - } - mCallback->SetSessionId(iter->second, aSessionId, aSessionIdSize); - mCallback->ResolvePromise(aPromiseId); - mPromiseIdToNewSessionTokens.erase(iter); -} - -void -WidevineDecryptor::OnResolvePromise(uint32_t aPromiseId) -{ - if (!mCallback) { - Log("Decryptor::OnResolvePromise(aPromiseId=0x%d) FAIL; !mCallback", aPromiseId); - return; - } - Log("Decryptor::OnResolvePromise(aPromiseId=%d)", aPromiseId); - mCallback->ResolvePromise(aPromiseId); -} - -static GMPDOMException -ConvertCDMExceptionToGMPDOMException(cdm::Exception aException) -{ - switch (aException) { - case kExceptionNotSupportedError: return kGMPNotSupportedError; - case kExceptionInvalidStateError: return kGMPInvalidStateError; - case kExceptionTypeError: return kGMPTypeError; - case kExceptionQuotaExceededError: return kGMPQuotaExceededError; - case kUnknownError: return kGMPInvalidModificationError; // Note: Unique placeholder. - case kClientError: return kGMPAbortError; // Note: Unique placeholder. - case kOutputError: return kGMPSecurityError; // Note: Unique placeholder. - }; - return kGMPInvalidStateError; // Note: Unique placeholder. -} - -// Align with spec, the Exceptions used by CDM to reject promises . -// https://w3c.github.io/encrypted-media/#exceptions -cdm::Exception -ConvertCDMErrorToCDMException(cdm::Error error) { - switch (error) { - case cdm::kNotSupportedError: - return cdm::Exception::kExceptionNotSupportedError; - case cdm::kInvalidStateError: - return cdm::Exception::kExceptionInvalidStateError; - case cdm::kInvalidAccessError: - return cdm::Exception::kExceptionTypeError; - case cdm::kQuotaExceededError: - return cdm::Exception::kExceptionQuotaExceededError; - - case cdm::kUnknownError: - case cdm::kClientError: - case cdm::kOutputError: - break; - } - - return cdm::Exception::kExceptionInvalidStateError; -} - -void -WidevineDecryptor::OnRejectPromise(uint32_t aPromiseId, - cdm::Exception aException, - uint32_t aSystemCode, - const char* aErrorMessage, - uint32_t aErrorMessageSize) -{ - if (!mCallback) { - Log("Decryptor::OnRejectPromise(aPromiseId=%d, err=%d, sysCode=%u, msg=%s) FAIL; !mCallback", - aPromiseId, (int)aException, aSystemCode, aErrorMessage); - return; - } - Log("Decryptor::OnRejectPromise(aPromiseId=%d, err=%d, sysCode=%u, msg=%s)", - aPromiseId, (int)aException, aSystemCode, aErrorMessage); - mCallback->RejectPromise(aPromiseId, - ConvertCDMExceptionToGMPDOMException(aException), - !aErrorMessageSize ? "" : aErrorMessage, - aErrorMessageSize); -} - -static GMPSessionMessageType -ToGMPMessageType(MessageType message_type) -{ - switch (message_type) { - case kLicenseRequest: return kGMPLicenseRequest; - case kLicenseRenewal: return kGMPLicenseRenewal; - case kLicenseRelease: return kGMPLicenseRelease; - } - return kGMPMessageInvalid; -} - -void -WidevineDecryptor::OnSessionMessage(const char* aSessionId, - uint32_t aSessionIdSize, - cdm::MessageType aMessageType, - const char* aMessage, - uint32_t aMessageSize) -{ - if (!mCallback) { - Log("Decryptor::OnSessionMessage() FAIL; !mCallback"); - return; - } - Log("Decryptor::OnSessionMessage()"); - mCallback->SessionMessage(aSessionId, - aSessionIdSize, - ToGMPMessageType(aMessageType), - reinterpret_cast(aMessage), - aMessageSize); -} - -static GMPMediaKeyStatus -ToGMPKeyStatus(KeyStatus aStatus) -{ - switch (aStatus) { - case kUsable: return kGMPUsable; - case kInternalError: return kGMPInternalError; - case kExpired: return kGMPExpired; - case kOutputRestricted: return kGMPOutputRestricted; - case kOutputDownscaled: return kGMPOutputDownscaled; - case kStatusPending: return kGMPStatusPending; - case kReleased: return kGMPReleased; - } - return kGMPUnknown; -} - -void -WidevineDecryptor::OnSessionKeysChange(const char* aSessionId, - uint32_t aSessionIdSize, - bool aHasAdditionalUsableKey, - const KeyInformation* aKeysInfo, - uint32_t aKeysInfoCount) -{ - if (!mCallback) { - Log("Decryptor::OnSessionKeysChange() FAIL; !mCallback"); - return; - } - Log("Decryptor::OnSessionKeysChange()"); - - nsTArray key_infos; - for (uint32_t i = 0; i < aKeysInfoCount; i++) { - key_infos.AppendElement(GMPMediaKeyInfo(aKeysInfo[i].key_id, - aKeysInfo[i].key_id_size, - ToGMPKeyStatus(aKeysInfo[i].status))); - } - mCallback->BatchedKeyStatusChanged(aSessionId, aSessionIdSize, - key_infos.Elements(), key_infos.Length()); -} - -static GMPTimestamp -ToGMPTime(Time aCDMTime) -{ - return static_cast(aCDMTime * 1000); -} - -void -WidevineDecryptor::OnExpirationChange(const char* aSessionId, - uint32_t aSessionIdSize, - Time aNewExpiryTime) -{ - if (!mCallback) { - Log("Decryptor::OnExpirationChange(sid=%s) t=%lf FAIL; !mCallback", - aSessionId, aNewExpiryTime); - return; - } - Log("Decryptor::OnExpirationChange(sid=%s) t=%lf", aSessionId, aNewExpiryTime); - GMPTimestamp expiry = ToGMPTime(aNewExpiryTime); - if (aNewExpiryTime == 0) { - return; - } - mCallback->ExpirationChange(aSessionId, aSessionIdSize, expiry); -} - -void -WidevineDecryptor::OnSessionClosed(const char* aSessionId, - uint32_t aSessionIdSize) -{ - if (!mCallback) { - Log("Decryptor::OnSessionClosed(sid=%s) FAIL; !mCallback", aSessionId); - return; - } - Log("Decryptor::OnSessionClosed(sid=%s)", aSessionId); - mCallback->SessionClosed(aSessionId, aSessionIdSize); -} - -void -WidevineDecryptor::SendPlatformChallenge(const char* aServiceId, - uint32_t aServiceIdSize, - const char* aChallenge, - uint32_t aChallengeSize) -{ - Log("Decryptor::SendPlatformChallenge(service_id=%s)", aServiceId); -} - -void -WidevineDecryptor::EnableOutputProtection(uint32_t aDesiredProtectionMask) -{ - Log("Decryptor::EnableOutputProtection(mask=0x%x)", aDesiredProtectionMask); -} - -void -WidevineDecryptor::QueryOutputProtectionStatus() -{ - Log("Decryptor::QueryOutputProtectionStatus()"); -} - -void -WidevineDecryptor::OnDeferredInitializationDone(StreamType aStreamType, - Status aDecoderStatus) -{ - Log("Decryptor::OnDeferredInitializationDone()"); -} - -FileIO* -WidevineDecryptor::CreateFileIO(FileIOClient* aClient) -{ - Log("Decryptor::CreateFileIO()"); - if (!mPersistentStateRequired) { - return nullptr; - } - return new WidevineFileIO(aClient); -} - -void -WidevineDecryptor::RequestStorageId(uint32_t aVersion) -{ - Log("Decryptor::RequestStorageId() aVersion = %u", aVersion); - if (aVersion >= 0x80000000) { - mCDM->OnStorageId(aVersion, nullptr, 0); - return; - } - - //TODO: Need to provide a menaingful buffer instead of a dummy one. - mCDM->OnStorageId(aVersion, new uint8_t[1024*1024], 1024 * 1024); -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineDecryptor.h b/dom/media/gmp/widevine-adapter/WidevineDecryptor.h deleted file mode 100644 index f291c321d3..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineDecryptor.h +++ /dev/null @@ -1,132 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 WidevineDecryptor_h_ -#define WidevineDecryptor_h_ - -#include "stddef.h" -#include "content_decryption_module.h" -#include "gmp-api/gmp-decryption.h" -#include "mozilla/RefPtr.h" -#include "WidevineUtils.h" -#include - -namespace mozilla { - -class WidevineDecryptor : public GMPDecryptor - , public cdm::Host_9 -{ -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WidevineDecryptor) - - WidevineDecryptor(); - - void SetCDM(RefPtr aCDM, uint32_t aDecryptorId); - - static RefPtr GetInstance(uint32_t aDecryptorId); - - // GMPDecryptor - void Init(GMPDecryptorCallback* aCallback, - bool aDistinctiveIdentifierRequired, - bool aPersistentStateRequired) override; - - void CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const char* aInitDataType, - uint32_t aInitDataTypeSize, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) override; - - void LoadSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - void UpdateSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aResponse, - uint32_t aResponseSize) override; - - void CloseSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - void RemoveSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - void SetServerCertificate(uint32_t aPromiseId, - const uint8_t* aServerCert, - uint32_t aServerCertSize) override; - - void Decrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) override; - - void DecryptingComplete() override; - - - // cdm::Host_9 implementation - cdm::Buffer* Allocate(uint32_t aCapacity) override; - void SetTimer(int64_t aDelayMs, void* aContext) override; - cdm::Time GetCurrentWallTime() override; - // cdm::Host_9 interface - void OnResolveKeyStatusPromise(uint32_t aPromiseId, - cdm::KeyStatus aKeyStatus) override; - void OnResolveNewSessionPromise(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdSize) override; - void OnResolvePromise(uint32_t aPromiseId) override; - void OnRejectPromise(uint32_t aPromiseId, - cdm::Exception aException, - uint32_t aSystemCode, - const char* aErrorMessage, - uint32_t aErrorMessageSize) override; - void OnSessionMessage(const char* aSessionId, - uint32_t aSessionIdSize, - cdm::MessageType aMessageType, - const char* aMessage, - uint32_t aMessageSize) override; - void OnSessionKeysChange(const char* aSessionId, - uint32_t aSessionIdSize, - bool aHasAdditionalUsableKey, - const cdm::KeyInformation* aKeysInfo, - uint32_t aKeysInfoCount) override; - void OnExpirationChange(const char* aSessionId, - uint32_t aSessionIdSize, - cdm::Time aNewExpiryTime) override; - void OnSessionClosed(const char* aSessionId, - uint32_t aSessionIdSize) override; - void SendPlatformChallenge(const char* aServiceId, - uint32_t aServiceIdSize, - const char* aChallenge, - uint32_t aChallengeSize) override; - void EnableOutputProtection(uint32_t aDesiredProtectionMask) override; - void QueryOutputProtectionStatus() override; - void OnDeferredInitializationDone(cdm::StreamType aStreamType, - cdm::Status aDecoderStatus) override; - // cdm::Host_9 interface - // NOTE: the interface has changed upstream. - void RequestStorageId(uint32_t aVersion) override; - cdm::FileIO* CreateFileIO(cdm::FileIOClient* aClient) override; - - GMPDecryptorCallback* Callback() const { return mCallback; } - RefPtr GetCDMWrapper() const { return mCDM; } -private: - ~WidevineDecryptor(); - RefPtr mCDM; - cdm::ContentDecryptionModule_9* CDM() { return mCDM->GetCDM(); } - - GMPDecryptorCallback* mCallback; - std::map mPromiseIdToNewSessionTokens; - bool mDistinctiveIdentifierRequired = false; - bool mPersistentStateRequired = false; - uint32_t mInstanceId = 0; -}; - -} // namespace mozilla - -#endif // WidevineDecryptor_h_ diff --git a/dom/media/gmp/widevine-adapter/WidevineFileIO.cpp b/dom/media/gmp/widevine-adapter/WidevineFileIO.cpp deleted file mode 100644 index b5fb1d705c..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineFileIO.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include "WidevineFileIO.h" -#include "WidevineUtils.h" -#include "WidevineAdapter.h" - -using namespace cdm; - -namespace mozilla { - -void -WidevineFileIO::Open(const char* aFilename, uint32_t aFilenameLength) -{ - mName = std::string(aFilename, aFilename + aFilenameLength); - GMPRecord* record = nullptr; - GMPErr err = GMPCreateRecord(aFilename, aFilenameLength, &record, static_cast(this)); - if (GMP_FAILED(err)) { - Log("WidevineFileIO::Open() '%s' GMPCreateRecord failed", mName.c_str()); - mClient->OnOpenComplete(FileIOClient::kError); - return; - } - if (GMP_FAILED(record->Open())) { - Log("WidevineFileIO::Open() '%s' record open failed", mName.c_str()); - mClient->OnOpenComplete(FileIOClient::kError); - return; - } - - Log("WidevineFileIO::Open() '%s'", mName.c_str()); - mRecord = record; -} - -void -WidevineFileIO::Read() -{ - if (!mRecord) { - Log("WidevineFileIO::Read() '%s' used uninitialized!", mName.c_str()); - mClient->OnReadComplete(FileIOClient::kError, nullptr, 0); - return; - } - Log("WidevineFileIO::Read() '%s'", mName.c_str()); - mRecord->Read(); -} - -void -WidevineFileIO::Write(const uint8_t* aData, uint32_t aDataSize) -{ - if (!mRecord) { - Log("WidevineFileIO::Write() '%s' used uninitialized!", mName.c_str()); - mClient->OnWriteComplete(FileIOClient::kError); - return; - } - mRecord->Write(aData, aDataSize); -} - -void -WidevineFileIO::Close() -{ - Log("WidevineFileIO::Close() '%s'", mName.c_str()); - if (mRecord) { - mRecord->Close(); - mRecord = nullptr; - } - delete this; -} - -static FileIOClient::Status -GMPToWidevineFileStatus(GMPErr aStatus) -{ - switch (aStatus) { - case GMPRecordInUse: return FileIOClient::kInUse; - case GMPNoErr: return FileIOClient::kSuccess; - default: return FileIOClient::kError; - } -} - -void -WidevineFileIO::OpenComplete(GMPErr aStatus) -{ - Log("WidevineFileIO::OpenComplete() '%s' status=%d", mName.c_str(), aStatus); - mClient->OnOpenComplete(GMPToWidevineFileStatus(aStatus)); -} - -void -WidevineFileIO::ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aDataSize) -{ - Log("WidevineFileIO::OnReadComplete() '%s' status=%d", mName.c_str(), aStatus); - mClient->OnReadComplete(GMPToWidevineFileStatus(aStatus), aData, aDataSize); -} - -void -WidevineFileIO::WriteComplete(GMPErr aStatus) -{ - Log("WidevineFileIO::WriteComplete() '%s' status=%d", mName.c_str(), aStatus); - mClient->OnWriteComplete(GMPToWidevineFileStatus(aStatus)); -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineFileIO.h b/dom/media/gmp/widevine-adapter/WidevineFileIO.h deleted file mode 100644 index 63003d9b60..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineFileIO.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 WidevineFileIO_h_ -#define WidevineFileIO_h_ - -#include -#include "content_decryption_module.h" -#include "gmp-api/gmp-storage.h" -#include - -namespace mozilla { - -class WidevineFileIO : public cdm::FileIO - , public GMPRecordClient -{ -public: - explicit WidevineFileIO(cdm::FileIOClient* aClient) - : mClient(aClient) - , mRecord(nullptr) - {} - - // cdm::FileIO - void Open(const char* aFilename, uint32_t aFilenameLength) override; - void Read() override; - void Write(const uint8_t* aData, uint32_t aDataSize) override; - void Close() override; - - // GMPRecordClient - void OpenComplete(GMPErr aStatus) override; - void ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aDataSize) override; - void WriteComplete(GMPErr aStatus) override; - -private: - cdm::FileIOClient* mClient; - GMPRecord* mRecord; - std::string mName; -}; - -} // namespace mozilla - -#endif // WidevineFileIO_h_ \ No newline at end of file diff --git a/dom/media/gmp/widevine-adapter/WidevineUtils.cpp b/dom/media/gmp/widevine-adapter/WidevineUtils.cpp deleted file mode 100644 index 10c6c2e18c..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineUtils.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "WidevineUtils.h" -#include "WidevineDecryptor.h" - -#include "gmp-api/gmp-errors.h" -#include -#include - -namespace mozilla { - -#ifdef ENABLE_WIDEVINE_LOG -void -Log(const char* aFormat, ...) -{ - va_list ap; - va_start(ap, aFormat); - const size_t len = 1024; - char buf[len]; - vsnprintf(buf, len, aFormat, ap); - va_end(ap); - if (getenv("GMP_LOG_FILE")) { - FILE* f = fopen(getenv("GMP_LOG_FILE"), "a"); - if (f) { - fprintf(f, "%s\n", buf); - fflush(f); - fclose(f); - f = nullptr; - } - } else { - printf("LOG: %s\n", buf); - } -} -#endif // ENABLE_WIDEVINE_LOG - -GMPErr -ToGMPErr(cdm::Status aStatus) -{ - switch (aStatus) { - case cdm::kSuccess: return GMPNoErr; - case cdm::kNeedMoreData: return GMPGenericErr; - case cdm::kNoKey: return GMPNoKeyErr; - case cdm::kInitializationError: return GMPGenericErr; - case cdm::kDecryptError: return GMPCryptoErr; - case cdm::kDecodeError: return GMPDecodeErr; - case cdm::kDeferredInitialization: return GMPGenericErr; - default: return GMPGenericErr; - } -} - -void InitInputBuffer(const GMPEncryptedBufferMetadata* aCrypto, - int64_t aTimestamp, - const uint8_t* aData, - size_t aDataSize, - cdm::InputBuffer &aInputBuffer, - nsTArray &aSubsamples) -{ - if (aCrypto) { - aInputBuffer.key_id = aCrypto->KeyId(); - aInputBuffer.key_id_size = aCrypto->KeyIdSize(); - aInputBuffer.iv = aCrypto->IV(); - aInputBuffer.iv_size = aCrypto->IVSize(); - aInputBuffer.num_subsamples = aCrypto->NumSubsamples(); - aSubsamples.SetCapacity(aInputBuffer.num_subsamples); - const uint16_t* clear = aCrypto->ClearBytes(); - const uint32_t* cipher = aCrypto->CipherBytes(); - for (size_t i = 0; i < aCrypto->NumSubsamples(); i++) { - aSubsamples.AppendElement(cdm::SubsampleEntry(clear[i], cipher[i])); - } - } - aInputBuffer.data = aData; - aInputBuffer.data_size = aDataSize; - aInputBuffer.subsamples = aSubsamples.Elements(); - aInputBuffer.timestamp = aTimestamp; -} - -CDMWrapper::CDMWrapper(cdm::ContentDecryptionModule_9* aCDM, - WidevineDecryptor* aDecryptor) - : mCDM(aCDM) - , mDecryptor(aDecryptor) -{ - MOZ_ASSERT(mCDM); -} - -CDMWrapper::~CDMWrapper() -{ - Log("CDMWrapper destroying CDM=%p", mCDM); - mCDM->Destroy(); - mCDM = nullptr; -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineUtils.h b/dom/media/gmp/widevine-adapter/WidevineUtils.h deleted file mode 100644 index 2f6137fe3b..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineUtils.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 WidevineUtils_h_ -#define WidevineUtils_h_ - -#include "stddef.h" -#include "content_decryption_module.h" -#include "gmp-api/gmp-decryption.h" -#include "gmp-api/gmp-platform.h" -#include "nsISupportsImpl.h" -#include "nsTArray.h" - -namespace mozilla { - -// Uncomment for logging... -//#define ENABLE_WIDEVINE_LOG 1 -#ifdef ENABLE_WIDEVINE_LOG -void -Log(const char* aFormat, ...); -#else -#define Log(...) -#endif // ENABLE_WIDEVINE_LOG - - -#define ENSURE_TRUE(condition, rv) { \ - if (!(condition)) {\ - Log("ENSURE_TRUE FAILED %s:%d", __FILE__, __LINE__); \ - return rv; \ - } \ -} \ - -#define ENSURE_GMP_SUCCESS(err, rv) { \ - if (GMP_FAILED(err)) {\ - Log("ENSURE_GMP_SUCCESS FAILED %s:%d", __FILE__, __LINE__); \ - return rv; \ - } \ -} \ - -GMPErr -ToGMPErr(cdm::Status aStatus); - -class WidevineDecryptor; - -class CDMWrapper { -public: - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(CDMWrapper) - - explicit CDMWrapper(cdm::ContentDecryptionModule_9* aCDM, - WidevineDecryptor* aDecryptor); - cdm::ContentDecryptionModule_9* GetCDM() const { return mCDM; } - void OnStorageId(uint32_t aVersion, const uint8_t* aStorageId, - uint32_t aStorageIdSize) { - mCDM->OnStorageId(aVersion, aStorageId, aStorageIdSize); - } -private: - ~CDMWrapper(); - cdm::ContentDecryptionModule_9* mCDM; - RefPtr mDecryptor; -}; - -void InitInputBuffer(const GMPEncryptedBufferMetadata* aCrypto, - int64_t aTimestamp, - const uint8_t* aData, - size_t aDataSize, - cdm::InputBuffer &aInputBuffer, - nsTArray &aSubsamples); - -} // namespace mozilla - -#endif // WidevineUtils_h_ diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.cpp b/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.cpp deleted file mode 100644 index 70d2fd8e08..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.cpp +++ /dev/null @@ -1,400 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "WidevineVideoDecoder.h" - -#include "mp4_demuxer/AnnexB.h" -#include "WidevineUtils.h" -#include "WidevineVideoFrame.h" -#include "mozilla/Move.h" - -using namespace cdm; - -namespace mozilla { - -WidevineVideoDecoder::WidevineVideoDecoder(GMPVideoHost* aVideoHost, - RefPtr aCDMWrapper) - : mVideoHost(aVideoHost) - , mCDMWrapper(Move(aCDMWrapper)) - , mExtraData(new MediaByteBuffer()) - , mSentInput(false) - , mCodecType(kGMPVideoCodecInvalid) - , mReturnOutputCallDepth(0) - , mDrainPending(false) - , mResetInProgress(false) -{ - // Expect to start with a CDM wrapper, will release it in DecodingComplete(). - MOZ_ASSERT(mCDMWrapper); - Log("WidevineVideoDecoder created this=%p", this); - - // Corresponding Release is in DecodingComplete(). - AddRef(); -} - -WidevineVideoDecoder::~WidevineVideoDecoder() -{ - Log("WidevineVideoDecoder destroyed this=%p", this); -} - -static -VideoDecoderConfig::VideoCodecProfile -ToCDMH264Profile(uint8_t aProfile) -{ - switch (aProfile) { - case 66: return VideoDecoderConfig::kH264ProfileBaseline; - case 77: return VideoDecoderConfig::kH264ProfileMain; - case 88: return VideoDecoderConfig::kH264ProfileExtended; - case 100: return VideoDecoderConfig::kH264ProfileHigh; - case 110: return VideoDecoderConfig::kH264ProfileHigh10; - case 122: return VideoDecoderConfig::kH264ProfileHigh422; - case 144: return VideoDecoderConfig::kH264ProfileHigh444Predictive; - } - return VideoDecoderConfig::kUnknownVideoCodecProfile; -} - -void -WidevineVideoDecoder::InitDecode(const GMPVideoCodec& aCodecSettings, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - GMPVideoDecoderCallback* aCallback, - int32_t aCoreCount) -{ - mCallback = aCallback; - VideoDecoderConfig config; - mCodecType = aCodecSettings.mCodecType; - if (mCodecType == kGMPVideoCodecH264) { - config.codec = VideoDecoderConfig::kCodecH264; - const GMPVideoCodecH264* h264 = (const GMPVideoCodecH264*)(aCodecSpecific); - config.profile = ToCDMH264Profile(h264->mAVCC.mProfile); - } else if (mCodecType == kGMPVideoCodecVP8) { - config.codec = VideoDecoderConfig::kCodecVp8; - config.profile = VideoDecoderConfig::kProfileNotNeeded; - } else if (mCodecType == kGMPVideoCodecVP9) { - config.codec = VideoDecoderConfig::kCodecVp9; - config.profile = VideoDecoderConfig::kProfileNotNeeded; - } else { - mCallback->Error(GMPInvalidArgErr); - return; - } - config.format = kYv12; - config.coded_size = Size(aCodecSettings.mWidth, aCodecSettings.mHeight); - mExtraData->AppendElements(aCodecSpecific + 1, aCodecSpecificLength); - config.extra_data = mExtraData->Elements(); - config.extra_data_size = mExtraData->Length(); - Status rv = CDM()->InitializeVideoDecoder(config); - if (rv != kSuccess) { - mCallback->Error(ToGMPErr(rv)); - return; - } - Log("WidevineVideoDecoder::InitDecode() rv=%d", rv); - mAnnexB = mp4_demuxer::AnnexB::ConvertExtraDataToAnnexB(mExtraData); -} - -void -WidevineVideoDecoder::Decode(GMPVideoEncodedFrame* aInputFrame, - bool aMissingFrames, - const uint8_t* aCodecSpecificInfo, - uint32_t aCodecSpecificInfoLength, - int64_t aRenderTimeMs) -{ - // We should not be given new input if a drain has been initiated - MOZ_ASSERT(!mDrainPending); - // We may not get the same out of the CDM decoder as we put in, and there - // may be some latency, i.e. we may need to input (say) 30 frames before - // we receive output. So we need to store the durations of the frames input, - // and retrieve them on output. - mFrameDurations[aInputFrame->TimeStamp()] = aInputFrame->Duration(); - - mSentInput = true; - InputBuffer sample; - - RefPtr raw( - new MediaRawData(aInputFrame->Buffer(), aInputFrame->Size())); - if (aInputFrame->Size() && !raw->Data()) { - // OOM. - mCallback->Error(GMPAllocErr); - return; - } - raw->mExtraData = mExtraData; - raw->mKeyframe = (aInputFrame->FrameType() == kGMPKeyFrame); - if (mCodecType == kGMPVideoCodecH264) { - // Convert input from AVCC, which GMPAPI passes in, to AnnexB, which - // Chromium uses internally. - mp4_demuxer::AnnexB::ConvertSampleToAnnexB(raw); - } - - const GMPEncryptedBufferMetadata* crypto = aInputFrame->GetDecryptionData(); - nsTArray subsamples; - InitInputBuffer(crypto, aInputFrame->TimeStamp(), raw->Data(), raw->Size(), sample, subsamples); - - // For keyframes, ConvertSampleToAnnexB will stick the AnnexB extra data - // at the start of the input. So we need to account for that as clear data - // in the subsamples. - if (raw->mKeyframe && !subsamples.IsEmpty() && mCodecType == kGMPVideoCodecH264) { - subsamples[0].clear_bytes += mAnnexB->Length(); - } - - WidevineVideoFrame frame; - Status rv = CDM()->DecryptAndDecodeFrame(sample, &frame); - Log("WidevineVideoDecoder::Decode(timestamp=%lld) rv=%d", sample.timestamp, rv); - - // Destroy frame, so that the shmem is now free to be used to return - // output to the Gecko process. - aInputFrame->Destroy(); - aInputFrame = nullptr; - - if (rv == kSuccess) { - if (!ReturnOutput(frame)) { - Log("WidevineVideoDecoder::Decode() Failed in ReturnOutput()"); - mCallback->Error(GMPDecodeErr); - return; - } - // A reset should only be started at most at level mReturnOutputCallDepth 1, - // and if it's started it should be finished by that call by the time - // the it returns, so it should always be false by this point. - MOZ_ASSERT(!mResetInProgress); - // Only request more data if we don't have pending samples. - if (mFrameAllocationQueue.empty()) { - MOZ_ASSERT(mCDMWrapper); - mCallback->InputDataExhausted(); - } - } else if (rv == kNeedMoreData) { - MOZ_ASSERT(mCDMWrapper); - mCallback->InputDataExhausted(); - } else { - mCallback->Error(ToGMPErr(rv)); - } - // Finish a drain if pending and we have no pending ReturnOutput calls on the stack. - if (mDrainPending && mReturnOutputCallDepth == 0) { - Drain(); - } -} - -// Util class to assist with counting mReturnOutputCallDepth. -class CounterHelper { -public: - // RAII, increment counter - explicit CounterHelper(int32_t& counter) - : mCounter(counter) - { - mCounter++; - } - - // RAII, decrement counter - ~CounterHelper() - { - mCounter--; - } - -private: - int32_t& mCounter; -}; - -// Util class to make sure GMP frames are freed. Holds a GMPVideoi420Frame* -// and will destroy it when the helper is destroyed unless the held frame -// if forgotten with ForgetFrame. -class FrameDestroyerHelper { -public: - explicit FrameDestroyerHelper(GMPVideoi420Frame*& frame) - : frame(frame) - { - } - - // RAII, destroy frame if held. - ~FrameDestroyerHelper() - { - if (frame) { - frame->Destroy(); - } - frame = nullptr; - } - - // Forget the frame without destroying it. - void ForgetFrame() - { - frame = nullptr; - } - -private: - GMPVideoi420Frame* frame; -}; - - -// Special handing is needed around ReturnOutput as it spins the IPC message -// queue when creating an empty frame and can end up with reentrant calls into -// the class methods. -bool -WidevineVideoDecoder::ReturnOutput(WidevineVideoFrame& aCDMFrame) -{ - MOZ_ASSERT(mReturnOutputCallDepth >= 0); - CounterHelper counterHelper(mReturnOutputCallDepth); - mFrameAllocationQueue.push_back(Move(aCDMFrame)); - if (mReturnOutputCallDepth > 1) { - // In a reentrant call. - return true; - } - while (!mFrameAllocationQueue.empty()) { - MOZ_ASSERT(mReturnOutputCallDepth == 1); - // If we're at call level 1 a reset should not have been started. A - // reset may be received during CreateEmptyFrame below, but we should not - // be in a reset at this stage -- this would indicate receiving decode - // messages before completing our reset, which we should not. - MOZ_ASSERT(!mResetInProgress); - WidevineVideoFrame currentCDMFrame = Move(mFrameAllocationQueue.front()); - mFrameAllocationQueue.pop_front(); - GMPVideoFrame* f = nullptr; - auto err = mVideoHost->CreateFrame(kGMPI420VideoFrame, &f); - if (GMP_FAILED(err) || !f) { - Log("Failed to create i420 frame!\n"); - return false; - } - auto gmpFrame = static_cast(f); - FrameDestroyerHelper frameDestroyerHelper(gmpFrame); - Size size = currentCDMFrame.Size(); - const int32_t yStride = currentCDMFrame.Stride(VideoFrame::kYPlane); - const int32_t uStride = currentCDMFrame.Stride(VideoFrame::kUPlane); - const int32_t vStride = currentCDMFrame.Stride(VideoFrame::kVPlane); - const int32_t halfHeight = size.height / 2; - // This call can cause a shmem alloc, during this alloc other calls - // may be made to this class and placed on the stack. ***WARNING***: - // other IPC calls can happen during this call, resulting in calls - // being made to the CDM. After this call state can have changed, - // and should be reevaluated. - err = gmpFrame->CreateEmptyFrame(size.width, - size.height, - yStride, - uStride, - vStride); - // Assert possible reentrant calls or resets haven't altered level unexpectedly. - MOZ_ASSERT(mReturnOutputCallDepth == 1); - ENSURE_GMP_SUCCESS(err, false); - - // If a reset started we need to dump the current frame and complete the reset. - if (mResetInProgress) { - MOZ_ASSERT(mCDMWrapper); - MOZ_ASSERT(mFrameAllocationQueue.empty()); - CompleteReset(); - return true; - } - - err = gmpFrame->SetWidth(size.width); - ENSURE_GMP_SUCCESS(err, false); - - err = gmpFrame->SetHeight(size.height); - ENSURE_GMP_SUCCESS(err, false); - - Buffer* buffer = currentCDMFrame.FrameBuffer(); - uint8_t* outBuffer = gmpFrame->Buffer(kGMPYPlane); - ENSURE_TRUE(outBuffer != nullptr, false); - MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPYPlane) >= yStride*size.height); - memcpy(outBuffer, - buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kYPlane), - yStride * size.height); - - outBuffer = gmpFrame->Buffer(kGMPUPlane); - ENSURE_TRUE(outBuffer != nullptr, false); - MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPUPlane) >= uStride * halfHeight); - memcpy(outBuffer, - buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kUPlane), - uStride * halfHeight); - - outBuffer = gmpFrame->Buffer(kGMPVPlane); - ENSURE_TRUE(outBuffer != nullptr, false); - MOZ_ASSERT(gmpFrame->AllocatedSize(kGMPVPlane) >= vStride * halfHeight); - memcpy(outBuffer, - buffer->Data() + currentCDMFrame.PlaneOffset(VideoFrame::kVPlane), - vStride * halfHeight); - - gmpFrame->SetTimestamp(currentCDMFrame.Timestamp()); - - auto d = mFrameDurations.find(currentCDMFrame.Timestamp()); - if (d != mFrameDurations.end()) { - gmpFrame->SetDuration(d->second); - mFrameDurations.erase(d); - } - - // Forget frame so it's not deleted, call back taking ownership. - frameDestroyerHelper.ForgetFrame(); - mCallback->Decoded(gmpFrame); - } - - return true; -} - -void -WidevineVideoDecoder::Reset() -{ - Log("WidevineVideoDecoder::Reset() mSentInput=%d", mSentInput); - // We shouldn't reset if a drain is pending. - MOZ_ASSERT(!mDrainPending); - mResetInProgress = true; - if (mSentInput) { - CDM()->ResetDecoder(kStreamTypeVideo); - } - // Remove queued frames, but do not reset mReturnOutputCallDepth, let the - // ReturnOutput calls unwind and decrement the counter as needed. - mFrameAllocationQueue.clear(); - mFrameDurations.clear(); - // Only if no ReturnOutput calls are in progress can we complete, otherwise - // ReturnOutput needs to finalize the reset. - if (mReturnOutputCallDepth == 0) { - CompleteReset(); - } -} - -void -WidevineVideoDecoder::CompleteReset() -{ - mCallback->ResetComplete(); - mSentInput = false; - mResetInProgress = false; -} - -void -WidevineVideoDecoder::Drain() -{ - Log("WidevineVideoDecoder::Drain()"); - if (mReturnOutputCallDepth > 0) { - Log("Drain call is reentrant, postponing drain"); - mDrainPending = true; - return; - } - - Status rv = kSuccess; - while (rv == kSuccess) { - WidevineVideoFrame frame; - InputBuffer sample; - Status rv = CDM()->DecryptAndDecodeFrame(sample, &frame); - Log("WidevineVideoDecoder::Drain(); DecryptAndDecodeFrame() rv=%d", rv); - if (frame.Format() == kUnknownVideoFormat) { - break; - } - if (rv == kSuccess) { - if (!ReturnOutput(frame)) { - Log("WidevineVideoDecoder::Decode() Failed in ReturnOutput()"); - } - } - } - // Shouldn't be reset while draining. - MOZ_ASSERT(!mResetInProgress); - - CDM()->ResetDecoder(kStreamTypeVideo); - mDrainPending = false; - mCallback->DrainComplete(); -} - -void -WidevineVideoDecoder::DecodingComplete() -{ - Log("WidevineVideoDecoder::DecodingComplete()"); - if (mCDMWrapper) { - CDM()->DeinitializeDecoder(kStreamTypeVideo); - mCDMWrapper = nullptr; - } - // Release that corresponds to AddRef() in constructor. - Release(); -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h b/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h deleted file mode 100644 index f5e63519be..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineVideoDecoder.h +++ /dev/null @@ -1,80 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 WidevineVideoDecoder_h_ -#define WidevineVideoDecoder_h_ - -#include "stddef.h" -#include "content_decryption_module.h" -#include "gmp-api/gmp-video-decode.h" -#include "gmp-api/gmp-video-host.h" -#include "MediaData.h" -#include "nsISupportsImpl.h" -#include "nsTArray.h" -#include "WidevineDecryptor.h" -#include "WidevineVideoFrame.h" -#include -#include - -namespace mozilla { - -class WidevineVideoDecoder : public GMPVideoDecoder { -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(WidevineVideoDecoder) - - WidevineVideoDecoder(GMPVideoHost* aVideoHost, - RefPtr aCDMWrapper); - void InitDecode(const GMPVideoCodec& aCodecSettings, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - GMPVideoDecoderCallback* aCallback, - int32_t aCoreCount) override; - void Decode(GMPVideoEncodedFrame* aInputFrame, - bool aMissingFrames, - const uint8_t* aCodecSpecificInfo, - uint32_t aCodecSpecificInfoLength, - int64_t aRenderTimeMs = -1) override; - void Reset() override; - void Drain() override; - void DecodingComplete() override; - -private: - - ~WidevineVideoDecoder(); - - cdm::ContentDecryptionModule_9* CDM() const { - // CDM should only be accessed before 'DecodingComplete'. - MOZ_ASSERT(mCDMWrapper); - // CDMWrapper ensure the CDM is non-null, no need to check again. - return mCDMWrapper->GetCDM(); - } - - bool ReturnOutput(WidevineVideoFrame& aFrame); - void CompleteReset(); - - GMPVideoHost* mVideoHost; - RefPtr mCDMWrapper; - RefPtr mExtraData; - RefPtr mAnnexB; - GMPVideoDecoderCallback* mCallback; - std::map mFrameDurations; - bool mSentInput; - GMPVideoCodecType mCodecType; - // Frames waiting on allocation - std::deque mFrameAllocationQueue; - // Number of calls of ReturnOutput currently in progress. - int32_t mReturnOutputCallDepth; - // If we're waiting to drain. Used to prevent drain completing while - // ReturnOutput calls are still on the stack. - bool mDrainPending; - // If a reset is being performed. Used to track if ReturnOutput should - // dump current frame. - bool mResetInProgress; -}; - -} // namespace mozilla - -#endif // WidevineVideoDecoder_h_ diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp b/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp deleted file mode 100644 index 4221bf15b8..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "WidevineVideoFrame.h" - -#include "WidevineUtils.h" - -using namespace cdm; - -namespace mozilla { - -WidevineVideoFrame::WidevineVideoFrame() - : mFormat(kUnknownVideoFormat) - , mSize(0,0) - , mBuffer(nullptr) - , mTimestamp(0) -{ - Log("WidevineVideoFrame::WidevineVideoFrame() this=%p", this); - memset(mPlaneOffsets, 0, sizeof(mPlaneOffsets)); - memset(mPlaneStrides, 0, sizeof(mPlaneStrides)); -} - -WidevineVideoFrame::WidevineVideoFrame(WidevineVideoFrame&& aOther) - : mFormat(aOther.mFormat) - , mSize(aOther.mSize) - , mBuffer(aOther.mBuffer) - , mTimestamp(aOther.mTimestamp) -{ - Log("WidevineVideoFrame::WidevineVideoFrame(WidevineVideoFrame&&) this=%p, other=%p", - this, &aOther); - memcpy(mPlaneOffsets, aOther.mPlaneOffsets, sizeof(mPlaneOffsets)); - memcpy(mPlaneStrides, aOther.mPlaneStrides, sizeof(mPlaneStrides)); - aOther.mBuffer = nullptr; -} - -WidevineVideoFrame::~WidevineVideoFrame() -{ - if (mBuffer) { - mBuffer->Destroy(); - mBuffer = nullptr; - } -} - -void -WidevineVideoFrame::SetFormat(cdm::VideoFormat aFormat) -{ - Log("WidevineVideoFrame::SetFormat(%d) this=%p", aFormat, this); - mFormat = aFormat; -} - -cdm::VideoFormat -WidevineVideoFrame::Format() const -{ - return mFormat; -} - -void -WidevineVideoFrame::SetSize(cdm::Size aSize) -{ - Log("WidevineVideoFrame::SetSize(%d,%d) this=%p", aSize.width, aSize.height, this); - mSize.width = aSize.width; - mSize.height = aSize.height; -} - -cdm::Size -WidevineVideoFrame::Size() const -{ - return mSize; -} - -void -WidevineVideoFrame::SetFrameBuffer(cdm::Buffer* aFrameBuffer) -{ - Log("WidevineVideoFrame::SetFrameBuffer(%p) this=%p", aFrameBuffer, this); - MOZ_ASSERT(!mBuffer); - mBuffer = aFrameBuffer; -} - -cdm::Buffer* -WidevineVideoFrame::FrameBuffer() -{ - return mBuffer; -} - -void -WidevineVideoFrame::SetPlaneOffset(cdm::VideoFrame::VideoPlane aPlane, uint32_t aOffset) -{ - Log("WidevineVideoFrame::SetPlaneOffset(%d, %d) this=%p", aPlane, aOffset, this); - mPlaneOffsets[aPlane] = aOffset; -} - -uint32_t -WidevineVideoFrame::PlaneOffset(cdm::VideoFrame::VideoPlane aPlane) -{ - return mPlaneOffsets[aPlane]; -} - -void -WidevineVideoFrame::SetStride(cdm::VideoFrame::VideoPlane aPlane, uint32_t aStride) -{ - Log("WidevineVideoFrame::SetStride(%d, %d) this=%p", aPlane, aStride, this); - mPlaneStrides[aPlane] = aStride; -} - -uint32_t -WidevineVideoFrame::Stride(cdm::VideoFrame::VideoPlane aPlane) -{ - return mPlaneStrides[aPlane]; -} - -void -WidevineVideoFrame::SetTimestamp(int64_t timestamp) -{ - Log("WidevineVideoFrame::SetTimestamp(%lld) this=%p", timestamp, this); - mTimestamp = timestamp; -} - -int64_t -WidevineVideoFrame::Timestamp() const -{ - return mTimestamp; -} - -} // namespace mozilla diff --git a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.h b/dom/media/gmp/widevine-adapter/WidevineVideoFrame.h deleted file mode 100644 index 96d4f20f8e..0000000000 --- a/dom/media/gmp/widevine-adapter/WidevineVideoFrame.h +++ /dev/null @@ -1,50 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 WidevineVideoFrame_h_ -#define WidevineVideoFrame_h_ - -#include "stddef.h" -#include "content_decryption_module.h" -#include - -namespace mozilla { - -class WidevineVideoFrame : public cdm::VideoFrame { -public: - WidevineVideoFrame(); - WidevineVideoFrame(WidevineVideoFrame&& other); - ~WidevineVideoFrame(); - - void SetFormat(cdm::VideoFormat aFormat) override; - cdm::VideoFormat Format() const override; - - void SetSize(cdm::Size aSize) override; - cdm::Size Size() const override; - - void SetFrameBuffer(cdm::Buffer* aFrameBuffer) override; - cdm::Buffer* FrameBuffer() override; - - void SetPlaneOffset(cdm::VideoFrame::VideoPlane aPlane, uint32_t aOffset) override; - uint32_t PlaneOffset(cdm::VideoFrame::VideoPlane aPlane) override; - - void SetStride(cdm::VideoFrame::VideoPlane aPlane, uint32_t aStride) override; - uint32_t Stride(cdm::VideoFrame::VideoPlane aPlane) override; - - void SetTimestamp(int64_t aTimestamp) override; - int64_t Timestamp() const override; - -protected: - cdm::VideoFormat mFormat; - cdm::Size mSize; - cdm::Buffer* mBuffer; - uint32_t mPlaneOffsets[kMaxPlanes]; - uint32_t mPlaneStrides[kMaxPlanes]; - int64_t mTimestamp; -}; - -} // namespace mozilla - -#endif diff --git a/dom/media/gmp/widevine-adapter/content_decryption_module.h b/dom/media/gmp/widevine-adapter/content_decryption_module.h deleted file mode 100644 index 0539135fbe..0000000000 --- a/dom/media/gmp/widevine-adapter/content_decryption_module.h +++ /dev/null @@ -1,1278 +0,0 @@ -// Copyright (c) 2012 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 CDM_CONTENT_DECRYPTION_MODULE_H_ -#define CDM_CONTENT_DECRYPTION_MODULE_H_ - -#include "content_decryption_module_export.h" - -#if defined(_MSC_VER) -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -typedef int int32_t; -typedef __int64 int64_t; -#else -#include -#endif - -// Define CDM_CLASS_API to export class types. We have to add visibility -// attributes to make sure virtual tables in CDM consumer and CDM implementation -// are the same. Generally, it was always a good idea, as there're no guarantees -// about that for the internal symbols, but it has only become a practical issue -// after introduction of LTO devirtualization. See more details on -// https://crbug.com/609564#c35 -#if defined(_WIN32) -#if defined(__clang__) -#define CDM_CLASS_API [[clang::lto_visibility_public]] -#else -#define CDM_CLASS_API -#endif -#else // defined(_WIN32) -#define CDM_CLASS_API __attribute__((visibility("default"))) -#endif // defined(_WIN32) - -// The version number must be rolled when the exported functions are updated! -// If the CDM and the adapter use different versions of these functions, the -// adapter will fail to load or crash! -#define CDM_MODULE_VERSION 4 - -// Build the versioned entrypoint name. -// The extra macros are necessary to expand version to an actual value. -#define INITIALIZE_CDM_MODULE \ - BUILD_ENTRYPOINT(InitializeCdmModule, CDM_MODULE_VERSION) -#define BUILD_ENTRYPOINT(name, version) \ - BUILD_ENTRYPOINT_NO_EXPANSION(name, version) -#define BUILD_ENTRYPOINT_NO_EXPANSION(name, version) name##_##version - -extern "C" { -CDM_API void INITIALIZE_CDM_MODULE(); - -CDM_API void DeinitializeCdmModule(); - -// Returns a pointer to the requested CDM Host interface upon success. -// Returns NULL if the requested CDM Host interface is not supported. -// The caller should cast the returned pointer to the type matching -// |host_interface_version|. -typedef void* (*GetCdmHostFunc)(int host_interface_version, void* user_data); - -// Returns a pointer to the requested CDM upon success. -// Returns NULL if an error occurs or the requested |cdm_interface_version| or -// |key_system| is not supported or another error occurs. -// The caller should cast the returned pointer to the type matching -// |cdm_interface_version|. -// Caller retains ownership of arguments and must call Destroy() on the returned -// object. -CDM_API void* CreateCdmInstance( - int cdm_interface_version, - const char* key_system, uint32_t key_system_size, - GetCdmHostFunc get_cdm_host_func, void* user_data); - -CDM_API const char* GetCdmVersion(); -} - -namespace cdm { - -class CDM_CLASS_API AudioFrames; -class CDM_CLASS_API DecryptedBlock; -class CDM_CLASS_API VideoFrame; - -class CDM_CLASS_API Host_8; -class CDM_CLASS_API Host_9; - -enum Status { - kSuccess = 0, - kNeedMoreData, // Decoder needs more data to produce a decoded frame/sample. - kNoKey, // The required decryption key is not available. - kInitializationError, // Initialization error. - kDecryptError, // Decryption failed. - kDecodeError, // Error decoding audio or video. - kDeferredInitialization // Decoder is not ready for initialization. -}; - -// This must at least contain the exceptions defined in the spec: -// https://w3c.github.io/encrypted-media/#exceptions -// The following starts with the list of DOM4 exceptions from: -// http://www.w3.org/TR/dom/#domexception -// Some DOM4 exceptions are not included as they are not expected to be used. -// Should only be used on Host_8 and before. -enum Error { - kNotSupportedError = 9, - kInvalidStateError = 11, - kInvalidAccessError = 15, - kQuotaExceededError = 22, - - // Additional exceptions that do not have assigned codes. - // There are other non-EME-specific values, not included in this list. - kUnknownError = 30, - - // Additional values from previous EME versions. They currently have no - // matching DOMException. - kClientError = 100, - kOutputError = 101 -}; - -// Exceptions used by the CDM to reject promises. -// https://w3c.github.io/encrypted-media/#exceptions -enum Exception { - kExceptionTypeError, - kExceptionNotSupportedError, - kExceptionInvalidStateError, - kExceptionQuotaExceededError -}; - -// Time is defined as the number of seconds since the Epoch -// (00:00:00 UTC, January 1, 1970), not including any added leap second. -// Also see Time definition in spec: https://w3c.github.io/encrypted-media/#time -// Note that Time is defined in millisecond accuracy in the spec but in second -// accuracy here. -typedef double Time; - -// An input buffer can be split into several continuous subsamples. -// A SubsampleEntry specifies the number of clear and cipher bytes in each -// subsample. For example, the following buffer has three subsamples: -// -// |<----- subsample1 ----->|<----- subsample2 ----->|<----- subsample3 ----->| -// | clear1 | cipher1 | clear2 | cipher2 | clear3 | cipher3 | -// -// For decryption, all of the cipher bytes in a buffer should be concatenated -// (in the subsample order) into a single logical stream. The clear bytes should -// not be considered as part of decryption. -// -// Stream to decrypt: | cipher1 | cipher2 | cipher3 | -// Decrypted stream: | decrypted1| decrypted2 | decrypted3 | -// -// After decryption, the decrypted bytes should be copied over the position -// of the corresponding cipher bytes in the original buffer to form the output -// buffer. Following the above example, the decrypted buffer should be: -// -// |<----- subsample1 ----->|<----- subsample2 ----->|<----- subsample3 ----->| -// | clear1 | decrypted1| clear2 | decrypted2 | clear3 | decrypted3 | -// -struct SubsampleEntry { - SubsampleEntry(uint32_t clear_bytes, uint32_t cipher_bytes) - : clear_bytes(clear_bytes), cipher_bytes(cipher_bytes) {} - - uint32_t clear_bytes; - uint32_t cipher_bytes; -}; - -// Represents an input buffer to be decrypted (and possibly decoded). It does -// not own any pointers in this struct. If |iv_size| = 0, the data is -// unencrypted. -struct InputBuffer { - InputBuffer() - : data(nullptr), - data_size(0), - key_id(nullptr), - key_id_size(0), - iv(nullptr), - iv_size(0), - subsamples(nullptr), - num_subsamples(0), - timestamp(0) {} - - const uint8_t* data; // Pointer to the beginning of the input data. - uint32_t data_size; // Size (in bytes) of |data|. - - const uint8_t* key_id; // Key ID to identify the decryption key. - uint32_t key_id_size; // Size (in bytes) of |key_id|. - - const uint8_t* iv; // Initialization vector. - uint32_t iv_size; // Size (in bytes) of |iv|. - - const struct SubsampleEntry* subsamples; - uint32_t num_subsamples; // Number of subsamples in |subsamples|. - - int64_t timestamp; // Presentation timestamp in microseconds. -}; - -struct AudioDecoderConfig { - enum AudioCodec { - kUnknownAudioCodec = 0, - kCodecVorbis, - kCodecAac - }; - - AudioDecoderConfig() - : codec(kUnknownAudioCodec), - channel_count(0), - bits_per_channel(0), - samples_per_second(0), - extra_data(nullptr), - extra_data_size(0) {} - - AudioCodec codec; - int32_t channel_count; - int32_t bits_per_channel; - int32_t samples_per_second; - - // Optional byte data required to initialize audio decoders, such as the - // vorbis setup header. - uint8_t* extra_data; - uint32_t extra_data_size; -}; - -// Supported sample formats for AudioFrames. -enum AudioFormat { - kUnknownAudioFormat = 0, // Unknown format value. Used for error reporting. - kAudioFormatU8, // Interleaved unsigned 8-bit w/ bias of 128. - kAudioFormatS16, // Interleaved signed 16-bit. - kAudioFormatS32, // Interleaved signed 32-bit. - kAudioFormatF32, // Interleaved float 32-bit. - kAudioFormatPlanarS16, // Signed 16-bit planar. - kAudioFormatPlanarF32, // Float 32-bit planar. -}; - -// Surface formats based on FOURCC labels, see: http://www.fourcc.org/yuv.php -// Values are chosen to be consistent with Chromium's VideoPixelFormat values. -enum VideoFormat { - kUnknownVideoFormat = 0, // Unknown format value. Used for error reporting. - kYv12 = 1, // 12bpp YVU planar 1x1 Y, 2x2 VU samples. - kI420 = 2, // 12bpp YUV planar 1x1 Y, 2x2 UV samples. - - // In the following formats, each sample uses 16-bit in storage, while the - // sample value is stored in the least significant N bits where N is - // specified by the number after "P". For example, for YUV420P9, each Y, U, - // and V sample is stored in the least significant 9 bits in a 2-byte block. - kYUV420P9 = 16, - kYUV420P10 = 17, - kYUV422P9 = 18, - kYUV422P10 = 19, - kYUV444P9 = 20, - kYUV444P10 = 21, - kYUV420P12 = 22, - kYUV422P12 = 23, - kYUV444P12 = 24, -}; - -struct Size { - Size() : width(0), height(0) {} - Size(int32_t width, int32_t height) : width(width), height(height) {} - - int32_t width; - int32_t height; -}; - -struct VideoDecoderConfig { - enum VideoCodec { - kUnknownVideoCodec = 0, - kCodecVp8, - kCodecH264, - kCodecVp9 - }; - - enum VideoCodecProfile { - kUnknownVideoCodecProfile = 0, - kProfileNotNeeded, - kH264ProfileBaseline, - kH264ProfileMain, - kH264ProfileExtended, - kH264ProfileHigh, - kH264ProfileHigh10, - kH264ProfileHigh422, - kH264ProfileHigh444Predictive, - // VP9 Profiles are only passed in starting from CDM_9. - kVP9Profile0, - kVP9Profile1, - kVP9Profile2, - kVP9Profile3 - }; - - VideoDecoderConfig() - : codec(kUnknownVideoCodec), - profile(kUnknownVideoCodecProfile), - format(kUnknownVideoFormat), - extra_data(nullptr), - extra_data_size(0) {} - - VideoCodec codec; - VideoCodecProfile profile; - VideoFormat format; - - // Width and height of video frame immediately post-decode. Not all pixels - // in this region are valid. - Size coded_size; - - // Optional byte data required to initialize video decoders, such as H.264 - // AAVC data. - uint8_t* extra_data; - uint32_t extra_data_size; -}; - -enum StreamType { - kStreamTypeAudio = 0, - kStreamTypeVideo = 1 -}; - -// Structure provided to ContentDecryptionModule::OnPlatformChallengeResponse() -// after a platform challenge was initiated via Host::SendPlatformChallenge(). -// All values will be NULL / zero in the event of a challenge failure. -struct PlatformChallengeResponse { - // |challenge| provided during Host::SendPlatformChallenge() combined with - // nonce data and signed with the platform's private key. - const uint8_t* signed_data; - uint32_t signed_data_length; - - // RSASSA-PKCS1-v1_5-SHA256 signature of the |signed_data| block. - const uint8_t* signed_data_signature; - uint32_t signed_data_signature_length; - - // X.509 device specific certificate for the |service_id| requested. - const uint8_t* platform_key_certificate; - uint32_t platform_key_certificate_length; -}; - -// Used when passing arrays of binary data. Does not own the referenced data. -struct BinaryData { - BinaryData() : data(nullptr), length(0) {} - const uint8_t* data; - uint32_t length; -}; - -// The current status of the associated key. The valid types are defined in the -// spec: https://w3c.github.io/encrypted-media/#idl-def-MediaKeyStatus -enum KeyStatus { - kUsable = 0, - kInternalError = 1, - kExpired = 2, - kOutputRestricted = 3, - kOutputDownscaled = 4, - kStatusPending = 5, - kReleased = 6 -}; - -// Used when passing arrays of key information. Does not own the referenced -// data. |system_code| is an additional error code for unusable keys and -// should be 0 when |status| == kUsable. -struct KeyInformation { - KeyInformation() - : key_id(nullptr), - key_id_size(0), - status(kInternalError), - system_code(0) {} - const uint8_t* key_id; - uint32_t key_id_size; - KeyStatus status; - uint32_t system_code; -}; - -// Supported output protection methods for use with EnableOutputProtection() and -// returned by OnQueryOutputProtectionStatus(). -enum OutputProtectionMethods { - kProtectionNone = 0, - kProtectionHDCP = 1 << 0 -}; - -// Connected output link types returned by OnQueryOutputProtectionStatus(). -enum OutputLinkTypes { - kLinkTypeNone = 0, - kLinkTypeUnknown = 1 << 0, - kLinkTypeInternal = 1 << 1, - kLinkTypeVGA = 1 << 2, - kLinkTypeHDMI = 1 << 3, - kLinkTypeDVI = 1 << 4, - kLinkTypeDisplayPort = 1 << 5, - kLinkTypeNetwork = 1 << 6 -}; - -// Result of the QueryOutputProtectionStatus() call. -enum QueryResult { - kQuerySucceeded = 0, - kQueryFailed -}; - -// The Initialization Data Type. The valid types are defined in the spec: -// http://w3c.github.io/encrypted-media/initdata-format-registry.html#registry -enum InitDataType { - kCenc = 0, - kKeyIds = 1, - kWebM = 2 -}; - -// The type of session to create. The valid types are defined in the spec: -// https://w3c.github.io/encrypted-media/#idl-def-SessionType -enum SessionType { - kTemporary = 0, - kPersistentLicense = 1, - kPersistentKeyRelease = 2 -}; - -// The type of the message event. The valid types are defined in the spec: -// https://w3c.github.io/encrypted-media/#idl-def-MediaKeyMessageType -enum MessageType { - kLicenseRequest = 0, - kLicenseRenewal = 1, - kLicenseRelease = 2 -}; - -enum HdcpVersion { - kHdcpVersionNone, - kHdcpVersion1_0, - kHdcpVersion1_1, - kHdcpVersion1_2, - kHdcpVersion1_3, - kHdcpVersion1_4, - kHdcpVersion2_0, - kHdcpVersion2_1, - kHdcpVersion2_2 -}; - -struct Policy { - Policy() : min_hdcp_version(kHdcpVersionNone) {} - - HdcpVersion min_hdcp_version; -}; - -// FileIO interface provides a way for the CDM to store data in a file in -// persistent storage. This interface aims only at providing basic read/write -// capabilities and should not be used as a full fledged file IO API. -// Each CDM and origin (e.g. HTTPS, "foo.example.com", 443) combination has -// its own persistent storage. All instances of a given CDM associated with a -// given origin share the same persistent storage. -// Note to implementors of this interface: -// Per-origin storage and the ability for users to clear it are important. -// See http://www.w3.org/TR/encrypted-media/#privacy-storedinfo. -class CDM_CLASS_API FileIO { - public: - // Opens the file with |file_name| for read and write. - // FileIOClient::OnOpenComplete() will be called after the opening - // operation finishes. - // - When the file is opened by a CDM instance, it will be classified as "in - // use". In this case other CDM instances in the same domain may receive - // kInUse status when trying to open it. - // - |file_name| must only contain letters (A-Za-z), digits(0-9), or "._-". - // It must not start with an underscore ('_'), and must be at least 1 - // character and no more than 256 characters long. - virtual void Open(const char* file_name, uint32_t file_name_size) = 0; - - // Reads the contents of the file. FileIOClient::OnReadComplete() will be - // called with the read status. Read() should not be called if a previous - // Read() or Write() call is still pending; otherwise OnReadComplete() will - // be called with kInUse. - virtual void Read() = 0; - - // Writes |data_size| bytes of |data| into the file. - // FileIOClient::OnWriteComplete() will be called with the write status. - // All existing contents in the file will be overwritten. Calling Write() with - // NULL |data| will clear all contents in the file. Write() should not be - // called if a previous Write() or Read() call is still pending; otherwise - // OnWriteComplete() will be called with kInUse. - virtual void Write(const uint8_t* data, uint32_t data_size) = 0; - - // Closes the file if opened, destroys this FileIO object and releases any - // resources allocated. The CDM must call this method when it finished using - // this object. A FileIO object must not be used after Close() is called. - virtual void Close() = 0; - - protected: - FileIO() {} - virtual ~FileIO() {} -}; - -// Responses to FileIO calls. All responses will be called asynchronously. -// When kError is returned, the FileIO object could be in an error state. All -// following calls (other than Close()) could return kError. The CDM should -// still call Close() to destroy the FileIO object. -class CDM_CLASS_API FileIOClient { - public: - enum Status { - kSuccess = 0, - kInUse, - kError - }; - - // Response to a FileIO::Open() call with the open |status|. - virtual void OnOpenComplete(Status status) = 0; - - // Response to a FileIO::Read() call to provide |data_size| bytes of |data| - // read from the file. - // - kSuccess indicates that all contents of the file has been successfully - // read. In this case, 0 |data_size| means that the file is empty. - // - kInUse indicates that there are other read/write operations pending. - // - kError indicates read failure, e.g. the storage is not open or cannot be - // fully read. - virtual void OnReadComplete(Status status, - const uint8_t* data, uint32_t data_size) = 0; - - // Response to a FileIO::Write() call. - // - kSuccess indicates that all the data has been written into the file - // successfully. - // - kInUse indicates that there are other read/write operations pending. - // - kError indicates write failure, e.g. the storage is not open or cannot be - // fully written. Upon write failure, the contents of the file should be - // regarded as corrupt and should not used. - virtual void OnWriteComplete(Status status) = 0; - - protected: - FileIOClient() {} - virtual ~FileIOClient() {} -}; - -// ContentDecryptionModule interface that all CDMs need to implement. -// The interface is versioned for backward compatibility. -// Note: ContentDecryptionModule implementations must use the allocator -// provided in CreateCdmInstance() to allocate any Buffer that needs to -// be passed back to the caller. Implementations must call Buffer::Destroy() -// when a Buffer is created that will never be returned to the caller. -class CDM_CLASS_API ContentDecryptionModule_8 { - public: - static const int kVersion = 8; - typedef Host_8 Host; - - // Initializes the CDM instance, providing information about permitted - // functionalities. - // If |allow_distinctive_identifier| is false, messages from the CDM, - // such as message events, must not contain a Distinctive Identifier, - // even in an encrypted form. - // If |allow_persistent_state| is false, the CDM must not attempt to - // persist state. Calls to CreateFileIO() will fail. - virtual void Initialize(bool allow_distinctive_identifier, - bool allow_persistent_state) = 0; - - // SetServerCertificate(), CreateSessionAndGenerateRequest(), LoadSession(), - // UpdateSession(), CloseSession(), and RemoveSession() all accept a - // |promise_id|, which must be passed to the completion Host method - // (e.g. Host::OnResolveNewSessionPromise()). - - // Provides a server certificate to be used to encrypt messages to the - // license server. The CDM must respond by calling either - // Host::OnResolvePromise() or Host::OnRejectPromise(). - virtual void SetServerCertificate(uint32_t promise_id, - const uint8_t* server_certificate_data, - uint32_t server_certificate_data_size) = 0; - - // Creates a session given |session_type|, |init_data_type|, and |init_data|. - // The CDM must respond by calling either Host::OnResolveNewSessionPromise() - // or Host::OnRejectPromise(). - virtual void CreateSessionAndGenerateRequest(uint32_t promise_id, - SessionType session_type, - InitDataType init_data_type, - const uint8_t* init_data, - uint32_t init_data_size) = 0; - - // Loads the session of type |session_type| specified by |session_id|. - // The CDM must respond by calling either Host::OnResolveNewSessionPromise() - // or Host::OnRejectPromise(). If the session is not found, call - // Host::OnResolveNewSessionPromise() with session_id = NULL. - virtual void LoadSession(uint32_t promise_id, - SessionType session_type, - const char* session_id, - uint32_t session_id_size) = 0; - - // Updates the session with |response|. The CDM must respond by calling - // either Host::OnResolvePromise() or Host::OnRejectPromise(). - virtual void UpdateSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size, - const uint8_t* response, - uint32_t response_size) = 0; - - // Requests that the CDM close the session. The CDM must respond by calling - // either Host::OnResolvePromise() or Host::OnRejectPromise() when the request - // has been processed. This may be before the session is closed. Once the - // session is closed, Host::OnSessionClosed() must also be called. - virtual void CloseSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Removes any stored session data associated with this session. Will only be - // called for persistent sessions. The CDM must respond by calling either - // Host::OnResolvePromise() or Host::OnRejectPromise() when the request has - // been processed. - virtual void RemoveSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Performs scheduled operation with |context| when the timer fires. - virtual void TimerExpired(void* context) = 0; - - // Decrypts the |encrypted_buffer|. - // - // Returns kSuccess if decryption succeeded, in which case the callee - // should have filled the |decrypted_buffer| and passed the ownership of - // |data| in |decrypted_buffer| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kDecryptError if any other error happened. - // If the return value is not kSuccess, |decrypted_buffer| should be ignored - // by the caller. - virtual Status Decrypt(const InputBuffer& encrypted_buffer, - DecryptedBlock* decrypted_buffer) = 0; - - // Initializes the CDM audio decoder with |audio_decoder_config|. This - // function must be called before DecryptAndDecodeSamples() is called. - // - // Returns kSuccess if the |audio_decoder_config| is supported and the CDM - // audio decoder is successfully initialized. - // Returns kSessionError if |audio_decoder_config| is not supported. The CDM - // may still be able to do Decrypt(). - // Returns kDeferredInitialization if the CDM is not ready to initialize the - // decoder at this time. Must call Host::OnDeferredInitializationDone() once - // initialization is complete. - virtual Status InitializeAudioDecoder( - const AudioDecoderConfig& audio_decoder_config) = 0; - - // Initializes the CDM video decoder with |video_decoder_config|. This - // function must be called before DecryptAndDecodeFrame() is called. - // - // Returns kSuccess if the |video_decoder_config| is supported and the CDM - // video decoder is successfully initialized. - // Returns kSessionError if |video_decoder_config| is not supported. The CDM - // may still be able to do Decrypt(). - // Returns kDeferredInitialization if the CDM is not ready to initialize the - // decoder at this time. Must call Host::OnDeferredInitializationDone() once - // initialization is complete. - virtual Status InitializeVideoDecoder( - const VideoDecoderConfig& video_decoder_config) = 0; - - // De-initializes the CDM decoder and sets it to an uninitialized state. The - // caller can initialize the decoder again after this call to re-initialize - // it. This can be used to reconfigure the decoder if the configuration - // changes. - virtual void DeinitializeDecoder(StreamType decoder_type) = 0; - - // Resets the CDM decoder to an initialized clean state. All internal buffers - // MUST be flushed. - virtual void ResetDecoder(StreamType decoder_type) = 0; - - // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into a - // |video_frame|. Upon end-of-stream, the caller should call this function - // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty - // |video_frame| (|format| == kEmptyVideoFrame) is produced. - // - // Returns kSuccess if decryption and decoding both succeeded, in which case - // the callee will have filled the |video_frame| and passed the ownership of - // |frame_buffer| in |video_frame| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kNeedMoreData if more data was needed by the decoder to generate - // a decoded frame (e.g. during initialization and end-of-stream). - // Returns kDecryptError if any decryption error happened. - // Returns kDecodeError if any decoding error happened. - // If the return value is not kSuccess, |video_frame| should be ignored by - // the caller. - virtual Status DecryptAndDecodeFrame(const InputBuffer& encrypted_buffer, - VideoFrame* video_frame) = 0; - - // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into - // |audio_frames|. Upon end-of-stream, the caller should call this function - // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty - // |audio_frames| is produced. - // - // Returns kSuccess if decryption and decoding both succeeded, in which case - // the callee will have filled |audio_frames| and passed the ownership of - // |data| in |audio_frames| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kNeedMoreData if more data was needed by the decoder to generate - // audio samples (e.g. during initialization and end-of-stream). - // Returns kDecryptError if any decryption error happened. - // Returns kDecodeError if any decoding error happened. - // If the return value is not kSuccess, |audio_frames| should be ignored by - // the caller. - virtual Status DecryptAndDecodeSamples(const InputBuffer& encrypted_buffer, - AudioFrames* audio_frames) = 0; - - // Called by the host after a platform challenge was initiated via - // Host::SendPlatformChallenge(). - virtual void OnPlatformChallengeResponse( - const PlatformChallengeResponse& response) = 0; - - // Called by the host after a call to Host::QueryOutputProtectionStatus(). The - // |link_mask| is a bit mask of OutputLinkTypes and |output_protection_mask| - // is a bit mask of OutputProtectionMethods. If |result| is kQueryFailed, - // then |link_mask| and |output_protection_mask| are undefined and should - // be ignored. - virtual void OnQueryOutputProtectionStatus( - QueryResult result, - uint32_t link_mask, - uint32_t output_protection_mask) = 0; - - // Destroys the object in the same context as it was created. - virtual void Destroy() = 0; - - protected: - ContentDecryptionModule_8() {} - virtual ~ContentDecryptionModule_8() {} -}; - -// ContentDecryptionModule interface that all CDMs need to implement. -// The interface is versioned for backward compatibility. -// Note: ContentDecryptionModule implementations must use the allocator -// provided in CreateCdmInstance() to allocate any Buffer that needs to -// be passed back to the caller. Implementations must call Buffer::Destroy() -// when a Buffer is created that will never be returned to the caller. -class CDM_CLASS_API ContentDecryptionModule_9 { - public: - static const int kVersion = 9; - typedef Host_9 Host; - - // Initializes the CDM instance, providing information about permitted - // functionalities. - // If |allow_distinctive_identifier| is false, messages from the CDM, - // such as message events, must not contain a Distinctive Identifier, - // even in an encrypted form. - // If |allow_persistent_state| is false, the CDM must not attempt to - // persist state. Calls to CreateFileIO() will fail. - virtual void Initialize(bool allow_distinctive_identifier, - bool allow_persistent_state) = 0; - - // Gets the key status if the CDM has a hypothetical key with the |policy|. - // The CDM must respond by calling either Host::OnResolveKeyStatusPromise() - // with the result key status or Host::OnRejectPromise() if an unexpected - // error happened or this method is not supported. - virtual void GetStatusForPolicy(uint32_t promise_id, - const Policy& policy) = 0; - - // SetServerCertificate(), CreateSessionAndGenerateRequest(), LoadSession(), - // UpdateSession(), CloseSession(), and RemoveSession() all accept a - // |promise_id|, which must be passed to the completion Host method - // (e.g. Host::OnResolveNewSessionPromise()). - - // Provides a server certificate to be used to encrypt messages to the - // license server. The CDM must respond by calling either - // Host::OnResolvePromise() or Host::OnRejectPromise(). - virtual void SetServerCertificate(uint32_t promise_id, - const uint8_t* server_certificate_data, - uint32_t server_certificate_data_size) = 0; - - // Creates a session given |session_type|, |init_data_type|, and |init_data|. - // The CDM must respond by calling either Host::OnResolveNewSessionPromise() - // or Host::OnRejectPromise(). - virtual void CreateSessionAndGenerateRequest(uint32_t promise_id, - SessionType session_type, - InitDataType init_data_type, - const uint8_t* init_data, - uint32_t init_data_size) = 0; - - // Loads the session of type |session_type| specified by |session_id|. - // The CDM must respond by calling either Host::OnResolveNewSessionPromise() - // or Host::OnRejectPromise(). If the session is not found, call - // Host::OnResolveNewSessionPromise() with session_id = NULL. - virtual void LoadSession(uint32_t promise_id, - SessionType session_type, - const char* session_id, - uint32_t session_id_size) = 0; - - // Updates the session with |response|. The CDM must respond by calling - // either Host::OnResolvePromise() or Host::OnRejectPromise(). - virtual void UpdateSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size, - const uint8_t* response, - uint32_t response_size) = 0; - - // Requests that the CDM close the session. The CDM must respond by calling - // either Host::OnResolvePromise() or Host::OnRejectPromise() when the request - // has been processed. This may be before the session is closed. Once the - // session is closed, Host::OnSessionClosed() must also be called. - virtual void CloseSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Removes any stored session data associated with this session. Will only be - // called for persistent sessions. The CDM must respond by calling either - // Host::OnResolvePromise() or Host::OnRejectPromise() when the request has - // been processed. - virtual void RemoveSession(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Performs scheduled operation with |context| when the timer fires. - virtual void TimerExpired(void* context) = 0; - - // Decrypts the |encrypted_buffer|. - // - // Returns kSuccess if decryption succeeded, in which case the callee - // should have filled the |decrypted_buffer| and passed the ownership of - // |data| in |decrypted_buffer| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kDecryptError if any other error happened. - // If the return value is not kSuccess, |decrypted_buffer| should be ignored - // by the caller. - virtual Status Decrypt(const InputBuffer& encrypted_buffer, - DecryptedBlock* decrypted_buffer) = 0; - - // Initializes the CDM audio decoder with |audio_decoder_config|. This - // function must be called before DecryptAndDecodeSamples() is called. - // - // Returns kSuccess if the |audio_decoder_config| is supported and the CDM - // audio decoder is successfully initialized. - // Returns kInitializationError if |audio_decoder_config| is not supported. - // The CDM may still be able to do Decrypt(). - // Returns kDeferredInitialization if the CDM is not ready to initialize the - // decoder at this time. Must call Host::OnDeferredInitializationDone() once - // initialization is complete. - virtual Status InitializeAudioDecoder( - const AudioDecoderConfig& audio_decoder_config) = 0; - - // Initializes the CDM video decoder with |video_decoder_config|. This - // function must be called before DecryptAndDecodeFrame() is called. - // - // Returns kSuccess if the |video_decoder_config| is supported and the CDM - // video decoder is successfully initialized. - // Returns kInitializationError if |video_decoder_config| is not supported. - // The CDM may still be able to do Decrypt(). - // Returns kDeferredInitialization if the CDM is not ready to initialize the - // decoder at this time. Must call Host::OnDeferredInitializationDone() once - // initialization is complete. - virtual Status InitializeVideoDecoder( - const VideoDecoderConfig& video_decoder_config) = 0; - - // De-initializes the CDM decoder and sets it to an uninitialized state. The - // caller can initialize the decoder again after this call to re-initialize - // it. This can be used to reconfigure the decoder if the configuration - // changes. - virtual void DeinitializeDecoder(StreamType decoder_type) = 0; - - // Resets the CDM decoder to an initialized clean state. All internal buffers - // MUST be flushed. - virtual void ResetDecoder(StreamType decoder_type) = 0; - - // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into a - // |video_frame|. Upon end-of-stream, the caller should call this function - // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty - // |video_frame| (|format| == kEmptyVideoFrame) is produced. - // - // Returns kSuccess if decryption and decoding both succeeded, in which case - // the callee will have filled the |video_frame| and passed the ownership of - // |frame_buffer| in |video_frame| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kNeedMoreData if more data was needed by the decoder to generate - // a decoded frame (e.g. during initialization and end-of-stream). - // Returns kDecryptError if any decryption error happened. - // Returns kDecodeError if any decoding error happened. - // If the return value is not kSuccess, |video_frame| should be ignored by - // the caller. - virtual Status DecryptAndDecodeFrame(const InputBuffer& encrypted_buffer, - VideoFrame* video_frame) = 0; - - // Decrypts the |encrypted_buffer| and decodes the decrypted buffer into - // |audio_frames|. Upon end-of-stream, the caller should call this function - // repeatedly with empty |encrypted_buffer| (|data| == NULL) until only empty - // |audio_frames| is produced. - // - // Returns kSuccess if decryption and decoding both succeeded, in which case - // the callee will have filled |audio_frames| and passed the ownership of - // |data| in |audio_frames| to the caller. - // Returns kNoKey if the CDM did not have the necessary decryption key - // to decrypt. - // Returns kNeedMoreData if more data was needed by the decoder to generate - // audio samples (e.g. during initialization and end-of-stream). - // Returns kDecryptError if any decryption error happened. - // Returns kDecodeError if any decoding error happened. - // If the return value is not kSuccess, |audio_frames| should be ignored by - // the caller. - virtual Status DecryptAndDecodeSamples(const InputBuffer& encrypted_buffer, - AudioFrames* audio_frames) = 0; - - // Called by the host after a platform challenge was initiated via - // Host::SendPlatformChallenge(). - virtual void OnPlatformChallengeResponse( - const PlatformChallengeResponse& response) = 0; - - // Called by the host after a call to Host::QueryOutputProtectionStatus(). The - // |link_mask| is a bit mask of OutputLinkTypes and |output_protection_mask| - // is a bit mask of OutputProtectionMethods. If |result| is kQueryFailed, - // then |link_mask| and |output_protection_mask| are undefined and should - // be ignored. - virtual void OnQueryOutputProtectionStatus( - QueryResult result, - uint32_t link_mask, - uint32_t output_protection_mask) = 0; - - // Called by the host after a call to Host::RequestStorageId(). If the - // version of the storage ID requested is available, |storage_id| and - // |storage_id_size| are set appropriately. |version| will be the same as - // what was requested, unless 0 (latest) was requested, in which case - // |version| will be the actual version number for the |storage_id| returned. - // If the requested version is not available, null/zero will be provided as - // |storage_id| and |storage_id_size|, respectively, and |version| should be - // ignored. - virtual void OnStorageId(uint32_t version, - const uint8_t* storage_id, - uint32_t storage_id_size) = 0; - - // Destroys the object in the same context as it was created. - virtual void Destroy() = 0; - - protected: - ContentDecryptionModule_9() {} - virtual ~ContentDecryptionModule_9() {} -}; - -typedef ContentDecryptionModule_9 ContentDecryptionModule; - -// Represents a buffer created by Allocator implementations. -class CDM_CLASS_API Buffer { - public: - // Destroys the buffer in the same context as it was created. - virtual void Destroy() = 0; - - virtual uint32_t Capacity() const = 0; - virtual uint8_t* Data() = 0; - virtual void SetSize(uint32_t size) = 0; - virtual uint32_t Size() const = 0; - - protected: - Buffer() {} - virtual ~Buffer() {} - - private: - Buffer(const Buffer&); - void operator=(const Buffer&); -}; - -class CDM_CLASS_API Host_8 { - public: - static const int kVersion = 8; - - // Returns a Buffer* containing non-zero members upon success, or NULL on - // failure. The caller owns the Buffer* after this call. The buffer is not - // guaranteed to be zero initialized. The capacity of the allocated Buffer - // is guaranteed to be not less than |capacity|. - virtual Buffer* Allocate(uint32_t capacity) = 0; - - // Requests the host to call ContentDecryptionModule::TimerFired() |delay_ms| - // from now with |context|. - virtual void SetTimer(int64_t delay_ms, void* context) = 0; - - // Returns the current wall time. - virtual Time GetCurrentWallTime() = 0; - - // Called by the CDM when a session is created or loaded and the value for the - // MediaKeySession's sessionId attribute is available (|session_id|). - // This must be called before OnSessionMessage() or - // OnSessionKeysChange() is called for the same session. |session_id_size| - // should not include null termination. - // When called in response to LoadSession(), the |session_id| must be the - // same as the |session_id| passed in LoadSession(), or NULL if the - // session could not be loaded. - virtual void OnResolveNewSessionPromise(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Called by the CDM when a session is updated or released. - virtual void OnResolvePromise(uint32_t promise_id) = 0; - - // Called by the CDM when an error occurs as a result of one of the - // ContentDecryptionModule calls that accept a |promise_id|. - // |error| must be specified, |error_message| and |system_code| - // are optional. |error_message_size| should not include null termination. - virtual void OnRejectPromise(uint32_t promise_id, - Error error, - uint32_t system_code, - const char* error_message, - uint32_t error_message_size) = 0; - - // Called by the CDM when it has a message for session |session_id|. - // Size parameters should not include null termination. - // |legacy_destination_url| is only for supporting the prefixed EME API and - // is ignored by unprefixed EME. It should only be non-null if |message_type| - // is kLicenseRenewal. - virtual void OnSessionMessage(const char* session_id, - uint32_t session_id_size, - MessageType message_type, - const char* message, - uint32_t message_size, - const char* legacy_destination_url, - uint32_t legacy_destination_url_length) = 0; - - // Called by the CDM when there has been a change in keys or their status for - // session |session_id|. |has_additional_usable_key| should be set if a - // key is newly usable (e.g. new key available, previously expired key has - // been renewed, etc.) and the browser should attempt to resume playback. - // |key_ids| is the list of key ids for this session along with their - // current status. |key_ids_count| is the number of entries in |key_ids|. - // Size parameter for |session_id| should not include null termination. - virtual void OnSessionKeysChange(const char* session_id, - uint32_t session_id_size, - bool has_additional_usable_key, - const KeyInformation* keys_info, - uint32_t keys_info_count) = 0; - - // Called by the CDM when there has been a change in the expiration time for - // session |session_id|. This can happen as the result of an Update() call - // or some other event. If this happens as a result of a call to Update(), - // it must be called before resolving the Update() promise. |new_expiry_time| - // represents the time after which the key(s) in the session will no longer - // be usable for decryption. It can be 0 if no such time exists or if the - // license explicitly never expires. Size parameter should not include null - // termination. - virtual void OnExpirationChange(const char* session_id, - uint32_t session_id_size, - Time new_expiry_time) = 0; - - // Called by the CDM when session |session_id| is closed. Size - // parameter should not include null termination. - virtual void OnSessionClosed(const char* session_id, - uint32_t session_id_size) = 0; - - // Called by the CDM when an error occurs in session |session_id| - // unrelated to one of the ContentDecryptionModule calls that accept a - // |promise_id|. |error| must be specified, |error_message| and - // |system_code| are optional. Length parameters should not include null - // termination. - // Note: - // - This method is only for supporting prefixed EME API. - // - This method will be ignored by unprefixed EME. All errors reported - // in this method should probably also be reported by one of other methods. - virtual void OnLegacySessionError( - const char* session_id, uint32_t session_id_length, - Error error, - uint32_t system_code, - const char* error_message, uint32_t error_message_length) = 0; - - // The following are optional methods that may not be implemented on all - // platforms. - - // Sends a platform challenge for the given |service_id|. |challenge| is at - // most 256 bits of data to be signed. Once the challenge has been completed, - // the host will call ContentDecryptionModule::OnPlatformChallengeResponse() - // with the signed challenge response and platform certificate. Size - // parameters should not include null termination. - virtual void SendPlatformChallenge(const char* service_id, - uint32_t service_id_size, - const char* challenge, - uint32_t challenge_size) = 0; - - // Attempts to enable output protection (e.g. HDCP) on the display link. The - // |desired_protection_mask| is a bit mask of OutputProtectionMethods. No - // status callback is issued, the CDM must call QueryOutputProtectionStatus() - // periodically to ensure the desired protections are applied. - virtual void EnableOutputProtection(uint32_t desired_protection_mask) = 0; - - // Requests the current output protection status. Once the host has the status - // it will call ContentDecryptionModule::OnQueryOutputProtectionStatus(). - virtual void QueryOutputProtectionStatus() = 0; - - // Must be called by the CDM if it returned kDeferredInitialization during - // InitializeAudioDecoder() or InitializeVideoDecoder(). - virtual void OnDeferredInitializationDone(StreamType stream_type, - Status decoder_status) = 0; - - // Creates a FileIO object from the host to do file IO operation. Returns NULL - // if a FileIO object cannot be obtained. Once a valid FileIO object is - // returned, |client| must be valid until FileIO::Close() is called. The - // CDM can call this method multiple times to operate on different files. - virtual FileIO* CreateFileIO(FileIOClient* client) = 0; - - protected: - Host_8() {} - virtual ~Host_8() {} -}; - -class CDM_CLASS_API Host_9 { - public: - static const int kVersion = 9; - - // Returns a Buffer* containing non-zero members upon success, or NULL on - // failure. The caller owns the Buffer* after this call. The buffer is not - // guaranteed to be zero initialized. The capacity of the allocated Buffer - // is guaranteed to be not less than |capacity|. - virtual Buffer* Allocate(uint32_t capacity) = 0; - - // Requests the host to call ContentDecryptionModule::TimerFired() |delay_ms| - // from now with |context|. - virtual void SetTimer(int64_t delay_ms, void* context) = 0; - - // Returns the current wall time. - virtual Time GetCurrentWallTime() = 0; - - // Called by the CDM when a key status is available in response to - // GetStatusForPolicy(). - virtual void OnResolveKeyStatusPromise(uint32_t promise_id, - KeyStatus key_status) = 0; - - // Called by the CDM when a session is created or loaded and the value for the - // MediaKeySession's sessionId attribute is available (|session_id|). - // This must be called before OnSessionMessage() or - // OnSessionKeysChange() is called for the same session. |session_id_size| - // should not include null termination. - // When called in response to LoadSession(), the |session_id| must be the - // same as the |session_id| passed in LoadSession(), or NULL if the - // session could not be loaded. - virtual void OnResolveNewSessionPromise(uint32_t promise_id, - const char* session_id, - uint32_t session_id_size) = 0; - - // Called by the CDM when a session is updated or released. - virtual void OnResolvePromise(uint32_t promise_id) = 0; - - // Called by the CDM when an error occurs as a result of one of the - // ContentDecryptionModule calls that accept a |promise_id|. - // |exception| must be specified. |error_message| and |system_code| - // are optional. |error_message_size| should not include null termination. - virtual void OnRejectPromise(uint32_t promise_id, - Exception exception, - uint32_t system_code, - const char* error_message, - uint32_t error_message_size) = 0; - - // Called by the CDM when it has a message for session |session_id|. - // Size parameters should not include null termination. - virtual void OnSessionMessage(const char* session_id, - uint32_t session_id_size, - MessageType message_type, - const char* message, - uint32_t message_size) = 0; - - // Called by the CDM when there has been a change in keys or their status for - // session |session_id|. |has_additional_usable_key| should be set if a - // key is newly usable (e.g. new key available, previously expired key has - // been renewed, etc.) and the browser should attempt to resume playback. - // |key_ids| is the list of key ids for this session along with their - // current status. |key_ids_count| is the number of entries in |key_ids|. - // Size parameter for |session_id| should not include null termination. - virtual void OnSessionKeysChange(const char* session_id, - uint32_t session_id_size, - bool has_additional_usable_key, - const KeyInformation* keys_info, - uint32_t keys_info_count) = 0; - - // Called by the CDM when there has been a change in the expiration time for - // session |session_id|. This can happen as the result of an Update() call - // or some other event. If this happens as a result of a call to Update(), - // it must be called before resolving the Update() promise. |new_expiry_time| - // represents the time after which the key(s) in the session will no longer - // be usable for decryption. It can be 0 if no such time exists or if the - // license explicitly never expires. Size parameter should not include null - // termination. - virtual void OnExpirationChange(const char* session_id, - uint32_t session_id_size, - Time new_expiry_time) = 0; - - // Called by the CDM when session |session_id| is closed. Size - // parameter should not include null termination. - virtual void OnSessionClosed(const char* session_id, - uint32_t session_id_size) = 0; - - // The following are optional methods that may not be implemented on all - // platforms. - - // Sends a platform challenge for the given |service_id|. |challenge| is at - // most 256 bits of data to be signed. Once the challenge has been completed, - // the host will call ContentDecryptionModule::OnPlatformChallengeResponse() - // with the signed challenge response and platform certificate. Size - // parameters should not include null termination. - virtual void SendPlatformChallenge(const char* service_id, - uint32_t service_id_size, - const char* challenge, - uint32_t challenge_size) = 0; - - // Attempts to enable output protection (e.g. HDCP) on the display link. The - // |desired_protection_mask| is a bit mask of OutputProtectionMethods. No - // status callback is issued, the CDM must call QueryOutputProtectionStatus() - // periodically to ensure the desired protections are applied. - virtual void EnableOutputProtection(uint32_t desired_protection_mask) = 0; - - // Requests the current output protection status. Once the host has the status - // it will call ContentDecryptionModule::OnQueryOutputProtectionStatus(). - virtual void QueryOutputProtectionStatus() = 0; - - // Must be called by the CDM if it returned kDeferredInitialization during - // InitializeAudioDecoder() or InitializeVideoDecoder(). - virtual void OnDeferredInitializationDone(StreamType stream_type, - Status decoder_status) = 0; - - // Creates a FileIO object from the host to do file IO operation. Returns NULL - // if a FileIO object cannot be obtained. Once a valid FileIO object is - // returned, |client| must be valid until FileIO::Close() is called. The - // CDM can call this method multiple times to operate on different files. - virtual FileIO* CreateFileIO(FileIOClient* client) = 0; - - // Requests a specific version of the storage ID. A storage ID is a stable, - // device specific ID used by the CDM to securely store persistent data. The - // ID will be returned by the host via ContentDecryptionModule::OnStorageId(). - // If |version| is 0, the latest version will be returned. All |version|s - // that are greater than or equal to 0x80000000 are reserved for the CDM and - // should not be supported or returned by the host. The CDM must not expose - // the ID outside the client device, even in encrypted form. - virtual void RequestStorageId(uint32_t version) = 0; - - protected: - Host_9() {} - virtual ~Host_9() {} -}; - -// Represents a decrypted block that has not been decoded. -class CDM_CLASS_API DecryptedBlock { - public: - virtual void SetDecryptedBuffer(Buffer* buffer) = 0; - virtual Buffer* DecryptedBuffer() = 0; - - // TODO(tomfinegan): Figure out if timestamp is really needed. If it is not, - // we can just pass Buffer pointers around. - virtual void SetTimestamp(int64_t timestamp) = 0; - virtual int64_t Timestamp() const = 0; - - protected: - DecryptedBlock() {} - virtual ~DecryptedBlock() {} -}; - -class CDM_CLASS_API VideoFrame { - public: - enum VideoPlane { - kYPlane = 0, - kUPlane = 1, - kVPlane = 2, - kMaxPlanes = 3, - }; - - virtual void SetFormat(VideoFormat format) = 0; - virtual VideoFormat Format() const = 0; - - virtual void SetSize(cdm::Size size) = 0; - virtual cdm::Size Size() const = 0; - - virtual void SetFrameBuffer(Buffer* frame_buffer) = 0; - virtual Buffer* FrameBuffer() = 0; - - virtual void SetPlaneOffset(VideoPlane plane, uint32_t offset) = 0; - virtual uint32_t PlaneOffset(VideoPlane plane) = 0; - - virtual void SetStride(VideoPlane plane, uint32_t stride) = 0; - virtual uint32_t Stride(VideoPlane plane) = 0; - - virtual void SetTimestamp(int64_t timestamp) = 0; - virtual int64_t Timestamp() const = 0; - - protected: - VideoFrame() {} - virtual ~VideoFrame() {} -}; - -// Represents decrypted and decoded audio frames. AudioFrames can contain -// multiple audio output buffers, which are serialized into this format: -// -// |<------------------- serialized audio buffer ------------------->| -// | int64_t timestamp | int64_t length | length bytes of audio data | -// -// For example, with three audio output buffers, the AudioFrames will look -// like this: -// -// |<----------------- AudioFrames ------------------>| -// | audio buffer 0 | audio buffer 1 | audio buffer 2 | -class CDM_CLASS_API AudioFrames { - public: - virtual void SetFrameBuffer(Buffer* buffer) = 0; - virtual Buffer* FrameBuffer() = 0; - - // The CDM must call this method, providing a valid format, when providing - // frame buffers. Planar data should be stored end to end; e.g., - // |ch1 sample1||ch1 sample2|....|ch1 sample_last||ch2 sample1|... - virtual void SetFormat(AudioFormat format) = 0; - virtual AudioFormat Format() const = 0; - - protected: - AudioFrames() {} - virtual ~AudioFrames() {} -}; - -} // namespace cdm - -#endif // CDM_CONTENT_DECRYPTION_MODULE_H_ diff --git a/dom/media/gmp/widevine-adapter/content_decryption_module_export.h b/dom/media/gmp/widevine-adapter/content_decryption_module_export.h deleted file mode 100644 index 51d485892b..0000000000 --- a/dom/media/gmp/widevine-adapter/content_decryption_module_export.h +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright 2017 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 CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ -#define CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ - -// Define CDM_API so that functionality implemented by the CDM module -// can be exported to consumers. -#if defined(_WIN32) - -#if defined(CDM_IMPLEMENTATION) -#define CDM_API __declspec(dllexport) -#else -#define CDM_API __declspec(dllimport) -#endif // defined(CDM_IMPLEMENTATION) - -#else // defined(_WIN32) -#define CDM_API __attribute__((visibility("default"))) -#endif // defined(_WIN32) - -#endif // CDM_CONTENT_DECRYPTION_MODULE_EXPORT_H_ diff --git a/dom/media/gmp/widevine-adapter/content_decryption_module_ext.h b/dom/media/gmp/widevine-adapter/content_decryption_module_ext.h deleted file mode 100644 index 5df8344e60..0000000000 --- a/dom/media/gmp/widevine-adapter/content_decryption_module_ext.h +++ /dev/null @@ -1,64 +0,0 @@ -// Copyright 2017 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 CDM_CONTENT_DECRYPTION_MODULE_EXT_H_ -#define CDM_CONTENT_DECRYPTION_MODULE_EXT_H_ - -#if defined(_WIN32) -#include -#endif - -#include "content_decryption_module_export.h" - -#if defined(_MSC_VER) -typedef unsigned int uint32_t; -#else -#include -#endif - -namespace cdm { - -#if defined(_WIN32) -typedef wchar_t FilePathCharType; -typedef HANDLE PlatformFile; -const PlatformFile kInvalidPlatformFile = INVALID_HANDLE_VALUE; -#else -typedef char FilePathCharType; -typedef int PlatformFile; -const PlatformFile kInvalidPlatformFile = -1; -#endif // defined(_WIN32) - -struct HostFile { - HostFile(const FilePathCharType* file_path, - PlatformFile file, - PlatformFile sig_file) - : file_path(file_path), file(file), sig_file(sig_file) {} - - // File that is part of the host of the CDM. - const FilePathCharType* file_path = nullptr; - PlatformFile file = kInvalidPlatformFile; - - // Signature file for |file|. - PlatformFile sig_file = kInvalidPlatformFile; -}; - -} // namespace cdm - -extern "C" { - -// Functions in this file are dynamically retrieved by their versioned function -// names. Increment the version number for any backward incompatible API -// changes. - -// Verifies CDM host. All files in |host_files| are opened in read-only mode. -// -// Returns false and closes all files if there is an immediate failure. -// Otherwise returns true as soon as possible and processes the files -// asynchronously. All files MUST be closed by the CDM after this one-time -// processing is finished. -CDM_API bool VerifyCdmHost_0(const cdm::HostFile* host_files, - uint32_t num_files); -} - -#endif // CDM_CONTENT_DECRYPTION_MODULE_EXT_H_ diff --git a/dom/media/gmp/widevine-adapter/moz.build b/dom/media/gmp/widevine-adapter/moz.build deleted file mode 100644 index 4a3a079cec..0000000000 --- a/dom/media/gmp/widevine-adapter/moz.build +++ /dev/null @@ -1,24 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -SOURCES += [ - 'WidevineAdapter.cpp', - 'WidevineDecryptor.cpp', - 'WidevineFileIO.cpp', - 'WidevineUtils.cpp', - 'WidevineVideoDecoder.cpp', - 'WidevineVideoFrame.cpp', -] - -FINAL_LIBRARY = 'xul' - -LOCAL_INCLUDES += [ - '/dom/media/gmp', -] - -if CONFIG['CLANG_CXX']: - CXXFLAGS += ['-Wno-error=shadow'] - -include('/ipc/chromium/chromium-config.mozbuild') diff --git a/dom/media/platforms/agnostic/eme/EMEAudioDecoder.cpp b/dom/media/platforms/agnostic/eme/EMEAudioDecoder.cpp deleted file mode 100644 index fd0449d66f..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEAudioDecoder.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "EMEAudioDecoder.h" -#include "mozilla/CDMProxy.h" - -namespace mozilla { - -void -EMEAudioCallbackAdapter::Error(GMPErr aErr) -{ - if (aErr == GMPNoKeyErr) { - // The GMP failed to decrypt a frame due to not having a key. This can - // happen if a key expires or a session is closed during playback. - NS_WARNING("GMP failed to decrypt due to lack of key"); - return; - } - AudioCallbackAdapter::Error(aErr); -} - -EMEAudioDecoder::EMEAudioDecoder(CDMProxy* aProxy, - const GMPAudioDecoderParams& aParams) - : GMPAudioDecoder(GMPAudioDecoderParams(aParams).WithAdapter( - new EMEAudioCallbackAdapter(aParams.mCallback))) - , mProxy(aProxy) -{} - -void -EMEAudioDecoder::InitTags(nsTArray& aTags) -{ - aTags.AppendElement(NS_LITERAL_CSTRING("aac")); - aTags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem())); -} - -nsCString -EMEAudioDecoder::GetNodeId() -{ - return mProxy->GetNodeId(); -} - -} // namespace mozilla diff --git a/dom/media/platforms/agnostic/eme/EMEAudioDecoder.h b/dom/media/platforms/agnostic/eme/EMEAudioDecoder.h deleted file mode 100644 index fd41125d87..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEAudioDecoder.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 EMEAudioDecoder_h_ -#define EMEAudioDecoder_h_ - -#include "GMPAudioDecoder.h" -#include "PlatformDecoderModule.h" - -namespace mozilla { - -class EMEAudioCallbackAdapter : public AudioCallbackAdapter { -public: - explicit EMEAudioCallbackAdapter(MediaDataDecoderCallbackProxy* aCallback) - : AudioCallbackAdapter(aCallback) - {} - - void Error(GMPErr aErr) override; -}; - -class EMEAudioDecoder : public GMPAudioDecoder { -public: - EMEAudioDecoder(CDMProxy* aProxy, const GMPAudioDecoderParams& aParams); - -private: - void InitTags(nsTArray& aTags) override; - nsCString GetNodeId() override; - - RefPtr mProxy; -}; - -} // namespace mozilla - -#endif diff --git a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp b/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp deleted file mode 100644 index a293824608..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "EMEDecoderModule.h" -#include "EMEAudioDecoder.h" -#include "EMEVideoDecoder.h" -#include "MediaDataDecoderProxy.h" -#include "mozIGeckoMediaPluginService.h" -#include "mozilla/CDMProxy.h" -#include "mozilla/Unused.h" -#include "nsAutoPtr.h" -#include "nsServiceManagerUtils.h" -#include "MediaInfo.h" -#include "nsClassHashtable.h" -#include "GMPDecoderModule.h" -#include "MP4Decoder.h" - -namespace mozilla { - -typedef MozPromiseRequestHolder DecryptPromiseRequestHolder; - -class EMEDecryptor : public MediaDataDecoder { - -public: - - EMEDecryptor(MediaDataDecoder* aDecoder, - MediaDataDecoderCallback* aCallback, - CDMProxy* aProxy, - TaskQueue* aDecodeTaskQueue) - : mDecoder(aDecoder) - , mCallback(aCallback) - , mTaskQueue(aDecodeTaskQueue) - , mProxy(aProxy) - , mSamplesWaitingForKey(new SamplesWaitingForKey(this, this->mCallback, - mTaskQueue, mProxy)) - , mIsShutdown(false) - { - } - - RefPtr Init() override { - MOZ_ASSERT(!mIsShutdown); - return mDecoder->Init(); - } - - void Input(MediaRawData* aSample) override { - MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); - if (mIsShutdown) { - NS_WARNING("EME encrypted sample arrived after shutdown"); - return; - } - if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) { - return; - } - - nsAutoPtr writer(aSample->CreateWriter()); - mProxy->GetSessionIdsForKeyId(aSample->mCrypto.mKeyId, - writer->mCrypto.mSessionIds); - - mDecrypts.Put(aSample, new DecryptPromiseRequestHolder()); - mDecrypts.Get(aSample)->Begin(mProxy->Decrypt(aSample)->Then( - mTaskQueue, __func__, this, - &EMEDecryptor::Decrypted, - &EMEDecryptor::Decrypted)); - return; - } - - void Decrypted(const DecryptResult& aDecrypted) { - MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); - MOZ_ASSERT(aDecrypted.mSample); - - nsAutoPtr holder; - mDecrypts.RemoveAndForget(aDecrypted.mSample, holder); - if (holder) { - holder->Complete(); - } else { - // Decryption is not in the list of decrypt operations waiting - // for a result. It must have been flushed or drained. Ignore result. - return; - } - - if (mIsShutdown) { - NS_WARNING("EME decrypted sample arrived after shutdown"); - return; - } - - if (aDecrypted.mStatus == NoKeyErr) { - // Key became unusable after we sent the sample to CDM to decrypt. - // Call Input() again, so that the sample is enqueued for decryption - // if the key becomes usable again. - Input(aDecrypted.mSample); - } else if (aDecrypted.mStatus != Ok) { - if (mCallback) { - mCallback->Error(MediaResult( - NS_ERROR_DOM_MEDIA_FATAL_ERR, - RESULT_DETAIL("decrypted.mStatus=%u", uint32_t(aDecrypted.mStatus)))); - } - } else { - MOZ_ASSERT(!mIsShutdown); - // The Adobe GMP AAC decoder gets confused if we pass it non-encrypted - // samples with valid crypto data. So clear the crypto data, since the - // sample should be decrypted now anyway. If we don't do this and we're - // using the Adobe GMP for unencrypted decoding of data that is decrypted - // by gmp-clearkey, decoding will fail. - UniquePtr writer(aDecrypted.mSample->CreateWriter()); - writer->mCrypto = CryptoSample(); - mDecoder->Input(aDecrypted.mSample); - } - } - - void Flush() override { - MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); - MOZ_ASSERT(!mIsShutdown); - for (auto iter = mDecrypts.Iter(); !iter.Done(); iter.Next()) { - nsAutoPtr& holder = iter.Data(); - holder->DisconnectIfExists(); - iter.Remove(); - } - mDecoder->Flush(); - mSamplesWaitingForKey->Flush(); - } - - void Drain() override { - MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); - MOZ_ASSERT(!mIsShutdown); - for (auto iter = mDecrypts.Iter(); !iter.Done(); iter.Next()) { - nsAutoPtr& holder = iter.Data(); - holder->DisconnectIfExists(); - iter.Remove(); - } - mDecoder->Drain(); - } - - void Shutdown() override { - MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn()); - MOZ_ASSERT(!mIsShutdown); - mIsShutdown = true; - mDecoder->Shutdown(); - mSamplesWaitingForKey->BreakCycles(); - mSamplesWaitingForKey = nullptr; - mDecoder = nullptr; - mProxy = nullptr; - mCallback = nullptr; - } - - const char* GetDescriptionName() const override { - return mDecoder->GetDescriptionName(); - } - -private: - - RefPtr mDecoder; - MediaDataDecoderCallback* mCallback; - RefPtr mTaskQueue; - RefPtr mProxy; - nsClassHashtable, DecryptPromiseRequestHolder> mDecrypts; - RefPtr mSamplesWaitingForKey; - bool mIsShutdown; -}; - -class EMEMediaDataDecoderProxy : public MediaDataDecoderProxy { -public: - EMEMediaDataDecoderProxy(already_AddRefed aProxyThread, - MediaDataDecoderCallback* aCallback, - CDMProxy* aProxy, - TaskQueue* aTaskQueue) - : MediaDataDecoderProxy(Move(aProxyThread), aCallback) - , mSamplesWaitingForKey(new SamplesWaitingForKey(this, aCallback, - aTaskQueue, aProxy)) - , mProxy(aProxy) - { - } - - void Input(MediaRawData* aSample) override; - void Shutdown() override; - -private: - RefPtr mSamplesWaitingForKey; - RefPtr mProxy; -}; - -void -EMEMediaDataDecoderProxy::Input(MediaRawData* aSample) -{ - if (mSamplesWaitingForKey->WaitIfKeyNotUsable(aSample)) { - return; - } - - nsAutoPtr writer(aSample->CreateWriter()); - mProxy->GetSessionIdsForKeyId(aSample->mCrypto.mKeyId, - writer->mCrypto.mSessionIds); - - MediaDataDecoderProxy::Input(aSample); -} - -void -EMEMediaDataDecoderProxy::Shutdown() -{ - MediaDataDecoderProxy::Shutdown(); - - mSamplesWaitingForKey->BreakCycles(); - mSamplesWaitingForKey = nullptr; - mProxy = nullptr; -} - -EMEDecoderModule::EMEDecoderModule(CDMProxy* aProxy, PDMFactory* aPDM) - : mProxy(aProxy) - , mPDM(aPDM) -{ -} - -EMEDecoderModule::~EMEDecoderModule() -{ -} - -static already_AddRefed -CreateDecoderWrapper(MediaDataDecoderCallback* aCallback, CDMProxy* aProxy, TaskQueue* aTaskQueue) -{ - RefPtr s(gmp::GeckoMediaPluginService::GetGeckoMediaPluginService()); - if (!s) { - return nullptr; - } - RefPtr thread(s->GetAbstractGMPThread()); - if (!thread) { - return nullptr; - } - RefPtr decoder( - new EMEMediaDataDecoderProxy(thread.forget(), aCallback, aProxy, aTaskQueue)); - return decoder.forget(); -} - -already_AddRefed -EMEDecoderModule::CreateVideoDecoder(const CreateDecoderParams& aParams) -{ - MOZ_ASSERT(aParams.mConfig.mCrypto.mValid); - - if (SupportsMimeType(aParams.mConfig.mMimeType, nullptr)) { - // GMP decodes. Assume that means it can decrypt too. - RefPtr wrapper = - CreateDecoderWrapper(aParams.mCallback, mProxy, aParams.mTaskQueue); - auto params = GMPVideoDecoderParams(aParams).WithCallback(wrapper); - wrapper->SetProxyTarget(new EMEVideoDecoder(mProxy, params)); - return wrapper.forget(); - } - - MOZ_ASSERT(mPDM); - RefPtr decoder(mPDM->CreateDecoder(aParams)); - if (!decoder) { - return nullptr; - } - - RefPtr emeDecoder(new EMEDecryptor(decoder, - aParams.mCallback, - mProxy, - AbstractThread::GetCurrent()->AsTaskQueue())); - return emeDecoder.forget(); -} - -already_AddRefed -EMEDecoderModule::CreateAudioDecoder(const CreateDecoderParams& aParams) -{ - MOZ_ASSERT(aParams.mConfig.mCrypto.mValid); - - if (SupportsMimeType(aParams.mConfig.mMimeType, nullptr)) { - // GMP decodes. Assume that means it can decrypt too. - RefPtr wrapper = - CreateDecoderWrapper(aParams.mCallback, mProxy, aParams.mTaskQueue); - auto gmpParams = GMPAudioDecoderParams(aParams).WithCallback(wrapper); - wrapper->SetProxyTarget(new EMEAudioDecoder(mProxy, gmpParams)); - return wrapper.forget(); - } - - MOZ_ASSERT(mPDM); - RefPtr decoder(mPDM->CreateDecoder(aParams)); - if (!decoder) { - return nullptr; - } - - RefPtr emeDecoder(new EMEDecryptor(decoder, - aParams.mCallback, - mProxy, - AbstractThread::GetCurrent()->AsTaskQueue())); - return emeDecoder.forget(); -} - -PlatformDecoderModule::ConversionRequired -EMEDecoderModule::DecoderNeedsConversion(const TrackInfo& aConfig) const -{ - if (aConfig.IsVideo() && MP4Decoder::IsH264(aConfig.mMimeType)) { - return ConversionRequired::kNeedAVCC; - } else { - return ConversionRequired::kNeedNone; - } -} - -bool -EMEDecoderModule::SupportsMimeType(const nsACString& aMimeType, - DecoderDoctorDiagnostics* aDiagnostics) const -{ - Maybe gmp; - gmp.emplace(NS_ConvertUTF16toUTF8(mProxy->KeySystem())); - return GMPDecoderModule::SupportsMimeType(aMimeType, gmp); -} - -} // namespace mozilla diff --git a/dom/media/platforms/agnostic/eme/EMEDecoderModule.h b/dom/media/platforms/agnostic/eme/EMEDecoderModule.h deleted file mode 100644 index 8480e54536..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEDecoderModule.h +++ /dev/null @@ -1,51 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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/. */ - -#if !defined(EMEDecoderModule_h_) -#define EMEDecoderModule_h_ - -#include "PlatformDecoderModule.h" -#include "PDMFactory.h" -#include "gmp-decryption.h" - -namespace mozilla { - -class CDMProxy; - -class EMEDecoderModule : public PlatformDecoderModule { -private: - -public: - EMEDecoderModule(CDMProxy* aProxy, PDMFactory* aPDM); - - virtual ~EMEDecoderModule(); - -protected: - // Decode thread. - already_AddRefed - CreateVideoDecoder(const CreateDecoderParams& aParams) override; - - // Decode thread. - already_AddRefed - CreateAudioDecoder(const CreateDecoderParams& aParams) override; - - ConversionRequired - DecoderNeedsConversion(const TrackInfo& aConfig) const override; - - bool - SupportsMimeType(const nsACString& aMimeType, - DecoderDoctorDiagnostics* aDiagnostics) const override; - -private: - RefPtr mProxy; - // Will be null if CDM has decoding capability. - RefPtr mPDM; - // We run the PDM on its own task queue. - RefPtr mTaskQueue; -}; - -} // namespace mozilla - -#endif // EMEDecoderModule_h_ diff --git a/dom/media/platforms/agnostic/eme/EMEVideoDecoder.cpp b/dom/media/platforms/agnostic/eme/EMEVideoDecoder.cpp deleted file mode 100644 index d7b4b1c250..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEVideoDecoder.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "EMEVideoDecoder.h" -#include "GMPVideoEncodedFrameImpl.h" -#include "mozilla/CDMProxy.h" -#include "MediaData.h" -#include "MP4Decoder.h" -#include "VPXDecoder.h" - -namespace mozilla { - -void -EMEVideoCallbackAdapter::Error(GMPErr aErr) -{ - if (aErr == GMPNoKeyErr) { - // The GMP failed to decrypt a frame due to not having a key. This can - // happen if a key expires or a session is closed during playback. - NS_WARNING("GMP failed to decrypt due to lack of key"); - return; - } - VideoCallbackAdapter::Error(aErr); -} - -EMEVideoDecoder::EMEVideoDecoder(CDMProxy* aProxy, - const GMPVideoDecoderParams& aParams) - : GMPVideoDecoder(GMPVideoDecoderParams(aParams).WithAdapter( - new EMEVideoCallbackAdapter(aParams.mCallback, - VideoInfo(aParams.mConfig.mDisplay), - aParams.mImageContainer))) - , mProxy(aProxy) - , mDecryptorId(aProxy->GetDecryptorId()) -{} - -void -EMEVideoDecoder::InitTags(nsTArray& aTags) -{ - VideoInfo config = GetConfig(); - if (MP4Decoder::IsH264(config.mMimeType)) { - aTags.AppendElement(NS_LITERAL_CSTRING("h264")); - } else if (VPXDecoder::IsVP8(config.mMimeType)) { - aTags.AppendElement(NS_LITERAL_CSTRING("vp8")); - } else if (VPXDecoder::IsVP9(config.mMimeType)) { - aTags.AppendElement(NS_LITERAL_CSTRING("vp9")); - } - aTags.AppendElement(NS_ConvertUTF16toUTF8(mProxy->KeySystem())); -} - -nsCString -EMEVideoDecoder::GetNodeId() -{ - return mProxy->GetNodeId(); -} - -GMPUniquePtr -EMEVideoDecoder::CreateFrame(MediaRawData* aSample) -{ - GMPUniquePtr frame = GMPVideoDecoder::CreateFrame(aSample); - if (frame && aSample->mCrypto.mValid) { - static_cast(frame.get())->InitCrypto(aSample->mCrypto); - } - return frame; -} - -} // namespace mozilla diff --git a/dom/media/platforms/agnostic/eme/EMEVideoDecoder.h b/dom/media/platforms/agnostic/eme/EMEVideoDecoder.h deleted file mode 100644 index e3b63b5066..0000000000 --- a/dom/media/platforms/agnostic/eme/EMEVideoDecoder.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 EMEVideoDecoder_h_ -#define EMEVideoDecoder_h_ - -#include "GMPVideoDecoder.h" -#include "PlatformDecoderModule.h" - -namespace mozilla { - -class CDMProxy; -class TaskQueue; - -class EMEVideoCallbackAdapter : public VideoCallbackAdapter { -public: - EMEVideoCallbackAdapter(MediaDataDecoderCallbackProxy* aCallback, - VideoInfo aVideoInfo, - layers::ImageContainer* aImageContainer) - : VideoCallbackAdapter(aCallback, aVideoInfo, aImageContainer) - {} - - void Error(GMPErr aErr) override; -}; - -class EMEVideoDecoder : public GMPVideoDecoder { -public: - EMEVideoDecoder(CDMProxy* aProxy, const GMPVideoDecoderParams& aParams); - -private: - void InitTags(nsTArray& aTags) override; - nsCString GetNodeId() override; - uint32_t DecryptorId() const override { return mDecryptorId; } - GMPUniquePtr CreateFrame(MediaRawData* aSample) override; - - RefPtr mProxy; - uint32_t mDecryptorId; -}; - -} // namespace mozilla - -#endif // EMEVideoDecoder_h_ diff --git a/dom/media/platforms/agnostic/eme/SamplesWaitingForKey.cpp b/dom/media/platforms/agnostic/eme/SamplesWaitingForKey.cpp deleted file mode 100644 index 532fc63c01..0000000000 --- a/dom/media/platforms/agnostic/eme/SamplesWaitingForKey.cpp +++ /dev/null @@ -1,85 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "SamplesWaitingForKey.h" -#include "mozilla/CDMProxy.h" -#include "mozilla/CDMCaps.h" -#include "MediaData.h" - -namespace mozilla { - -SamplesWaitingForKey::SamplesWaitingForKey(MediaDataDecoder* aDecoder, - MediaDataDecoderCallback* aCallback, - TaskQueue* aTaskQueue, - CDMProxy* aProxy) - : mMutex("SamplesWaitingForKey") - , mDecoder(aDecoder) - , mDecoderCallback(aCallback) - , mTaskQueue(aTaskQueue) - , mProxy(aProxy) -{ -} - -SamplesWaitingForKey::~SamplesWaitingForKey() -{ -} - -bool -SamplesWaitingForKey::WaitIfKeyNotUsable(MediaRawData* aSample) -{ - if (!aSample || !aSample->mCrypto.mValid || !mProxy) { - return false; - } - CDMCaps::AutoLock caps(mProxy->Capabilites()); - const auto& keyid = aSample->mCrypto.mKeyId; - if (!caps.IsKeyUsable(keyid)) { - { - MutexAutoLock lock(mMutex); - mSamples.AppendElement(aSample); - } - mDecoderCallback->WaitingForKey(); - caps.NotifyWhenKeyIdUsable(aSample->mCrypto.mKeyId, this); - return true; - } - return false; -} - -void -SamplesWaitingForKey::NotifyUsable(const CencKeyId& aKeyId) -{ - MutexAutoLock lock(mMutex); - size_t i = 0; - while (i < mSamples.Length()) { - if (aKeyId == mSamples[i]->mCrypto.mKeyId) { - RefPtr task; - task = NewRunnableMethod>(mDecoder, - &MediaDataDecoder::Input, - RefPtr(mSamples[i])); - mSamples.RemoveElementAt(i); - mTaskQueue->Dispatch(task.forget()); - } else { - i++; - } - } -} - -void -SamplesWaitingForKey::Flush() -{ - MutexAutoLock lock(mMutex); - mSamples.Clear(); -} - -void -SamplesWaitingForKey::BreakCycles() -{ - MutexAutoLock lock(mMutex); - mDecoder = nullptr; - mTaskQueue = nullptr; - mProxy = nullptr; - mSamples.Clear(); -} - -} // namespace mozilla diff --git a/dom/media/platforms/agnostic/eme/SamplesWaitingForKey.h b/dom/media/platforms/agnostic/eme/SamplesWaitingForKey.h deleted file mode 100644 index 8672bccdd1..0000000000 --- a/dom/media/platforms/agnostic/eme/SamplesWaitingForKey.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 SamplesWaitingForKey_h_ -#define SamplesWaitingForKey_h_ - -#include "mozilla/TaskQueue.h" - -#include "PlatformDecoderModule.h" - -namespace mozilla { - -typedef nsTArray CencKeyId; - -class CDMProxy; - -// Encapsulates the task of waiting for the CDMProxy to have the necessary -// keys to decrypt a given sample. -class SamplesWaitingForKey { -public: - - NS_INLINE_DECL_THREADSAFE_REFCOUNTING(SamplesWaitingForKey) - - explicit SamplesWaitingForKey(MediaDataDecoder* aDecoder, - MediaDataDecoderCallback* aCallback, - TaskQueue* aTaskQueue, - CDMProxy* aProxy); - - // Returns true if we need to wait for a key to become usable. - // Will callback MediaDataDecoder::Input(aSample) on mDecoder once the - // sample is ready to be decrypted. The order of input samples is - // preserved. - bool WaitIfKeyNotUsable(MediaRawData* aSample); - - void NotifyUsable(const CencKeyId& aKeyId); - - void Flush(); - - void BreakCycles(); - -protected: - ~SamplesWaitingForKey(); - -private: - Mutex mMutex; - RefPtr mDecoder; - MediaDataDecoderCallback* mDecoderCallback; - RefPtr mTaskQueue; - RefPtr mProxy; - nsTArray> mSamples; -}; - -} // namespace mozilla - -#endif // SamplesWaitingForKey_h_ diff --git a/dom/media/platforms/agnostic/eme/moz.build b/dom/media/platforms/agnostic/eme/moz.build deleted file mode 100644 index 74260b3ba2..0000000000 --- a/dom/media/platforms/agnostic/eme/moz.build +++ /dev/null @@ -1,22 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -EXPORTS += [ - 'EMEAudioDecoder.h', - 'EMEDecoderModule.h', - 'EMEVideoDecoder.h', - 'SamplesWaitingForKey.h', -] - -UNIFIED_SOURCES += [ - 'EMEAudioDecoder.cpp', - 'EMEDecoderModule.cpp', - 'EMEVideoDecoder.cpp', - 'SamplesWaitingForKey.cpp', -] - -include('/ipc/chromium/chromium-config.mozbuild') - -FINAL_LIBRARY = 'xul' diff --git a/media/gmp-clearkey/0.1/AnnexB.cpp b/media/gmp-clearkey/0.1/AnnexB.cpp deleted file mode 100644 index 952936deb2..0000000000 --- a/media/gmp-clearkey/0.1/AnnexB.cpp +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "AnnexB.h" -#include "BigEndian.h" - -#include - -using mozilla::BigEndian; - -static const uint8_t kAnnexBDelimiter[] = { 0, 0, 0, 1 }; - -/* static */ void -AnnexB::ConvertFrameInPlace(std::vector& aBuffer) -{ - for (size_t i = 0; i < aBuffer.size() - 4 - sizeof(kAnnexBDelimiter) + 1; ) { - uint32_t nalLen = BigEndian::readUint32(&aBuffer[i]); - memcpy(&aBuffer[i], kAnnexBDelimiter, sizeof(kAnnexBDelimiter)); - i += nalLen + 4; - } -} - -static void -ConvertParamSetToAnnexB(std::vector::const_iterator& aIter, - size_t aCount, - std::vector& aOutAnnexB) -{ - for (size_t i = 0; i < aCount; i++) { - aOutAnnexB.insert(aOutAnnexB.end(), kAnnexBDelimiter, - kAnnexBDelimiter + sizeof(kAnnexBDelimiter)); - - uint16_t len = BigEndian::readUint16(&*aIter); aIter += 2; - aOutAnnexB.insert(aOutAnnexB.end(), aIter, aIter + len); aIter += len; - } -} - -/* static */ void -AnnexB::ConvertConfig(const std::vector& aBuffer, - std::vector& aOutAnnexB) -{ - // Skip past irrelevant headers - auto it = aBuffer.begin() + 5; - - if (it >= aBuffer.end()) { - return; - } - - size_t count = *(it++) & 31; - - // Check that we have enough bytes for the Annex B conversion - // and the next size field. Bail if not. - if (it + count * 2 >= aBuffer.end()) { - return; - } - - ConvertParamSetToAnnexB(it, count, aOutAnnexB); - - // Check that we have enough bytes for the Annex B conversion. - count = *(it++); - if (it + count * 2 > aBuffer.end()) { - aOutAnnexB.clear(); - return; - } - - ConvertParamSetToAnnexB(it, count, aOutAnnexB); -} diff --git a/media/gmp-clearkey/0.1/AnnexB.h b/media/gmp-clearkey/0.1/AnnexB.h deleted file mode 100644 index 81ca87e0cf..0000000000 --- a/media/gmp-clearkey/0.1/AnnexB.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AnnexB_h__ -#define __AnnexB_h__ - -#include -#include - -class AnnexB -{ -public: - static void ConvertFrameInPlace(std::vector& aBuffer); - - static void ConvertConfig(const std::vector& aBuffer, - std::vector& aOutAnnexB); -}; - -#endif // __AnnexB_h__ diff --git a/media/gmp-clearkey/0.1/ArrayUtils.h b/media/gmp-clearkey/0.1/ArrayUtils.h deleted file mode 100644 index c5e17689e7..0000000000 --- a/media/gmp-clearkey/0.1/ArrayUtils.h +++ /dev/null @@ -1,23 +0,0 @@ -/* -* Copyright 2015, Mozilla Foundation and contributors -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -#ifndef __ArrayUtils_h__ -#define __ArrayUtils_h__ - -#define MOZ_ARRAY_LENGTH(array_) \ - (sizeof(array_)/sizeof(array_[0])) - -#endif diff --git a/media/gmp-clearkey/0.1/AudioDecoder.cpp b/media/gmp-clearkey/0.1/AudioDecoder.cpp deleted file mode 100644 index b02e1a8545..0000000000 --- a/media/gmp-clearkey/0.1/AudioDecoder.cpp +++ /dev/null @@ -1,312 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "AudioDecoder.h" -#include "ClearKeyDecryptionManager.h" -#include "ClearKeyUtils.h" -#include "gmp-task-utils.h" - -using namespace wmf; - -AudioDecoder::AudioDecoder(GMPAudioHost *aHostAPI) - : mHostAPI(aHostAPI) - , mCallback(nullptr) - , mWorkerThread(nullptr) - , mMutex(nullptr) - , mNumInputTasks(0) - , mHasShutdown(false) -{ - // We drop the ref in DecodingComplete(). - AddRef(); -} - -AudioDecoder::~AudioDecoder() -{ - if (mMutex) { - mMutex->Destroy(); - } -} - -void -AudioDecoder::InitDecode(const GMPAudioCodec& aConfig, - GMPAudioDecoderCallback* aCallback) -{ - mCallback = aCallback; - assert(mCallback); - mDecoder = new WMFAACDecoder(); - HRESULT hr = mDecoder->Init(aConfig.mChannelCount, - aConfig.mSamplesPerSecond, - (BYTE*)aConfig.mExtraData, - aConfig.mExtraDataLen); - LOG("[%p] AudioDecoder::InitializeAudioDecoder() hr=0x%x\n", this, hr); - if (FAILED(hr)) { - mCallback->Error(GMPGenericErr); - return; - } - auto err = GetPlatform()->createmutex(&mMutex); - if (GMP_FAILED(err)) { - mCallback->Error(GMPGenericErr); - return; - } -} - -void -AudioDecoder::EnsureWorker() -{ - if (!mWorkerThread) { - GetPlatform()->createthread(&mWorkerThread); - if (!mWorkerThread) { - mCallback->Error(GMPAllocErr); - return; - } - } -} - -void -AudioDecoder::Decode(GMPAudioSamples* aInput) -{ - EnsureWorker(); - { - AutoLock lock(mMutex); - mNumInputTasks++; - } - mWorkerThread->Post(WrapTaskRefCounted(this, - &AudioDecoder::DecodeTask, - aInput)); -} - -void -AudioDecoder::DecodeTask(GMPAudioSamples* aInput) -{ - HRESULT hr; - - { - AutoLock lock(mMutex); - mNumInputTasks--; - assert(mNumInputTasks >= 0); - } - - if (!aInput || !mHostAPI || !mDecoder) { - LOG("Decode job not set up correctly!"); - return; - } - - const uint8_t* inBuffer = aInput->Buffer(); - if (!inBuffer) { - LOG("No buffer for encoded samples!\n"); - return; - } - - const GMPEncryptedBufferMetadata* crypto = aInput->GetDecryptionData(); - std::vector buffer(inBuffer, inBuffer + aInput->Size()); - if (crypto) { - // Plugin host should have set up its decryptor/key sessions - // before trying to decode! - GMPErr rv = - ClearKeyDecryptionManager::Get()->Decrypt(buffer, CryptoMetaData(crypto)); - - if (GMP_FAILED(rv)) { - CK_LOGE("Failed to decrypt with key id %08x...", *(uint32_t*)crypto->KeyId()); - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::Error, rv)); - return; - } - } - - hr = mDecoder->Input(&buffer[0], - buffer.size(), - aInput->TimeStamp()); - - // We must delete the input sample! - GetPlatform()->runonmainthread(WrapTask(aInput, &GMPAudioSamples::Destroy)); - - SAMPLE_LOG("AudioDecoder::DecodeTask() Input ret hr=0x%x\n", hr); - if (FAILED(hr)) { - LOG("AudioDecoder::DecodeTask() decode failed ret=0x%x%s\n", - hr, - ((hr == MF_E_NOTACCEPTING) ? " (MF_E_NOTACCEPTING)" : "")); - return; - } - - while (hr == S_OK) { - CComPtr output; - hr = mDecoder->Output(&output); - SAMPLE_LOG("AudioDecoder::DecodeTask() output ret=0x%x\n", hr); - if (hr == S_OK) { - ReturnOutput(output); - } - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - AutoLock lock(mMutex); - if (mNumInputTasks == 0) { - // We have run all input tasks. We *must* notify Gecko so that it will - // send us more data. - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::InputDataExhausted)); - } - } else if (FAILED(hr)) { - LOG("AudioDecoder::DecodeTask() output failed hr=0x%x\n", hr); - } - } -} - -void -AudioDecoder::ReturnOutput(IMFSample* aSample) -{ - SAMPLE_LOG("[%p] AudioDecoder::ReturnOutput()\n", this); - assert(aSample); - - HRESULT hr; - - GMPAudioSamples* samples = nullptr; - mHostAPI->CreateSamples(kGMPAudioIS16Samples, &samples); - if (!samples) { - LOG("Failed to create i420 frame!\n"); - return; - } - - hr = MFToGMPSample(aSample, samples); - if (FAILED(hr)) { - samples->Destroy(); - LOG("Failed to prepare output sample!"); - return; - } - ENSURE(SUCCEEDED(hr), /*void*/); - - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::Decoded, samples)); -} - -HRESULT -AudioDecoder::MFToGMPSample(IMFSample* aInput, - GMPAudioSamples* aOutput) -{ - ENSURE(aInput != nullptr, E_POINTER); - ENSURE(aOutput != nullptr, E_POINTER); - - HRESULT hr; - CComPtr mediaBuffer; - - hr = aInput->ConvertToContiguousBuffer(&mediaBuffer); - ENSURE(SUCCEEDED(hr), hr); - - BYTE* data = nullptr; // Note: *data will be owned by the IMFMediaBuffer, we don't need to free it. - DWORD maxLength = 0, currentLength = 0; - hr = mediaBuffer->Lock(&data, &maxLength, ¤tLength); - ENSURE(SUCCEEDED(hr), hr); - - auto err = aOutput->SetBufferSize(currentLength); - ENSURE(GMP_SUCCEEDED(err), E_FAIL); - - memcpy(aOutput->Buffer(), data, currentLength); - - mediaBuffer->Unlock(); - - LONGLONG hns = 0; - hr = aInput->GetSampleTime(&hns); - ENSURE(SUCCEEDED(hr), hr); - aOutput->SetTimeStamp(HNsToUsecs(hns)); - aOutput->SetChannels(mDecoder->Channels()); - aOutput->SetRate(mDecoder->Rate()); - - return S_OK; -} - -void -AudioDecoder::Reset() -{ - if (mDecoder) { - mDecoder->Reset(); - } - if (mCallback) { - mCallback->ResetComplete(); - } -} - -void -AudioDecoder::DrainTask() -{ - mDecoder->Drain(); - - // Return any pending output. - HRESULT hr = S_OK; - while (hr == S_OK) { - CComPtr output; - hr = mDecoder->Output(&output); - SAMPLE_LOG("AudioDecoder::DrainTask() output ret=0x%x\n", hr); - if (hr == S_OK) { - ReturnOutput(output); - } - } - MaybeRunOnMainThread(WrapTask(mCallback, &GMPAudioDecoderCallback::DrainComplete)); -} - -void -AudioDecoder::Drain() -{ - if (!mDecoder) { - return; - } - EnsureWorker(); - mWorkerThread->Post(WrapTaskRefCounted(this, - &AudioDecoder::DrainTask)); -} - -void -AudioDecoder::DecodingComplete() -{ - if (mWorkerThread) { - mWorkerThread->Join(); - } - mHasShutdown = true; - - // Release the reference we added in the constructor. There may be - // WrapRefCounted tasks that also hold references to us, and keep - // us alive a little longer. - Release(); -} - -void -AudioDecoder::MaybeRunOnMainThread(GMPTask* aTask) -{ - class MaybeRunTask : public GMPTask - { - public: - MaybeRunTask(AudioDecoder* aDecoder, GMPTask* aTask) - : mDecoder(aDecoder), mTask(aTask) - { } - - virtual void Run(void) { - if (mDecoder->HasShutdown()) { - CK_LOGD("Trying to dispatch to main thread after AudioDecoder has shut down"); - return; - } - - mTask->Run(); - } - - virtual void Destroy() - { - mTask->Destroy(); - delete this; - } - - private: - RefPtr mDecoder; - GMPTask* mTask; - }; - - GetPlatform()->runonmainthread(new MaybeRunTask(this, aTask)); -} diff --git a/media/gmp-clearkey/0.1/AudioDecoder.h b/media/gmp-clearkey/0.1/AudioDecoder.h deleted file mode 100644 index 98915bb7a7..0000000000 --- a/media/gmp-clearkey/0.1/AudioDecoder.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __AudioDecoder_h__ -#define __AudioDecoder_h__ - -#include "gmp-audio-decode.h" -#include "gmp-audio-host.h" -#include "gmp-task-utils.h" -#include "WMFAACDecoder.h" -#include "RefCounted.h" - -#include "mfobjects.h" - -class AudioDecoder : public GMPAudioDecoder - , public RefCounted -{ -public: - AudioDecoder(GMPAudioHost *aHostAPI); - - virtual void InitDecode(const GMPAudioCodec& aCodecSettings, - GMPAudioDecoderCallback* aCallback) override; - - virtual void Decode(GMPAudioSamples* aEncodedSamples); - - virtual void Reset() override; - - virtual void Drain() override; - - virtual void DecodingComplete() override; - - bool HasShutdown() { return mHasShutdown; } - -private: - virtual ~AudioDecoder(); - - void EnsureWorker(); - - void DecodeTask(GMPAudioSamples* aEncodedSamples); - void DrainTask(); - - void ReturnOutput(IMFSample* aSample); - - HRESULT MFToGMPSample(IMFSample* aSample, - GMPAudioSamples* aAudioFrame); - - void MaybeRunOnMainThread(GMPTask* aTask); - - GMPAudioHost *mHostAPI; // host-owned, invalid at DecodingComplete - GMPAudioDecoderCallback* mCallback; // host-owned, invalid at DecodingComplete - GMPThread* mWorkerThread; - GMPMutex* mMutex; - wmf::AutoPtr mDecoder; - - int32_t mNumInputTasks; - - bool mHasShutdown; -}; - -#endif // __AudioDecoder_h__ diff --git a/media/gmp-clearkey/0.1/BigEndian.h b/media/gmp-clearkey/0.1/BigEndian.h deleted file mode 100644 index 853cd4a025..0000000000 --- a/media/gmp-clearkey/0.1/BigEndian.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __BigEndian_h__ -#define __BigEndian_h__ - -#include - -namespace mozilla { - -class BigEndian { -public: - - static uint32_t readUint32(const void* aPtr) { - const uint8_t* p = reinterpret_cast(aPtr); - return uint32_t(p[0]) << 24 | - uint32_t(p[1]) << 16 | - uint32_t(p[2]) << 8 | - uint32_t(p[3]); - } - - static uint16_t readUint16(const void* aPtr) { - const uint8_t* p = reinterpret_cast(aPtr); - return uint32_t(p[0]) << 8 | - uint32_t(p[1]); - } - - static uint64_t readUint64(const void* aPtr) { - const uint8_t* p = reinterpret_cast(aPtr); - return uint64_t(p[0]) << 56 | - uint64_t(p[1]) << 48 | - uint64_t(p[2]) << 40 | - uint64_t(p[3]) << 32 | - uint64_t(p[4]) << 24 | - uint64_t(p[5]) << 16 | - uint64_t(p[6]) << 8 | - uint64_t(p[7]); - } - - static void writeUint64(void* aPtr, uint64_t aValue) { - uint8_t* p = reinterpret_cast(aPtr); - p[0] = uint8_t(aValue >> 56) & 0xff; - p[1] = uint8_t(aValue >> 48) & 0xff; - p[2] = uint8_t(aValue >> 40) & 0xff; - p[3] = uint8_t(aValue >> 32) & 0xff; - p[4] = uint8_t(aValue >> 24) & 0xff; - p[5] = uint8_t(aValue >> 16) & 0xff; - p[6] = uint8_t(aValue >> 8) & 0xff; - p[7] = uint8_t(aValue) & 0xff; - } -}; - -} // namespace mozilla - -#endif // __BigEndian_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp b/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp deleted file mode 100644 index ed1cac7388..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.cpp +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ClearKeyAsyncShutdown.h" -#include "gmp-task-utils.h" - -ClearKeyAsyncShutdown::ClearKeyAsyncShutdown(GMPAsyncShutdownHost *aHostAPI) - : mHost(aHostAPI) -{ - CK_LOGD("ClearKeyAsyncShutdown::ClearKeyAsyncShutdown"); - AddRef(); -} - -ClearKeyAsyncShutdown::~ClearKeyAsyncShutdown() -{ - CK_LOGD("ClearKeyAsyncShutdown::~ClearKeyAsyncShutdown"); -} - -void ShutdownTask(ClearKeyAsyncShutdown* aSelf, GMPAsyncShutdownHost* aHost) -{ - // Dumb implementation that just immediately reports completion. - // Real GMPs should ensure they are properly shutdown. - CK_LOGD("ClearKeyAsyncShutdown::BeginShutdown calling ShutdownComplete"); - aHost->ShutdownComplete(); - aSelf->Release(); -} - -void ClearKeyAsyncShutdown::BeginShutdown() -{ - CK_LOGD("ClearKeyAsyncShutdown::BeginShutdown dispatching asynchronous shutdown task"); - GetPlatform()->runonmainthread(WrapTaskNM(ShutdownTask, this, mHost)); -} diff --git a/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h b/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h deleted file mode 100644 index b828aae41d..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyAsyncShutdown.h +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyAsyncShutdown_h__ -#define __ClearKeyAsyncShutdown_h__ - -#include "gmp-api/gmp-async-shutdown.h" -#include "RefCounted.h" - -class ClearKeyAsyncShutdown : public GMPAsyncShutdown - , public RefCounted -{ -public: - explicit ClearKeyAsyncShutdown(GMPAsyncShutdownHost *aHostAPI); - - void BeginShutdown() override; - -private: - virtual ~ClearKeyAsyncShutdown(); - - GMPAsyncShutdownHost* mHost; -}; - -#endif // __ClearKeyAsyncShutdown_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeyBase64.cpp b/media/gmp-clearkey/0.1/ClearKeyBase64.cpp deleted file mode 100644 index c4c530a341..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyBase64.cpp +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ClearKeyBase64.h" - -#include - -using namespace std; - -/** -* Take a base64-encoded string, convert (in-place) each character to its -* corresponding value in the [0x00, 0x3f] range, and truncate any padding. -*/ -static bool -Decode6Bit(string& aStr) -{ - for (size_t i = 0; i < aStr.length(); i++) { - if (aStr[i] >= 'A' && aStr[i] <= 'Z') { - aStr[i] -= 'A'; - } - else if (aStr[i] >= 'a' && aStr[i] <= 'z') { - aStr[i] -= 'a' - 26; - } - else if (aStr[i] >= '0' && aStr[i] <= '9') { - aStr[i] -= '0' - 52; - } - else if (aStr[i] == '-' || aStr[i] == '+') { - aStr[i] = 62; - } - else if (aStr[i] == '_' || aStr[i] == '/') { - aStr[i] = 63; - } - else { - // Truncate '=' padding at the end of the aString. - if (aStr[i] != '=') { - aStr.erase(i, string::npos); - return false; - } - aStr[i] = '\0'; - aStr.resize(i); - break; - } - } - - return true; -} - -bool -DecodeBase64(const string& aEncoded, vector& aOutDecoded) -{ - if (aEncoded.empty()) { - aOutDecoded.clear(); - return true; - } - if (aEncoded.size() == 1) { - // Invalid Base64 encoding. - return false; - } - string encoded = aEncoded; - if (!Decode6Bit(encoded)) { - return false; - } - - // The number of bytes we haven't yet filled in the current byte, mod 8. - int shift = 0; - - aOutDecoded.resize((encoded.size() * 3) / 4); - vector::iterator out = aOutDecoded.begin(); - for (size_t i = 0; i < encoded.length(); i++) { - if (!shift) { - *out = encoded[i] << 2; - } - else { - *out |= encoded[i] >> (6 - shift); - out++; - if (out == aOutDecoded.end()) { - // Hit last 6bit octed in encoded, which is padding and can be ignored. - break; - } - *out = encoded[i] << (shift + 2); - } - shift = (shift + 2) % 8; - } - - return true; -} \ No newline at end of file diff --git a/media/gmp-clearkey/0.1/ClearKeyBase64.h b/media/gmp-clearkey/0.1/ClearKeyBase64.h deleted file mode 100644 index c0c928813d..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyBase64.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyBase64_h__ -#define __ClearKeyBase64_h__ - -#include -#include -#include - -// Decodes a base64 encoded string. Returns true on success. -bool -DecodeBase64(const std::string& aEncoded, std::vector& aOutDecoded); - -#endif diff --git a/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp b/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp deleted file mode 100644 index 87b316563e..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.cpp +++ /dev/null @@ -1,241 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "ClearKeyDecryptionManager.h" -#include "psshparser/PsshParser.h" -#include "gmp-api/gmp-decryption.h" -#include "mozilla/CheckedInt.h" -#include - -class ClearKeyDecryptor : public RefCounted -{ -public: - ClearKeyDecryptor(); - - void InitKey(const Key& aKey); - bool HasKey() const { return !!mKey.size(); } - - GMPErr Decrypt(uint8_t* aBuffer, uint32_t aBufferSize, - const CryptoMetaData& aMetadata); - - const Key& DecryptionKey() const { return mKey; } - -private: - ~ClearKeyDecryptor(); - - Key mKey; -}; - - -/* static */ ClearKeyDecryptionManager* ClearKeyDecryptionManager::sInstance = nullptr; - -/* static */ ClearKeyDecryptionManager* -ClearKeyDecryptionManager::Get() -{ - if (!sInstance) { - sInstance = new ClearKeyDecryptionManager(); - } - return sInstance; -} - -ClearKeyDecryptionManager::ClearKeyDecryptionManager() -{ - CK_LOGD("ClearKeyDecryptionManager::ClearKeyDecryptionManager"); -} - -ClearKeyDecryptionManager::~ClearKeyDecryptionManager() -{ - CK_LOGD("ClearKeyDecryptionManager::~ClearKeyDecryptionManager"); - - sInstance = nullptr; - - for (auto it = mDecryptors.begin(); it != mDecryptors.end(); it++) { - it->second->Release(); - } - mDecryptors.clear(); -} - -bool -ClearKeyDecryptionManager::HasSeenKeyId(const KeyId& aKeyId) const -{ - CK_LOGD("ClearKeyDecryptionManager::SeenKeyId %s", mDecryptors.find(aKeyId) != mDecryptors.end() ? "t" : "f"); - return mDecryptors.find(aKeyId) != mDecryptors.end(); -} - -bool -ClearKeyDecryptionManager::IsExpectingKeyForKeyId(const KeyId& aKeyId) const -{ - CK_LOGD("ClearKeyDecryptionManager::IsExpectingKeyForId %08x...", *(uint32_t*)&aKeyId[0]); - const auto& decryptor = mDecryptors.find(aKeyId); - return decryptor != mDecryptors.end() && !decryptor->second->HasKey(); -} - -bool -ClearKeyDecryptionManager::HasKeyForKeyId(const KeyId& aKeyId) const -{ - CK_LOGD("ClearKeyDecryptionManager::HasKeyForKeyId"); - const auto& decryptor = mDecryptors.find(aKeyId); - return decryptor != mDecryptors.end() && decryptor->second->HasKey(); -} - -const Key& -ClearKeyDecryptionManager::GetDecryptionKey(const KeyId& aKeyId) -{ - assert(HasKeyForKeyId(aKeyId)); - return mDecryptors[aKeyId]->DecryptionKey(); -} - -void -ClearKeyDecryptionManager::InitKey(KeyId aKeyId, Key aKey) -{ - CK_LOGD("ClearKeyDecryptionManager::InitKey %08x...", *(uint32_t*)&aKeyId[0]); - if (IsExpectingKeyForKeyId(aKeyId)) { - mDecryptors[aKeyId]->InitKey(aKey); - } -} - -void -ClearKeyDecryptionManager::ExpectKeyId(KeyId aKeyId) -{ - CK_LOGD("ClearKeyDecryptionManager::ExpectKeyId %08x...", *(uint32_t*)&aKeyId[0]); - if (!HasSeenKeyId(aKeyId)) { - mDecryptors[aKeyId] = new ClearKeyDecryptor(); - } - mDecryptors[aKeyId]->AddRef(); -} - -void -ClearKeyDecryptionManager::ReleaseKeyId(KeyId aKeyId) -{ - CK_LOGD("ClearKeyDecryptionManager::ReleaseKeyId"); - assert(HasSeenKeyId(aKeyId)); - - ClearKeyDecryptor* decryptor = mDecryptors[aKeyId]; - if (!decryptor->Release()) { - mDecryptors.erase(aKeyId); - } -} - -GMPErr -ClearKeyDecryptionManager::Decrypt(std::vector& aBuffer, - const CryptoMetaData& aMetadata) -{ - return Decrypt(&aBuffer[0], aBuffer.size(), aMetadata); -} - -GMPErr -ClearKeyDecryptionManager::Decrypt(uint8_t* aBuffer, uint32_t aBufferSize, - const CryptoMetaData& aMetadata) -{ - CK_LOGD("ClearKeyDecryptionManager::Decrypt"); - if (!HasKeyForKeyId(aMetadata.mKeyId)) { - return GMPNoKeyErr; - } - - return mDecryptors[aMetadata.mKeyId]->Decrypt(aBuffer, aBufferSize, aMetadata); -} - -ClearKeyDecryptor::ClearKeyDecryptor() -{ - CK_LOGD("ClearKeyDecryptor ctor"); -} - -ClearKeyDecryptor::~ClearKeyDecryptor() -{ - if (HasKey()) { - CK_LOGD("ClearKeyDecryptor dtor; key = %08x...", *(uint32_t*)&mKey[0]); - } else { - CK_LOGD("ClearKeyDecryptor dtor"); - } -} - -void -ClearKeyDecryptor::InitKey(const Key& aKey) -{ - mKey = aKey; -} - -GMPErr -ClearKeyDecryptor::Decrypt(uint8_t* aBuffer, uint32_t aBufferSize, - const CryptoMetaData& aMetadata) -{ - CK_LOGD("ClearKeyDecryptor::Decrypt"); - // If the sample is split up into multiple encrypted subsamples, we need to - // stitch them into one continuous buffer for decryption. - std::vector tmp(aBufferSize); - - if (aMetadata.NumSubsamples()) { - // Take all encrypted parts of subsamples and stitch them into one - // continuous encrypted buffer. - static_assert(sizeof(uintptr_t) == sizeof(uint8_t*), - "We need uintptr_t to be exactly the same size as a pointer"); - mozilla::CheckedInt data = reinterpret_cast(aBuffer); - const uintptr_t endBuffer = - reinterpret_cast(aBuffer + aBufferSize); - uint8_t* iter = &tmp[0]; - for (size_t i = 0; i < aMetadata.NumSubsamples(); i++) { - data += aMetadata.mClearBytes[i]; - if (!data.isValid() || data.value() > endBuffer) { - // Trying to read past the end of the buffer! - return GMPCryptoErr; - } - const uint32_t& cipherBytes = aMetadata.mCipherBytes[i]; - mozilla::CheckedInt dataAfterCipher = data + cipherBytes; - if (!dataAfterCipher.isValid() || dataAfterCipher.value() > endBuffer) { - // Trying to read past the end of the buffer! - return GMPCryptoErr; - } - - memcpy(iter, reinterpret_cast(data.value()), cipherBytes); - - data = dataAfterCipher; - iter += cipherBytes; - } - - tmp.resize((size_t)(iter - &tmp[0])); - } else { - memcpy(&tmp[0], aBuffer, aBufferSize); - } - - assert(aMetadata.mIV.size() == 8 || aMetadata.mIV.size() == 16); - std::vector iv(aMetadata.mIV); - iv.insert(iv.end(), CENC_KEY_LEN - aMetadata.mIV.size(), 0); - - ClearKeyUtils::DecryptAES(mKey, tmp, iv); - - if (aMetadata.NumSubsamples()) { - // Take the decrypted buffer, split up into subsamples, and insert those - // subsamples back into their original position in the original buffer. - uint8_t* data = aBuffer; - uint8_t* iter = &tmp[0]; - for (size_t i = 0; i < aMetadata.NumSubsamples(); i++) { - data += aMetadata.mClearBytes[i]; - uint32_t cipherBytes = aMetadata.mCipherBytes[i]; - - memcpy(data, iter, cipherBytes); - - data += cipherBytes; - iter += cipherBytes; - } - } else { - memcpy(aBuffer, &tmp[0], aBufferSize); - } - - return GMPNoErr; -} diff --git a/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h b/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h deleted file mode 100644 index 7a6c9a5607..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyDecryptionManager.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyDecryptionManager_h__ -#define __ClearKeyDecryptionManager_h__ - -#include - -#include "ClearKeyUtils.h" -#include "RefCounted.h" - -class ClearKeyDecryptor; - -class CryptoMetaData { -public: - CryptoMetaData() {} - - explicit CryptoMetaData(const GMPEncryptedBufferMetadata* aCrypto) - { - Init(aCrypto); - } - - void Init(const GMPEncryptedBufferMetadata* aCrypto) - { - if (!aCrypto) { - assert(!IsValid()); - return; - } - Assign(mKeyId, aCrypto->KeyId(), aCrypto->KeyIdSize()); - Assign(mIV, aCrypto->IV(), aCrypto->IVSize()); - Assign(mClearBytes, aCrypto->ClearBytes(), aCrypto->NumSubsamples()); - Assign(mCipherBytes, aCrypto->CipherBytes(), aCrypto->NumSubsamples()); - } - - bool IsValid() const { - return !mKeyId.empty() && - !mIV.empty() && - !mCipherBytes.empty() && - !mClearBytes.empty(); - } - - size_t NumSubsamples() const { - assert(mClearBytes.size() == mCipherBytes.size()); - return mClearBytes.size(); - } - - std::vector mKeyId; - std::vector mIV; - std::vector mClearBytes; - std::vector mCipherBytes; -}; - -class ClearKeyDecryptionManager : public RefCounted -{ -private: - ClearKeyDecryptionManager(); - ~ClearKeyDecryptionManager(); - - static ClearKeyDecryptionManager* sInstance; - -public: - static ClearKeyDecryptionManager* Get(); - - bool HasSeenKeyId(const KeyId& aKeyId) const; - bool HasKeyForKeyId(const KeyId& aKeyId) const; - - const Key& GetDecryptionKey(const KeyId& aKeyId); - - // Create a decryptor for the given KeyId if one does not already exist. - void InitKey(KeyId aKeyId, Key aKey); - void ExpectKeyId(KeyId aKeyId); - void ReleaseKeyId(KeyId aKeyId); - - // Decrypts buffer *in place*. - GMPErr Decrypt(uint8_t* aBuffer, uint32_t aBufferSize, - const CryptoMetaData& aMetadata); - GMPErr Decrypt(std::vector& aBuffer, - const CryptoMetaData& aMetadata); - - void Shutdown(); - -private: - bool IsExpectingKeyForKeyId(const KeyId& aKeyId) const; - - std::map mDecryptors; -}; - -#endif // __ClearKeyDecryptionManager_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeyPersistence.cpp b/media/gmp-clearkey/0.1/ClearKeyPersistence.cpp deleted file mode 100644 index 2e14d822ee..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyPersistence.cpp +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ClearKeyPersistence.h" -#include "ClearKeyUtils.h" -#include "ClearKeyStorage.h" -#include "ClearKeySessionManager.h" -#include "RefCounted.h" - -#include -#include -#include -#include -#include -#include - -using namespace std; - -// Whether we've loaded the persistent session ids from GMPStorage yet. -enum PersistentKeyState { - UNINITIALIZED, - LOADING, - LOADED -}; -static PersistentKeyState sPersistentKeyState = UNINITIALIZED; - -// Set of session Ids of the persistent sessions created or residing in -// storage. -static set sPersistentSessionIds; - -static vector sTasksBlockedOnSessionIdLoad; - -static void -ReadAllRecordsFromIterator(GMPRecordIterator* aRecordIterator, - void* aUserArg, - GMPErr aStatus) -{ - assert(sPersistentKeyState == LOADING); - if (GMP_SUCCEEDED(aStatus)) { - // Extract the record names which are valid uint32_t's; they're - // the persistent session ids. - const char* name = nullptr; - uint32_t len = 0; - while (GMP_SUCCEEDED(aRecordIterator->GetName(&name, &len))) { - if (ClearKeyUtils::IsValidSessionId(name, len)) { - assert(name[len] == 0); - sPersistentSessionIds.insert(atoi(name)); - } - aRecordIterator->NextRecord(); - } - } - sPersistentKeyState = LOADED; - aRecordIterator->Close(); - - for (size_t i = 0; i < sTasksBlockedOnSessionIdLoad.size(); i++) { - sTasksBlockedOnSessionIdLoad[i]->Run(); - sTasksBlockedOnSessionIdLoad[i]->Destroy(); - } - sTasksBlockedOnSessionIdLoad.clear(); -} - -/* static */ void -ClearKeyPersistence::EnsureInitialized() -{ - if (sPersistentKeyState == UNINITIALIZED) { - sPersistentKeyState = LOADING; - if (GMP_FAILED(EnumRecordNames(&ReadAllRecordsFromIterator))) { - sPersistentKeyState = LOADED; - } - } -} - -/* static */ string -ClearKeyPersistence::GetNewSessionId(GMPSessionType aSessionType) -{ - static uint32_t sNextSessionId = 1; - - // Ensure we don't re-use a session id that was persisted. - while (Contains(sPersistentSessionIds, sNextSessionId)) { - sNextSessionId++; - } - - string sessionId; - stringstream ss; - ss << sNextSessionId; - ss >> sessionId; - - if (aSessionType == kGMPPersistentSession) { - sPersistentSessionIds.insert(sNextSessionId); - } - - sNextSessionId++; - - return sessionId; -} - - -class CreateSessionTask : public GMPTask { -public: - CreateSessionTask(ClearKeySessionManager* aTarget, - uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const string& aInitDataType, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) - : mTarget(aTarget) - , mCreateSessionToken(aCreateSessionToken) - , mPromiseId(aPromiseId) - , mInitDataType(aInitDataType) - , mSessionType(aSessionType) - { - mInitData.insert(mInitData.end(), - aInitData, - aInitData + aInitDataSize); - } - virtual void Run() override { - mTarget->CreateSession(mCreateSessionToken, - mPromiseId, - mInitDataType.c_str(), - mInitDataType.size(), - &mInitData.front(), - mInitData.size(), - mSessionType); - } - virtual void Destroy() override { - delete this; - } -private: - RefPtr mTarget; - uint32_t mCreateSessionToken; - uint32_t mPromiseId; - const string mInitDataType; - vector mInitData; - GMPSessionType mSessionType; -}; - - -/* static */ bool -ClearKeyPersistence::DeferCreateSessionIfNotReady(ClearKeySessionManager* aInstance, - uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const string& aInitDataType, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) -{ - if (sPersistentKeyState >= LOADED) { - return false; - } - GMPTask* t = new CreateSessionTask(aInstance, - aCreateSessionToken, - aPromiseId, - aInitDataType, - aInitData, - aInitDataSize, - aSessionType); - sTasksBlockedOnSessionIdLoad.push_back(t); - return true; -} - -class LoadSessionTask : public GMPTask { -public: - LoadSessionTask(ClearKeySessionManager* aTarget, - uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) - : mTarget(aTarget) - , mPromiseId(aPromiseId) - , mSessionId(aSessionId, aSessionId + aSessionIdLength) - { - } - virtual void Run() override { - mTarget->LoadSession(mPromiseId, - mSessionId.c_str(), - mSessionId.size()); - } - virtual void Destroy() override { - delete this; - } -private: - RefPtr mTarget; - uint32_t mPromiseId; - string mSessionId; -}; - -/* static */ bool -ClearKeyPersistence::DeferLoadSessionIfNotReady(ClearKeySessionManager* aInstance, - uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - if (sPersistentKeyState >= LOADED) { - return false; - } - GMPTask* t = new LoadSessionTask(aInstance, - aPromiseId, - aSessionId, - aSessionIdLength); - sTasksBlockedOnSessionIdLoad.push_back(t); - return true; -} - -/* static */ bool -ClearKeyPersistence::IsPersistentSessionId(const string& aSessionId) -{ - return Contains(sPersistentSessionIds, atoi(aSessionId.c_str())); -} - -class LoadSessionFromKeysTask : public ReadContinuation { -public: - LoadSessionFromKeysTask(ClearKeySessionManager* aTarget, - const string& aSessionId, - uint32_t aPromiseId) - : mTarget(aTarget) - , mSessionId(aSessionId) - , mPromiseId(aPromiseId) - { - } - - virtual void ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aLength) override - { - mTarget->PersistentSessionDataLoaded(aStatus, mPromiseId, mSessionId, aData, aLength); - } -private: - RefPtr mTarget; - string mSessionId; - uint32_t mPromiseId; -}; - -/* static */ void -ClearKeyPersistence::LoadSessionData(ClearKeySessionManager* aInstance, - const string& aSid, - uint32_t aPromiseId) -{ - LoadSessionFromKeysTask* loadTask = - new LoadSessionFromKeysTask(aInstance, aSid, aPromiseId); - ReadData(aSid, loadTask); -} - -/* static */ void -ClearKeyPersistence::PersistentSessionRemoved(const string& aSessionId) -{ - sPersistentSessionIds.erase(atoi(aSessionId.c_str())); -} diff --git a/media/gmp-clearkey/0.1/ClearKeyPersistence.h b/media/gmp-clearkey/0.1/ClearKeyPersistence.h deleted file mode 100644 index ddab9f783c..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyPersistence.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyPersistence_h__ -#define __ClearKeyPersistence_h__ - -#include -#include "gmp-api/gmp-decryption.h" - -class ClearKeySessionManager; - -class ClearKeyPersistence { -public: - static void EnsureInitialized(); - - static std::string GetNewSessionId(GMPSessionType aSessionType); - - static bool DeferCreateSessionIfNotReady(ClearKeySessionManager* aInstance, - uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const std::string& aInitDataType, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType); - - static bool DeferLoadSessionIfNotReady(ClearKeySessionManager* aInstance, - uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength); - - static bool IsPersistentSessionId(const std::string& aSid); - - static void LoadSessionData(ClearKeySessionManager* aInstance, - const std::string& aSid, - uint32_t aPromiseId); - - static void PersistentSessionRemoved(const std::string& aSid); -}; - -#endif // __ClearKeyPersistence_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeySession.cpp b/media/gmp-clearkey/0.1/ClearKeySession.cpp deleted file mode 100644 index fb45dd2ebf..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeySession.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "BigEndian.h" -#include "ClearKeyDecryptionManager.h" -#include "ClearKeySession.h" -#include "ClearKeyUtils.h" -#include "ClearKeyStorage.h" -#include "psshparser/PsshParser.h" -#include "gmp-task-utils.h" -#include "gmp-api/gmp-decryption.h" -#include -#include - -using namespace mozilla; - -ClearKeySession::ClearKeySession(const std::string& aSessionId, - GMPDecryptorCallback* aCallback, - GMPSessionType aSessionType) - : mSessionId(aSessionId) - , mCallback(aCallback) - , mSessionType(aSessionType) -{ - CK_LOGD("ClearKeySession ctor %p", this); -} - -ClearKeySession::~ClearKeySession() -{ - CK_LOGD("ClearKeySession dtor %p", this); - - std::vector key_infos; - for (const KeyId& keyId : mKeyIds) { - assert(ClearKeyDecryptionManager::Get()->HasSeenKeyId(keyId)); - ClearKeyDecryptionManager::Get()->ReleaseKeyId(keyId); - key_infos.push_back(GMPMediaKeyInfo(&keyId[0], keyId.size(), kGMPUnknown)); - } - mCallback->BatchedKeyStatusChanged(&mSessionId[0], mSessionId.size(), - key_infos.data(), key_infos.size()); -} - -void -ClearKeySession::Init(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const std::string& aInitDataType, - const uint8_t* aInitData, uint32_t aInitDataSize) -{ - CK_LOGD("ClearKeySession::Init"); - - if (aInitDataType == "cenc") { - ParseCENCInitData(aInitData, aInitDataSize, mKeyIds); - } else if (aInitDataType == "keyids") { - ClearKeyUtils::ParseKeyIdsInitData(aInitData, aInitDataSize, mKeyIds); - } else if (aInitDataType == "webm" && aInitDataSize <= kMaxWebmInitDataSize) { - // "webm" initData format is simply the raw bytes of the keyId. - vector keyId; - keyId.assign(aInitData, aInitData+aInitDataSize); - mKeyIds.push_back(keyId); - } - - if (!mKeyIds.size()) { - const char message[] = "Couldn't parse init data"; - mCallback->RejectPromise(aPromiseId, kGMPTypeError, message, strlen(message)); - return; - } - - mCallback->SetSessionId(aCreateSessionToken, &mSessionId[0], mSessionId.length()); - - mCallback->ResolvePromise(aPromiseId); -} - -GMPSessionType -ClearKeySession::Type() const -{ - return mSessionType; -} - -void -ClearKeySession::AddKeyId(const KeyId& aKeyId) -{ - mKeyIds.push_back(aKeyId); -} diff --git a/media/gmp-clearkey/0.1/ClearKeySession.h b/media/gmp-clearkey/0.1/ClearKeySession.h deleted file mode 100644 index 2783b2253b..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeySession.h +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeySession_h__ -#define __ClearKeySession_h__ - -#include "ClearKeyUtils.h" -#include "gmp-api/gmp-decryption.h" - -class GMPBuffer; -class GMPDecryptorCallback; -class GMPDecryptorHost; -class GMPEncryptedBufferMetadata; - -class ClearKeySession -{ -public: - explicit ClearKeySession(const std::string& aSessionId, - GMPDecryptorCallback* aCallback, - GMPSessionType aSessionType); - - ~ClearKeySession(); - - const std::vector& GetKeyIds() const { return mKeyIds; } - - void Init(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const string& aInitDataType, - const uint8_t* aInitData, uint32_t aInitDataSize); - - GMPSessionType Type() const; - - void AddKeyId(const KeyId& aKeyId); - - const std::string& Id() const { return mSessionId; } - -private: - const std::string mSessionId; - std::vector mKeyIds; - - GMPDecryptorCallback* mCallback; - const GMPSessionType mSessionType; -}; - -#endif // __ClearKeySession_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp b/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp deleted file mode 100644 index 4dbb062992..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeySessionManager.cpp +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include "ClearKeyDecryptionManager.h" -#include "ClearKeySessionManager.h" -#include "ClearKeyUtils.h" -#include "ClearKeyStorage.h" -#include "ClearKeyPersistence.h" -#include "gmp-task-utils.h" -#include - -using namespace std; - -ClearKeySessionManager::ClearKeySessionManager() - : mDecryptionManager(ClearKeyDecryptionManager::Get()) -{ - CK_LOGD("ClearKeySessionManager ctor %p", this); - AddRef(); - - if (GetPlatform()->createthread(&mThread) != GMPNoErr) { - CK_LOGD("failed to create thread in clearkey cdm"); - mThread = nullptr; - } -} - -ClearKeySessionManager::~ClearKeySessionManager() -{ - CK_LOGD("ClearKeySessionManager dtor %p", this); -} - -void -ClearKeySessionManager::Init(GMPDecryptorCallback* aCallback, - bool aDistinctiveIdentifierAllowed, - bool aPersistentStateAllowed) -{ - CK_LOGD("ClearKeySessionManager::Init"); - mCallback = aCallback; - ClearKeyPersistence::EnsureInitialized(); -} - -void -ClearKeySessionManager::CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const char* aInitDataType, - uint32_t aInitDataTypeSize, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) -{ - CK_LOGD("ClearKeySessionManager::CreateSession type:%s", aInitDataType); - - string initDataType(aInitDataType, aInitDataType + aInitDataTypeSize); - // initDataType must be "cenc", "keyids", or "webm". - if (initDataType != "cenc" && - initDataType != "keyids" && - initDataType != "webm") { - string message = "'" + initDataType + "' is an initDataType unsupported by ClearKey"; - mCallback->RejectPromise(aPromiseId, kGMPNotSupportedError, - message.c_str(), message.size()); - return; - } - - if (ClearKeyPersistence::DeferCreateSessionIfNotReady(this, - aCreateSessionToken, - aPromiseId, - initDataType, - aInitData, - aInitDataSize, - aSessionType)) { - return; - } - - string sessionId = ClearKeyPersistence::GetNewSessionId(aSessionType); - assert(mSessions.find(sessionId) == mSessions.end()); - - ClearKeySession* session = new ClearKeySession(sessionId, mCallback, aSessionType); - session->Init(aCreateSessionToken, aPromiseId, initDataType, aInitData, aInitDataSize); - mSessions[sessionId] = session; - - const vector& sessionKeys = session->GetKeyIds(); - vector neededKeys; - for (auto it = sessionKeys.begin(); it != sessionKeys.end(); it++) { - // Need to request this key ID from the client. We always send a key - // request, whether or not another session has sent a request with the same - // key ID. Otherwise a script can end up waiting for another script to - // respond to the request (which may not necessarily happen). - neededKeys.push_back(*it); - mDecryptionManager->ExpectKeyId(*it); - } - - if (neededKeys.empty()) { - CK_LOGD("No keys needed from client."); - return; - } - - // Send a request for needed key data. - string request; - ClearKeyUtils::MakeKeyRequest(neededKeys, request, aSessionType); - mCallback->SessionMessage(&sessionId[0], sessionId.length(), - kGMPLicenseRequest, - (uint8_t*)&request[0], request.length()); -} - -void -ClearKeySessionManager::LoadSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - CK_LOGD("ClearKeySessionManager::LoadSession"); - - if (!ClearKeyUtils::IsValidSessionId(aSessionId, aSessionIdLength)) { - mCallback->ResolveLoadSessionPromise(aPromiseId, false); - return; - } - - if (ClearKeyPersistence::DeferLoadSessionIfNotReady(this, - aPromiseId, - aSessionId, - aSessionIdLength)) { - return; - } - - string sid(aSessionId, aSessionId + aSessionIdLength); - if (!ClearKeyPersistence::IsPersistentSessionId(sid)) { - mCallback->ResolveLoadSessionPromise(aPromiseId, false); - return; - } - - // Callsback PersistentSessionDataLoaded with results... - ClearKeyPersistence::LoadSessionData(this, sid, aPromiseId); -} - -void -ClearKeySessionManager::PersistentSessionDataLoaded(GMPErr aStatus, - uint32_t aPromiseId, - const string& aSessionId, - const uint8_t* aKeyData, - uint32_t aKeyDataSize) -{ - CK_LOGD("ClearKeySessionManager::PersistentSessionDataLoaded"); - if (GMP_FAILED(aStatus) || - Contains(mSessions, aSessionId) || - (aKeyDataSize % (2 * CENC_KEY_LEN)) != 0) { - mCallback->ResolveLoadSessionPromise(aPromiseId, false); - return; - } - - ClearKeySession* session = new ClearKeySession(aSessionId, - mCallback, - kGMPPersistentSession); - mSessions[aSessionId] = session; - - uint32_t numKeys = aKeyDataSize / (2 * CENC_KEY_LEN); - - vector key_infos; - vector keyPairs; - for (uint32_t i = 0; i < numKeys; i ++) { - const uint8_t* base = aKeyData + 2 * CENC_KEY_LEN * i; - - KeyIdPair keyPair; - - keyPair.mKeyId = KeyId(base, base + CENC_KEY_LEN); - assert(keyPair.mKeyId.size() == CENC_KEY_LEN); - - keyPair.mKey = Key(base + CENC_KEY_LEN, base + 2 * CENC_KEY_LEN); - assert(keyPair.mKey.size() == CENC_KEY_LEN); - - session->AddKeyId(keyPair.mKeyId); - - mDecryptionManager->ExpectKeyId(keyPair.mKeyId); - mDecryptionManager->InitKey(keyPair.mKeyId, keyPair.mKey); - mKeyIds.insert(keyPair.mKey); - - keyPairs.push_back(keyPair); - key_infos.push_back(GMPMediaKeyInfo(&keyPairs[i].mKeyId[0], - keyPairs[i].mKeyId.size(), - kGMPUsable)); - } - mCallback->BatchedKeyStatusChanged(&aSessionId[0], aSessionId.size(), - key_infos.data(), key_infos.size()); - - mCallback->ResolveLoadSessionPromise(aPromiseId, true); -} - -void -ClearKeySessionManager::UpdateSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aResponse, - uint32_t aResponseSize) -{ - CK_LOGD("ClearKeySessionManager::UpdateSession"); - string sessionId(aSessionId, aSessionId + aSessionIdLength); - - auto itr = mSessions.find(sessionId); - if (itr == mSessions.end() || !(itr->second)) { - CK_LOGW("ClearKey CDM couldn't resolve session ID in UpdateSession."); - mCallback->RejectPromise(aPromiseId, kGMPNotFoundError, nullptr, 0); - return; - } - ClearKeySession* session = itr->second; - - // Verify the size of session response. - if (aResponseSize >= kMaxSessionResponseLength) { - CK_LOGW("Session response size is not within a reasonable size."); - mCallback->RejectPromise(aPromiseId, kGMPTypeError, nullptr, 0); - return; - } - - // Parse the response for any (key ID, key) pairs. - vector keyPairs; - if (!ClearKeyUtils::ParseJWK(aResponse, aResponseSize, keyPairs, session->Type())) { - CK_LOGW("ClearKey CDM failed to parse JSON Web Key."); - mCallback->RejectPromise(aPromiseId, kGMPTypeError, nullptr, 0); - return; - } - - vector key_infos; - for (size_t i = 0; i < keyPairs.size(); i++) { - KeyIdPair& keyPair = keyPairs[i]; - mDecryptionManager->InitKey(keyPair.mKeyId, keyPair.mKey); - mKeyIds.insert(keyPair.mKeyId); - key_infos.push_back(GMPMediaKeyInfo(&keyPair.mKeyId[0], - keyPair.mKeyId.size(), - kGMPUsable)); - } - mCallback->BatchedKeyStatusChanged(aSessionId, aSessionIdLength, - key_infos.data(), key_infos.size()); - - if (session->Type() != kGMPPersistentSession) { - mCallback->ResolvePromise(aPromiseId); - return; - } - - // Store the keys on disk. We store a record whose name is the sessionId, - // and simply append each keyId followed by its key. - vector keydata; - Serialize(session, keydata); - GMPTask* resolve = WrapTask(mCallback, &GMPDecryptorCallback::ResolvePromise, aPromiseId); - static const char* message = "Couldn't store cenc key init data"; - GMPTask* reject = WrapTask(mCallback, - &GMPDecryptorCallback::RejectPromise, - aPromiseId, - kGMPInvalidStateError, - message, - strlen(message)); - StoreData(sessionId, keydata, resolve, reject); -} - -void -ClearKeySessionManager::Serialize(const ClearKeySession* aSession, - std::vector& aOutKeyData) -{ - const std::vector& keyIds = aSession->GetKeyIds(); - for (size_t i = 0; i < keyIds.size(); i++) { - const KeyId& keyId = keyIds[i]; - if (!mDecryptionManager->HasKeyForKeyId(keyId)) { - continue; - } - assert(keyId.size() == CENC_KEY_LEN); - aOutKeyData.insert(aOutKeyData.end(), keyId.begin(), keyId.end()); - const Key& key = mDecryptionManager->GetDecryptionKey(keyId); - assert(key.size() == CENC_KEY_LEN); - aOutKeyData.insert(aOutKeyData.end(), key.begin(), key.end()); - } -} - -void -ClearKeySessionManager::CloseSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - CK_LOGD("ClearKeySessionManager::CloseSession"); - - string sessionId(aSessionId, aSessionId + aSessionIdLength); - auto itr = mSessions.find(sessionId); - if (itr == mSessions.end()) { - CK_LOGW("ClearKey CDM couldn't close non-existent session."); - mCallback->RejectPromise(aPromiseId, kGMPNotFoundError, nullptr, 0); - return; - } - - ClearKeySession* session = itr->second; - assert(session); - - ClearInMemorySessionData(session); - mCallback->SessionClosed(aSessionId, aSessionIdLength); - mCallback->ResolvePromise(aPromiseId); -} - -void -ClearKeySessionManager::ClearInMemorySessionData(ClearKeySession* aSession) -{ - mSessions.erase(aSession->Id()); - delete aSession; -} - -void -ClearKeySessionManager::RemoveSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) -{ - CK_LOGD("ClearKeySessionManager::RemoveSession"); - string sessionId(aSessionId, aSessionId + aSessionIdLength); - auto itr = mSessions.find(sessionId); - if (itr == mSessions.end()) { - CK_LOGW("ClearKey CDM couldn't remove non-existent session."); - mCallback->RejectPromise(aPromiseId, kGMPNotFoundError, nullptr, 0); - return; - } - - ClearKeySession* session = itr->second; - assert(session); - string sid = session->Id(); - bool isPersistent = session->Type() == kGMPPersistentSession; - ClearInMemorySessionData(session); - - if (!isPersistent) { - mCallback->ResolvePromise(aPromiseId); - return; - } - - ClearKeyPersistence::PersistentSessionRemoved(sid); - - // Overwrite the record storing the sessionId's key data with a zero - // length record to delete it. - vector emptyKeydata; - GMPTask* resolve = WrapTask(mCallback, &GMPDecryptorCallback::ResolvePromise, aPromiseId); - static const char* message = "Could not remove session"; - GMPTask* reject = WrapTask(mCallback, - &GMPDecryptorCallback::RejectPromise, - aPromiseId, - kGMPInvalidAccessError, - message, - strlen(message)); - StoreData(sessionId, emptyKeydata, resolve, reject); -} - -void -ClearKeySessionManager::SetServerCertificate(uint32_t aPromiseId, - const uint8_t* aServerCert, - uint32_t aServerCertSize) -{ - // ClearKey CDM doesn't support this method by spec. - CK_LOGD("ClearKeySessionManager::SetServerCertificate"); - mCallback->RejectPromise(aPromiseId, kGMPNotSupportedError, - nullptr /* message */, 0 /* messageLen */); -} - -void -ClearKeySessionManager::Decrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) -{ - CK_LOGD("ClearKeySessionManager::Decrypt"); - - if (!mThread) { - CK_LOGW("No decrypt thread"); - mCallback->Decrypted(aBuffer, GMPGenericErr); - return; - } - - mThread->Post(WrapTaskRefCounted(this, - &ClearKeySessionManager::DoDecrypt, - aBuffer, aMetadata)); -} - -void -ClearKeySessionManager::DoDecrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) -{ - CK_LOGD("ClearKeySessionManager::DoDecrypt"); - - GMPErr rv = mDecryptionManager->Decrypt(aBuffer->Data(), aBuffer->Size(), - CryptoMetaData(aMetadata)); - CK_LOGD("DeDecrypt finished with code %x\n", rv); - mCallback->Decrypted(aBuffer, rv); -} - -void -ClearKeySessionManager::Shutdown() -{ - CK_LOGD("ClearKeySessionManager::Shutdown %p", this); - - for (auto it = mSessions.begin(); it != mSessions.end(); it++) { - delete it->second; - } - mSessions.clear(); -} - -void -ClearKeySessionManager::DecryptingComplete() -{ - CK_LOGD("ClearKeySessionManager::DecryptingComplete %p", this); - - GMPThread* thread = mThread; - thread->Join(); - - Shutdown(); - mDecryptionManager = nullptr; - Release(); -} diff --git a/media/gmp-clearkey/0.1/ClearKeySessionManager.h b/media/gmp-clearkey/0.1/ClearKeySessionManager.h deleted file mode 100644 index 041b3f0362..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeySessionManager.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyDecryptor_h__ -#define __ClearKeyDecryptor_h__ - -#include -#include -#include -#include - -#include "ClearKeyDecryptionManager.h" -#include "ClearKeySession.h" -#include "ClearKeyUtils.h" -#include "gmp-api/gmp-decryption.h" -#include "RefCounted.h" - -class ClearKeySessionManager final : public GMPDecryptor - , public RefCounted -{ -public: - ClearKeySessionManager(); - - virtual void Init(GMPDecryptorCallback* aCallback, - bool aDistinctiveIdentifierAllowed, - bool aPersistentStateAllowed) override; - - virtual void CreateSession(uint32_t aCreateSessionToken, - uint32_t aPromiseId, - const char* aInitDataType, - uint32_t aInitDataTypeSize, - const uint8_t* aInitData, - uint32_t aInitDataSize, - GMPSessionType aSessionType) override; - - virtual void LoadSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - virtual void UpdateSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength, - const uint8_t* aResponse, - uint32_t aResponseSize) override; - - virtual void CloseSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - virtual void RemoveSession(uint32_t aPromiseId, - const char* aSessionId, - uint32_t aSessionIdLength) override; - - virtual void SetServerCertificate(uint32_t aPromiseId, - const uint8_t* aServerCert, - uint32_t aServerCertSize) override; - - virtual void Decrypt(GMPBuffer* aBuffer, - GMPEncryptedBufferMetadata* aMetadata) override; - - virtual void DecryptingComplete() override; - - void PersistentSessionDataLoaded(GMPErr aStatus, - uint32_t aPromiseId, - const std::string& aSessionId, - const uint8_t* aKeyData, - uint32_t aKeyDataSize); - -private: - ~ClearKeySessionManager(); - - void DoDecrypt(GMPBuffer* aBuffer, GMPEncryptedBufferMetadata* aMetadata); - void Shutdown(); - - void ClearInMemorySessionData(ClearKeySession* aSession); - void Serialize(const ClearKeySession* aSession, std::vector& aOutKeyData); - - RefPtr mDecryptionManager; - - GMPDecryptorCallback* mCallback; - GMPThread* mThread; - - std::set mKeyIds; - std::map mSessions; -}; - -#endif // __ClearKeyDecryptor_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeyStorage.cpp b/media/gmp-clearkey/0.1/ClearKeyStorage.cpp deleted file mode 100644 index 0db51c9b7e..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyStorage.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "ClearKeyStorage.h" -#include "ClearKeyUtils.h" - -#include "gmp-task-utils.h" - -#include -#include "ArrayUtils.h" - -#include - -static GMPErr -RunOnMainThread(GMPTask* aTask) -{ - return GetPlatform()->runonmainthread(aTask); -} - -GMPErr -OpenRecord(const char* aName, - uint32_t aNameLength, - GMPRecord** aOutRecord, - GMPRecordClient* aClient) -{ - return GetPlatform()->createrecord(aName, aNameLength, aOutRecord, aClient); -} - -class WriteRecordClient : public GMPRecordClient { -public: - /* - * This function will take the memory ownership of the parameters and - * delete them when done. - */ - static void Write(const std::string& aRecordName, - const std::vector& aData, - GMPTask* aOnSuccess, - GMPTask* aOnFailure) { - (new WriteRecordClient(aData, aOnSuccess, aOnFailure))->Do(aRecordName); - } - - virtual void OpenComplete(GMPErr aStatus) override { - if (GMP_FAILED(aStatus) || - GMP_FAILED(mRecord->Write(&mData.front(), mData.size()))) { - Done(mOnFailure, mOnSuccess); - } - } - - virtual void ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aDataSize) override { - assert(false); // Should not reach here. - } - - virtual void WriteComplete(GMPErr aStatus) override { - if (GMP_FAILED(aStatus)) { - Done(mOnFailure, mOnSuccess); - } else { - Done(mOnSuccess, mOnFailure); - } - } - -private: - WriteRecordClient(const std::vector& aData, - GMPTask* aOnSuccess, - GMPTask* aOnFailure) - : mRecord(nullptr) - , mOnSuccess(aOnSuccess) - , mOnFailure(aOnFailure) - , mData(aData) {} - - void Do(const std::string& aName) { - auto err = OpenRecord(aName.c_str(), aName.size(), &mRecord, this); - if (GMP_FAILED(err) || - GMP_FAILED(mRecord->Open())) { - Done(mOnFailure, mOnSuccess); - } - } - - void Done(GMPTask* aToRun, GMPTask* aToDestroy) { - // Note: Call Close() before running continuation, in case the - // continuation tries to open the same record; if we call Close() - // after running the continuation, the Close() call will arrive - // just after the Open() call succeeds, immediately closing the - // record we just opened. - if (mRecord) { - mRecord->Close(); - } - aToDestroy->Destroy(); - RunOnMainThread(aToRun); - delete this; - } - - GMPRecord* mRecord; - GMPTask* mOnSuccess; - GMPTask* mOnFailure; - const std::vector mData; -}; - -void -StoreData(const std::string& aRecordName, - const std::vector& aData, - GMPTask* aOnSuccess, - GMPTask* aOnFailure) -{ - WriteRecordClient::Write(aRecordName, aData, aOnSuccess, aOnFailure); -} - -class ReadRecordClient : public GMPRecordClient { -public: - /* - * This function will take the memory ownership of the parameters and - * delete them when done. - */ - static void Read(const std::string& aRecordName, - ReadContinuation* aContinuation) { - assert(aContinuation); - (new ReadRecordClient(aContinuation))->Do(aRecordName); - } - - virtual void OpenComplete(GMPErr aStatus) override { - auto err = aStatus; - if (GMP_FAILED(err) || - GMP_FAILED(err = mRecord->Read())) { - Done(err, nullptr, 0); - } - } - - virtual void ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aDataSize) override { - Done(aStatus, aData, aDataSize); - } - - virtual void WriteComplete(GMPErr aStatus) override { - assert(false); // Should not reach here. - } - -private: - explicit ReadRecordClient(ReadContinuation* aContinuation) - : mRecord(nullptr) - , mContinuation(aContinuation) {} - - void Do(const std::string& aName) { - auto err = OpenRecord(aName.c_str(), aName.size(), &mRecord, this); - if (GMP_FAILED(err) || - GMP_FAILED(err = mRecord->Open())) { - Done(err, nullptr, 0); - } - } - - void Done(GMPErr err, const uint8_t* aData, uint32_t aDataSize) { - // Note: Call Close() before running continuation, in case the - // continuation tries to open the same record; if we call Close() - // after running the continuation, the Close() call will arrive - // just after the Open() call succeeds, immediately closing the - // record we just opened. - if (mRecord) { - mRecord->Close(); - } - mContinuation->ReadComplete(err, aData, aDataSize); - delete mContinuation; - delete this; - } - - GMPRecord* mRecord; - ReadContinuation* mContinuation; -}; - -void -ReadData(const std::string& aRecordName, - ReadContinuation* aContinuation) -{ - ReadRecordClient::Read(aRecordName, aContinuation); -} - -GMPErr -EnumRecordNames(RecvGMPRecordIteratorPtr aRecvIteratorFunc) -{ - return GetPlatform()->getrecordenumerator(aRecvIteratorFunc, nullptr); -} diff --git a/media/gmp-clearkey/0.1/ClearKeyStorage.h b/media/gmp-clearkey/0.1/ClearKeyStorage.h deleted file mode 100644 index 695f67d9ea..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyStorage.h +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyStorage_h__ -#define __ClearKeyStorage_h__ - -#include "gmp-api/gmp-errors.h" -#include "gmp-api/gmp-platform.h" -#include -#include -#include - -class GMPTask; - -// Responsible for ensuring that both aOnSuccess and aOnFailure are destroyed. -void StoreData(const std::string& aRecordName, - const std::vector& aData, - GMPTask* aOnSuccess, - GMPTask* aOnFailure); - -class ReadContinuation { -public: - virtual void ReadComplete(GMPErr aStatus, - const uint8_t* aData, - uint32_t aLength) = 0; - virtual ~ReadContinuation() {} -}; - -// Deletes aContinuation after running it to report the result. -void ReadData(const std::string& aSessionId, - ReadContinuation* aContinuation); - -GMPErr EnumRecordNames(RecvGMPRecordIteratorPtr aRecvIteratorFunc); - -#endif // __ClearKeyStorage_h__ diff --git a/media/gmp-clearkey/0.1/ClearKeyUtils.cpp b/media/gmp-clearkey/0.1/ClearKeyUtils.cpp deleted file mode 100644 index b99a50a4dc..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyUtils.cpp +++ /dev/null @@ -1,541 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include -#include -#include - -#include "ClearKeyUtils.h" -#include "ClearKeyBase64.h" -#include "ArrayUtils.h" -#include -#include -#include "BigEndian.h" -#include "openaes/oaes_lib.h" - -using namespace std; - -void -CK_Log(const char* aFmt, ...) -{ - va_list ap; - - va_start(ap, aFmt); - vprintf(aFmt, ap); - va_end(ap); - - printf("\n"); - fflush(stdout); -} - -static void -IncrementIV(vector& aIV) { - using mozilla::BigEndian; - - assert(aIV.size() == 16); - BigEndian::writeUint64(&aIV[8], BigEndian::readUint64(&aIV[8]) + 1); -} - -/* static */ void -ClearKeyUtils::DecryptAES(const vector& aKey, - vector& aData, vector& aIV) -{ - assert(aIV.size() == CENC_KEY_LEN); - assert(aKey.size() == CENC_KEY_LEN); - - OAES_CTX* aes = oaes_alloc(); - oaes_key_import_data(aes, &aKey[0], aKey.size()); - oaes_set_option(aes, OAES_OPTION_ECB, nullptr); - - for (size_t i = 0; i < aData.size(); i += CENC_KEY_LEN) { - size_t encLen; - oaes_encrypt(aes, &aIV[0], CENC_KEY_LEN, nullptr, &encLen); - - vector enc(encLen); - oaes_encrypt(aes, &aIV[0], CENC_KEY_LEN, &enc[0], &encLen); - - assert(encLen >= 2 * OAES_BLOCK_SIZE + CENC_KEY_LEN); - size_t blockLen = min(aData.size() - i, CENC_KEY_LEN); - for (size_t j = 0; j < blockLen; j++) { - aData[i + j] ^= enc[2 * OAES_BLOCK_SIZE + j]; - } - IncrementIV(aIV); - } - - oaes_free(&aes); -} - -/** - * ClearKey expects all Key IDs to be base64 encoded with non-standard alphabet - * and padding. - */ -static bool -EncodeBase64Web(vector aBinary, string& aEncoded) -{ - const char sAlphabet[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - const uint8_t sMask = 0x3f; - - aEncoded.resize((aBinary.size() * 8 + 5) / 6); - - // Pad binary data in case there's rubbish past the last byte. - aBinary.push_back(0); - - // Number of bytes not consumed in the previous character - uint32_t shift = 0; - - auto out = aEncoded.begin(); - auto data = aBinary.begin(); - for (string::size_type i = 0; i < aEncoded.length(); i++) { - if (shift) { - out[i] = (*data << (6 - shift)) & sMask; - data++; - } else { - out[i] = 0; - } - - out[i] += (*data >> (shift + 2)) & sMask; - shift = (shift + 2) % 8; - - // Cast idx to size_t before using it as an array-index, - // to pacify clang 'Wchar-subscripts' warning: - size_t idx = static_cast(out[i]); - assert(idx < MOZ_ARRAY_LENGTH(sAlphabet)); // out of bounds index for 'sAlphabet' - out[i] = sAlphabet[idx]; - } - - return true; -} - -/* static */ void -ClearKeyUtils::MakeKeyRequest(const vector& aKeyIDs, - string& aOutRequest, - GMPSessionType aSessionType) -{ - assert(aKeyIDs.size() && aOutRequest.empty()); - - aOutRequest.append("{\"kids\":["); - for (size_t i = 0; i < aKeyIDs.size(); i++) { - if (i) { - aOutRequest.append(","); - } - aOutRequest.append("\""); - - string base64key; - EncodeBase64Web(aKeyIDs[i], base64key); - aOutRequest.append(base64key); - - aOutRequest.append("\""); - } - aOutRequest.append("],\"type\":"); - - aOutRequest.append("\""); - aOutRequest.append(SessionTypeToString(aSessionType)); - aOutRequest.append("\"}"); -} - -#define EXPECT_SYMBOL(CTX, X) do { \ - if (GetNextSymbol(CTX) != (X)) { \ - CK_LOGE("Unexpected symbol in JWK parser"); \ - return false; \ - } \ -} while (false) - -struct ParserContext { - const uint8_t* mIter; - const uint8_t* mEnd; -}; - -static uint8_t -PeekSymbol(ParserContext& aCtx) -{ - for (; aCtx.mIter < aCtx.mEnd; (aCtx.mIter)++) { - if (!isspace(*aCtx.mIter)) { - return *aCtx.mIter; - } - } - - return 0; -} - -static uint8_t -GetNextSymbol(ParserContext& aCtx) -{ - uint8_t sym = PeekSymbol(aCtx); - aCtx.mIter++; - return sym; -} - -static bool SkipToken(ParserContext& aCtx); - -static bool -SkipString(ParserContext& aCtx) -{ - EXPECT_SYMBOL(aCtx, '"'); - for (uint8_t sym = GetNextSymbol(aCtx); sym; sym = GetNextSymbol(aCtx)) { - if (sym == '\\') { - sym = GetNextSymbol(aCtx); - } else if (sym == '"') { - return true; - } - } - - return false; -} - -/** - * Skip whole object and values it contains. - */ -static bool -SkipObject(ParserContext& aCtx) -{ - EXPECT_SYMBOL(aCtx, '{'); - - if (PeekSymbol(aCtx) == '}') { - GetNextSymbol(aCtx); - return true; - } - - while (true) { - if (!SkipString(aCtx)) return false; - EXPECT_SYMBOL(aCtx, ':'); - if (!SkipToken(aCtx)) return false; - - if (PeekSymbol(aCtx) == '}') { - GetNextSymbol(aCtx); - return true; - } - EXPECT_SYMBOL(aCtx, ','); - } - - return false; -} - -/** - * Skip array value and the values it contains. - */ -static bool -SkipArray(ParserContext& aCtx) -{ - EXPECT_SYMBOL(aCtx, '['); - - if (PeekSymbol(aCtx) == ']') { - GetNextSymbol(aCtx); - return true; - } - - while (SkipToken(aCtx)) { - if (PeekSymbol(aCtx) == ']') { - GetNextSymbol(aCtx); - return true; - } - EXPECT_SYMBOL(aCtx, ','); - } - - return false; -} - -/** - * Skip unquoted literals like numbers, |true|, and |null|. - * (XXX and anything else that matches /([:alnum:]|[+-.])+/) - */ -static bool -SkipLiteral(ParserContext& aCtx) -{ - for (; aCtx.mIter < aCtx.mEnd; aCtx.mIter++) { - if (!isalnum(*aCtx.mIter) && - *aCtx.mIter != '.' && *aCtx.mIter != '-' && *aCtx.mIter != '+') { - return true; - } - } - - return false; -} - -static bool -SkipToken(ParserContext& aCtx) -{ - uint8_t startSym = PeekSymbol(aCtx); - if (startSym == '"') { - CK_LOGD("JWK parser skipping string"); - return SkipString(aCtx); - } else if (startSym == '{') { - CK_LOGD("JWK parser skipping object"); - return SkipObject(aCtx); - } else if (startSym == '[') { - CK_LOGD("JWK parser skipping array"); - return SkipArray(aCtx); - } else { - CK_LOGD("JWK parser skipping literal"); - return SkipLiteral(aCtx); - } - - return false; -} - -static bool -GetNextLabel(ParserContext& aCtx, string& aOutLabel) -{ - EXPECT_SYMBOL(aCtx, '"'); - - const uint8_t* start = aCtx.mIter; - for (uint8_t sym = GetNextSymbol(aCtx); sym; sym = GetNextSymbol(aCtx)) { - if (sym == '\\') { - GetNextSymbol(aCtx); - continue; - } - - if (sym == '"') { - aOutLabel.assign(start, aCtx.mIter - 1); - return true; - } - } - - return false; -} - -static bool -ParseKeyObject(ParserContext& aCtx, KeyIdPair& aOutKey) -{ - EXPECT_SYMBOL(aCtx, '{'); - - // Reject empty objects as invalid licenses. - if (PeekSymbol(aCtx) == '}') { - GetNextSymbol(aCtx); - return false; - } - - string keyId; - string key; - - while (true) { - string label; - string value; - - if (!GetNextLabel(aCtx, label)) { - return false; - } - - EXPECT_SYMBOL(aCtx, ':'); - if (label == "kty") { - if (!GetNextLabel(aCtx, value)) return false; - // By spec, type must be "oct". - if (value != "oct") return false; - } else if (label == "k" && PeekSymbol(aCtx) == '"') { - // if this isn't a string we will fall through to the SkipToken() path. - if (!GetNextLabel(aCtx, key)) return false; - } else if (label == "kid" && PeekSymbol(aCtx) == '"') { - if (!GetNextLabel(aCtx, keyId)) return false; - } else { - if (!SkipToken(aCtx)) return false; - } - - uint8_t sym = PeekSymbol(aCtx); - if (!sym || sym == '}') { - break; - } - EXPECT_SYMBOL(aCtx, ','); - } - - return !key.empty() && - !keyId.empty() && - DecodeBase64(keyId, aOutKey.mKeyId) && - DecodeBase64(key, aOutKey.mKey) && - GetNextSymbol(aCtx) == '}'; -} - -static bool -ParseKeys(ParserContext& aCtx, vector& aOutKeys) -{ - // Consume start of array. - EXPECT_SYMBOL(aCtx, '['); - - while (true) { - KeyIdPair key; - if (!ParseKeyObject(aCtx, key)) { - CK_LOGE("Failed to parse key object"); - return false; - } - - assert(!key.mKey.empty() && !key.mKeyId.empty()); - aOutKeys.push_back(key); - - uint8_t sym = PeekSymbol(aCtx); - if (!sym || sym == ']') { - break; - } - - EXPECT_SYMBOL(aCtx, ','); - } - - return GetNextSymbol(aCtx) == ']'; -} - -/* static */ bool -ClearKeyUtils::ParseJWK(const uint8_t* aKeyData, uint32_t aKeyDataSize, - vector& aOutKeys, - GMPSessionType aSessionType) -{ - ParserContext ctx; - ctx.mIter = aKeyData; - ctx.mEnd = aKeyData + aKeyDataSize; - - // Consume '{' from start of object. - EXPECT_SYMBOL(ctx, '{'); - - while (true) { - string label; - // Consume member key. - if (!GetNextLabel(ctx, label)) return false; - EXPECT_SYMBOL(ctx, ':'); - - if (label == "keys") { - // Parse "keys" array. - if (!ParseKeys(ctx, aOutKeys)) return false; - } else if (label == "type") { - // Consume type string. - string type; - if (!GetNextLabel(ctx, type)) return false; - if (type != SessionTypeToString(aSessionType)) { - return false; - } - } else { - SkipToken(ctx); - } - - // Check for end of object. - if (PeekSymbol(ctx) == '}') { - break; - } - - // Consume ',' between object members. - EXPECT_SYMBOL(ctx, ','); - } - - // Consume '}' from end of object. - EXPECT_SYMBOL(ctx, '}'); - - return true; -} - -static bool -ParseKeyIds(ParserContext& aCtx, vector& aOutKeyIds) -{ - // Consume start of array. - EXPECT_SYMBOL(aCtx, '['); - - while (true) { - string label; - vector keyId; - if (!GetNextLabel(aCtx, label) || !DecodeBase64(label, keyId)) { - return false; - } - if (!keyId.empty() && keyId.size() <= kMaxKeyIdsLength) { - aOutKeyIds.push_back(keyId); - } - - uint8_t sym = PeekSymbol(aCtx); - if (!sym || sym == ']') { - break; - } - - EXPECT_SYMBOL(aCtx, ','); - } - - return GetNextSymbol(aCtx) == ']'; -} - - -/* static */ bool -ClearKeyUtils::ParseKeyIdsInitData(const uint8_t* aInitData, - uint32_t aInitDataSize, - vector& aOutKeyIds) -{ - ParserContext ctx; - ctx.mIter = aInitData; - ctx.mEnd = aInitData + aInitDataSize; - - // Consume '{' from start of object. - EXPECT_SYMBOL(ctx, '{'); - - while (true) { - string label; - // Consume member kids. - if (!GetNextLabel(ctx, label)) return false; - EXPECT_SYMBOL(ctx, ':'); - - if (label == "kids") { - // Parse "kids" array. - if (!ParseKeyIds(ctx, aOutKeyIds) || - aOutKeyIds.empty()) { - return false; - } - } else { - SkipToken(ctx); - } - - // Check for end of object. - if (PeekSymbol(ctx) == '}') { - break; - } - - // Consume ',' between object members. - EXPECT_SYMBOL(ctx, ','); - } - - // Consume '}' from end of object. - EXPECT_SYMBOL(ctx, '}'); - - return true; -} - -/* static */ const char* -ClearKeyUtils::SessionTypeToString(GMPSessionType aSessionType) -{ - switch (aSessionType) { - case kGMPTemporySession: return "temporary"; - case kGMPPersistentSession: return "persistent-license"; - default: { - assert(false); // Should not reach here. - return "invalid"; - } - } -} - -/* static */ bool -ClearKeyUtils::IsValidSessionId(const char* aBuff, uint32_t aLength) -{ - if (aLength > 10) { - // 10 is the max number of characters in UINT32_MAX when - // represented as a string; ClearKey session ids are integers. - return false; - } - for (uint32_t i = 0; i < aLength; i++) { - if (!isdigit(aBuff[i])) { - return false; - } - } - return true; -} - -GMPMutex* GMPCreateMutex() { - GMPMutex* mutex; - auto err = GetPlatform()->createmutex(&mutex); - assert(mutex); - return GMP_FAILED(err) ? nullptr : mutex; -} diff --git a/media/gmp-clearkey/0.1/ClearKeyUtils.h b/media/gmp-clearkey/0.1/ClearKeyUtils.h deleted file mode 100644 index fc29b92119..0000000000 --- a/media/gmp-clearkey/0.1/ClearKeyUtils.h +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __ClearKeyUtils_h__ -#define __ClearKeyUtils_h__ - -#include -#include -#include -#include -#include "gmp-api/gmp-decryption.h" - -#if 0 -void CK_Log(const char* aFmt, ...); -#define CK_LOGE(...) CK_Log(__VA_ARGS__) -#define CK_LOGD(...) CK_Log(__VA_ARGS__) -#define CK_LOGW(...) CK_Log(__VA_ARGS__) -#else -#define CK_LOGE(...) -#define CK_LOGD(...) -#define CK_LOGW(...) -#endif - -struct GMPPlatformAPI; -extern GMPPlatformAPI* GetPlatform(); - -typedef std::vector KeyId; -typedef std::vector Key; - -// The session response size should be within a reasonable limit. -// The size 64 KB is referenced from web-platform-test. -static const uint32_t kMaxSessionResponseLength = 65536; - -// Provide limitation for KeyIds length and webm initData size. -static const uint32_t kMaxWebmInitDataSize = 65536; -static const uint32_t kMaxKeyIdsLength = 512; - -struct KeyIdPair -{ - KeyId mKeyId; - Key mKey; -}; - -class ClearKeyUtils -{ -public: - static void DecryptAES(const std::vector& aKey, - std::vector& aData, std::vector& aIV); - - static bool ParseKeyIdsInitData(const uint8_t* aInitData, - uint32_t aInitDataSize, - std::vector& aOutKeyIds); - - static void MakeKeyRequest(const std::vector& aKeyIds, - std::string& aOutRequest, - GMPSessionType aSessionType); - - static bool ParseJWK(const uint8_t* aKeyData, uint32_t aKeyDataSize, - std::vector& aOutKeys, - GMPSessionType aSessionType); - static const char* SessionTypeToString(GMPSessionType aSessionType); - - static bool IsValidSessionId(const char* aBuff, uint32_t aLength); -}; - -template -inline bool -Contains(const Container& aContainer, const Element& aElement) -{ - return aContainer.find(aElement) != aContainer.end(); -} - -class AutoLock { -public: - explicit AutoLock(GMPMutex* aMutex) - : mMutex(aMutex) - { - assert(aMutex); - if (mMutex) { - mMutex->Acquire(); - } - } - ~AutoLock() { - if (mMutex) { - mMutex->Release(); - } - } -private: - GMPMutex* mMutex; -}; - -GMPMutex* GMPCreateMutex(); - -template -inline void -Assign(std::vector& aVec, const T* aData, size_t aLength) -{ - aVec.assign(aData, aData + aLength); -} - -#endif // __ClearKeyUtils_h__ diff --git a/media/gmp-clearkey/0.1/RefCounted.h b/media/gmp-clearkey/0.1/RefCounted.h deleted file mode 100644 index 6da6942958..0000000000 --- a/media/gmp-clearkey/0.1/RefCounted.h +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __RefCount_h__ -#define __RefCount_h__ - -#include -#include -#include "ClearKeyUtils.h" - -#if defined(_MSC_VER) -#include -typedef std::atomic AtomicRefCount; -#else -class AtomicRefCount { -public: - explicit AtomicRefCount(uint32_t aValue) - : mCount(aValue) - , mMutex(GMPCreateMutex()) - { - assert(mMutex); - } - ~AtomicRefCount() - { - if (mMutex) { - mMutex->Destroy(); - } - } - uint32_t operator--() { - AutoLock lock(mMutex); - return --mCount; - } - uint32_t operator++() { - AutoLock lock(mMutex); - return ++mCount; - } - operator uint32_t() { - AutoLock lock(mMutex); - return mCount; - } -private: - uint32_t mCount; - GMPMutex* mMutex; -}; -#endif - -// Note: Thread safe. -class RefCounted { -public: - void AddRef() { - ++mRefCount; - } - - uint32_t Release() { - uint32_t newCount = --mRefCount; - if (!newCount) { - delete this; - } - return newCount; - } - -protected: - RefCounted() - : mRefCount(0) - { - } - virtual ~RefCounted() - { - assert(!mRefCount); - } - AtomicRefCount mRefCount; -}; - -template -class RefPtr { -public: - explicit RefPtr(T* aPtr) : mPtr(nullptr) { - Assign(aPtr); - } - ~RefPtr() { - Assign(nullptr); - } - T* operator->() const { return mPtr; } - - RefPtr& operator=(T* aVal) { - Assign(aVal); - return *this; - } - -private: - void Assign(T* aPtr) { - if (mPtr) { - mPtr->Release(); - } - mPtr = aPtr; - if (mPtr) { - aPtr->AddRef(); - } - } - T* mPtr; -}; - -#endif // __RefCount_h__ diff --git a/media/gmp-clearkey/0.1/VideoDecoder.cpp b/media/gmp-clearkey/0.1/VideoDecoder.cpp deleted file mode 100644 index a3f25402b1..0000000000 --- a/media/gmp-clearkey/0.1/VideoDecoder.cpp +++ /dev/null @@ -1,455 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include - -#include "AnnexB.h" -#include "BigEndian.h" -#include "ClearKeyDecryptionManager.h" -#include "ClearKeyUtils.h" -#include "gmp-task-utils.h" -#include "VideoDecoder.h" - -using namespace wmf; - -VideoDecoder::VideoDecoder(GMPVideoHost *aHostAPI) - : mHostAPI(aHostAPI) - , mCallback(nullptr) - , mWorkerThread(nullptr) - , mMutex(nullptr) - , mNumInputTasks(0) - , mSentExtraData(false) - , mIsFlushing(false) - , mHasShutdown(false) -{ - // We drop the ref in DecodingComplete(). - AddRef(); -} - -VideoDecoder::~VideoDecoder() -{ - if (mMutex) { - mMutex->Destroy(); - } -} - -void -VideoDecoder::InitDecode(const GMPVideoCodec& aCodecSettings, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - GMPVideoDecoderCallback* aCallback, - int32_t aCoreCount) -{ - mCallback = aCallback; - assert(mCallback); - mDecoder = new WMFH264Decoder(); - HRESULT hr = mDecoder->Init(aCoreCount); - if (FAILED(hr)) { - CK_LOGD("VideoDecoder::InitDecode failed to init WMFH264Decoder"); - mCallback->Error(GMPGenericErr); - return; - } - - auto err = GetPlatform()->createmutex(&mMutex); - if (GMP_FAILED(err)) { - CK_LOGD("VideoDecoder::InitDecode failed to create GMPMutex"); - mCallback->Error(GMPGenericErr); - return; - } - - // The first byte is mPacketizationMode, which is only relevant for - // WebRTC/OpenH264 usecase. - const uint8_t* avcc = aCodecSpecific + 1; - const uint8_t* avccEnd = aCodecSpecific + aCodecSpecificLength; - mExtraData.insert(mExtraData.end(), avcc, avccEnd); - - AnnexB::ConvertConfig(mExtraData, mAnnexB); -} - -void -VideoDecoder::EnsureWorker() -{ - if (!mWorkerThread) { - GetPlatform()->createthread(&mWorkerThread); - if (!mWorkerThread) { - mCallback->Error(GMPAllocErr); - return; - } - } -} - -void -VideoDecoder::Decode(GMPVideoEncodedFrame* aInputFrame, - bool aMissingFrames, - const uint8_t* aCodecSpecificInfo, - uint32_t aCodecSpecificInfoLength, - int64_t aRenderTimeMs) -{ - if (aInputFrame->BufferType() != GMP_BufferLength32) { - // Gecko should only send frames with 4 byte NAL sizes to GMPs. - mCallback->Error(GMPGenericErr); - return; - } - - EnsureWorker(); - - { - AutoLock lock(mMutex); - mNumInputTasks++; - } - - // Note: we don't need the codec specific info on a per-frame basis. - // It's mostly useful for WebRTC use cases. - - // Make a copy of the data, so we can release aInputFrame ASAP, - // to avoid too many shmem handles being held by the GMP process. - // If the GMP process holds on to too many shmem handles, the Gecko - // side can fail to allocate a shmem to send more input. This is - // particularly a problem in Gecko mochitests, which can open multiple - // actors at once which share the same pool of shmems. - DecodeData* data = new DecodeData(); - Assign(data->mBuffer, aInputFrame->Buffer(), aInputFrame->Size()); - data->mTimestamp = aInputFrame->TimeStamp(); - data->mDuration = aInputFrame->Duration(); - data->mIsKeyframe = (aInputFrame->FrameType() == kGMPKeyFrame); - const GMPEncryptedBufferMetadata* crypto = aInputFrame->GetDecryptionData(); - if (crypto) { - data->mCrypto.Init(crypto); - } - aInputFrame->Destroy(); - mWorkerThread->Post(WrapTaskRefCounted(this, - &VideoDecoder::DecodeTask, - data)); -} - -void -VideoDecoder::DecodeTask(DecodeData* aData) -{ - CK_LOGD("VideoDecoder::DecodeTask"); - AutoPtr d(aData); - HRESULT hr; - - { - AutoLock lock(mMutex); - mNumInputTasks--; - assert(mNumInputTasks >= 0); - } - - if (mIsFlushing) { - CK_LOGD("VideoDecoder::DecodeTask rejecting frame: flushing."); - return; - } - - if (!aData || !mHostAPI || !mDecoder) { - CK_LOGE("Decode job not set up correctly!"); - return; - } - - std::vector& buffer = aData->mBuffer; - if (aData->mCrypto.IsValid()) { - // Plugin host should have set up its decryptor/key sessions - // before trying to decode! - GMPErr rv = - ClearKeyDecryptionManager::Get()->Decrypt(buffer, aData->mCrypto); - - if (GMP_FAILED(rv)) { - MaybeRunOnMainThread(WrapTask(mCallback, &GMPVideoDecoderCallback::Error, rv)); - return; - } - } - - AnnexB::ConvertFrameInPlace(buffer); - - if (aData->mIsKeyframe) { - // We must send the SPS and PPS to Windows Media Foundation's decoder. - // Note: We do this *after* decryption, otherwise the subsample info - // would be incorrect. - buffer.insert(buffer.begin(), mAnnexB.begin(), mAnnexB.end()); - } - - hr = mDecoder->Input(buffer.data(), - buffer.size(), - aData->mTimestamp, - aData->mDuration); - - CK_LOGD("VideoDecoder::DecodeTask() Input ret hr=0x%x\n", hr); - if (FAILED(hr)) { - CK_LOGE("VideoDecoder::DecodeTask() decode failed ret=0x%x%s\n", - hr, - ((hr == MF_E_NOTACCEPTING) ? " (MF_E_NOTACCEPTING)" : "")); - return; - } - - while (hr == S_OK) { - CComPtr output; - hr = mDecoder->Output(&output); - CK_LOGD("VideoDecoder::DecodeTask() output ret=0x%x\n", hr); - if (hr == S_OK) { - MaybeRunOnMainThread( - WrapTaskRefCounted(this, - &VideoDecoder::ReturnOutput, - CComPtr(output), - mDecoder->GetFrameWidth(), - mDecoder->GetFrameHeight(), - mDecoder->GetStride())); - } - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - AutoLock lock(mMutex); - if (mNumInputTasks == 0) { - // We have run all input tasks. We *must* notify Gecko so that it will - // send us more data. - MaybeRunOnMainThread( - WrapTask(mCallback, - &GMPVideoDecoderCallback::InputDataExhausted)); - } - } - if (FAILED(hr)) { - CK_LOGE("VideoDecoder::DecodeTask() output failed hr=0x%x\n", hr); - } - } -} - -void -VideoDecoder::ReturnOutput(IMFSample* aSample, - int32_t aWidth, - int32_t aHeight, - int32_t aStride) -{ - CK_LOGD("[%p] VideoDecoder::ReturnOutput()\n", this); - assert(aSample); - - HRESULT hr; - - GMPVideoFrame* f = nullptr; - auto err = mHostAPI->CreateFrame(kGMPI420VideoFrame, &f); - if (GMP_FAILED(err) || !f) { - CK_LOGE("Failed to create i420 frame!\n"); - return; - } - if (HasShutdown()) { - // Note: GMPVideoHost::CreateFrame() can process messages before returning, - // including a message that calls VideoDecoder::DecodingComplete(), i.e. - // we can shutdown during the call! - CK_LOGD("Shutdown while waiting on GMPVideoHost::CreateFrame()!\n"); - f->Destroy(); - return; - } - - auto vf = static_cast(f); - - hr = SampleToVideoFrame(aSample, aWidth, aHeight, aStride, vf); - ENSURE(SUCCEEDED(hr), /*void*/); - - mCallback->Decoded(vf); -} - -HRESULT -VideoDecoder::SampleToVideoFrame(IMFSample* aSample, - int32_t aWidth, - int32_t aHeight, - int32_t aStride, - GMPVideoi420Frame* aVideoFrame) -{ - ENSURE(aSample != nullptr, E_POINTER); - ENSURE(aVideoFrame != nullptr, E_POINTER); - - HRESULT hr; - CComPtr mediaBuffer; - - // Must convert to contiguous mediaBuffer to use IMD2DBuffer interface. - hr = aSample->ConvertToContiguousBuffer(&mediaBuffer); - ENSURE(SUCCEEDED(hr), hr); - - // Try and use the IMF2DBuffer interface if available, otherwise fallback - // to the IMFMediaBuffer interface. Apparently IMF2DBuffer is more efficient, - // but only some systems (Windows 8?) support it. - BYTE* data = nullptr; - LONG stride = 0; - CComPtr twoDBuffer; - hr = mediaBuffer->QueryInterface(static_cast(&twoDBuffer)); - if (SUCCEEDED(hr)) { - hr = twoDBuffer->Lock2D(&data, &stride); - ENSURE(SUCCEEDED(hr), hr); - } else { - hr = mediaBuffer->Lock(&data, NULL, NULL); - ENSURE(SUCCEEDED(hr), hr); - stride = aStride; - } - - // The V and U planes are stored 16-row-aligned, so we need to add padding - // to the row heights to ensure the Y'CbCr planes are referenced properly. - // YV12, planar format: [YYYY....][VVVV....][UUUU....] - // i.e., Y, then V, then U. - uint32_t padding = 0; - if (aHeight % 16 != 0) { - padding = 16 - (aHeight % 16); - } - int32_t y_size = stride * (aHeight + padding); - int32_t v_size = stride * (aHeight + padding) / 4; - int32_t halfStride = (stride + 1) / 2; - int32_t halfHeight = (aHeight + 1) / 2; - - auto err = aVideoFrame->CreateEmptyFrame(stride, aHeight, stride, halfStride, halfStride); - ENSURE(GMP_SUCCEEDED(err), E_FAIL); - - err = aVideoFrame->SetWidth(aWidth); - ENSURE(GMP_SUCCEEDED(err), E_FAIL); - err = aVideoFrame->SetHeight(aHeight); - ENSURE(GMP_SUCCEEDED(err), E_FAIL); - - uint8_t* outBuffer = aVideoFrame->Buffer(kGMPYPlane); - ENSURE(outBuffer != nullptr, E_FAIL); - assert(aVideoFrame->AllocatedSize(kGMPYPlane) >= stride*aHeight); - memcpy(outBuffer, data, stride*aHeight); - - outBuffer = aVideoFrame->Buffer(kGMPUPlane); - ENSURE(outBuffer != nullptr, E_FAIL); - assert(aVideoFrame->AllocatedSize(kGMPUPlane) >= halfStride*halfHeight); - memcpy(outBuffer, data+y_size, halfStride*halfHeight); - - outBuffer = aVideoFrame->Buffer(kGMPVPlane); - ENSURE(outBuffer != nullptr, E_FAIL); - assert(aVideoFrame->AllocatedSize(kGMPVPlane) >= halfStride*halfHeight); - memcpy(outBuffer, data + y_size + v_size, halfStride*halfHeight); - - if (twoDBuffer) { - twoDBuffer->Unlock2D(); - } else { - mediaBuffer->Unlock(); - } - - LONGLONG hns = 0; - hr = aSample->GetSampleTime(&hns); - ENSURE(SUCCEEDED(hr), hr); - aVideoFrame->SetTimestamp(HNsToUsecs(hns)); - - hr = aSample->GetSampleDuration(&hns); - ENSURE(SUCCEEDED(hr), hr); - aVideoFrame->SetDuration(HNsToUsecs(hns)); - - return S_OK; -} - -void -VideoDecoder::ResetCompleteTask() -{ - mIsFlushing = false; - if (mCallback) { - MaybeRunOnMainThread(WrapTask(mCallback, - &GMPVideoDecoderCallback::ResetComplete)); - } -} - -void -VideoDecoder::Reset() -{ - mIsFlushing = true; - if (mDecoder) { - mDecoder->Reset(); - } - - // Schedule ResetComplete callback to run after existing frames have been - // flushed out of the task queue. - EnsureWorker(); - mWorkerThread->Post(WrapTaskRefCounted(this, - &VideoDecoder::ResetCompleteTask)); -} - -void -VideoDecoder::DrainTask() -{ - mDecoder->Drain(); - - // Return any pending output. - HRESULT hr = S_OK; - while (hr == S_OK) { - CComPtr output; - hr = mDecoder->Output(&output); - CK_LOGD("VideoDecoder::DrainTask() output ret=0x%x\n", hr); - if (hr == S_OK) { - MaybeRunOnMainThread( - WrapTaskRefCounted(this, - &VideoDecoder::ReturnOutput, - CComPtr(output), - mDecoder->GetFrameWidth(), - mDecoder->GetFrameHeight(), - mDecoder->GetStride())); - } - } - MaybeRunOnMainThread(WrapTask(mCallback, &GMPVideoDecoderCallback::DrainComplete)); -} - -void -VideoDecoder::Drain() -{ - if (!mDecoder) { - if (mCallback) { - mCallback->DrainComplete(); - } - return; - } - EnsureWorker(); - mWorkerThread->Post(WrapTaskRefCounted(this, - &VideoDecoder::DrainTask)); -} - -void -VideoDecoder::DecodingComplete() -{ - if (mWorkerThread) { - mWorkerThread->Join(); - } - mHasShutdown = true; - - // Release the reference we added in the constructor. There may be - // WrapRefCounted tasks that also hold references to us, and keep - // us alive a little longer. - Release(); -} - -void -VideoDecoder::MaybeRunOnMainThread(GMPTask* aTask) -{ - class MaybeRunTask : public GMPTask - { - public: - MaybeRunTask(VideoDecoder* aDecoder, GMPTask* aTask) - : mDecoder(aDecoder), mTask(aTask) - { } - - virtual void Run(void) { - if (mDecoder->HasShutdown()) { - CK_LOGD("Trying to dispatch to main thread after VideoDecoder has shut down"); - return; - } - - mTask->Run(); - } - - virtual void Destroy() - { - mTask->Destroy(); - delete this; - } - - private: - RefPtr mDecoder; - GMPTask* mTask; - }; - - GetPlatform()->runonmainthread(new MaybeRunTask(this, aTask)); -} diff --git a/media/gmp-clearkey/0.1/VideoDecoder.h b/media/gmp-clearkey/0.1/VideoDecoder.h deleted file mode 100644 index cf021efd73..0000000000 --- a/media/gmp-clearkey/0.1/VideoDecoder.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __VideoDecoder_h__ -#define __VideoDecoder_h__ - -#include - -#include "gmp-task-utils.h" -#include "gmp-video-decode.h" -#include "gmp-video-host.h" -#include "WMFH264Decoder.h" - -#include "mfobjects.h" - -class VideoDecoder : public GMPVideoDecoder - , public RefCounted -{ -public: - VideoDecoder(GMPVideoHost *aHostAPI); - - virtual void InitDecode(const GMPVideoCodec& aCodecSettings, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - GMPVideoDecoderCallback* aCallback, - int32_t aCoreCount) override; - - virtual void Decode(GMPVideoEncodedFrame* aInputFrame, - bool aMissingFrames, - const uint8_t* aCodecSpecific, - uint32_t aCodecSpecificLength, - int64_t aRenderTimeMs = -1); - - virtual void Reset() override; - - virtual void Drain() override; - - virtual void DecodingComplete() override; - - bool HasShutdown() { return mHasShutdown; } - -private: - - virtual ~VideoDecoder(); - - void EnsureWorker(); - - void DrainTask(); - - struct DecodeData { - DecodeData() - : mTimestamp(0) - , mDuration(0) - , mIsKeyframe(false) - {} - std::vector mBuffer; - uint64_t mTimestamp; - uint64_t mDuration; - bool mIsKeyframe; - CryptoMetaData mCrypto; - }; - - void DecodeTask(DecodeData* aData); - - void ResetCompleteTask(); - - void ReturnOutput(IMFSample* aSample, - int32_t aWidth, - int32_t aHeight, - int32_t aStride); - - HRESULT SampleToVideoFrame(IMFSample* aSample, - int32_t aWidth, - int32_t aHeight, - int32_t aStride, - GMPVideoi420Frame* aVideoFrame); - - void MaybeRunOnMainThread(GMPTask* aTask); - - GMPVideoHost *mHostAPI; // host-owned, invalid at DecodingComplete - GMPVideoDecoderCallback* mCallback; // host-owned, invalid at DecodingComplete - GMPThread* mWorkerThread; - GMPMutex* mMutex; - wmf::AutoPtr mDecoder; - - std::vector mExtraData; - std::vector mAnnexB; - - int32_t mNumInputTasks; - bool mSentExtraData; - - std::atomic mIsFlushing; - - bool mHasShutdown; -}; - -#endif // __VideoDecoder_h__ diff --git a/media/gmp-clearkey/0.1/WMFAACDecoder.cpp b/media/gmp-clearkey/0.1/WMFAACDecoder.cpp deleted file mode 100644 index 495f840e8d..0000000000 --- a/media/gmp-clearkey/0.1/WMFAACDecoder.cpp +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WMFAACDecoder.h" -#include -#include -#include - -using std::vector; - -namespace wmf { - -WMFAACDecoder::WMFAACDecoder() - : mDecoder(nullptr) - , mChannels(0) - , mRate(0) -{ - memset(&mInputStreamInfo, 0, sizeof(MFT_INPUT_STREAM_INFO)); - memset(&mOutputStreamInfo, 0, sizeof(MFT_OUTPUT_STREAM_INFO)); -} - -WMFAACDecoder::~WMFAACDecoder() -{ - Reset(); -} - -HRESULT -AACAudioSpecificConfigToUserData(BYTE* aAudioSpecConfig, UINT32 aConfigLength, - BYTE** aOutUserData, UINT32* aOutUserDataLength) -{ - // For MFAudioFormat_AAC, MF_MT_USER_DATA - // Contains the portion of the HEAACWAVEINFO structure that appears - // after the WAVEFORMATEX structure (that is, after the wfx member). - // This is followed by the AudioSpecificConfig() data, as defined - // by ISO/IEC 14496-3. - // ... - // The length of the AudioSpecificConfig() data is 2 bytes for AAC-LC - // or HE-AAC with implicit signaling of SBR/PS. It is more than 2 bytes - // for HE-AAC with explicit signaling of SBR/PS. - // - // The value of audioObjectType as defined in AudioSpecificConfig() - // must be 2, indicating AAC-LC. The value of extensionAudioObjectType - // must be 5 for SBR or 29 for PS. - // - // See: - // http://msdn.microsoft.com/en-us/library/windows/desktop/dd742784%28v=vs.85%29.aspx - // - // HEAACWAVEINFO structure: - // typedef struct heaacwaveinfo_tag { - // WAVEFORMATEX wfx; - // WORD wPayloadType; - // WORD wAudioProfileLevelIndication; - // WORD wStructType; - // WORD wReserved1; - // DWORD dwReserved2; - // } - const UINT32 heeInfoLen = 4 * sizeof(WORD) + sizeof(DWORD); - BYTE heeInfo[heeInfoLen] = {0}; - WORD* w = (WORD*)heeInfo; - w[0] = 0x0; // Payload type raw AAC - w[1] = 0; // Profile level unspecified - - const UINT32 len = heeInfoLen + aConfigLength; - BYTE* data = new BYTE[len]; - memcpy(data, heeInfo, heeInfoLen); - memcpy(data+heeInfoLen, aAudioSpecConfig, aConfigLength); - *aOutUserData = data; - *aOutUserDataLength = len; - return S_OK; -} - -HRESULT -WMFAACDecoder::Init(int32_t aChannelCount, - int32_t aSampleRate, - BYTE* aAACAudioSpecificConfig, - UINT32 aAudioConfigLength) -{ - HRESULT hr; - - // AAC decoder is in msauddecmft on Win8, and msmpeg2adec in earlier versions. - hr = CreateMFT(CLSID_CMSAACDecMFT, - WMFDecoderDllNameFor(AAC), - mDecoder); - if (FAILED(hr)) { - hr = CreateMFT(CLSID_CMSAACDecMFT, - WMFDecoderDllNameFor(AAC), - mDecoder); - if (FAILED(hr)) { - LOG("Failed to create AAC decoder\n"); - return E_FAIL; - } - } - - BYTE* userData = nullptr; - UINT32 userDataLength; - hr = AACAudioSpecificConfigToUserData(aAACAudioSpecificConfig, - aAudioConfigLength, - &userData, - &userDataLength); - ENSURE(SUCCEEDED(hr), hr); - hr = SetDecoderInputType(aChannelCount, aSampleRate, userData, userDataLength); - delete userData; - ENSURE(SUCCEEDED(hr), hr); - - hr = SetDecoderOutputType(); - ENSURE(SUCCEEDED(hr), hr); - - hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->GetInputStreamInfo(0, &mInputStreamInfo); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->GetOutputStreamInfo(0, &mOutputStreamInfo); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFAACDecoder::SetDecoderInputType(int32_t aChannelCount, - int32_t aSampleRate, - BYTE* aUserData, - UINT32 aUserDataLength) -{ - HRESULT hr; - - CComPtr type; - hr = MFCreateMediaType(&type); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetGUID(MF_MT_SUBTYPE, MFAudioFormat_AAC); - ENSURE(SUCCEEDED(hr), hr); - - mRate = aSampleRate; - hr = type->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, mRate); - ENSURE(SUCCEEDED(hr), hr); - - mChannels = aChannelCount; - hr = type->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, mChannels); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetBlob(MF_MT_USER_DATA, aUserData, aUserDataLength); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->SetInputType(0, type, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFAACDecoder::SetDecoderOutputType() -{ - HRESULT hr; - - CComPtr type; - - UINT32 typeIndex = 0; - while (type = nullptr, SUCCEEDED(mDecoder->GetOutputAvailableType(0, typeIndex++, &type))) { - GUID subtype; - hr = type->GetGUID(MF_MT_SUBTYPE, &subtype); - if (FAILED(hr)) { - continue; - } - if (subtype == MFAudioFormat_PCM) { - hr = mDecoder->SetOutputType(0, type, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->GetUINT32(MF_MT_AUDIO_NUM_CHANNELS, &mChannels); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->GetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND, &mRate); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; - } - } - - return E_FAIL; -} - -HRESULT -WMFAACDecoder::SendMFTMessage(MFT_MESSAGE_TYPE aMsg, UINT32 aData) -{ - ENSURE(mDecoder != nullptr, E_POINTER); - HRESULT hr = mDecoder->ProcessMessage(aMsg, aData); - ENSURE(SUCCEEDED(hr), hr); - return S_OK; -} - -HRESULT -WMFAACDecoder::CreateInputSample(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - IMFSample** aOutSample) -{ - HRESULT hr; - CComPtr sample = nullptr; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr buffer = nullptr; - int32_t bufferSize = std::max(uint32_t(mInputStreamInfo.cbSize), aDataSize); - UINT32 alignment = (mInputStreamInfo.cbAlignment > 1) ? mInputStreamInfo.cbAlignment - 1 : 0; - hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer); - ENSURE(SUCCEEDED(hr), hr); - - DWORD maxLength = 0; - DWORD currentLength = 0; - BYTE* dst = nullptr; - hr = buffer->Lock(&dst, &maxLength, ¤tLength); - ENSURE(SUCCEEDED(hr), hr); - - // Copy data into sample's buffer. - memcpy(dst, aData, aDataSize); - - hr = buffer->Unlock(); - ENSURE(SUCCEEDED(hr), hr); - - hr = buffer->SetCurrentLength(aDataSize); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->AddBuffer(buffer); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->SetSampleTime(UsecsToHNs(aTimestamp)); - ENSURE(SUCCEEDED(hr), hr); - - *aOutSample = sample.Detach(); - - return S_OK; -} - -HRESULT -WMFAACDecoder::CreateOutputSample(IMFSample** aOutSample) -{ - HRESULT hr; - CComPtr sample = nullptr; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr buffer = nullptr; - int32_t bufferSize = mOutputStreamInfo.cbSize; - UINT32 alignment = (mOutputStreamInfo.cbAlignment > 1) ? mOutputStreamInfo.cbAlignment - 1 : 0; - hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->AddBuffer(buffer); - ENSURE(SUCCEEDED(hr), hr); - - *aOutSample = sample.Detach(); - - return S_OK; -} - - -HRESULT -WMFAACDecoder::GetOutputSample(IMFSample** aOutSample) -{ - HRESULT hr; - // We allocate samples for MFT output. - MFT_OUTPUT_DATA_BUFFER output = {0}; - - CComPtr sample = nullptr; - hr = CreateOutputSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - output.pSample = sample; - - DWORD status = 0; - hr = mDecoder->ProcessOutput(0, 1, &output, &status); - CComPtr events = output.pEvents; // Ensure this is released. - - if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { - // Type change. Probably geometric apperature change. - hr = SetDecoderOutputType(); - ENSURE(SUCCEEDED(hr), hr); - - return GetOutputSample(aOutSample); - } else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT || !sample) { - return MF_E_TRANSFORM_NEED_MORE_INPUT; - } - // Treat other errors as fatal. - ENSURE(SUCCEEDED(hr), hr); - - assert(sample); - - *aOutSample = sample.Detach(); - return S_OK; -} - -HRESULT -WMFAACDecoder::Input(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp) -{ - CComPtr input = nullptr; - HRESULT hr = CreateInputSample(aData, aDataSize, aTimestamp, &input); - ENSURE(SUCCEEDED(hr) && input!=nullptr, hr); - - hr = mDecoder->ProcessInput(0, input, 0); - if (hr == MF_E_NOTACCEPTING) { - // MFT *already* has enough data to produce a sample. Retrieve it. - LOG("ProcessInput returned MF_E_NOTACCEPTING\n"); - return MF_E_NOTACCEPTING; - } - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFAACDecoder::Output(IMFSample** aOutput) -{ - CComPtr outputSample = nullptr; - HRESULT hr = GetOutputSample(&outputSample); - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - return MF_E_TRANSFORM_NEED_MORE_INPUT; - } - // Treat other errors as fatal. - ENSURE(SUCCEEDED(hr) && outputSample, hr); - - *aOutput = outputSample.Detach(); - - return S_OK; -} - -HRESULT -WMFAACDecoder::Reset() -{ - HRESULT hr = SendMFTMessage(MFT_MESSAGE_COMMAND_FLUSH, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFAACDecoder::Drain() -{ - HRESULT hr = SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -} diff --git a/media/gmp-clearkey/0.1/WMFAACDecoder.h b/media/gmp-clearkey/0.1/WMFAACDecoder.h deleted file mode 100644 index 3099eeea28..0000000000 --- a/media/gmp-clearkey/0.1/WMFAACDecoder.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined(WMFAACDecoder_h_) -#define WMFAACDecoder_h_ - -#include "WMFUtils.h" - -namespace wmf { - -class WMFAACDecoder { -public: - WMFAACDecoder(); - ~WMFAACDecoder(); - - HRESULT Init(int32_t aChannelCount, - int32_t aSampleRate, - BYTE* aUserData, - UINT32 aUserDataLength); - - HRESULT Input(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp); - - HRESULT Output(IMFSample** aOutput); - - HRESULT Reset(); - - HRESULT Drain(); - - UINT32 Channels() const { return mChannels; } - UINT32 Rate() const { return mRate; } - -private: - - HRESULT GetOutputSample(IMFSample** aOutSample); - HRESULT CreateOutputSample(IMFSample** aOutSample); - HRESULT CreateInputSample(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - IMFSample** aOutSample); - - HRESULT SetDecoderInputType(int32_t aChannelCount, - int32_t aSampleRate, - BYTE* aUserData, - UINT32 aUserDataLength); - HRESULT SetDecoderOutputType(); - HRESULT SendMFTMessage(MFT_MESSAGE_TYPE aMsg, UINT32 aData); - - MFT_INPUT_STREAM_INFO mInputStreamInfo; - MFT_OUTPUT_STREAM_INFO mOutputStreamInfo; - - CComPtr mDecoder; - - UINT32 mChannels; - UINT32 mRate; -}; - -} - -#endif diff --git a/media/gmp-clearkey/0.1/WMFH264Decoder.cpp b/media/gmp-clearkey/0.1/WMFH264Decoder.cpp deleted file mode 100644 index 8a3ed4fff4..0000000000 --- a/media/gmp-clearkey/0.1/WMFH264Decoder.cpp +++ /dev/null @@ -1,365 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WMFH264Decoder.h" -#include -#include - -namespace wmf { - -WMFH264Decoder::WMFH264Decoder() - : mDecoder(nullptr) -{ - memset(&mInputStreamInfo, 0, sizeof(MFT_INPUT_STREAM_INFO)); - memset(&mOutputStreamInfo, 0, sizeof(MFT_OUTPUT_STREAM_INFO)); -} - -WMFH264Decoder::~WMFH264Decoder() -{ -} - -HRESULT -WMFH264Decoder::Init(int32_t aCoreCount) -{ - HRESULT hr; - - hr = CreateMFT(__uuidof(CMSH264DecoderMFT), - WMFDecoderDllNameFor(H264), - mDecoder); - if (FAILED(hr)) { - // Windows 7 Enterprise Server N (which is what Mozilla's mochitests run - // on) need a different CLSID to instantiate the H.264 decoder. - hr = CreateMFT(CLSID_CMSH264DecMFT, - WMFDecoderDllNameFor(H264), - mDecoder); - } - ENSURE(SUCCEEDED(hr), hr); - - CComPtr attr; - hr = mDecoder->GetAttributes(&attr); - ENSURE(SUCCEEDED(hr), hr); - hr = attr->SetUINT32(CODECAPI_AVDecNumWorkerThreads, - GetNumThreads(aCoreCount)); - ENSURE(SUCCEEDED(hr), hr); - - hr = SetDecoderInputType(); - ENSURE(SUCCEEDED(hr), hr); - - hr = SetDecoderOutputType(); - ENSURE(SUCCEEDED(hr), hr); - - hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_BEGIN_STREAMING, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = SendMFTMessage(MFT_MESSAGE_NOTIFY_START_OF_STREAM, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->GetInputStreamInfo(0, &mInputStreamInfo); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->GetOutputStreamInfo(0, &mOutputStreamInfo); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFH264Decoder::ConfigureVideoFrameGeometry(IMFMediaType* aMediaType) -{ - ENSURE(aMediaType != nullptr, E_POINTER); - HRESULT hr; - - IntRect pictureRegion; - hr = wmf::GetPictureRegion(aMediaType, pictureRegion); - ENSURE(SUCCEEDED(hr), hr); - - UINT32 width = 0, height = 0; - hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height); - ENSURE(SUCCEEDED(hr), hr); - ENSURE(width <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - ENSURE(height <= mozilla::MAX_VIDEO_HEIGHT, E_FAIL); - - UINT32 stride = 0; - hr = GetDefaultStride(aMediaType, &stride); - ENSURE(SUCCEEDED(hr), hr); - ENSURE(stride <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - - // Success! Save state. - mStride = stride; - mVideoWidth = width; - mVideoHeight = height; - mPictureRegion = pictureRegion; - - LOG("WMFH264Decoder frame geometry frame=(%u,%u) stride=%u picture=(%d, %d, %d, %d)\n", - width, height, - mStride, - mPictureRegion.x, mPictureRegion.y, mPictureRegion.width, mPictureRegion.height); - - return S_OK; -} - -int32_t -WMFH264Decoder::GetFrameWidth() const -{ - return mVideoWidth; -} - -int32_t -WMFH264Decoder::GetFrameHeight() const -{ - return mVideoHeight; -} - -const IntRect& -WMFH264Decoder::GetPictureRegion() const -{ - return mPictureRegion; -} - -int32_t -WMFH264Decoder::GetStride() const -{ - return mStride; -} - -HRESULT -WMFH264Decoder::SetDecoderInputType() -{ - HRESULT hr; - - CComPtr type; - hr = MFCreateMediaType(&type); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); - ENSURE(SUCCEEDED(hr), hr); - - hr = type->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_MixedInterlaceOrProgressive); - ENSURE(SUCCEEDED(hr), hr); - - hr = mDecoder->SetInputType(0, type, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFH264Decoder::SetDecoderOutputType() -{ - HRESULT hr; - - CComPtr type; - - UINT32 typeIndex = 0; - while (type = nullptr, SUCCEEDED(mDecoder->GetOutputAvailableType(0, typeIndex++, &type))) { - GUID subtype; - hr = type->GetGUID(MF_MT_SUBTYPE, &subtype); - if (FAILED(hr)) { - continue; - } - if (subtype == MFVideoFormat_I420 || subtype == MFVideoFormat_IYUV) { - // On Windows 7 Enterprise N the MFT reports it reports IYUV instead - // of I420. Other Windows' report I420. The formats are the same, so - // support both. - hr = mDecoder->SetOutputType(0, type, 0); - ENSURE(SUCCEEDED(hr), hr); - - hr = ConfigureVideoFrameGeometry(type); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; - } - } - - return E_FAIL; -} - -HRESULT -WMFH264Decoder::SendMFTMessage(MFT_MESSAGE_TYPE aMsg, UINT32 aData) -{ - ENSURE(mDecoder != nullptr, E_POINTER); - HRESULT hr = mDecoder->ProcessMessage(aMsg, aData); - ENSURE(SUCCEEDED(hr), hr); - return S_OK; -} - -HRESULT -WMFH264Decoder::CreateInputSample(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - Microseconds aDuration, - IMFSample** aOutSample) -{ - HRESULT hr; - CComPtr sample; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr buffer; - int32_t bufferSize = std::max(uint32_t(mInputStreamInfo.cbSize), aDataSize); - UINT32 alignment = (mInputStreamInfo.cbAlignment > 1) ? mInputStreamInfo.cbAlignment - 1 : 0; - hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer); - ENSURE(SUCCEEDED(hr), hr); - - DWORD maxLength = 0; - DWORD currentLength = 0; - BYTE* dst = nullptr; - hr = buffer->Lock(&dst, &maxLength, ¤tLength); - ENSURE(SUCCEEDED(hr), hr); - - // Copy data into sample's buffer. - memcpy(dst, aData, aDataSize); - - hr = buffer->Unlock(); - ENSURE(SUCCEEDED(hr), hr); - - hr = buffer->SetCurrentLength(aDataSize); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->AddBuffer(buffer); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->SetSampleTime(UsecsToHNs(aTimestamp)); - ENSURE(SUCCEEDED(hr), hr); - - sample->SetSampleDuration(UsecsToHNs(aDuration)); - - *aOutSample = sample.Detach(); - - return S_OK; -} - -HRESULT -WMFH264Decoder::CreateOutputSample(IMFSample** aOutSample) -{ - HRESULT hr; - CComPtr sample; - hr = MFCreateSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - CComPtr buffer; - int32_t bufferSize = mOutputStreamInfo.cbSize; - UINT32 alignment = (mOutputStreamInfo.cbAlignment > 1) ? mOutputStreamInfo.cbAlignment - 1 : 0; - hr = MFCreateAlignedMemoryBuffer(bufferSize, alignment, &buffer); - ENSURE(SUCCEEDED(hr), hr); - - hr = sample->AddBuffer(buffer); - ENSURE(SUCCEEDED(hr), hr); - - *aOutSample = sample.Detach(); - - return S_OK; -} - - -HRESULT -WMFH264Decoder::GetOutputSample(IMFSample** aOutSample) -{ - HRESULT hr; - // We allocate samples for MFT output. - MFT_OUTPUT_DATA_BUFFER output = {0}; - - CComPtr sample; - hr = CreateOutputSample(&sample); - ENSURE(SUCCEEDED(hr), hr); - - output.pSample = sample; - - DWORD status = 0; - hr = mDecoder->ProcessOutput(0, 1, &output, &status); - //LOG(L"WMFH264Decoder::GetOutputSample() ProcessOutput returned 0x%x\n", hr); - CComPtr events = output.pEvents; // Ensure this is released. - - if (hr == MF_E_TRANSFORM_STREAM_CHANGE) { - // Type change. Probably geometric apperature change. - hr = SetDecoderOutputType(); - ENSURE(SUCCEEDED(hr), hr); - - return GetOutputSample(aOutSample); - } else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - return MF_E_TRANSFORM_NEED_MORE_INPUT; - } - // Treat other errors as fatal. - ENSURE(SUCCEEDED(hr), hr); - - assert(sample); - - // output.pSample - *aOutSample = sample.Detach(); // AddRefs - return S_OK; -} - -HRESULT -WMFH264Decoder::Input(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - Microseconds aDuration) -{ - HRESULT hr; - CComPtr input = nullptr; - hr = CreateInputSample(aData, aDataSize, aTimestamp, aDuration, &input); - ENSURE(SUCCEEDED(hr) && input!=nullptr, hr); - - hr = mDecoder->ProcessInput(0, input, 0); - if (hr == MF_E_NOTACCEPTING) { - // MFT *already* has enough data to produce a sample. Retrieve it. - LOG("ProcessInput returned MF_E_NOTACCEPTING\n"); - return MF_E_NOTACCEPTING; - } - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFH264Decoder::Output(IMFSample** aOutput) -{ - HRESULT hr; - CComPtr outputSample; - hr = GetOutputSample(&outputSample); - if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) { - return MF_E_TRANSFORM_NEED_MORE_INPUT; - } - // Treat other errors as fatal. - ENSURE(SUCCEEDED(hr) && outputSample, hr); - - *aOutput = outputSample.Detach(); - - return S_OK; -} - -HRESULT -WMFH264Decoder::Reset() -{ - HRESULT hr = SendMFTMessage(MFT_MESSAGE_COMMAND_FLUSH, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -HRESULT -WMFH264Decoder::Drain() -{ - HRESULT hr = SendMFTMessage(MFT_MESSAGE_COMMAND_DRAIN, 0); - ENSURE(SUCCEEDED(hr), hr); - - return S_OK; -} - -} // namespace wmf diff --git a/media/gmp-clearkey/0.1/WMFH264Decoder.h b/media/gmp-clearkey/0.1/WMFH264Decoder.h deleted file mode 100644 index 91b7e046ff..0000000000 --- a/media/gmp-clearkey/0.1/WMFH264Decoder.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#if !defined(WMFH264Decoder_h_) -#define WMFH264Decoder_h_ - -#include "WMFUtils.h" - -namespace wmf { - -class WMFH264Decoder { -public: - WMFH264Decoder(); - ~WMFH264Decoder(); - - HRESULT Init(int32_t aCoreCount); - - HRESULT Input(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - Microseconds aDuration); - - HRESULT Output(IMFSample** aOutput); - - HRESULT Reset(); - - int32_t GetFrameWidth() const; - int32_t GetFrameHeight() const; - const IntRect& GetPictureRegion() const; - int32_t GetStride() const; - - HRESULT Drain(); - -private: - - HRESULT SetDecoderInputType(); - HRESULT SetDecoderOutputType(); - HRESULT SendMFTMessage(MFT_MESSAGE_TYPE aMsg, UINT32 aData); - - HRESULT CreateInputSample(const uint8_t* aData, - uint32_t aDataSize, - Microseconds aTimestamp, - Microseconds aDuration, - IMFSample** aOutSample); - - HRESULT CreateOutputSample(IMFSample** aOutSample); - - HRESULT GetOutputSample(IMFSample** aOutSample); - HRESULT ConfigureVideoFrameGeometry(IMFMediaType* aMediaType); - - MFT_INPUT_STREAM_INFO mInputStreamInfo; - MFT_OUTPUT_STREAM_INFO mOutputStreamInfo; - - CComPtr mDecoder; - - int32_t mVideoWidth; - int32_t mVideoHeight; - IntRect mPictureRegion; - int32_t mStride; - -}; - -} // namespace wmf - -#endif diff --git a/media/gmp-clearkey/0.1/WMFSymbols.h b/media/gmp-clearkey/0.1/WMFSymbols.h deleted file mode 100644 index 60a0a6854b..0000000000 --- a/media/gmp-clearkey/0.1/WMFSymbols.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -MFPLAT_FUNC(MFCreateSample, "mfplat.dll"); -MFPLAT_FUNC(MFCreateAlignedMemoryBuffer, "mfplat.dll"); -MFPLAT_FUNC(MFGetStrideForBitmapInfoHeader, "evr.dll"); -MFPLAT_FUNC(MFCreateMediaType, "mfplat.dll"); diff --git a/media/gmp-clearkey/0.1/WMFUtils.cpp b/media/gmp-clearkey/0.1/WMFUtils.cpp deleted file mode 100644 index cb3cfe9fc9..0000000000 --- a/media/gmp-clearkey/0.1/WMFUtils.cpp +++ /dev/null @@ -1,276 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "WMFUtils.h" -#include "ClearKeyUtils.h" -#include - -#include -#include - -#define INITGUID -#include - -#pragma comment(lib, "mfuuid.lib") -#pragma comment(lib, "wmcodecdspuuid") - -void LOG(const char* format, ...) -{ -#ifdef WMF_DECODER_LOG - va_list args; - va_start(args, format); - vprintf(format, args); -#endif -} - -#ifdef WMF_MUST_DEFINE_AAC_MFT_CLSID -// Some SDK versions don't define the AAC decoder CLSID. -// {32D186A7-218F-4C75-8876-DD77273A8999} -DEFINE_GUID(CLSID_CMSAACDecMFT, 0x32D186A7, 0x218F, 0x4C75, 0x88, 0x76, 0xDD, 0x77, 0x27, 0x3A, 0x89, 0x99); -#endif - -DEFINE_GUID(CLSID_CMSH264DecMFT, 0x62CE7E72, 0x4C71, 0x4d20, 0xB1, 0x5D, 0x45, 0x28, 0x31, 0xA8, 0x7D, 0x9D); - -namespace wmf { - - -#define MFPLAT_FUNC(_func, _dllname) \ - decltype(::_func)* _func; -#include "WMFSymbols.h" -#undef MFPLAT_FUNC - -static bool -LinkMfplat() -{ - static bool sInitDone = false; - static bool sInitOk = false; - if (!sInitDone) { - sInitDone = true; - HMODULE handle; - -#define MFPLAT_FUNC(_func, _dllname) \ - handle = GetModuleHandleA(_dllname); \ - if (!(_func = (decltype(_func))(GetProcAddress(handle, #_func)))) { \ - return false; \ - } - -#include "WMFSymbols.h" -#undef MFPLAT_FUNC - sInitOk = true; - } - return sInitOk; -} - -const char* -WMFDecoderDllNameFor(CodecType aCodec) -{ - if (aCodec == H264) { - // For H.264 decoding, we need msmpeg2vdec.dll on Win 7 & 8, - // and mfh264dec.dll on Vista. - if (IsWindows7OrGreater()) { - return "msmpeg2vdec.dll"; - } else { - return "mfh264dec.dll"; - } - } else if (aCodec == AAC) { - // For AAC decoding, we need to use msauddecmft.dll on Win8, - // msmpeg2adec.dll on Win7, and msheaacdec.dll on Vista. - if (IsWindows8OrGreater()) { - return "msauddecmft.dll"; - } else if (IsWindows7OrGreater()) { - return "msmpeg2adec.dll"; - } else { - return "mfheaacdec.dll"; - } - } else { - return ""; - } -} - - -bool -EnsureLibs() -{ - static bool sInitDone = false; - static bool sInitOk = false; - if (!sInitDone) { - sInitOk = LinkMfplat() && - !!GetModuleHandleA(WMFDecoderDllNameFor(AAC)) && - !!GetModuleHandleA(WMFDecoderDllNameFor(H264)); - sInitDone = true; - } - return sInitOk; -} - -int32_t -MFOffsetToInt32(const MFOffset& aOffset) -{ - return int32_t(aOffset.value + (aOffset.fract / 65536.0f)); -} - -// Gets the sub-region of the video frame that should be displayed. -// See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb530115(v=vs.85).aspx -HRESULT -GetPictureRegion(IMFMediaType* aMediaType, IntRect& aOutPictureRegion) -{ - // Determine if "pan and scan" is enabled for this media. If it is, we - // only display a region of the video frame, not the entire frame. - BOOL panScan = MFGetAttributeUINT32(aMediaType, MF_MT_PAN_SCAN_ENABLED, FALSE); - - // If pan and scan mode is enabled. Try to get the display region. - HRESULT hr = E_FAIL; - MFVideoArea videoArea; - memset(&videoArea, 0, sizeof(MFVideoArea)); - if (panScan) { - hr = aMediaType->GetBlob(MF_MT_PAN_SCAN_APERTURE, - (UINT8*)&videoArea, - sizeof(MFVideoArea), - NULL); - } - - // If we're not in pan-and-scan mode, or the pan-and-scan region is not set, - // check for a minimimum display aperture. - if (!panScan || hr == MF_E_ATTRIBUTENOTFOUND) { - hr = aMediaType->GetBlob(MF_MT_MINIMUM_DISPLAY_APERTURE, - (UINT8*)&videoArea, - sizeof(MFVideoArea), - NULL); - } - - if (hr == MF_E_ATTRIBUTENOTFOUND) { - // Minimum display aperture is not set, for "backward compatibility with - // some components", check for a geometric aperture. - hr = aMediaType->GetBlob(MF_MT_GEOMETRIC_APERTURE, - (UINT8*)&videoArea, - sizeof(MFVideoArea), - NULL); - } - - if (SUCCEEDED(hr)) { - // The media specified a picture region, return it. - IntRect picture = IntRect(MFOffsetToInt32(videoArea.OffsetX), - MFOffsetToInt32(videoArea.OffsetY), - videoArea.Area.cx, - videoArea.Area.cy); - ENSURE(picture.width <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - ENSURE(picture.height <= mozilla::MAX_VIDEO_HEIGHT, E_FAIL); - aOutPictureRegion = picture; - return S_OK; - } - - // No picture region defined, fall back to using the entire video area. - UINT32 width = 0, height = 0; - hr = MFGetAttributeSize(aMediaType, MF_MT_FRAME_SIZE, &width, &height); - ENSURE(SUCCEEDED(hr), hr); - ENSURE(width <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - ENSURE(height <= mozilla::MAX_VIDEO_HEIGHT, E_FAIL); - aOutPictureRegion = IntRect(0, 0, width, height); - return S_OK; -} - - -HRESULT -GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride) -{ - // Try to get the default stride from the media type. - UINT32 stride = 0; - HRESULT hr = aType->GetUINT32(MF_MT_DEFAULT_STRIDE, &stride); - if (SUCCEEDED(hr)) { - ENSURE(stride <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - *aOutStride = stride; - return S_OK; - } - - // Stride attribute not set, calculate it. - GUID subtype = GUID_NULL; - uint32_t width = 0; - uint32_t height = 0; - - hr = aType->GetGUID(MF_MT_SUBTYPE, &subtype); - ENSURE(SUCCEEDED(hr), hr); - - hr = MFGetAttributeSize(aType, MF_MT_FRAME_SIZE, &width, &height); - ENSURE(SUCCEEDED(hr), hr); - ENSURE(width <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - ENSURE(height <= mozilla::MAX_VIDEO_HEIGHT, E_FAIL); - - LONG lstride = 0; - hr = MFGetStrideForBitmapInfoHeader(subtype.Data1, width, &lstride); - ENSURE(SUCCEEDED(hr), hr); - ENSURE(lstride <= mozilla::MAX_VIDEO_WIDTH, E_FAIL); - ENSURE(lstride >= 0, E_FAIL); - *aOutStride = lstride; - - return hr; -} - -void dump(const uint8_t* data, uint32_t len, const char* filename) -{ - FILE* f = 0; - fopen_s(&f, filename, "wb"); - fwrite(data, len, 1, f); - fclose(f); -} - -HRESULT -CreateMFT(const CLSID& clsid, - const char* aDllName, - CComPtr& aOutMFT) -{ - HMODULE module = ::GetModuleHandleA(aDllName); - if (!module) { - LOG("Failed to get %S\n", aDllName); - return E_FAIL; - } - - typedef HRESULT (WINAPI* DllGetClassObjectFnPtr)(const CLSID& clsid, - const IID& iid, - void** object); - - DllGetClassObjectFnPtr GetClassObjPtr = - reinterpret_cast(GetProcAddress(module, "DllGetClassObject")); - if (!GetClassObjPtr) { - LOG("Failed to get DllGetClassObject\n"); - return E_FAIL; - } - - CComPtr classFactory; - HRESULT hr = GetClassObjPtr(clsid, - __uuidof(IClassFactory), - reinterpret_cast(static_cast(&classFactory))); - if (FAILED(hr)) { - LOG("Failed to get H264 IClassFactory\n"); - return E_FAIL; - } - - hr = classFactory->CreateInstance(NULL, - __uuidof(IMFTransform), - reinterpret_cast(static_cast(&aOutMFT))); - if (FAILED(hr)) { - LOG("Failed to get create MFT\n"); - return E_FAIL; - } - - return S_OK; -} - -int32_t -GetNumThreads(int32_t aCoreCount) -{ - return aCoreCount > 4 ? -1 : (std::max)(aCoreCount - 1, 1); -} - -} // namespace diff --git a/media/gmp-clearkey/0.1/WMFUtils.h b/media/gmp-clearkey/0.1/WMFUtils.h deleted file mode 100644 index 51d46d70d4..0000000000 --- a/media/gmp-clearkey/0.1/WMFUtils.h +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright 2013, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef __WMFUtils_h__ -#define __WMFUtils_h__ - -#include -#include - -#include -#include -#include -#include -#include -#include -#include "VideoLimits.h" - -#include "gmp-platform.h" - -void LOG(const char* format, ...); - -#ifdef LOG_SAMPLE_DECODE -#define SAMPLE_LOG LOG -#else -#define SAMPLE_LOG(...) -#endif - -#ifndef CLSID_CMSAACDecMFT -#define WMF_MUST_DEFINE_AAC_MFT_CLSID -extern "C" const CLSID CLSID_CMSAACDecMFT; -#endif - -extern "C" const CLSID CLSID_CMSH264DecMFT; - -namespace wmf { - -// Reimplementation of CComPtr to reduce dependence on system -// shared libraries. -template -class CComPtr { -public: - CComPtr(CComPtr&& aOther) : mPtr(aOther.Detach()) { } - CComPtr& operator=(CComPtr&& other) { mPtr = other.Detach(); } - - CComPtr(const CComPtr& aOther) : mPtr(nullptr) { Set(aOther.Get()); } - CComPtr() : mPtr(nullptr) { } - CComPtr(T* const & aPtr) : mPtr(nullptr) { Set(aPtr); } - CComPtr(const std::nullptr_t& aNullPtr) : mPtr(aNullPtr) { } - T** operator&() { return &mPtr; } - T* operator->(){ return mPtr; } - operator T*() { return mPtr; } - T* operator=(T* const & aPtr) { return Set(aPtr); } - T* operator=(const std::nullptr_t& aPtr) { return mPtr = aPtr; } - - T* Get() const { return mPtr; } - - T* Detach() { - T* tmp = mPtr; - mPtr = nullptr; - return tmp; - } - - ~CComPtr() { - if (mPtr) { - mPtr->Release(); - } - mPtr = nullptr; - } - -private: - - T* Set(T* aPtr) { - if (mPtr == aPtr) { - return aPtr; - } - if (mPtr) { - mPtr->Release(); - } - mPtr = aPtr; - if (mPtr) { - mPtr->AddRef(); - } - return mPtr; - } - - T* mPtr; -}; - -class IntRect { -public: - IntRect(int32_t _x, int32_t _y, int32_t _w, int32_t _h) - : x(_x), y(_y), width(_w), height(_h) {} - IntRect() - : x(0), y(0), width(0), height(0) {} - int32_t x; - int32_t y; - int32_t width; - int32_t height; -}; - -typedef int64_t Microseconds; - -#ifdef ENSURE -#undef ENSURE -#endif - -#define ENSURE(condition, ret) \ -{ if (!(condition)) { LOG("##condition## FAILED %S:%d\n", __FILE__, __LINE__); return ret; } } - -#define GMP_SUCCEEDED(x) ((x) == GMPNoErr) -#define GMP_FAILED(x) ((x) != GMPNoErr) - -#define MFPLAT_FUNC(_func, _dllname) \ - extern decltype(::_func)* _func; -#include "WMFSymbols.h" -#undef MFPLAT_FUNC - -bool -EnsureLibs(); - -HRESULT -GetPictureRegion(IMFMediaType* aMediaType, IntRect& aOutPictureRegion); - -HRESULT -GetDefaultStride(IMFMediaType *aType, uint32_t* aOutStride); - -// Converts from microseconds to hundreds of nanoseconds. -// We use microseconds for our timestamps, whereas WMF uses -// hundreds of nanoseconds. -inline int64_t -UsecsToHNs(int64_t aUsecs) { - return aUsecs * 10; -} - -// Converts from hundreds of nanoseconds to microseconds. -// We use microseconds for our timestamps, whereas WMF uses -// hundreds of nanoseconds. -inline int64_t -HNsToUsecs(int64_t hNanoSecs) { - return hNanoSecs / 10; -} - -inline std::string narrow(std::wstring &wide) { - std::string ns(wide.begin(), wide.end()); - return ns; -} - -inline std::wstring widen(std::string &narrow) { - std::wstring ws(narrow.begin(), narrow.end()); - return ws; -} - -#define ARRAY_LENGTH(array_) \ - (sizeof(array_)/sizeof(array_[0])) - -template -class AutoPtr { -public: - AutoPtr() - : mPtr(nullptr) - { - } - - AutoPtr(AutoPtr& aPtr) - : mPtr(aPtr.Forget()) - { - } - - AutoPtr(Type* aPtr) - : mPtr(aPtr) - { - } - - ~AutoPtr() { - if (mPtr) { - delete mPtr; - } - } - - Type* Forget() { - Type* rv = mPtr; - mPtr = nullptr; - return rv; - } - - AutoPtr& operator=(Type* aOther) { - Assign(aOther); - return *this; - } - - AutoPtr& operator=(AutoPtr& aOther) { - Assign(aOther.Forget()); - return *this; - } - - Type* Get() const { - return mPtr; - } - - Type* operator->() const { - assert(mPtr); - return Get(); - } - - operator Type*() const { - return Get(); - } - - Type** Receive() { - return &mPtr; - } -private: - - void Assign(Type* aPtr) { - if (mPtr) { - delete mPtr; - } - mPtr = aPtr; - } - - Type* mPtr; -}; - -// Video frame microseconds are (currently) in 90kHz units, as used by RTP. -// Use this to convert to microseconds... -inline Microseconds RTPTimeToMicroseconds(int64_t rtptime) { - return (rtptime * 1000000) / 90000; -} - -inline uint32_t MicrosecondsToRTPTime(Microseconds us) { - return uint32_t(0xffffffff & (us * 90000) / 1000000); -} - -void dump(const uint8_t* data, uint32_t len, const char* filename); - -HRESULT -CreateMFT(const CLSID& clsid, - const char* aDllName, - CComPtr& aOutMFT); - -enum CodecType { - H264, - AAC, -}; - -// Returns the name of the DLL that is needed to decode H.264 or AAC on -// the given windows version we're running on. -const char* WMFDecoderDllNameFor(CodecType aCodec); - -// Returns the maximum number of threads we want WMF to use for decoding -// given the number of logical processors available. -int32_t GetNumThreads(int32_t aCoreCount); - -} // namespace wmf - -#endif // __WMFUtils_h__ diff --git a/media/gmp-clearkey/0.1/clearkey.info.in b/media/gmp-clearkey/0.1/clearkey.info.in deleted file mode 100644 index 8b3445d599..0000000000 --- a/media/gmp-clearkey/0.1/clearkey.info.in +++ /dev/null @@ -1,10 +0,0 @@ -Name: clearkey -Description: ClearKey Gecko Media Plugin -Version: 1 -#ifdef ENABLE_WMF -APIs: eme-decrypt-v9[org.w3.clearkey], decode-audio[aac:org.w3.clearkey], decode-video[h264:org.w3.clearkey] -Libraries: dxva2.dll, d3d9.dll, msmpeg2vdec.dll, msmpeg2adec.dll, MSAudDecMFT.dll, evr.dll, mfheaacdec.dll, mfh264dec.dll, mfplat.dll -#else -APIs: eme-decrypt-v9[org.w3.clearkey] -Libraries: -#endif diff --git a/media/gmp-clearkey/0.1/gmp-clearkey.cpp b/media/gmp-clearkey/0.1/gmp-clearkey.cpp deleted file mode 100644 index fae7ce9f82..0000000000 --- a/media/gmp-clearkey/0.1/gmp-clearkey.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include -#include -#include - -#include "ClearKeyAsyncShutdown.h" -#include "ClearKeySessionManager.h" -#include "gmp-api/gmp-async-shutdown.h" -#include "gmp-api/gmp-decryption.h" -#include "gmp-api/gmp-platform.h" - -#if defined(ENABLE_WMF) -#include "WMFUtils.h" -#include "AudioDecoder.h" -#include "VideoDecoder.h" -#endif - -#if defined(WIN32) -#define GMP_EXPORT __declspec(dllexport) -#else -#define GMP_EXPORT __attribute__((visibility("default"))) -#endif - -static GMPPlatformAPI* sPlatform = nullptr; -GMPPlatformAPI* -GetPlatform() -{ - return sPlatform; -} - -extern "C" { - -GMP_EXPORT GMPErr -GMPInit(GMPPlatformAPI* aPlatformAPI) -{ - sPlatform = aPlatformAPI; - return GMPNoErr; -} - -GMP_EXPORT GMPErr -GMPGetAPI(const char* aApiName, void* aHostAPI, void** aPluginAPI) -{ - CK_LOGD("ClearKey GMPGetAPI |%s|", aApiName); - assert(!*aPluginAPI); - - if (!strcmp(aApiName, GMP_API_DECRYPTOR)) { - *aPluginAPI = new ClearKeySessionManager(); - } -#if defined(ENABLE_WMF) - else if (!strcmp(aApiName, GMP_API_AUDIO_DECODER) && - wmf::EnsureLibs()) { - *aPluginAPI = new AudioDecoder(static_cast(aHostAPI)); - } else if (!strcmp(aApiName, GMP_API_VIDEO_DECODER) && - wmf::EnsureLibs()) { - *aPluginAPI = new VideoDecoder(static_cast(aHostAPI)); - } -#endif - else if (!strcmp(aApiName, GMP_API_ASYNC_SHUTDOWN)) { - *aPluginAPI = new ClearKeyAsyncShutdown(static_cast (aHostAPI)); - } else { - CK_LOGE("GMPGetAPI couldn't resolve API name |%s|\n", aApiName); - } - - return *aPluginAPI ? GMPNoErr : GMPNotImplementedErr; -} - -GMP_EXPORT GMPErr -GMPShutdown(void) -{ - CK_LOGD("ClearKey GMPShutdown"); - return GMPNoErr; -} - -} diff --git a/media/gmp-clearkey/0.1/gmp-task-utils-generated.h b/media/gmp-clearkey/0.1/gmp-task-utils-generated.h deleted file mode 100644 index 597ed47210..0000000000 --- a/media/gmp-clearkey/0.1/gmp-task-utils-generated.h +++ /dev/null @@ -1,1938 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "RefCounted.h" - -// 0 arguments -- -template class gmp_task_args_nm_0 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_0(M m) : - m_(m) {} - - void Run() { - m_(); - } - - private: - M m_; -}; - - - -// 0 arguments -- -template class gmp_task_args_nm_0_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_0_ret(M m, R *r) : - m_(m), r_(r) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(); - } - - private: - M m_; - R* r_; -}; - - - -// 0 arguments -- -template class gmp_task_args_m_0 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_0(C o, M m) : - o_(o), m_(m) {} - - void Run() { - ((*o_).*m_)(); - } - - private: - C o_; - M m_; -}; - - - -// 0 arguments -- -template class gmp_task_args_m_0_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_0_ret(C o, M m, R *r) : - o_(o), m_(m), r_(r) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(); - } - - private: - C o_; - M m_; - R* r_; -}; - - - -// 1 arguments -- -template class gmp_task_args_nm_1 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_1(M m, A0 a0) : - m_(m), a0_(a0) {} - - void Run() { - m_(a0_); - } - - private: - M m_; - A0 a0_; -}; - - - -// 1 arguments -- -template class gmp_task_args_nm_1_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_1_ret(M m, A0 a0, R *r) : - m_(m), r_(r), a0_(a0) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_); - } - - private: - M m_; - R* r_; - A0 a0_; -}; - - - -// 1 arguments -- -template class gmp_task_args_m_1 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_1(C o, M m, A0 a0) : - o_(o), m_(m), a0_(a0) {} - - void Run() { - ((*o_).*m_)(a0_); - } - - private: - C o_; - M m_; - A0 a0_; -}; - - - -// 1 arguments -- -template class gmp_task_args_m_1_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_1_ret(C o, M m, A0 a0, R *r) : - o_(o), m_(m), r_(r), a0_(a0) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; -}; - - - -// 2 arguments -- -template class gmp_task_args_nm_2 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_2(M m, A0 a0, A1 a1) : - m_(m), a0_(a0), a1_(a1) {} - - void Run() { - m_(a0_, a1_); - } - - private: - M m_; - A0 a0_; - A1 a1_; -}; - - - -// 2 arguments -- -template class gmp_task_args_nm_2_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_2_ret(M m, A0 a0, A1 a1, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; -}; - - - -// 2 arguments -- -template class gmp_task_args_m_2 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_2(C o, M m, A0 a0, A1 a1) : - o_(o), m_(m), a0_(a0), a1_(a1) {} - - void Run() { - ((*o_).*m_)(a0_, a1_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; -}; - - - -// 2 arguments -- -template class gmp_task_args_m_2_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_2_ret(C o, M m, A0 a0, A1 a1, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; -}; - - - -// 3 arguments -- -template class gmp_task_args_nm_3 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_3(M m, A0 a0, A1 a1, A2 a2) : - m_(m), a0_(a0), a1_(a1), a2_(a2) {} - - void Run() { - m_(a0_, a1_, a2_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; -}; - - - -// 3 arguments -- -template class gmp_task_args_nm_3_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_3_ret(M m, A0 a0, A1 a1, A2 a2, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; -}; - - - -// 3 arguments -- -template class gmp_task_args_m_3 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_3(C o, M m, A0 a0, A1 a1, A2 a2) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; -}; - - - -// 3 arguments -- -template class gmp_task_args_m_3_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_3_ret(C o, M m, A0 a0, A1 a1, A2 a2, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; -}; - - - -// 4 arguments -- -template class gmp_task_args_nm_4 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_4(M m, A0 a0, A1 a1, A2 a2, A3 a3) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3) {} - - void Run() { - m_(a0_, a1_, a2_, a3_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; -}; - - - -// 4 arguments -- -template class gmp_task_args_nm_4_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_4_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; -}; - - - -// 4 arguments -- -template class gmp_task_args_m_4 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_4(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; -}; - - - -// 4 arguments -- -template class gmp_task_args_m_4_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_4_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; -}; - - - -// 5 arguments -- -template class gmp_task_args_nm_5 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_5(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; -}; - - - -// 5 arguments -- -template class gmp_task_args_nm_5_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_5_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; -}; - - - -// 5 arguments -- -template class gmp_task_args_m_5 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_5(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; -}; - - - -// 5 arguments -- -template class gmp_task_args_m_5_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_5_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; -}; - - - -// 6 arguments -- -template class gmp_task_args_nm_6 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_6(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; -}; - - - -// 6 arguments -- -template class gmp_task_args_nm_6_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_6_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; -}; - - - -// 6 arguments -- -template class gmp_task_args_m_6 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_6(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; -}; - - - -// 6 arguments -- -template class gmp_task_args_m_6_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_6_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; -}; - - - -// 7 arguments -- -template class gmp_task_args_nm_7 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_7(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; -}; - - - -// 7 arguments -- -template class gmp_task_args_nm_7_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_7_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; -}; - - - -// 7 arguments -- -template class gmp_task_args_m_7 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_7(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; -}; - - - -// 7 arguments -- -template class gmp_task_args_m_7_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_7_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; -}; - - - -// 8 arguments -- -template class gmp_task_args_nm_8 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_8(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; -}; - - - -// 8 arguments -- -template class gmp_task_args_nm_8_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_8_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; -}; - - - -// 8 arguments -- -template class gmp_task_args_m_8 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_8(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; -}; - - - -// 8 arguments -- -template class gmp_task_args_m_8_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_8_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; -}; - - - -// 9 arguments -- -template class gmp_task_args_nm_9 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_9(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; -}; - - - -// 9 arguments -- -template class gmp_task_args_nm_9_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_9_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; -}; - - - -// 9 arguments -- -template class gmp_task_args_m_9 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_9(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; -}; - - - -// 9 arguments -- -template class gmp_task_args_m_9_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_9_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; -}; - - - -// 10 arguments -- -template class gmp_task_args_nm_10 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_10(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; -}; - - - -// 10 arguments -- -template class gmp_task_args_nm_10_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_10_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; -}; - - - -// 10 arguments -- -template class gmp_task_args_m_10 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_10(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; -}; - - - -// 10 arguments -- -template class gmp_task_args_m_10_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_10_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; -}; - - - -// 11 arguments -- -template class gmp_task_args_nm_11 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_11(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; -}; - - - -// 11 arguments -- -template class gmp_task_args_nm_11_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_11_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; -}; - - - -// 11 arguments -- -template class gmp_task_args_m_11 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_11(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; -}; - - - -// 11 arguments -- -template class gmp_task_args_m_11_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_11_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; -}; - - - -// 12 arguments -- -template class gmp_task_args_nm_12 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_12(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; -}; - - - -// 12 arguments -- -template class gmp_task_args_nm_12_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_12_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; -}; - - - -// 12 arguments -- -template class gmp_task_args_m_12 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_12(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; -}; - - - -// 12 arguments -- -template class gmp_task_args_m_12_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_12_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; -}; - - - -// 13 arguments -- -template class gmp_task_args_nm_13 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_13(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; -}; - - - -// 13 arguments -- -template class gmp_task_args_nm_13_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_13_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; -}; - - - -// 13 arguments -- -template class gmp_task_args_m_13 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_13(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; -}; - - - -// 13 arguments -- -template class gmp_task_args_m_13_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_13_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; -}; - - - -// 14 arguments -- -template class gmp_task_args_nm_14 : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_14(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) : - m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} - - void Run() { - m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); - } - - private: - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; - A13 a13_; -}; - - - -// 14 arguments -- -template class gmp_task_args_nm_14_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_nm_14_ret(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R *r) : - m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = m_(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); - } - - private: - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; - A13 a13_; -}; - - - -// 14 arguments -- -template class gmp_task_args_m_14 : public gmp_task_args_base { - public: - explicit gmp_task_args_m_14(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) : - o_(o), m_(m), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} - - void Run() { - ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); - } - - private: - C o_; - M m_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; - A13 a13_; -}; - - - -// 14 arguments -- -template class gmp_task_args_m_14_ret : public gmp_task_args_base { - public: - explicit gmp_task_args_m_14_ret(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R *r) : - o_(o), m_(m), r_(r), a0_(a0), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5), a6_(a6), a7_(a7), a8_(a8), a9_(a9), a10_(a10), a11_(a11), a12_(a12), a13_(a13) {} - virtual bool returns_value() const { return true; } - - void Run() { - *r_ = ((*o_).*m_)(a0_, a1_, a2_, a3_, a4_, a5_, a6_, a7_, a8_, a9_, a10_, a11_, a12_, a13_); - } - - private: - C o_; - M m_; - R* r_; - A0 a0_; - A1 a1_; - A2 a2_; - A3 a3_; - A4 a4_; - A5 a5_; - A6 a6_; - A7 a7_; - A8 a8_; - A9 a9_; - A10 a10_; - A11 a11_; - A12 a12_; - A13 a13_; -}; - - - - - - -// 0 arguments -- -template -gmp_task_args_nm_0* WrapTaskNM(M m) { - return new gmp_task_args_nm_0 - (m); -} - -// 0 arguments -- -template -gmp_task_args_nm_0_ret* WrapTaskNMRet(M m, R* r) { - return new gmp_task_args_nm_0_ret - (m, r); -} - -// 0 arguments -- -template -gmp_task_args_m_0* WrapTask(C o, M m) { - return new gmp_task_args_m_0 - (o, m); -} - -// 0 arguments -- -template -gmp_task_args_m_0_ret* WrapTaskRet(C o, M m, R* r) { - return new gmp_task_args_m_0_ret - (o, m, r); -} - -// 1 arguments -- -template -gmp_task_args_nm_1* WrapTaskNM(M m, A0 a0) { - return new gmp_task_args_nm_1 - (m, a0); -} - -// 1 arguments -- -template -gmp_task_args_nm_1_ret* WrapTaskNMRet(M m, A0 a0, R* r) { - return new gmp_task_args_nm_1_ret - (m, a0, r); -} - -// 1 arguments -- -template -gmp_task_args_m_1* WrapTask(C o, M m, A0 a0) { - return new gmp_task_args_m_1 - (o, m, a0); -} - -// 1 arguments -- -template -gmp_task_args_m_1_ret* WrapTaskRet(C o, M m, A0 a0, R* r) { - return new gmp_task_args_m_1_ret - (o, m, a0, r); -} - -// 2 arguments -- -template -gmp_task_args_nm_2* WrapTaskNM(M m, A0 a0, A1 a1) { - return new gmp_task_args_nm_2 - (m, a0, a1); -} - -// 2 arguments -- -template -gmp_task_args_nm_2_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, R* r) { - return new gmp_task_args_nm_2_ret - (m, a0, a1, r); -} - -// 2 arguments -- -template -gmp_task_args_m_2* WrapTask(C o, M m, A0 a0, A1 a1) { - return new gmp_task_args_m_2 - (o, m, a0, a1); -} - -// 2 arguments -- -template -gmp_task_args_m_2_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, R* r) { - return new gmp_task_args_m_2_ret - (o, m, a0, a1, r); -} - -// 3 arguments -- -template -gmp_task_args_nm_3* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2) { - return new gmp_task_args_nm_3 - (m, a0, a1, a2); -} - -// 3 arguments -- -template -gmp_task_args_nm_3_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, R* r) { - return new gmp_task_args_nm_3_ret - (m, a0, a1, a2, r); -} - -// 3 arguments -- -template -gmp_task_args_m_3* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2) { - return new gmp_task_args_m_3 - (o, m, a0, a1, a2); -} - -// 3 arguments -- -template -gmp_task_args_m_3_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, R* r) { - return new gmp_task_args_m_3_ret - (o, m, a0, a1, a2, r); -} - -// 4 arguments -- -template -gmp_task_args_nm_4* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3) { - return new gmp_task_args_nm_4 - (m, a0, a1, a2, a3); -} - -// 4 arguments -- -template -gmp_task_args_nm_4_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, R* r) { - return new gmp_task_args_nm_4_ret - (m, a0, a1, a2, a3, r); -} - -// 4 arguments -- -template -gmp_task_args_m_4* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3) { - return new gmp_task_args_m_4 - (o, m, a0, a1, a2, a3); -} - -// 4 arguments -- -template -gmp_task_args_m_4_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, R* r) { - return new gmp_task_args_m_4_ret - (o, m, a0, a1, a2, a3, r); -} - -// 5 arguments -- -template -gmp_task_args_nm_5* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return new gmp_task_args_nm_5 - (m, a0, a1, a2, a3, a4); -} - -// 5 arguments -- -template -gmp_task_args_nm_5_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R* r) { - return new gmp_task_args_nm_5_ret - (m, a0, a1, a2, a3, a4, r); -} - -// 5 arguments -- -template -gmp_task_args_m_5* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4) { - return new gmp_task_args_m_5 - (o, m, a0, a1, a2, a3, a4); -} - -// 5 arguments -- -template -gmp_task_args_m_5_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, R* r) { - return new gmp_task_args_m_5_ret - (o, m, a0, a1, a2, a3, a4, r); -} - -// 6 arguments -- -template -gmp_task_args_nm_6* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - return new gmp_task_args_nm_6 - (m, a0, a1, a2, a3, a4, a5); -} - -// 6 arguments -- -template -gmp_task_args_nm_6_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R* r) { - return new gmp_task_args_nm_6_ret - (m, a0, a1, a2, a3, a4, a5, r); -} - -// 6 arguments -- -template -gmp_task_args_m_6* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) { - return new gmp_task_args_m_6 - (o, m, a0, a1, a2, a3, a4, a5); -} - -// 6 arguments -- -template -gmp_task_args_m_6_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, R* r) { - return new gmp_task_args_m_6_ret - (o, m, a0, a1, a2, a3, a4, a5, r); -} - -// 7 arguments -- -template -gmp_task_args_nm_7* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { - return new gmp_task_args_nm_7 - (m, a0, a1, a2, a3, a4, a5, a6); -} - -// 7 arguments -- -template -gmp_task_args_nm_7_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R* r) { - return new gmp_task_args_nm_7_ret - (m, a0, a1, a2, a3, a4, a5, a6, r); -} - -// 7 arguments -- -template -gmp_task_args_m_7* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) { - return new gmp_task_args_m_7 - (o, m, a0, a1, a2, a3, a4, a5, a6); -} - -// 7 arguments -- -template -gmp_task_args_m_7_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, R* r) { - return new gmp_task_args_m_7_ret - (o, m, a0, a1, a2, a3, a4, a5, a6, r); -} - -// 8 arguments -- -template -gmp_task_args_nm_8* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { - return new gmp_task_args_nm_8 - (m, a0, a1, a2, a3, a4, a5, a6, a7); -} - -// 8 arguments -- -template -gmp_task_args_nm_8_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R* r) { - return new gmp_task_args_nm_8_ret - (m, a0, a1, a2, a3, a4, a5, a6, a7, r); -} - -// 8 arguments -- -template -gmp_task_args_m_8* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) { - return new gmp_task_args_m_8 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7); -} - -// 8 arguments -- -template -gmp_task_args_m_8_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, R* r) { - return new gmp_task_args_m_8_ret - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, r); -} - -// 9 arguments -- -template -gmp_task_args_nm_9* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { - return new gmp_task_args_nm_9 - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8); -} - -// 9 arguments -- -template -gmp_task_args_nm_9_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R* r) { - return new gmp_task_args_nm_9_ret - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, r); -} - -// 9 arguments -- -template -gmp_task_args_m_9* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8) { - return new gmp_task_args_m_9 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8); -} - -// 9 arguments -- -template -gmp_task_args_m_9_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, R* r) { - return new gmp_task_args_m_9_ret - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, r); -} - -// 10 arguments -- -template -gmp_task_args_nm_10* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { - return new gmp_task_args_nm_10 - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); -} - -// 10 arguments -- -template -gmp_task_args_nm_10_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R* r) { - return new gmp_task_args_nm_10_ret - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, r); -} - -// 10 arguments -- -template -gmp_task_args_m_10* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9) { - return new gmp_task_args_m_10 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); -} - -// 10 arguments -- -template -gmp_task_args_m_10_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, R* r) { - return new gmp_task_args_m_10_ret - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, r); -} - -// 11 arguments -- -template -gmp_task_args_nm_11* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) { - return new gmp_task_args_nm_11 - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); -} - -// 11 arguments -- -template -gmp_task_args_nm_11_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R* r) { - return new gmp_task_args_nm_11_ret - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, r); -} - -// 11 arguments -- -template -gmp_task_args_m_11* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10) { - return new gmp_task_args_m_11 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); -} - -// 11 arguments -- -template -gmp_task_args_m_11_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, R* r) { - return new gmp_task_args_m_11_ret - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, r); -} - -// 12 arguments -- -template -gmp_task_args_nm_12* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) { - return new gmp_task_args_nm_12 - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); -} - -// 12 arguments -- -template -gmp_task_args_nm_12_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R* r) { - return new gmp_task_args_nm_12_ret - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, r); -} - -// 12 arguments -- -template -gmp_task_args_m_12* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11) { - return new gmp_task_args_m_12 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); -} - -// 12 arguments -- -template -gmp_task_args_m_12_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, R* r) { - return new gmp_task_args_m_12_ret - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, r); -} - -// 13 arguments -- -template -gmp_task_args_nm_13* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) { - return new gmp_task_args_nm_13 - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); -} - -// 13 arguments -- -template -gmp_task_args_nm_13_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R* r) { - return new gmp_task_args_nm_13_ret - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, r); -} - -// 13 arguments -- -template -gmp_task_args_m_13* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12) { - return new gmp_task_args_m_13 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); -} - -// 13 arguments -- -template -gmp_task_args_m_13_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, R* r) { - return new gmp_task_args_m_13_ret - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, r); -} - -// 14 arguments -- -template -gmp_task_args_nm_14* WrapTaskNM(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) { - return new gmp_task_args_nm_14 - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); -} - -// 14 arguments -- -template -gmp_task_args_nm_14_ret* WrapTaskNMRet(M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R* r) { - return new gmp_task_args_nm_14_ret - (m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, r); -} - -// 14 arguments -- -template -gmp_task_args_m_14* WrapTask(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13) { - return new gmp_task_args_m_14 - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13); -} - -// 14 arguments -- -template -gmp_task_args_m_14_ret* WrapTaskRet(C o, M m, A0 a0, A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7, A8 a8, A9 a9, A10 a10, A11 a11, A12 a12, A13 a13, R* r) { - return new gmp_task_args_m_14_ret - (o, m, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, r); -} - -class RefCountTaskWrapper : public gmp_task_args_base { -public: - RefCountTaskWrapper(GMPTask* aTask, RefCounted* aRefCounted) - : mTask(aTask) - , mRefCounted(aRefCounted) - {} - virtual void Run() override { - mTask->Run(); - } - virtual void Destroy() override { - mTask->Destroy(); - gmp_task_args_base::Destroy(); - } -private: - ~RefCountTaskWrapper() {} - - GMPTask* mTask; - RefPtr mRefCounted; -}; - -template -GMPTask* -WrapTaskRefCounted(Type* aType, Method aMethod, Args&&... args) -{ - GMPTask* t = WrapTask(aType, aMethod, std::forward(args)...); - return new RefCountTaskWrapper(t, aType); -} diff --git a/media/gmp-clearkey/0.1/gmp-task-utils.h b/media/gmp-clearkey/0.1/gmp-task-utils.h deleted file mode 100644 index 82e08373f2..0000000000 --- a/media/gmp-clearkey/0.1/gmp-task-utils.h +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2015, Mozilla Foundation and contributors - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// Original author: ekr@rtfm.com - -#ifndef gmp_task_utils_h_ -#define gmp_task_utils_h_ - -#include "gmp-api/gmp-platform.h" - -class gmp_task_args_base : public GMPTask { -public: - virtual void Destroy() { delete this; } - virtual void Run() = 0; -}; - -// The generated file contains four major function templates -// (in variants for arbitrary numbers of arguments up to 10, -// which is why it is machine generated). The four templates -// are: -// -// WrapTask(o, m, ...) -- wraps a member function m of an object ptr o -// WrapTaskRet(o, m, ..., r) -- wraps a member function m of an object ptr o -// the function returns something that can -// be assigned to *r -// WrapTaskNM(f, ...) -- wraps a function f -// WrapTaskNMRet(f, ..., r) -- wraps a function f that returns something -// that can be assigned to *r -// -// All of these template functions return a GMPTask* which can be passed -// to DispatchXX(). -#include "gmp-task-utils-generated.h" - -#endif // gmp_task_utils_h_ diff --git a/media/gmp-clearkey/0.1/gtest/TestClearKeyUtils.cpp b/media/gmp-clearkey/0.1/gtest/TestClearKeyUtils.cpp deleted file mode 100644 index 021d1af68d..0000000000 --- a/media/gmp-clearkey/0.1/gtest/TestClearKeyUtils.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* 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 "gtest/gtest.h" -#include -#include -#include - -#include "../ClearKeyBase64.cpp" - -using namespace std; - -struct B64Test { - string b64; - vector raw; - bool shouldPass; -}; - -const B64Test tests[] = { - { - "AAAAADk4AU4AAAAAAAAAAA", - { 0x0, 0x0, 0x0, 0x0, 0x39, 0x38, 0x1, 0x4e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }, - true - }, - { - "h2mqp1zAJjDIC34YXEXBxA==", - { 0x87, 0x69, 0xaa, 0xa7, 0x5c, 0xc0, 0x26, 0x30, 0xc8, 0xb, 0x7e, 0x18, 0x5c, 0x45, 0xc1, 0xc4 }, - true - }, - { - "flcdA35XHQN-Vx0DflcdAw", - { 0x7e, 0x57, 0x1d, 0x3, 0x7e, 0x57, 0x1d, 0x3, 0x7e, 0x57, 0x1d, 0x3, 0x7e, 0x57, 0x1d, 0x3 }, - true - }, - { - "flczM35XMzN-VzMzflczMw", - { 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33 }, - true, - }, - { - "flcdBH5XHQR-Vx0EflcdBA", - { 0x7e, 0x57, 0x1d, 0x4, 0x7e, 0x57, 0x1d, 0x4, 0x7e, 0x57, 0x1d, 0x4, 0x7e, 0x57, 0x1d, 0x4 }, - true - }, - { - "fldERH5XRER-V0REfldERA", - { 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44 }, - true - }, - { - "fuzzbiz=", - { 0x7e, 0xec, 0xf3, 0x6e, 0x2c }, - true - }, - { - "fuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbiz", - { - 0x7e, 0xec, 0xf3, 0x6e, 0x2c, 0xdf, 0xbb, 0x3c, 0xdb, 0x8b, - 0x37, 0xee, 0xcf, 0x36, 0xe2, 0xcd, 0xfb, 0xb3, 0xcd, 0xb8, - 0xb3, 0x7e, 0xec, 0xf3, 0x6e, 0x2c, 0xdf, 0xbb, 0x3c, 0xdb, - 0x8b, 0x37, 0xee, 0xcf, 0x36, 0xe2, 0xcd, 0xfb, 0xb3, 0xcd, - 0xb8, 0xb3 - }, - true - }, - { "", { }, true }, - { "00", { 0xd3 }, true }, - { "000", { 0xd3, 0x4d }, true }, - - { "invalid", { 0x8a, 0x7b, 0xda, 0x96, 0x27 }, true }, - { "invalic", { 0x8a, 0x7b, 0xda, 0x96, 0x27 }, true }, - - // Failure tests - { "A", { }, false }, // 1 character is too few. - { "_", { }, false }, // 1 character is too few. -}; - -TEST(ClearKey, DecodeBase64) { - for (const B64Test& test : tests) { - vector v; - bool rv = DecodeBase64(string(test.b64), v); - EXPECT_EQ(test.shouldPass, rv); - if (test.shouldPass) { - EXPECT_EQ(test.raw.size(), v.size()); - for (size_t k = 0; k < test.raw.size(); k++) { - EXPECT_EQ(test.raw[k], v[k]); - } - } - } -} diff --git a/media/gmp-clearkey/0.1/gtest/moz.build b/media/gmp-clearkey/0.1/gtest/moz.build deleted file mode 100644 index 22a61d280e..0000000000 --- a/media/gmp-clearkey/0.1/gtest/moz.build +++ /dev/null @@ -1,14 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -UNIFIED_SOURCES += [ - 'TestClearKeyUtils.cpp', -] - -FINAL_LIBRARY = 'xul-gtest' - -LOCAL_INCLUDES += [ - '..', -] diff --git a/media/gmp-clearkey/0.1/moz.build b/media/gmp-clearkey/0.1/moz.build deleted file mode 100644 index fb25fa8fcc..0000000000 --- a/media/gmp-clearkey/0.1/moz.build +++ /dev/null @@ -1,74 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# 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/. - -SharedLibrary('clearkey') - -FINAL_TARGET = 'dist/bin/gmp-clearkey/0.1' - -FINAL_TARGET_PP_FILES += ['clearkey.info.in'] - -UNIFIED_SOURCES += [ - 'ClearKeyAsyncShutdown.cpp', - 'ClearKeyBase64.cpp', - 'ClearKeyDecryptionManager.cpp', - 'ClearKeyPersistence.cpp', - 'ClearKeySession.cpp', - 'ClearKeySessionManager.cpp', - 'ClearKeyStorage.cpp', - 'ClearKeyUtils.cpp', - 'gmp-clearkey.cpp', -] - -SOURCES += [ - 'openaes/oaes_lib.c', -] - -if CONFIG['OS_ARCH'] == 'WINNT': - UNIFIED_SOURCES += [ - 'AnnexB.cpp', - 'AudioDecoder.cpp', - 'VideoDecoder.cpp', - 'WMFAACDecoder.cpp', - 'WMFH264Decoder.cpp', - ] - - SOURCES += [ - 'WMFUtils.cpp', - ] - - OS_LIBS += [ - 'mfuuid', - ] - - DEFINES['ENABLE_WMF'] = True - -TEST_DIRS += [ - 'gtest', -] - - -LOCAL_INCLUDES += [ - '/dom/media/gmp', -] - -DISABLE_STL_WRAPPING = True -DEFINES['MOZ_NO_MOZALLOC'] = True - -USE_LIBS += ['psshparser'] - -# Suppress warnings in third-party code. -if CONFIG['GNU_CXX']: - CFLAGS += [ - '-Wno-missing-braces', - '-Wno-pointer-to-int-cast', - '-Wno-sign-compare', - '-include', 'stdio.h', # for sprintf() prototype - '-include', 'unistd.h', # for getpid() prototype - ] -elif CONFIG['_MSC_VER']: - CFLAGS += [ - '-FI', 'stdio.h', # for sprintf() prototype - '-wd4090', # '=' : different 'const' qualifiers - ] diff --git a/media/gmp-clearkey/0.1/openaes/LICENSE b/media/gmp-clearkey/0.1/openaes/LICENSE deleted file mode 100644 index d824e13ddb..0000000000 --- a/media/gmp-clearkey/0.1/openaes/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ ---------------------------------------------------------------------------- -OpenAES Licence ---------------------------------------------------------------------------- -Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - - - Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - - Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE -LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR -CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF -SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS -INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN -CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) -ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE -POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------------- diff --git a/media/gmp-clearkey/0.1/openaes/oaes_common.h b/media/gmp-clearkey/0.1/openaes/oaes_common.h deleted file mode 100644 index 7e2bf513f6..0000000000 --- a/media/gmp-clearkey/0.1/openaes/oaes_common.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * OpenAES License - * --------------------------------------------------------------------------- - * Copyright (c) 2013, Nabil S. Al Ramli, www.nalramli.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#ifndef _OAES_COMMON_H -#define _OAES_COMMON_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -# ifdef OAES_SHARED -# ifdef oaes_lib_EXPORTS -# define OAES_API __declspec(dllexport) -# else -# define OAES_API __declspec(dllimport) -# endif -# else -# define OAES_API -# endif -#else -# define OAES_API -#endif // WIN32 - -#define OAES_VERSION "0.9.0" - -typedef enum -{ - OAES_RET_FIRST = 0, - OAES_RET_SUCCESS = 0, - OAES_RET_ERROR, - OAES_RET_ARG1, - OAES_RET_ARG2, - OAES_RET_ARG3, - OAES_RET_ARG4, - OAES_RET_ARG5, - OAES_RET_NOKEY, - OAES_RET_MEM, - OAES_RET_BUF, - OAES_RET_HEADER, - OAES_RET_COUNT -} OAES_RET; - -#ifdef __cplusplus -} -#endif - -#endif // _OAES_COMMON_H diff --git a/media/gmp-clearkey/0.1/openaes/oaes_config.h b/media/gmp-clearkey/0.1/openaes/oaes_config.h deleted file mode 100644 index cb9f4e7be7..0000000000 --- a/media/gmp-clearkey/0.1/openaes/oaes_config.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * OpenAES License - * --------------------------------------------------------------------------- - * Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#ifndef _OAES_CONFIG_H -#define _OAES_CONFIG_H - -#ifdef __cplusplus -extern "C" { -#endif - -#ifndef OAES_DEBUG -#define OAES_DEBUG 0 -#endif // OAES_DEBUG - -#ifdef __cplusplus -} -#endif - -#endif // _OAES_CONFIG_H diff --git a/media/gmp-clearkey/0.1/openaes/oaes_lib.c b/media/gmp-clearkey/0.1/openaes/oaes_lib.c deleted file mode 100644 index aa13623ce8..0000000000 --- a/media/gmp-clearkey/0.1/openaes/oaes_lib.c +++ /dev/null @@ -1,1393 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * OpenAES License - * --------------------------------------------------------------------------- - * Copyright (c) 2012, Nabil S. Al Ramli, www.nalramli.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#include -#include -#include -#include - -#include "mozilla/Sprintf.h" - -#ifdef WIN32 -#include -#endif - -#include "oaes_config.h" -#include "oaes_lib.h" - -#ifdef OAES_HAVE_ISAAC -#include "rand.h" -#define OAES_RAND(x) rand(x) -#else -#define OAES_RAND(x) rand() -#endif // OAES_HAVE_ISAAC - -#define OAES_RKEY_LEN 4 -#define OAES_COL_LEN 4 -#define OAES_ROUND_BASE 7 - -// the block is padded -#define OAES_FLAG_PAD 0x01 - -#ifndef min -# define min(a,b) (((a)<(b)) ? (a) : (b)) -#endif /* min */ - -typedef struct _oaes_key -{ - size_t data_len; - uint8_t *data; - size_t exp_data_len; - uint8_t *exp_data; - size_t num_keys; - size_t key_base; -} oaes_key; - -typedef struct _oaes_ctx -{ -#ifdef OAES_HAVE_ISAAC - randctx * rctx; -#endif // OAES_HAVE_ISAAC - -#ifdef OAES_DEBUG - oaes_step_cb step_cb; -#endif // OAES_DEBUG - - oaes_key * key; - OAES_OPTION options; - uint8_t iv[OAES_BLOCK_SIZE]; -} oaes_ctx; - -// "OAES<8-bit header version><8-bit type><16-bit options><8-bit flags><56-bit reserved>" -static uint8_t oaes_header[OAES_BLOCK_SIZE] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x4f, 0x41, 0x45, 0x53, 0x01, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -}; -static uint8_t oaes_gf_8[] = { - 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36 }; - -static uint8_t oaes_sub_byte_value[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, - /*1*/ 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, - /*2*/ 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, - /*3*/ 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, - /*4*/ 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, - /*5*/ 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, - /*6*/ 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, - /*7*/ 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, - /*8*/ 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, - /*9*/ 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, - /*a*/ 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, - /*b*/ 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, - /*c*/ 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, - /*d*/ 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, - /*e*/ 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, - /*f*/ 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16, -}; - -static uint8_t oaes_inv_sub_byte_value[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, - /*1*/ 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, - /*2*/ 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, - /*3*/ 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, - /*4*/ 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, - /*5*/ 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, - /*6*/ 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, - /*7*/ 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, - /*8*/ 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, - /*9*/ 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, - /*a*/ 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, - /*b*/ 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, - /*c*/ 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, - /*d*/ 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, - /*e*/ 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, - /*f*/ 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d, -}; - -static uint8_t oaes_gf_mul_2[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e, - /*1*/ 0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e, - /*2*/ 0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e, - /*3*/ 0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e, - /*4*/ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e, - /*5*/ 0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe, - /*6*/ 0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde, - /*7*/ 0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe, - /*8*/ 0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05, - /*9*/ 0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25, - /*a*/ 0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45, - /*b*/ 0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65, - /*c*/ 0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85, - /*d*/ 0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5, - /*e*/ 0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5, - /*f*/ 0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5, -}; - -static uint8_t oaes_gf_mul_3[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x03, 0x06, 0x05, 0x0c, 0x0f, 0x0a, 0x09, 0x18, 0x1b, 0x1e, 0x1d, 0x14, 0x17, 0x12, 0x11, - /*1*/ 0x30, 0x33, 0x36, 0x35, 0x3c, 0x3f, 0x3a, 0x39, 0x28, 0x2b, 0x2e, 0x2d, 0x24, 0x27, 0x22, 0x21, - /*2*/ 0x60, 0x63, 0x66, 0x65, 0x6c, 0x6f, 0x6a, 0x69, 0x78, 0x7b, 0x7e, 0x7d, 0x74, 0x77, 0x72, 0x71, - /*3*/ 0x50, 0x53, 0x56, 0x55, 0x5c, 0x5f, 0x5a, 0x59, 0x48, 0x4b, 0x4e, 0x4d, 0x44, 0x47, 0x42, 0x41, - /*4*/ 0xc0, 0xc3, 0xc6, 0xc5, 0xcc, 0xcf, 0xca, 0xc9, 0xd8, 0xdb, 0xde, 0xdd, 0xd4, 0xd7, 0xd2, 0xd1, - /*5*/ 0xf0, 0xf3, 0xf6, 0xf5, 0xfc, 0xff, 0xfa, 0xf9, 0xe8, 0xeb, 0xee, 0xed, 0xe4, 0xe7, 0xe2, 0xe1, - /*6*/ 0xa0, 0xa3, 0xa6, 0xa5, 0xac, 0xaf, 0xaa, 0xa9, 0xb8, 0xbb, 0xbe, 0xbd, 0xb4, 0xb7, 0xb2, 0xb1, - /*7*/ 0x90, 0x93, 0x96, 0x95, 0x9c, 0x9f, 0x9a, 0x99, 0x88, 0x8b, 0x8e, 0x8d, 0x84, 0x87, 0x82, 0x81, - /*8*/ 0x9b, 0x98, 0x9d, 0x9e, 0x97, 0x94, 0x91, 0x92, 0x83, 0x80, 0x85, 0x86, 0x8f, 0x8c, 0x89, 0x8a, - /*9*/ 0xab, 0xa8, 0xad, 0xae, 0xa7, 0xa4, 0xa1, 0xa2, 0xb3, 0xb0, 0xb5, 0xb6, 0xbf, 0xbc, 0xb9, 0xba, - /*a*/ 0xfb, 0xf8, 0xfd, 0xfe, 0xf7, 0xf4, 0xf1, 0xf2, 0xe3, 0xe0, 0xe5, 0xe6, 0xef, 0xec, 0xe9, 0xea, - /*b*/ 0xcb, 0xc8, 0xcd, 0xce, 0xc7, 0xc4, 0xc1, 0xc2, 0xd3, 0xd0, 0xd5, 0xd6, 0xdf, 0xdc, 0xd9, 0xda, - /*c*/ 0x5b, 0x58, 0x5d, 0x5e, 0x57, 0x54, 0x51, 0x52, 0x43, 0x40, 0x45, 0x46, 0x4f, 0x4c, 0x49, 0x4a, - /*d*/ 0x6b, 0x68, 0x6d, 0x6e, 0x67, 0x64, 0x61, 0x62, 0x73, 0x70, 0x75, 0x76, 0x7f, 0x7c, 0x79, 0x7a, - /*e*/ 0x3b, 0x38, 0x3d, 0x3e, 0x37, 0x34, 0x31, 0x32, 0x23, 0x20, 0x25, 0x26, 0x2f, 0x2c, 0x29, 0x2a, - /*f*/ 0x0b, 0x08, 0x0d, 0x0e, 0x07, 0x04, 0x01, 0x02, 0x13, 0x10, 0x15, 0x16, 0x1f, 0x1c, 0x19, 0x1a, -}; - -static uint8_t oaes_gf_mul_9[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77, - /*1*/ 0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7, - /*2*/ 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c, - /*3*/ 0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc, - /*4*/ 0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01, - /*5*/ 0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91, - /*6*/ 0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a, - /*7*/ 0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa, - /*8*/ 0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b, - /*9*/ 0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b, - /*a*/ 0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0, - /*b*/ 0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30, - /*c*/ 0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed, - /*d*/ 0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d, - /*e*/ 0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6, - /*f*/ 0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46, -}; - -static uint8_t oaes_gf_mul_b[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69, - /*1*/ 0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9, - /*2*/ 0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12, - /*3*/ 0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2, - /*4*/ 0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f, - /*5*/ 0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f, - /*6*/ 0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4, - /*7*/ 0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54, - /*8*/ 0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e, - /*9*/ 0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e, - /*a*/ 0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5, - /*b*/ 0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55, - /*c*/ 0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68, - /*d*/ 0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8, - /*e*/ 0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13, - /*f*/ 0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3, -}; - -static uint8_t oaes_gf_mul_d[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b, - /*1*/ 0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b, - /*2*/ 0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0, - /*3*/ 0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20, - /*4*/ 0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26, - /*5*/ 0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6, - /*6*/ 0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d, - /*7*/ 0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d, - /*8*/ 0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91, - /*9*/ 0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41, - /*a*/ 0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a, - /*b*/ 0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa, - /*c*/ 0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc, - /*d*/ 0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c, - /*e*/ 0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47, - /*f*/ 0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97, -}; - -static uint8_t oaes_gf_mul_e[16][16] = { - // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f, - /*0*/ 0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a, - /*1*/ 0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba, - /*2*/ 0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81, - /*3*/ 0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61, - /*4*/ 0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7, - /*5*/ 0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17, - /*6*/ 0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c, - /*7*/ 0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc, - /*8*/ 0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b, - /*9*/ 0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb, - /*a*/ 0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0, - /*b*/ 0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20, - /*c*/ 0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6, - /*d*/ 0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56, - /*e*/ 0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d, - /*f*/ 0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d, -}; - -static OAES_RET oaes_sub_byte( uint8_t * byte ) -{ - size_t _x, _y; - - if( NULL == byte ) - return OAES_RET_ARG1; - - _x = _y = *byte; - _x &= 0x0f; - _y &= 0xf0; - _y >>= 4; - *byte = oaes_sub_byte_value[_y][_x]; - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_inv_sub_byte( uint8_t * byte ) -{ - size_t _x, _y; - - if( NULL == byte ) - return OAES_RET_ARG1; - - _x = _y = *byte; - _x &= 0x0f; - _y &= 0xf0; - _y >>= 4; - *byte = oaes_inv_sub_byte_value[_y][_x]; - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_word_rot_left( uint8_t word[OAES_COL_LEN] ) -{ - uint8_t _temp[OAES_COL_LEN]; - - if( NULL == word ) - return OAES_RET_ARG1; - - memcpy( _temp, word + 1, OAES_COL_LEN - 1 ); - _temp[OAES_COL_LEN - 1] = word[0]; - memcpy( word, _temp, OAES_COL_LEN ); - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_shift_rows( uint8_t block[OAES_BLOCK_SIZE] ) -{ - uint8_t _temp[OAES_BLOCK_SIZE]; - - if( NULL == block ) - return OAES_RET_ARG1; - - _temp[0x00] = block[0x00]; - _temp[0x01] = block[0x05]; - _temp[0x02] = block[0x0a]; - _temp[0x03] = block[0x0f]; - _temp[0x04] = block[0x04]; - _temp[0x05] = block[0x09]; - _temp[0x06] = block[0x0e]; - _temp[0x07] = block[0x03]; - _temp[0x08] = block[0x08]; - _temp[0x09] = block[0x0d]; - _temp[0x0a] = block[0x02]; - _temp[0x0b] = block[0x07]; - _temp[0x0c] = block[0x0c]; - _temp[0x0d] = block[0x01]; - _temp[0x0e] = block[0x06]; - _temp[0x0f] = block[0x0b]; - memcpy( block, _temp, OAES_BLOCK_SIZE ); - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_inv_shift_rows( uint8_t block[OAES_BLOCK_SIZE] ) -{ - uint8_t _temp[OAES_BLOCK_SIZE]; - - if( NULL == block ) - return OAES_RET_ARG1; - - _temp[0x00] = block[0x00]; - _temp[0x01] = block[0x0d]; - _temp[0x02] = block[0x0a]; - _temp[0x03] = block[0x07]; - _temp[0x04] = block[0x04]; - _temp[0x05] = block[0x01]; - _temp[0x06] = block[0x0e]; - _temp[0x07] = block[0x0b]; - _temp[0x08] = block[0x08]; - _temp[0x09] = block[0x05]; - _temp[0x0a] = block[0x02]; - _temp[0x0b] = block[0x0f]; - _temp[0x0c] = block[0x0c]; - _temp[0x0d] = block[0x09]; - _temp[0x0e] = block[0x06]; - _temp[0x0f] = block[0x03]; - memcpy( block, _temp, OAES_BLOCK_SIZE ); - - return OAES_RET_SUCCESS; -} - -static uint8_t oaes_gf_mul(uint8_t left, uint8_t right) -{ - size_t _x, _y; - - _x = _y = left; - _x &= 0x0f; - _y &= 0xf0; - _y >>= 4; - - switch( right ) - { - case 0x02: - return oaes_gf_mul_2[_y][_x]; - break; - case 0x03: - return oaes_gf_mul_3[_y][_x]; - break; - case 0x09: - return oaes_gf_mul_9[_y][_x]; - break; - case 0x0b: - return oaes_gf_mul_b[_y][_x]; - break; - case 0x0d: - return oaes_gf_mul_d[_y][_x]; - break; - case 0x0e: - return oaes_gf_mul_e[_y][_x]; - break; - default: - return left; - break; - } -} - -static OAES_RET oaes_mix_cols( uint8_t word[OAES_COL_LEN] ) -{ - uint8_t _temp[OAES_COL_LEN]; - - if( NULL == word ) - return OAES_RET_ARG1; - - _temp[0] = oaes_gf_mul(word[0], 0x02) ^ oaes_gf_mul( word[1], 0x03 ) ^ - word[2] ^ word[3]; - _temp[1] = word[0] ^ oaes_gf_mul( word[1], 0x02 ) ^ - oaes_gf_mul( word[2], 0x03 ) ^ word[3]; - _temp[2] = word[0] ^ word[1] ^ - oaes_gf_mul( word[2], 0x02 ) ^ oaes_gf_mul( word[3], 0x03 ); - _temp[3] = oaes_gf_mul( word[0], 0x03 ) ^ word[1] ^ - word[2] ^ oaes_gf_mul( word[3], 0x02 ); - memcpy( word, _temp, OAES_COL_LEN ); - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_inv_mix_cols( uint8_t word[OAES_COL_LEN] ) -{ - uint8_t _temp[OAES_COL_LEN]; - - if( NULL == word ) - return OAES_RET_ARG1; - - _temp[0] = oaes_gf_mul( word[0], 0x0e ) ^ oaes_gf_mul( word[1], 0x0b ) ^ - oaes_gf_mul( word[2], 0x0d ) ^ oaes_gf_mul( word[3], 0x09 ); - _temp[1] = oaes_gf_mul( word[0], 0x09 ) ^ oaes_gf_mul( word[1], 0x0e ) ^ - oaes_gf_mul( word[2], 0x0b ) ^ oaes_gf_mul( word[3], 0x0d ); - _temp[2] = oaes_gf_mul( word[0], 0x0d ) ^ oaes_gf_mul( word[1], 0x09 ) ^ - oaes_gf_mul( word[2], 0x0e ) ^ oaes_gf_mul( word[3], 0x0b ); - _temp[3] = oaes_gf_mul( word[0], 0x0b ) ^ oaes_gf_mul( word[1], 0x0d ) ^ - oaes_gf_mul( word[2], 0x09 ) ^ oaes_gf_mul( word[3], 0x0e ); - memcpy( word, _temp, OAES_COL_LEN ); - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_sprintf( - char * buf, size_t * buf_len, const uint8_t * data, size_t data_len ) -{ - size_t _i, _buf_len_in; - char _temp[4]; - - if( NULL == buf_len ) - return OAES_RET_ARG2; - - _buf_len_in = *buf_len; - *buf_len = data_len * 3 + data_len / OAES_BLOCK_SIZE + 1; - - if( NULL == buf ) - return OAES_RET_SUCCESS; - - if( *buf_len > _buf_len_in ) - return OAES_RET_BUF; - - if( NULL == data ) - return OAES_RET_ARG3; - - strcpy( buf, "" ); - - for( _i = 0; _i < data_len; _i++ ) - { - snprintf( _temp, sizeof(_temp), "%02x ", data[_i] ); - strcat( buf, _temp ); - if( _i && 0 == ( _i + 1 ) % OAES_BLOCK_SIZE ) - strcat( buf, "\n" ); - } - - return OAES_RET_SUCCESS; -} - -/* -#ifdef OAES_HAVE_ISAAC -static void oaes_get_seed( char buf[RANDSIZ + 1] ) -{ - struct timeb timer; - struct tm *gmTimer; - char * _test = NULL; - - ftime (&timer); - gmTimer = gmtime( &timer.time ); - _test = (char *) calloc( sizeof( char ), timer.millitm ); - sprintf( buf, "%04d%02d%02d%02d%02d%02d%03d%p%d", - gmTimer->tm_year + 1900, gmTimer->tm_mon + 1, gmTimer->tm_mday, - gmTimer->tm_hour, gmTimer->tm_min, gmTimer->tm_sec, timer.millitm, - _test + timer.millitm, getpid() ); - - if( _test ) - free( _test ); -} -#else -static uint32_t oaes_get_seed() -{ - struct timeb timer; - struct tm *gmTimer; - char * _test = NULL; - uint32_t _ret = 0; - - ftime (&timer); - gmTimer = gmtime( &timer.time ); - _test = (char *) calloc( sizeof( char ), timer.millitm ); - _ret = gmTimer->tm_year + 1900 + gmTimer->tm_mon + 1 + gmTimer->tm_mday + - gmTimer->tm_hour + gmTimer->tm_min + gmTimer->tm_sec + timer.millitm + - (uint32_t) ( _test + timer.millitm ) + getpid(); - - if( _test ) - free( _test ); - - return _ret; -} -#endif // OAES_HAVE_ISAAC -*/ - -static OAES_RET oaes_key_destroy( oaes_key ** key ) -{ - if( NULL == *key ) - return OAES_RET_SUCCESS; - - if( (*key)->data ) - { - free( (*key)->data ); - (*key)->data = NULL; - } - - if( (*key)->exp_data ) - { - free( (*key)->exp_data ); - (*key)->exp_data = NULL; - } - - (*key)->data_len = 0; - (*key)->exp_data_len = 0; - (*key)->num_keys = 0; - (*key)->key_base = 0; - free( *key ); - *key = NULL; - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_key_expand( OAES_CTX * ctx ) -{ - size_t _i, _j; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - _ctx->key->key_base = _ctx->key->data_len / OAES_RKEY_LEN; - _ctx->key->num_keys = _ctx->key->key_base + OAES_ROUND_BASE; - - _ctx->key->exp_data_len = _ctx->key->num_keys * OAES_RKEY_LEN * OAES_COL_LEN; - _ctx->key->exp_data = (uint8_t *) - calloc( _ctx->key->exp_data_len, sizeof( uint8_t )); - - if( NULL == _ctx->key->exp_data ) - return OAES_RET_MEM; - - // the first _ctx->key->data_len are a direct copy - memcpy( _ctx->key->exp_data, _ctx->key->data, _ctx->key->data_len ); - - // apply ExpandKey algorithm for remainder - for( _i = _ctx->key->key_base; _i < _ctx->key->num_keys * OAES_RKEY_LEN; _i++ ) - { - uint8_t _temp[OAES_COL_LEN]; - - memcpy( _temp, - _ctx->key->exp_data + ( _i - 1 ) * OAES_RKEY_LEN, OAES_COL_LEN ); - - // transform key column - if( 0 == _i % _ctx->key->key_base ) - { - oaes_word_rot_left( _temp ); - - for( _j = 0; _j < OAES_COL_LEN; _j++ ) - oaes_sub_byte( _temp + _j ); - - _temp[0] = _temp[0] ^ oaes_gf_8[ _i / _ctx->key->key_base - 1 ]; - } - else if( _ctx->key->key_base > 6 && 4 == _i % _ctx->key->key_base ) - { - for( _j = 0; _j < OAES_COL_LEN; _j++ ) - oaes_sub_byte( _temp + _j ); - } - - for( _j = 0; _j < OAES_COL_LEN; _j++ ) - { - _ctx->key->exp_data[ _i * OAES_RKEY_LEN + _j ] = - _ctx->key->exp_data[ ( _i - _ctx->key->key_base ) * - OAES_RKEY_LEN + _j ] ^ _temp[_j]; - } - } - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_key_gen( OAES_CTX * ctx, size_t key_size ) -{ - size_t _i; - oaes_key * _key = NULL; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - _key = (oaes_key *) calloc( sizeof( oaes_key ), 1 ); - - if( NULL == _key ) - return OAES_RET_MEM; - - if( _ctx->key ) - oaes_key_destroy( &(_ctx->key) ); - - _key->data_len = key_size; - _key->data = (uint8_t *) calloc( key_size, sizeof( uint8_t )); - - if( NULL == _key->data ) - { - oaes_key_destroy( &_key ); - return OAES_RET_MEM; - } - - for( _i = 0; _i < key_size; _i++ ) - _key->data[_i] = (uint8_t) OAES_RAND(_ctx->rctx); - - _ctx->key = _key; - _rc = _rc || oaes_key_expand( ctx ); - - if( _rc != OAES_RET_SUCCESS ) - { - oaes_key_destroy( &(_ctx->key) ); - return _rc; - } - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_gen_128( OAES_CTX * ctx ) -{ - return oaes_key_gen( ctx, 16 ); -} - -OAES_RET oaes_key_gen_192( OAES_CTX * ctx ) -{ - return oaes_key_gen( ctx, 24 ); -} - -OAES_RET oaes_key_gen_256( OAES_CTX * ctx ) -{ - return oaes_key_gen( ctx, 32 ); -} - -OAES_RET oaes_key_export( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ) -{ - size_t _data_len_in; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - if( NULL == data_len ) - return OAES_RET_ARG3; - - _data_len_in = *data_len; - // data + header - *data_len = _ctx->key->data_len + OAES_BLOCK_SIZE; - - if( NULL == data ) - return OAES_RET_SUCCESS; - - if( _data_len_in < *data_len ) - return OAES_RET_BUF; - - // header - memcpy( data, oaes_header, OAES_BLOCK_SIZE ); - data[5] = 0x01; - data[7] = _ctx->key->data_len; - memcpy( data + OAES_BLOCK_SIZE, _ctx->key->data, _ctx->key->data_len ); - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_export_data( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ) -{ - size_t _data_len_in; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - if( NULL == data_len ) - return OAES_RET_ARG3; - - _data_len_in = *data_len; - *data_len = _ctx->key->data_len; - - if( NULL == data ) - return OAES_RET_SUCCESS; - - if( _data_len_in < *data_len ) - return OAES_RET_BUF; - - memcpy( data, _ctx->key->data, *data_len ); - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_import( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ) -{ - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - int _key_length; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == data ) - return OAES_RET_ARG2; - - switch( data_len ) - { - case 16 + OAES_BLOCK_SIZE: - case 24 + OAES_BLOCK_SIZE: - case 32 + OAES_BLOCK_SIZE: - break; - default: - return OAES_RET_ARG3; - } - - // header - if( 0 != memcmp( data, oaes_header, 4 ) ) - return OAES_RET_HEADER; - - // header version - switch( data[4] ) - { - case 0x01: - break; - default: - return OAES_RET_HEADER; - } - - // header type - switch( data[5] ) - { - case 0x01: - break; - default: - return OAES_RET_HEADER; - } - - // options - _key_length = data[7]; - switch( _key_length ) - { - case 16: - case 24: - case 32: - break; - default: - return OAES_RET_HEADER; - } - - if( data_len != _key_length + OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( _ctx->key ) - oaes_key_destroy( &(_ctx->key) ); - - _ctx->key = (oaes_key *) calloc( sizeof( oaes_key ), 1 ); - - if( NULL == _ctx->key ) - return OAES_RET_MEM; - - _ctx->key->data_len = _key_length; - _ctx->key->data = (uint8_t *) - calloc( _key_length, sizeof( uint8_t )); - - if( NULL == _ctx->key->data ) - { - oaes_key_destroy( &(_ctx->key) ); - return OAES_RET_MEM; - } - - memcpy( _ctx->key->data, data + OAES_BLOCK_SIZE, _key_length ); - _rc = _rc || oaes_key_expand( ctx ); - - if( _rc != OAES_RET_SUCCESS ) - { - oaes_key_destroy( &(_ctx->key) ); - return _rc; - } - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_key_import_data( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ) -{ - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == data ) - return OAES_RET_ARG2; - - switch( data_len ) - { - case 16: - case 24: - case 32: - break; - default: - return OAES_RET_ARG3; - } - - if( _ctx->key ) - oaes_key_destroy( &(_ctx->key) ); - - _ctx->key = (oaes_key *) calloc( sizeof( oaes_key ), 1 ); - - if( NULL == _ctx->key ) - return OAES_RET_MEM; - - _ctx->key->data_len = data_len; - _ctx->key->data = (uint8_t *) - calloc( data_len, sizeof( uint8_t )); - - if( NULL == _ctx->key->data ) - { - oaes_key_destroy( &(_ctx->key) ); - return OAES_RET_MEM; - } - - memcpy( _ctx->key->data, data, data_len ); - _rc = _rc || oaes_key_expand( ctx ); - - if( _rc != OAES_RET_SUCCESS ) - { - oaes_key_destroy( &(_ctx->key) ); - return _rc; - } - - return OAES_RET_SUCCESS; -} - -OAES_CTX * oaes_alloc() -{ - oaes_ctx * _ctx = (oaes_ctx *) calloc( sizeof( oaes_ctx ), 1 ); - - if( NULL == _ctx ) - return NULL; - -#ifdef OAES_HAVE_ISAAC - { - ub4 _i = 0; - char _seed[RANDSIZ + 1]; - - _ctx->rctx = (randctx *) calloc( sizeof( randctx ), 1 ); - - if( NULL == _ctx->rctx ) - { - free( _ctx ); - return NULL; - } - - oaes_get_seed( _seed ); - memset( _ctx->rctx->randrsl, 0, RANDSIZ ); - memcpy( _ctx->rctx->randrsl, _seed, RANDSIZ ); - randinit( _ctx->rctx, TRUE); - } -#else - //srand( oaes_get_seed() ); -#endif // OAES_HAVE_ISAAC - - _ctx->key = NULL; - oaes_set_option( _ctx, OAES_OPTION_CBC, NULL ); - -#ifdef OAES_DEBUG - _ctx->step_cb = NULL; - oaes_set_option( _ctx, OAES_OPTION_STEP_OFF, NULL ); -#endif // OAES_DEBUG - - return (OAES_CTX *) _ctx; -} - -OAES_RET oaes_free( OAES_CTX ** ctx ) -{ - oaes_ctx ** _ctx = (oaes_ctx **) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == *_ctx ) - return OAES_RET_SUCCESS; - - if( (*_ctx)->key ) - oaes_key_destroy( &((*_ctx)->key) ); - -#ifdef OAES_HAVE_ISAAC - if( (*_ctx)->rctx ) - { - free( (*_ctx)->rctx ); - (*_ctx)->rctx = NULL; - } -#endif // OAES_HAVE_ISAAC - - free( *_ctx ); - *_ctx = NULL; - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_set_option( OAES_CTX * ctx, - OAES_OPTION option, const void * value ) -{ - size_t _i; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - switch( option ) - { - case OAES_OPTION_ECB: - _ctx->options &= ~OAES_OPTION_CBC; - memset( _ctx->iv, 0, OAES_BLOCK_SIZE ); - break; - - case OAES_OPTION_CBC: - _ctx->options &= ~OAES_OPTION_ECB; - if( value ) - memcpy( _ctx->iv, value, OAES_BLOCK_SIZE ); - else - { - for( _i = 0; _i < OAES_BLOCK_SIZE; _i++ ) - _ctx->iv[_i] = (uint8_t) OAES_RAND(_ctx->rctx); - } - break; - -#ifdef OAES_DEBUG - - case OAES_OPTION_STEP_ON: - if( value ) - { - _ctx->options &= ~OAES_OPTION_STEP_OFF; - _ctx->step_cb = value; - } - else - { - _ctx->options &= ~OAES_OPTION_STEP_ON; - _ctx->options |= OAES_OPTION_STEP_OFF; - _ctx->step_cb = NULL; - return OAES_RET_ARG3; - } - break; - - case OAES_OPTION_STEP_OFF: - _ctx->options &= ~OAES_OPTION_STEP_ON; - _ctx->step_cb = NULL; - break; - -#endif // OAES_DEBUG - - default: - return OAES_RET_ARG2; - } - - _ctx->options |= option; - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_encrypt_block( - OAES_CTX * ctx, uint8_t * c, size_t c_len ) -{ - size_t _i, _j; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == c ) - return OAES_RET_ARG2; - - if( c_len != OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "input", 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(State, K0) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[_i]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data, "k_sch", 1, NULL ); - _ctx->step_cb( c, "k_add", 1, NULL ); - } -#endif // OAES_DEBUG - - // for round = 1 step 1 to Nr–1 - for( _i = 1; _i < _ctx->key->num_keys - 1; _i++ ) - { - // SubBytes(state) - for( _j = 0; _j < c_len; _j++ ) - oaes_sub_byte( c + _j ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_box", _i, NULL ); -#endif // OAES_DEBUG - - // ShiftRows(state) - oaes_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_row", _i, NULL ); -#endif // OAES_DEBUG - - // MixColumns(state) - oaes_mix_cols( c ); - oaes_mix_cols( c + 4 ); - oaes_mix_cols( c + 8 ); - oaes_mix_cols( c + 12 ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "m_col", _i, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) - for( _j = 0; _j < c_len; _j++ ) - c[_j] = c[_j] ^ - _ctx->key->exp_data[_i * OAES_RKEY_LEN * OAES_COL_LEN + _j]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + _i * OAES_RKEY_LEN * OAES_COL_LEN, - "k_sch", _i, NULL ); - _ctx->step_cb( c, "k_add", _i, NULL ); - } -#endif // OAES_DEBUG - - } - - // SubBytes(state) - for( _i = 0; _i < c_len; _i++ ) - oaes_sub_byte( c + _i ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_box", _ctx->key->num_keys - 1, NULL ); -#endif // OAES_DEBUG - - // ShiftRows(state) - oaes_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "s_row", _ctx->key->num_keys - 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[ - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN + _i ]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN, - "k_sch", _ctx->key->num_keys - 1, NULL ); - _ctx->step_cb( c, "output", _ctx->key->num_keys - 1, NULL ); - } -#endif // OAES_DEBUG - - return OAES_RET_SUCCESS; -} - -static OAES_RET oaes_decrypt_block( - OAES_CTX * ctx, uint8_t * c, size_t c_len ) -{ - size_t _i, _j; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == c ) - return OAES_RET_ARG2; - - if( c_len != OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "iinput", _ctx->key->num_keys - 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[ - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN + _i ]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + - ( _ctx->key->num_keys - 1 ) * OAES_RKEY_LEN * OAES_COL_LEN, - "ik_sch", _ctx->key->num_keys - 1, NULL ); - _ctx->step_cb( c, "ik_add", _ctx->key->num_keys - 1, NULL ); - } -#endif // OAES_DEBUG - - for( _i = _ctx->key->num_keys - 2; _i > 0; _i-- ) - { - // InvShiftRows(state) - oaes_inv_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_row", _i, NULL ); -#endif // OAES_DEBUG - - // InvSubBytes(state) - for( _j = 0; _j < c_len; _j++ ) - oaes_inv_sub_byte( c + _j ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_box", _i, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) - for( _j = 0; _j < c_len; _j++ ) - c[_j] = c[_j] ^ - _ctx->key->exp_data[_i * OAES_RKEY_LEN * OAES_COL_LEN + _j]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data + _i * OAES_RKEY_LEN * OAES_COL_LEN, - "ik_sch", _i, NULL ); - _ctx->step_cb( c, "ik_add", _i, NULL ); - } -#endif // OAES_DEBUG - - // InvMixColums(state) - oaes_inv_mix_cols( c ); - oaes_inv_mix_cols( c + 4 ); - oaes_inv_mix_cols( c + 8 ); - oaes_inv_mix_cols( c + 12 ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "im_col", _i, NULL ); -#endif // OAES_DEBUG - - } - - // InvShiftRows(state) - oaes_inv_shift_rows( c ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_row", 1, NULL ); -#endif // OAES_DEBUG - - // InvSubBytes(state) - for( _i = 0; _i < c_len; _i++ ) - oaes_inv_sub_byte( c + _i ); - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - _ctx->step_cb( c, "is_box", 1, NULL ); -#endif // OAES_DEBUG - - // AddRoundKey(state, w[0, Nb-1]) - for( _i = 0; _i < c_len; _i++ ) - c[_i] = c[_i] ^ _ctx->key->exp_data[_i]; - -#ifdef OAES_DEBUG - if( _ctx->step_cb ) - { - _ctx->step_cb( _ctx->key->exp_data, "ik_sch", 1, NULL ); - _ctx->step_cb( c, "ioutput", 1, NULL ); - } -#endif // OAES_DEBUG - - return OAES_RET_SUCCESS; -} - -OAES_RET oaes_encrypt( OAES_CTX * ctx, - const uint8_t * m, size_t m_len, uint8_t * c, size_t * c_len ) -{ - size_t _i, _j, _c_len_in, _c_data_len; - size_t _pad_len = m_len % OAES_BLOCK_SIZE == 0 ? - 0 : OAES_BLOCK_SIZE - m_len % OAES_BLOCK_SIZE; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - uint8_t _flags = _pad_len ? OAES_FLAG_PAD : 0; - - if( NULL == _ctx ) - return OAES_RET_ARG1; - - if( NULL == m ) - return OAES_RET_ARG2; - - if( NULL == c_len ) - return OAES_RET_ARG5; - - _c_len_in = *c_len; - // data + pad - _c_data_len = m_len + _pad_len; - // header + iv + data + pad - *c_len = 2 * OAES_BLOCK_SIZE + m_len + _pad_len; - - if( NULL == c ) - return OAES_RET_SUCCESS; - - if( _c_len_in < *c_len ) - return OAES_RET_BUF; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - // fill with random data first - for( _i = 0; _i < OAES_BLOCK_SIZE; _i++ ) - c[_i] = (uint8_t) OAES_RAND(_ctx->rctx); - // header - memcpy(c + 6, &_ctx->options, sizeof(_ctx->options)); - memcpy(c + 8, &_flags, sizeof(_flags)); - // iv - memcpy(c + OAES_BLOCK_SIZE, _ctx->iv, OAES_BLOCK_SIZE ); - // data - memcpy(c + 2 * OAES_BLOCK_SIZE, m, m_len ); - - for( _i = 0; _i < _c_data_len; _i += OAES_BLOCK_SIZE ) - { - uint8_t _block[OAES_BLOCK_SIZE]; - size_t _block_size = min( m_len - _i, OAES_BLOCK_SIZE ); - - memcpy( _block, c + 2 * OAES_BLOCK_SIZE + _i, _block_size ); - - // insert pad - for( _j = 0; _j < OAES_BLOCK_SIZE - _block_size; _j++ ) - _block[ _block_size + _j ] = _j + 1; - - // CBC - if( _ctx->options & OAES_OPTION_CBC ) - { - for( _j = 0; _j < OAES_BLOCK_SIZE; _j++ ) - _block[_j] = _block[_j] ^ _ctx->iv[_j]; - } - - _rc = _rc || - oaes_encrypt_block( ctx, _block, OAES_BLOCK_SIZE ); - memcpy( c + 2 * OAES_BLOCK_SIZE + _i, _block, OAES_BLOCK_SIZE ); - - if( _ctx->options & OAES_OPTION_CBC ) - memcpy( _ctx->iv, _block, OAES_BLOCK_SIZE ); - } - - return _rc; -} - -OAES_RET oaes_decrypt( OAES_CTX * ctx, - const uint8_t * c, size_t c_len, uint8_t * m, size_t * m_len ) -{ - size_t _i, _j, _m_len_in; - oaes_ctx * _ctx = (oaes_ctx *) ctx; - OAES_RET _rc = OAES_RET_SUCCESS; - uint8_t _iv[OAES_BLOCK_SIZE]; - uint8_t _flags; - OAES_OPTION _options; - - if( NULL == ctx ) - return OAES_RET_ARG1; - - if( NULL == c ) - return OAES_RET_ARG2; - - if( c_len % OAES_BLOCK_SIZE ) - return OAES_RET_ARG3; - - if( NULL == m_len ) - return OAES_RET_ARG5; - - _m_len_in = *m_len; - *m_len = c_len - 2 * OAES_BLOCK_SIZE; - - if( NULL == m ) - return OAES_RET_SUCCESS; - - if( _m_len_in < *m_len ) - return OAES_RET_BUF; - - if( NULL == _ctx->key ) - return OAES_RET_NOKEY; - - // options - memcpy(&_options, c + 6, sizeof(_options)); - // validate that all options are valid - if( _options & ~( - OAES_OPTION_ECB - | OAES_OPTION_CBC -#ifdef OAES_DEBUG - | OAES_OPTION_STEP_ON - | OAES_OPTION_STEP_OFF -#endif // OAES_DEBUG - ) ) - return OAES_RET_HEADER; - if( ( _options & OAES_OPTION_ECB ) && - ( _options & OAES_OPTION_CBC ) ) - return OAES_RET_HEADER; - if( _options == OAES_OPTION_NONE ) - return OAES_RET_HEADER; - - // flags - memcpy(&_flags, c + 8, sizeof(_flags)); - // validate that all flags are valid - if( _flags & ~( - OAES_FLAG_PAD - ) ) - return OAES_RET_HEADER; - - // iv - memcpy( _iv, c + OAES_BLOCK_SIZE, OAES_BLOCK_SIZE); - // data + pad - memcpy( m, c + 2 * OAES_BLOCK_SIZE, *m_len ); - - for( _i = 0; _i < *m_len; _i += OAES_BLOCK_SIZE ) - { - if( ( _options & OAES_OPTION_CBC ) && _i > 0 ) - memcpy( _iv, c + OAES_BLOCK_SIZE + _i, OAES_BLOCK_SIZE ); - - _rc = _rc || - oaes_decrypt_block( ctx, m + _i, min( *m_len - _i, OAES_BLOCK_SIZE ) ); - - // CBC - if( _options & OAES_OPTION_CBC ) - { - for( _j = 0; _j < OAES_BLOCK_SIZE; _j++ ) - m[ _i + _j ] = m[ _i + _j ] ^ _iv[_j]; - } - } - - // remove pad - if( _flags & OAES_FLAG_PAD ) - { - int _is_pad = 1; - size_t _temp = (size_t) m[*m_len - 1]; - - if( _temp <= 0x00 || _temp > 0x0f ) - return OAES_RET_HEADER; - for( _i = 0; _i < _temp; _i++ ) - if( m[*m_len - 1 - _i] != _temp - _i ) - _is_pad = 0; - if( _is_pad ) - { - memset( m + *m_len - _temp, 0, _temp ); - *m_len -= _temp; - } - else - return OAES_RET_HEADER; - } - - return OAES_RET_SUCCESS; -} diff --git a/media/gmp-clearkey/0.1/openaes/oaes_lib.h b/media/gmp-clearkey/0.1/openaes/oaes_lib.h deleted file mode 100644 index 2344480e85..0000000000 --- a/media/gmp-clearkey/0.1/openaes/oaes_lib.h +++ /dev/null @@ -1,168 +0,0 @@ -/* - * --------------------------------------------------------------------------- - * OpenAES License - * --------------------------------------------------------------------------- - * Copyright (c) 2013, Nabil S. Al Ramli, www.nalramli.com - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * --------------------------------------------------------------------------- - */ - -#ifndef _OAES_LIB_H -#define _OAES_LIB_H - -#include "oaes_common.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef _WIN32 -# ifdef OAES_SHARED -# ifdef oaes_lib_EXPORTS -# define OAES_API __declspec(dllexport) -# else -# define OAES_API __declspec(dllimport) -# endif -# else -# define OAES_API -# endif -#else -# define OAES_API -#endif // WIN32 - -#define OAES_BLOCK_SIZE 16 - -typedef void OAES_CTX; - -/* - * oaes_set_option() takes one of these values for its [option] parameter - * some options accept either an optional or a required [value] parameter - */ -// no option -#define OAES_OPTION_NONE 0 -// enable ECB mode, disable CBC mode -#define OAES_OPTION_ECB 1 -// enable CBC mode, disable ECB mode -// value is optional, may pass uint8_t iv[OAES_BLOCK_SIZE] to specify -// the value of the initialization vector, iv -#define OAES_OPTION_CBC 2 - -#ifdef OAES_DEBUG -typedef int ( * oaes_step_cb ) ( - const uint8_t state[OAES_BLOCK_SIZE], - const char * step_name, - int step_count, - void * user_data ); -// enable state stepping mode -// value is required, must pass oaes_step_cb to receive the state at each step -#define OAES_OPTION_STEP_ON 4 -// disable state stepping mode -#define OAES_OPTION_STEP_OFF 8 -#endif // OAES_DEBUG - -typedef uint16_t OAES_OPTION; - -/* - * // usage: - * - * OAES_CTX * ctx = oaes_alloc(); - * . - * . - * . - * { - * oaes_gen_key_xxx( ctx ); - * { - * oaes_key_export( ctx, _buf, &_buf_len ); - * // or - * oaes_key_export_data( ctx, _buf, &_buf_len );\ - * } - * } - * // or - * { - * oaes_key_import( ctx, _buf, _buf_len ); - * // or - * oaes_key_import_data( ctx, _buf, _buf_len ); - * } - * . - * . - * . - * oaes_encrypt( ctx, m, m_len, c, &c_len ); - * . - * . - * . - * oaes_decrypt( ctx, c, c_len, m, &m_len ); - * . - * . - * . - * oaes_free( &ctx ); - */ - -OAES_API OAES_CTX * oaes_alloc(); - -OAES_API OAES_RET oaes_free( OAES_CTX ** ctx ); - -OAES_API OAES_RET oaes_set_option( OAES_CTX * ctx, - OAES_OPTION option, const void * value ); - -OAES_API OAES_RET oaes_key_gen_128( OAES_CTX * ctx ); - -OAES_API OAES_RET oaes_key_gen_192( OAES_CTX * ctx ); - -OAES_API OAES_RET oaes_key_gen_256( OAES_CTX * ctx ); - -// export key with header information -// set data == NULL to get the required data_len -OAES_API OAES_RET oaes_key_export( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ); - -// directly export the data from key -// set data == NULL to get the required data_len -OAES_API OAES_RET oaes_key_export_data( OAES_CTX * ctx, - uint8_t * data, size_t * data_len ); - -// import key with header information -OAES_API OAES_RET oaes_key_import( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ); - -// directly import data into key -OAES_API OAES_RET oaes_key_import_data( OAES_CTX * ctx, - const uint8_t * data, size_t data_len ); - -// set c == NULL to get the required c_len -OAES_API OAES_RET oaes_encrypt( OAES_CTX * ctx, - const uint8_t * m, size_t m_len, uint8_t * c, size_t * c_len ); - -// set m == NULL to get the required m_len -OAES_API OAES_RET oaes_decrypt( OAES_CTX * ctx, - const uint8_t * c, size_t c_len, uint8_t * m, size_t * m_len ); - -// set buf == NULL to get the required buf_len -OAES_API OAES_RET oaes_sprintf( - char * buf, size_t * buf_len, const uint8_t * data, size_t data_len ); - -#ifdef __cplusplus -} -#endif - -#endif // _OAES_LIB_H diff --git a/media/gmp-clearkey/0.1/openaes/standard.h b/media/gmp-clearkey/0.1/openaes/standard.h deleted file mode 100644 index fbe6ef5bef..0000000000 --- a/media/gmp-clearkey/0.1/openaes/standard.h +++ /dev/null @@ -1,57 +0,0 @@ -/* ------------------------------------------------------------------------------- -Standard definitions and types, Bob Jenkins ------------------------------------------------------------------------------- -*/ -#ifndef STANDARD -# define STANDARD -# ifndef STDIO -# include -# define STDIO -# endif -# ifndef STDDEF -# include -# define STDDEF -# endif -typedef unsigned long long ub8; -#define UB8MAXVAL 0xffffffffffffffffLL -#define UB8BITS 64 -typedef signed long long sb8; -#define SB8MAXVAL 0x7fffffffffffffffLL -typedef unsigned long int ub4; /* unsigned 4-byte quantities */ -#define UB4MAXVAL 0xffffffff -typedef signed long int sb4; -#define UB4BITS 32 -#define SB4MAXVAL 0x7fffffff -typedef unsigned short int ub2; -#define UB2MAXVAL 0xffff -#define UB2BITS 16 -typedef signed short int sb2; -#define SB2MAXVAL 0x7fff -typedef unsigned char ub1; -#define UB1MAXVAL 0xff -#define UB1BITS 8 -typedef signed char sb1; /* signed 1-byte quantities */ -#define SB1MAXVAL 0x7f -typedef int word; /* fastest type available */ - -#define bis(target,mask) ((target) |= (mask)) -#define bic(target,mask) ((target) &= ~(mask)) -#define bit(target,mask) ((target) & (mask)) -// #ifndef min -// # define min(a,b) (((a)<(b)) ? (a) : (b)) -// #endif /* min */ -// #ifndef max -// # define max(a,b) (((a)<(b)) ? (b) : (a)) -// #endif /* max */ -#ifndef align -# define align(a) (((ub4)a+(sizeof(void *)-1))&(~(sizeof(void *)-1))) -#endif /* align */ -// #ifndef abs -// # define abs(a) (((a)>0) ? (a) : -(a)) -// #endif -#define TRUE 1 -#define FALSE 0 -#define SUCCESS 0 /* 1 on VAX */ - -#endif /* STANDARD */ -- cgit v1.2.3