Source code

Revision control

Copy as Markdown

Other Tools

/* 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
// 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}
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);
#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