diff options
Diffstat (limited to 'media/wmf-clearkey/WMFClearKeyUtils.h')
-rw-r--r-- | media/wmf-clearkey/WMFClearKeyUtils.h | 229 |
1 files changed, 229 insertions, 0 deletions
diff --git a/media/wmf-clearkey/WMFClearKeyUtils.h b/media/wmf-clearkey/WMFClearKeyUtils.h new file mode 100644 index 0000000000..e834e6cb9a --- /dev/null +++ b/media/wmf-clearkey/WMFClearKeyUtils.h @@ -0,0 +1,229 @@ +/* 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 DOM_MEDIA_PLATFORM_WMF_CLEARKEY_WMFCLEARKEYCDMUTILS_H +#define DOM_MEDIA_PLATFORM_WMF_CLEARKEY_WMFCLEARKEYCDMUTILS_H + +#include <initguid.h> +#include <memory> +#include <mfidl.h> +#include <mutex> +#include <thread> +#include <windows.h> +#include <wrl.h> +#include <sstream> +#include <stdio.h> + +#include "MFCDMExtra.h" +#include "mozilla/Assertions.h" +#include "mozilla/Unused.h" + +namespace mozilla { + +inline constexpr WCHAR kCLEARKEY_SYSTEM_NAME[] = L"org.w3.clearkey"; + +#define WMF_CLEARKEY_DEBUG 0 + +#ifdef WMF_CLEARKEY_DEBUG +# define LOG(msg, ...) \ + printf(("[Thread %lu]: D/WMFClearKey " msg "\n"), \ + static_cast<unsigned long>( \ + std::hash<std::thread::id>{}(std::this_thread::get_id())), \ + ##__VA_ARGS__) +#else +# define LOG(msg, ...) +#endif + +#define PRETTY_FUNC \ + ([&]() -> std::string { \ + std::string prettyFunction(__PRETTY_FUNCTION__); \ + std::size_t pos1 = prettyFunction.find("::"); \ + std::size_t pos2 = prettyFunction.find("(", pos1); \ + return prettyFunction.substr(0, pos2); \ + })() \ + .c_str() + +// We can't reuse the definition in the `MediaEngineUtils.h` due to the +// restriction of not being able to use XPCOM string in the external library. +#ifndef RETURN_IF_FAILED +# define RETURN_IF_FAILED(x) \ + do { \ + HRESULT rv = x; \ + if (FAILED(rv)) { \ + LOG("(" #x ") failed, rv=%lx", rv); \ + return rv; \ + } \ + } while (false) +#endif + +#ifndef NOT_IMPLEMENTED +# define NOT_IMPLEMENTED() \ + do { \ + LOG("WARNING : '%s' NOT IMPLEMENTED!", PRETTY_FUNC); \ + } while (0) +#endif + +#ifndef ENTRY_LOG +# define ENTRY_LOG(...) \ + do { \ + LOG("%s [%p]", PRETTY_FUNC, this); \ + } while (0) +# define ENTRY_LOG_ARGS(fmt, ...) \ + do { \ + LOG("%s [%p]: " fmt, PRETTY_FUNC, this, ##__VA_ARGS__); \ + (void)(0, ##__VA_ARGS__); \ + } while (0) +#endif + +// TODO : should we use Microsoft's definition or Chromium's defintion? + +// This is defined in Microsoft's sample code +// https://github.com/microsoft/media-foundation/blob/dc81175a3e893c7c58fcbf1a943ac342e39f172c/samples/storecdm/clearkeyStoreCDM/clearkeydll/guids.h#L17-L18C14 +// DEFINE_GUID(CLEARKEY_GUID_CLEARKEY_PROTECTION_SYSTEM_ID, 0x9b0ff3ca, 0x1378, +// 0x4f28, 0x96, 0x65, 0x18, 0x9e, 0x15, 0x30, 0x2a, 0x71); + +// Media Foundation Clear Key protection system ID from Chromium +// {E4E94971-696A-447E-96E4-93FDF3A57A7A} +// https://source.chromium.org/chromium/chromium/src/+/main:media/cdm/win/test/media_foundation_clear_key_guids.h;l=16-29?q=CLEARKEY_GUID_CLEARKEY_PROTECTION_SYSTEM_ID&ss=chromium%2Fchromium%2Fsrc +DEFINE_GUID(CLEARKEY_GUID_CLEARKEY_PROTECTION_SYSTEM_ID, 0xe4e94971, 0x696a, + 0x447e, 0x96, 0xe4, 0x93, 0xfd, 0xf3, 0xa5, 0x7a, 0x7a); + +// Media Foundation Clear Key content enabler type +// {C262FD73-2F13-41C2-94E7-4CAF087AE1D1} +DEFINE_GUID(MEDIA_FOUNDATION_CLEARKEY_GUID_CONTENT_ENABLER_TYPE, 0xc262fd73, + 0x2f13, 0x41c2, 0x94, 0xe7, 0x4c, 0xaf, 0x8, 0x7a, 0xe1, 0xd1); + +// https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:media/cdm/win/test/media_foundation_clear_key_guids.h;l=46;drc=fcefb4563e8ea5b2036ecde882f4f228dd1e4338 +#define PLAYREADY_GUID_MEDIA_PROTECTION_SYSTEM_ID_STRING \ + L"{F4637010-03C3-42CD-B932-B48ADF3A6A54}" + +// A PROPVARIANT that is automatically initialized and cleared upon respective +// construction and destruction of this class. +class AutoPropVar final { + public: + AutoPropVar() { PropVariantInit(&mVar); } + + ~AutoPropVar() { Reset(); } + + AutoPropVar(const AutoPropVar&) = delete; + AutoPropVar& operator=(const AutoPropVar&) = delete; + bool operator==(const AutoPropVar&) const = delete; + bool operator!=(const AutoPropVar&) const = delete; + + // Returns a pointer to the underlying PROPVARIANT for use as an out param + // in a function call. + PROPVARIANT* Receive() { + MOZ_ASSERT(mVar.vt == VT_EMPTY); + return &mVar; + } + + // Clears the instance to prepare it for re-use (e.g., via Receive). + void Reset() { + if (mVar.vt != VT_EMPTY) { + HRESULT hr = PropVariantClear(&mVar); + MOZ_ASSERT(SUCCEEDED(hr)); + Unused << hr; + } + } + + const PROPVARIANT& get() const { return mVar; } + const PROPVARIANT* ptr() const { return &mVar; } + + private: + PROPVARIANT mVar; +}; + +template <typename T> +class ScopedCoMem final { + public: + ScopedCoMem() : mPtr(nullptr) {} + + ~ScopedCoMem() { Reset(nullptr); } + + ScopedCoMem(const ScopedCoMem&) = delete; + ScopedCoMem& operator=(const ScopedCoMem&) = delete; + + T** operator&() { // NOLINT + MOZ_ASSERT(mPtr == nullptr); // To catch memory leaks. + return &mPtr; + } + + operator T*() { return mPtr; } + + T* operator->() { + MOZ_ASSERT(mPtr != nullptr); + return mPtr; + } + + const T* operator->() const { + MOZ_ASSERT(mPtr != nullptr); + return mPtr; + } + + explicit operator bool() const { return mPtr; } + + friend bool operator==(const ScopedCoMem& lhs, std::nullptr_t) { + return lhs.Get() == nullptr; + } + + friend bool operator==(std::nullptr_t, const ScopedCoMem& rhs) { + return rhs.Get() == nullptr; + } + + friend bool operator!=(const ScopedCoMem& lhs, std::nullptr_t) { + return lhs.Get() != nullptr; + } + + friend bool operator!=(std::nullptr_t, const ScopedCoMem& rhs) { + return rhs.Get() != nullptr; + } + + void Reset(T* ptr) { + if (mPtr) { + CoTaskMemFree(mPtr); + } + mPtr = ptr; + } + + T* Get() const { return mPtr; } + + private: + T* mPtr; +}; + +template <typename T> +class DataMutex final { + public: + DataMutex() = default; + + template <typename... Args> + explicit DataMutex(Args&&... args) : mData(std::forward<Args>(args)...) {} + + class AutoLock { + public: + AutoLock(std::unique_lock<std::mutex>&& lock, DataMutex<T>* mutex) + : mLock(std::move(lock)), mMutex(mutex) {} + T& operator*() { return ref(); } + T* operator->() { return &ref(); } + T& ref() const& { return mMutex->mData; } + operator T*() const& { return &ref(); } + ~AutoLock() { mMutex = nullptr; } + + private: + std::unique_lock<std::mutex> mLock; + DataMutex<T>* mMutex; + }; + + AutoLock Lock() { + return AutoLock(std::unique_lock<std::mutex>(mMutex), this); + } + + private: + std::mutex mMutex; + T mData; +}; + +} // namespace mozilla + +#endif // DOM_MEDIA_PLATFORM_WMF_CLEARKEY_WMFCLEARKEYCDMUTILS_H |