-
Notifications
You must be signed in to change notification settings - Fork 242
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
54b3f50
commit 6168bb2
Showing
22 changed files
with
2,056 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
cmake_minimum_required(VERSION 3.10) | ||
project(mfcdm_library) | ||
|
||
add_library(mfcdm_library STATIC | ||
mfcdm/MediaFoundationCdm.h | ||
mfcdm/MediaFoundationCdm.cpp | ||
mfcdm/MediaFoundationCdmFactory.cpp | ||
mfcdm/MediaFoundationCdmSession.cpp | ||
mfcdm/MediaFoundationSession.cpp | ||
mfcdm/Log.cpp | ||
) | ||
|
||
target_include_directories(mfcdm_library PUBLIC ${PROJECT_SOURCE_DIR}) | ||
target_link_libraries(mfcdm_library PRIVATE cdm_library propsys mf mfplat mfplay mfreadwrite mfuuid wmcodecdspuuid) | ||
set_target_properties(mfcdm_library PROPERTIES POSITION_INDEPENDENT_CODE True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
#include "Log.h" | ||
|
||
#include <cstdarg> | ||
#include <cstdio> | ||
|
||
typedef struct | ||
{ | ||
const char* name; | ||
int cur_level; | ||
void (*msg_callback)(int level, char* msg); | ||
} debug_ctx_t; | ||
|
||
static debug_ctx_t debug_ctx = {"MF", MFCDM::MFLOG_NONE, NULL}; | ||
|
||
|
||
static inline void __dbg(debug_ctx_t* ctx, int level, const char* fmt, va_list ap) | ||
{ | ||
if (ctx != NULL && level <= ctx->cur_level) | ||
{ | ||
char msg[4096]; | ||
int len = snprintf(msg, sizeof(msg), "[%s] ", ctx->name); | ||
vsnprintf(msg + len, sizeof(msg) - len, fmt, ap); | ||
if (ctx->msg_callback) | ||
{ | ||
ctx->msg_callback(level, msg); | ||
} | ||
} | ||
} | ||
|
||
void MFCDM::LogAll() | ||
{ | ||
debug_ctx.cur_level = MFLOG_ALL; | ||
} | ||
|
||
void MFCDM::Log(LogLevel level, const char* fmt, ...) | ||
{ | ||
va_list ap; | ||
|
||
va_start(ap, fmt); | ||
__dbg(&debug_ctx, level, fmt, ap); | ||
va_end(ap); | ||
} | ||
|
||
void MFCDM::SetMFMsgCallback(void (*msgcb)(int level, char*)) | ||
{ | ||
debug_ctx.msg_callback = msgcb; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
namespace MFCDM | ||
{ | ||
enum LogLevel | ||
{ | ||
MFLOG_NONE = -1, | ||
MFLOG_ERROR, | ||
MFLOG_WARN, | ||
MFLOG_INFO, | ||
MFLOG_DEBUG, | ||
MFLOG_ALL = 100 | ||
}; | ||
|
||
void LogAll(); | ||
void Log(LogLevel level, const char* fmt, ...); | ||
void SetMFMsgCallback(void (*msgcb)(int level, char*)); | ||
|
||
} // namespace MFCDM |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
/* | ||
* Copyright (C) 2023 Team Kodi | ||
* This file is part of Kodi - https://kodi.tv | ||
* | ||
* SPDX-License-Identifier: GPL-2.0-or-later | ||
* See LICENSES/README.md for more information. | ||
*/ | ||
|
||
#include "MediaFoundationCdm.h" | ||
|
||
#include "Log.h" | ||
#include "MediaFoundationCdmFactory.h" | ||
#include "MediaFoundationCdmModule.h" | ||
#include "MediaFoundationCdmSession.h" | ||
|
||
#include "utils/PMPHostWrapper.h" | ||
|
||
MediaFoundationCdm::~MediaFoundationCdm() = default; | ||
|
||
bool MediaFoundationCdm::Initialize(const std::string &keySystem, | ||
const std::string &basePath, | ||
const media::CdmConfig &cdmConfig, | ||
media::CdmAdapterClient* client) | ||
{ | ||
bool ret = true; | ||
|
||
m_session.Startup(); | ||
|
||
ret = m_session.HasMediaFoundation(); | ||
if (!ret) | ||
{ | ||
Log(MFCDM::MFLOG_ERROR, "MF doesn't exist on current system"); | ||
return false; | ||
} | ||
|
||
const auto m_factory = std::make_unique<MediaFoundationCdmFactory>(keySystem); | ||
|
||
ret = m_factory->Initialize(); | ||
if (!ret) | ||
{ | ||
Log(MFCDM::MFLOG_ERROR, "MFFactory failed to initialize."); | ||
return false; | ||
} | ||
|
||
ret = m_factory->CreateMfCdm(cdmConfig, basePath, m_module); | ||
if (!ret) | ||
{ | ||
Log(MFCDM::MFLOG_ERROR, "MFFactory failed to create MF CDM."); | ||
return false; | ||
} | ||
|
||
Log(MFCDM::MFLOG_DEBUG, "MF CDM created."); | ||
|
||
SetupPMPServer(); | ||
|
||
m_client = client; | ||
return true; | ||
} | ||
|
||
/*! | ||
* \brief Setup PMPHostApp | ||
* IMFContentDecryptionModule->SetPMPHostApp | ||
* needs to be set if not under UWP or else GenerateChallenge will fail | ||
* \link https://github.com/microsoft/media-foundation/issues/37#issuecomment-1194534228 | ||
*/ | ||
void MediaFoundationCdm::SetupPMPServer() const | ||
{ | ||
if (!m_module) | ||
return; | ||
|
||
const winrt::com_ptr<IMFGetService> spIMFGetService = m_module->As<IMFGetService>(); | ||
winrt::com_ptr<IMFPMPHost> pmpHostApp; | ||
|
||
if(FAILED(spIMFGetService->GetService( | ||
MF_CONTENTDECRYPTIONMODULE_SERVICE, IID_PPV_ARGS(pmpHostApp.put())))) | ||
{ | ||
Log(MFCDM::MFLOG_ERROR, "Failed to get MF CDM service."); | ||
return; | ||
} | ||
|
||
winrt::com_ptr<PMPHostWrapper> spIMFPMPHostApp = winrt::make_self<PMPHostWrapper>(pmpHostApp); | ||
m_module->SetPMPHostApp(spIMFPMPHostApp.get()); | ||
} | ||
|
||
void MediaFoundationCdm::SetServerCertificate(uint32_t promise_id, | ||
const uint8_t* serverCertificateData, | ||
uint32_t serverCertificateDataSize) const | ||
{ | ||
m_module->SetServerCertificate(serverCertificateData, serverCertificateDataSize); | ||
} | ||
|
||
void MediaFoundationCdm::CreateSessionAndGenerateRequest(uint32_t promise_id, cdm::SessionType sessionType, | ||
cdm::InitDataType initDataType, const uint8_t *init_data, | ||
uint32_t init_data_size) | ||
{ | ||
auto session = std::make_unique<MediaFoundationCdmSession>(); | ||
|
||
if (!session->Initialize(sessionType, m_module.get())) | ||
{ | ||
Log(MFCDM::MFLOG_ERROR, "Failed to create session."); | ||
return; | ||
} | ||
|
||
int session_token = next_session_token_++; | ||
session->GenerateRequest(initDataType, init_data, init_data_size); | ||
|
||
m_cdm_sessions.emplace(session_token, std::move(session)); | ||
} | ||
|
||
void MediaFoundationCdm::LoadSession(cdm::SessionType session_type, | ||
const std::string &session_id) | ||
{ | ||
|
||
} | ||
|
||
void MediaFoundationCdm::UpdateSession(const std::string &session_id) | ||
{ | ||
|
||
} | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
/* | ||
* Copyright (C) 2023 Team Kodi | ||
* This file is part of Kodi - https://kodi.tv | ||
* | ||
* SPDX-License-Identifier: GPL-2.0-or-later | ||
* See LICENSES/README.md for more information. | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include "MediaFoundationSession.h" | ||
|
||
#include <string> | ||
#include <map> | ||
#include <memory> | ||
|
||
#include "cdm/media/base/cdm_config.h" | ||
#include "cdm/media/cdm/api/content_decryption_module.h" | ||
#include "cdm/media/cdm/cdm_adapter.h" | ||
|
||
class MediaFoundationCdmSession; | ||
class MediaFoundationCdmFactory; | ||
class MediaFoundationCdmModule; | ||
|
||
class MediaFoundationCdm { | ||
public: | ||
~MediaFoundationCdm(); | ||
|
||
bool IsInitialized() const { return m_module != nullptr; } | ||
|
||
bool Initialize(const std::string& keySystem, | ||
const std::string &basePath, | ||
const media::CdmConfig &cdmConfig, | ||
media::CdmAdapterClient* client); | ||
|
||
void SetServerCertificate(uint32_t promise_id, | ||
const uint8_t* serverCertificateData, | ||
uint32_t serverCertificateDataSize) const; | ||
|
||
void CreateSessionAndGenerateRequest(uint32_t promise_id, | ||
cdm::SessionType sessionType, | ||
cdm::InitDataType initDataType, | ||
const uint8_t* init_data, | ||
uint32_t init_data_size); | ||
|
||
void LoadSession(cdm::SessionType session_type, const std::string& session_id); | ||
|
||
void UpdateSession(const std::string& session_id); | ||
private: | ||
void SetupPMPServer() const; | ||
|
||
MediaFoundationSession m_session; | ||
|
||
std::unique_ptr<MediaFoundationCdmModule> m_module{nullptr}; | ||
|
||
int next_session_token_{0}; | ||
std::map<int, std::unique_ptr<MediaFoundationCdmSession>> m_cdm_sessions; | ||
|
||
media::CdmAdapterClient* m_client{nullptr}; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* Copyright (C) 2023 Team Kodi | ||
* This file is part of Kodi - https://kodi.tv | ||
* | ||
* SPDX-License-Identifier: GPL-2.0-or-later | ||
* See LICENSES/README.md for more information. | ||
*/ | ||
|
||
#pragma once | ||
|
||
/*! | ||
* \brief The runtime configuration for the CDM instance | ||
*/ | ||
struct MediaFoundationCdmConfig | ||
{ | ||
MediaFoundationCdmConfig(bool distinctive_identifier = false, bool persistent_state = false) | ||
: allow_distinctive_identifier(distinctive_identifier), | ||
allow_persistent_state(persistent_state), | ||
use_hw_secure_codecs(false) | ||
{ | ||
|
||
} | ||
|
||
// Allow access to a distinctive identifier. | ||
bool allow_distinctive_identifier; | ||
|
||
// Allow access to persistent state. | ||
bool allow_persistent_state; | ||
|
||
// Use hardware-secure codecs. | ||
bool use_hw_secure_codecs; | ||
}; |
Oops, something went wrong.