Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 55 additions & 6 deletions src/decrypters/DrmEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,73 @@ STREAM_CRYPTO_KEY_SYSTEM KSToCryptoKeySystem(std::string_view keySystem)
*/
DRM::DRMInfo* GetDRMInfoByKS(std::vector<DRM::DRMInfo>& drmInfos, std::string_view keySystem, bool isStrict = false)
{
// If no key system is provided its assumend CENC content compatible with any DRM
// Give priority to entries that explicitly match the requested key system, then try find entries with an empty key system (CENC)
auto itDrmInfo = std::find_if(drmInfos.begin(), drmInfos.end(), [&](const DRMInfo& info)
{ return info.keySystem == keySystem || !isStrict && info.keySystem.empty(); });
{ return !info.keySystem.empty() && info.keySystem == keySystem; });

if (itDrmInfo != drmInfos.end())
return &(*itDrmInfo);

if (!isStrict)
{
itDrmInfo = std::find_if(drmInfos.begin(), drmInfos.end(), [&](const DRMInfo& info)
{ return info.keySystem.empty(); });

if (itDrmInfo != drmInfos.end())
return &(*itDrmInfo);
}

return nullptr;
}

std::vector<DRM::DRMInfo> GetDRMInfosByKS(std::vector<DRM::DRMInfo>& drmInfos, std::string_view keySystem)
{
std::vector<DRM::DRMInfo> ret;
// If no key system is provided its assumend CENC content compatible with any DRM
std::copy_if(drmInfos.begin(), drmInfos.end(), std::back_inserter(ret),
[&](const DRM::DRMInfo& info)
{ return info.keySystem == keySystem || info.keySystem.empty(); });
// Give priority to entries that explicitly match the requested key system, then append entries with an empty key system (CENC)
for (const auto& info : drmInfos)
{
if (!info.keySystem.empty() && info.keySystem == keySystem)
ret.emplace_back(info);
}
for (const auto& info : drmInfos)
{
if (info.keySystem.empty())
ret.emplace_back(info);
}

return ret;
}

// \brief Common CENC DRMInfo need to be converted to a specific key system with appropriate PSSH init
void ConvertDRMInfoCENC(DRM::DRMInfo& drmInfo, const std::string& keySystem)
{
if (!drmInfo.keySystem.empty())
return; // Not a CENC DRMInfo, no need to convert

LOG::Log(LOGDEBUG, "Converting Common CENC DRMInfo to %s", keySystem.c_str());
std::vector<std::vector<uint8_t>> keyIds;

if (DRM::IsValidPsshHeader(drmInfo.initData))
{
DRM::PSSH parser;
if (parser.Parse(drmInfo.initData))
keyIds = parser.GetKeyIds();
}

if (keyIds.empty())
{
if (drmInfo.defaultKid.empty())
{
LOG::Log(LOGERROR, "Common CENC DRMInfo does not have a default KID, cannot convert to %s",
keySystem.c_str());
return;
}
keyIds.emplace_back(DRM::ConvertKidStrToBytes(drmInfo.defaultKid));
}

drmInfo.initData = DRM::PSSH::Make(KeySystemToUUID(keySystem), keyIds);
}

// \brief Query DRM decrypter to get capabilities and set it to session.
// \return True if has success, otherwise false.
bool GetCapabilities(const std::optional<bool> isForceSecureDecoder,
Expand Down Expand Up @@ -382,6 +429,8 @@ const std::shared_ptr<DRMSession> DRM::CDRMEngine::InitializeSession(
{
DRM::DRMInfo drmInfo = selDrmInfos[drmInfoIdx];

ConvertDRMInfoCENC(drmInfo, m_keySystem);

// Set custom init data PSSH provided from property,
// can allow to initialize a DRM that could be also not specified
// as supported in the manifest (e.g. missing DASH ContentProtection tags)
Expand Down
Loading