/* 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 #include #include #include #include #include #include #include #include #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( \ std::hash{}(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 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 class DataMutex final { public: DataMutex() = default; template explicit DataMutex(Args&&... args) : mData(std::forward(args)...) {} class AutoLock { public: AutoLock(std::unique_lock&& lock, DataMutex* 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 mLock; DataMutex* mMutex; }; AutoLock Lock() { return AutoLock(std::unique_lock(mMutex), this); } private: std::mutex mMutex; T mData; }; } // namespace mozilla #endif // DOM_MEDIA_PLATFORM_WMF_CLEARKEY_WMFCLEARKEYCDMUTILS_H