Skip to content

Commit

Permalink
Merge pull request #1165 from glennguy/wv-single-instance
Browse files Browse the repository at this point in the history
[DRM] Revert to single session decryption (when possible)
  • Loading branch information
glennguy authored Apr 12, 2023
2 parents 8af990f + f1ff510 commit 91a549c
Show file tree
Hide file tree
Showing 16 changed files with 247 additions and 197 deletions.
4 changes: 3 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ set(ADP_SOURCES
src/codechandler/WebVTTCodecHandler.cpp
src/codechandler/ttml/TTML.cpp
src/common/AdaptationSet.cpp
src/common/AdaptiveCencSampleDecrypter.cpp
src/common/AdaptiveStream.cpp
src/common/AdaptiveTree.cpp
src/common/AdaptiveUtils.cpp
Expand Down Expand Up @@ -67,7 +68,6 @@ set(ADP_SOURCES

set(ADP_HEADERS
src/AdaptiveByteStream.h
src/CryptoMode.h
src/main.h
src/oscompat.h
src/SSD_dll.h
Expand All @@ -81,6 +81,7 @@ set(ADP_HEADERS
src/codechandler/WebVTTCodecHandler.h
src/codechandler/ttml/TTML.h
src/common/AdaptationSet.h
src/common/AdaptiveCencSampleDecrypter.h
src/common/AdaptiveDecrypter.h
src/common/AdaptiveStream.h
src/common/AdaptiveTree.h
Expand Down Expand Up @@ -110,6 +111,7 @@ set(ADP_HEADERS
src/samplereader/TSSampleReader.h
src/samplereader/WebmSampleReader.h
src/utils/Base64Utils.h
src/utils/CryptoUtils.h
src/utils/DigestMD5Utils.h
src/utils/FileUtils.h
src/utils/log.h
Expand Down
2 changes: 1 addition & 1 deletion depends/common/bento4/bento4.sha256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
8afa4ae07a7629a65e0d5014750960ced33a8771d363652f3913261fb5d0c84f
4464cd47b597e6dedbfc231bb6eb097c45cfe5ee0051082460d9ac53e9d74dc3
2 changes: 1 addition & 1 deletion depends/common/bento4/bento4.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
bento4 https://github.com/xbmc/Bento4/archive/refs/tags/1.6.0-639-6-Nexus.tar.gz
bento4 https://github.com/xbmc/Bento4/archive/refs/tags/1.6.0-639-7-Omega.tar.gz
55 changes: 21 additions & 34 deletions src/Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,34 +459,14 @@ bool CSession::InitializeDRM(bool addDefaultKID /* = false */)

unsigned char key_system[16];
AP4_ParseHex(strkey.c_str(), key_system, 16);
uint32_t currentSessionTypes = 0;

// cdmSession 0 is reserved for unencrypted streams
for (size_t ses{1}; ses < m_cdmSessions.size(); ++ses)
{
AP4_DataBuffer init_data;
const char* optionalKeyParameter{nullptr};
CPeriod::PSSHSet& sessionPsshset = m_adaptiveTree->m_currentPeriod->GetPSSHSets()[ses];
uint32_t sessionType = 0;

if (sessionPsshset.media_ > 0)
{
sessionType = sessionPsshset.media_;
}
else
{
switch (sessionPsshset.adaptation_set_->GetStreamType())
{
case StreamType::VIDEO:
sessionType = CPeriod::PSSHSet::MEDIA_VIDEO;
break;
case StreamType::AUDIO:
sessionType = CPeriod::PSSHSet::MEDIA_AUDIO;
break;
default:
break;
}
}
CPeriod::PSSHSet& sessionPsshset = m_adaptiveTree->m_currentPeriod->GetPSSHSets()[ses];

if (sessionPsshset.pssh_ == "FILE")
{
Expand Down Expand Up @@ -625,27 +605,34 @@ bool CSession::InitializeDRM(bool addDefaultKID /* = false */)
std::string hexKid{StringUtils::ToHexadecimal(defaultKid)};
LOG::Log(LOGDEBUG, "Initializing stream with KID: %s", hexKid.c_str());

// use shared ssd session if we already have 1 of the same stream type
if (currentSessionTypes & sessionType)
for (size_t i{1}; i < ses; ++i)
{
for (size_t i{1}; i < ses; ++i)
if (m_decrypter->HasLicenseKey(m_cdmSessions[i].m_cencSingleSampleDecrypter, defkid))
{
if (m_decrypter->HasLicenseKey(m_cdmSessions[i].m_cencSingleSampleDecrypter, defkid))
{
session.m_cencSingleSampleDecrypter = m_cdmSessions[i].m_cencSingleSampleDecrypter;
session.m_sharedCencSsd = true;
break;
}
session.m_cencSingleSampleDecrypter = m_cdmSessions[i].m_cencSingleSampleDecrypter;
session.m_sharedCencSsd = true;
break;
}
}

}
else if (defaultKid.empty() && !session.m_cencSingleSampleDecrypter)
else if (defaultKid.empty())
{
LOG::Log(LOGWARNING, "Initializing stream with unknown KID!");
for (size_t i{1}; i < ses; ++i)
{
if (sessionPsshset.pssh_ == m_adaptiveTree->m_currentPeriod->GetPSSHSets()[i].pssh_)
{
session.m_cencSingleSampleDecrypter = m_cdmSessions[i].m_cencSingleSampleDecrypter;
session.m_sharedCencSsd = true;
break;
}
}
if (!session.m_cencSingleSampleDecrypter)
{
LOG::Log(LOGWARNING, "Initializing stream with unknown KID!");
}
}

currentSessionTypes |= sessionType;

if (m_decrypter && init_data.GetDataSize() >= 4 &&
(session.m_cencSingleSampleDecrypter ||
(session.m_cencSingleSampleDecrypter = m_decrypter->CreateSingleSampleDecrypter(
Expand Down
57 changes: 57 additions & 0 deletions src/common/AdaptiveCencSampleDecrypter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* 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 "AdaptiveCencSampleDecrypter.h"
#include "AdaptiveDecrypter.h"

#include "../utils/log.h"

AP4_Result CAdaptiveCencSampleDecrypter::DecryptSampleData(AP4_UI32 poolid,
AP4_DataBuffer& data_in,
AP4_DataBuffer& data_out,
const AP4_UI08* iv)
{
// increment the sample cursor
unsigned int sample_cursor = m_SampleCursor++;

// setup the IV
unsigned char iv_block[16];
if (!iv)
{
iv = m_SampleInfoTable->GetIv(sample_cursor);
}
if (!iv)
return AP4_ERROR_INVALID_FORMAT;
unsigned int iv_size = m_SampleInfoTable->GetIvSize();
AP4_CopyMemory(iv_block, iv, iv_size);
if (iv_size != 16)
AP4_SetMemory(&iv_block[iv_size], 0, 16 - iv_size);

// get the subsample info for this sample if needed
unsigned int subsample_count = 0;
const AP4_UI16* bytes_of_cleartext_data = nullptr;
const AP4_UI32* bytes_of_encrypted_data = nullptr;
if (m_SampleInfoTable)
{
AP4_Result result = m_SampleInfoTable->GetSampleInfo(
sample_cursor, subsample_count, bytes_of_cleartext_data, bytes_of_encrypted_data);
if (AP4_FAILED(result))
return result;
}

// decrypt the sample
Adaptive_CencSingleSampleDecrypter* decrypter =
dynamic_cast<Adaptive_CencSingleSampleDecrypter*>(m_SingleSampleDecrypter);
if (!decrypter)
{
LOG::LogF(LOGERROR, "Failed to cast AP4 decrypter to Adaptive");
return AP4_ERROR_INVALID_PARAMETERS;
}
return decrypter->DecryptSampleData(poolid, data_in, data_out, iv_block, subsample_count,
bytes_of_cleartext_data, bytes_of_encrypted_data);
}
24 changes: 24 additions & 0 deletions src/common/AdaptiveCencSampleDecrypter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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 <bento4/Ap4.h>

class CAdaptiveCencSampleDecrypter : public AP4_CencSampleDecrypter
{
public:
CAdaptiveCencSampleDecrypter(AP4_CencSingleSampleDecrypter* single_sample_decrypter,
AP4_CencSampleInfoTable* sample_info_table)
: AP4_CencSampleDecrypter(single_sample_decrypter, sample_info_table)
{
}

virtual AP4_Result DecryptSampleData(AP4_UI32 poolid,
AP4_DataBuffer& data_in,
AP4_DataBuffer& data_out,
const AP4_UI08* iv);
};
30 changes: 19 additions & 11 deletions src/common/AdaptiveDecrypter.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#pragma once

#include "../CryptoMode.h"
#include "../utils/CryptoUtils.h"

#include <stdexcept>
#include <string_view>
Expand All @@ -20,13 +20,6 @@ class Adaptive_CencSingleSampleDecrypter : public AP4_CencSingleSampleDecrypter
public:
Adaptive_CencSingleSampleDecrypter() : AP4_CencSingleSampleDecrypter(0){};

void SetCrypto(AP4_UI08 cryptBlocks, AP4_UI08 skipBlocks)
{
m_CryptBlocks = static_cast<uint32_t>(cryptBlocks);
m_SkipBlocks = static_cast<uint32_t>(skipBlocks);
};
virtual void SetEncryptionMode(CryptoMode encryptionMode){};

/*! \brief Add a Key ID to the current session
* \param keyId The KID
*/
Expand All @@ -43,7 +36,22 @@ class Adaptive_CencSingleSampleDecrypter : public AP4_CencSingleSampleDecrypter
throw std::logic_error("SetDefaultKeyId method not implemented.");
};

protected:
uint32_t m_CryptBlocks{0};
uint32_t m_SkipBlocks{0};
virtual AP4_Result SetFragmentInfo(AP4_UI32 pool_id,
const AP4_UI08* key,
const AP4_UI08 nal_length_size,
AP4_DataBuffer& annexb_sps_pps,
AP4_UI32 flags,
CryptoInfo cryptoInfo) = 0;

virtual AP4_Result DecryptSampleData(AP4_UI32 poolid,
AP4_DataBuffer& data_in,
AP4_DataBuffer& data_out,
const AP4_UI08* iv,
unsigned int subsample_count,
const AP4_UI16* bytes_of_cleartext_data,
const AP4_UI32* bytes_of_encrypted_data) = 0;

virtual AP4_UI32 AddPool() { return 0; }
virtual void RemovePool(AP4_UI32 poolid) {}
virtual const char* GetSessionId() { return nullptr; }
};
2 changes: 1 addition & 1 deletion src/common/AdaptiveTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

#pragma once

#include "../CryptoMode.h"
#include "../utils/CryptoUtils.h"
#include "../utils/PropertiesUtils.h"
#include "AdaptationSet.h"
#include "Period.h"
Expand Down
2 changes: 1 addition & 1 deletion src/common/Period.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
#include "CommonSegAttribs.h"
#include "SegTemplate.h"
#include "SegmentList.h"
#include "../CryptoMode.h"
#include "../utils/CryptoUtils.h"

#ifdef INPUTSTREAM_TEST_BUILD
#include "../test/KodiStubs.h"
Expand Down
2 changes: 1 addition & 1 deletion src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -459,7 +459,7 @@ DEMUX_PACKET* CInputStreamAdaptive::DemuxRead(void)
std::memcpy(p->cryptoInfo->kid, pData, 16);
pData += 16;
iSize -= (pData - sr->GetSampleData());
ReaderCryptoInfo cryptoInfo = sr->GetReaderCryptoInfo();
CryptoInfo cryptoInfo = sr->GetReaderCryptoInfo();
p->cryptoInfo->numSubSamples = numSubSamples;
p->cryptoInfo->cryptBlocks = cryptoInfo.m_cryptBlocks;
p->cryptoInfo->skipBlocks = cryptoInfo.m_skipBlocks;
Expand Down
17 changes: 8 additions & 9 deletions src/samplereader/FragmentedSampleReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,12 +421,14 @@ AP4_Result CFragmentedSampleReader::ProcessMoof(AP4_ContainerAtom* moof,
// we assume unencrypted fragment here
goto SUCCESS;

AP4_CencSampleDecrypter* decrypter = nullptr;
if (AP4_FAILED(result = AP4_CencSampleDecrypter::Create(sample_table, algorithm_id, 0, 0, 0,
reset_iv, m_singleSampleDecryptor,
m_decrypter)))
decrypter)))
{
return result;
}
m_decrypter = new CAdaptiveCencSampleDecrypter(m_singleSampleDecryptor, sample_table);

// Inform decrypter of pattern decryption (CBCS)
AP4_UI32 schemeType = m_protectedDesc->GetSchemeType();
Expand All @@ -442,10 +444,6 @@ AP4_Result CFragmentedSampleReader::ProcessMoof(AP4_ContainerAtom* moof,
m_readerCryptoInfo.m_mode = CryptoMode::AES_CTR;
else
m_readerCryptoInfo.m_mode = CryptoMode::AES_CBC;

m_singleSampleDecryptor->SetEncryptionMode(m_readerCryptoInfo.m_mode);
m_singleSampleDecryptor->SetCrypto(m_readerCryptoInfo.m_cryptBlocks,
m_readerCryptoInfo.m_skipBlocks);
}
else if (schemeType == AP4_PROTECTION_SCHEME_TYPE_CBC1 ||
schemeType == AP4_PROTECTION_SCHEME_TYPE_CENS)
Expand All @@ -456,10 +454,11 @@ AP4_Result CFragmentedSampleReader::ProcessMoof(AP4_ContainerAtom* moof,
}
SUCCESS:
if (m_singleSampleDecryptor && m_codecHandler)
m_singleSampleDecryptor->SetFragmentInfo(m_poolId, m_defaultKey,
m_codecHandler->m_naluLengthSize,
m_codecHandler->m_extraData, m_decrypterCaps.flags);

{
m_singleSampleDecryptor->SetFragmentInfo(
m_poolId, m_defaultKey, m_codecHandler->m_naluLengthSize, m_codecHandler->m_extraData,
m_decrypterCaps.flags, m_readerCryptoInfo);
}
return AP4_SUCCESS;
}

Expand Down
7 changes: 4 additions & 3 deletions src/samplereader/FragmentedSampleReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "../SSD_dll.h"
#include "../codechandler/CodecHandler.h"
#include "../common/AdaptiveDecrypter.h"
#include "../common/AdaptiveCencSampleDecrypter.h"
#include "../utils/log.h"
#include "SampleReader.h"

Expand Down Expand Up @@ -46,7 +47,7 @@ class ATTR_DLL_LOCAL CFragmentedSampleReader : public ISampleReader, public AP4_
int64_t GetPTSDiff() const override { return m_ptsDiff; }
bool GetNextFragmentInfo(uint64_t& ts, uint64_t& dur) override;
uint32_t GetTimeScale() const override { return m_track->GetMediaTimeScale(); }
ReaderCryptoInfo GetReaderCryptoInfo() const override { return m_readerCryptoInfo; }
CryptoInfo GetReaderCryptoInfo() const override { return m_readerCryptoInfo; }

static const AP4_UI32 TRACKID_UNKNOWN = -1;

Expand Down Expand Up @@ -82,8 +83,8 @@ class ATTR_DLL_LOCAL CFragmentedSampleReader : public ISampleReader, public AP4_
const AP4_UI08* m_defaultKey{nullptr};
AP4_ProtectedSampleDescription* m_protectedDesc{nullptr};
Adaptive_CencSingleSampleDecrypter* m_singleSampleDecryptor;
AP4_CencSampleDecrypter* m_decrypter{nullptr};
CAdaptiveCencSampleDecrypter* m_decrypter{nullptr};
uint64_t m_nextDuration{0};
uint64_t m_nextTimestamp{0};
ReaderCryptoInfo m_readerCryptoInfo{};
CryptoInfo m_readerCryptoInfo{};
};
10 changes: 2 additions & 8 deletions src/samplereader/SampleReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#pragma once

#include "../common/AdaptiveDecrypter.h"
#include "../utils/CryptoUtils.h"

#include <bento4/Ap4.h>

Expand All @@ -27,13 +28,6 @@ namespace SESSION
class CSession;
}

struct ReaderCryptoInfo
{
uint8_t m_cryptBlocks{0};
uint8_t m_skipBlocks{0};
CryptoMode m_mode{CryptoMode::NONE};
};

class ATTR_DLL_LOCAL ISampleReader
{
public:
Expand Down Expand Up @@ -63,7 +57,7 @@ class ATTR_DLL_LOCAL ISampleReader
virtual void SetStreamType(INPUTSTREAM_TYPE type, uint32_t sid) {};
virtual bool RemoveStreamType(INPUTSTREAM_TYPE type) { return true; };
virtual bool IsStarted() const = 0;
virtual ReaderCryptoInfo GetReaderCryptoInfo() const { return ReaderCryptoInfo(); }
virtual CryptoInfo GetReaderCryptoInfo() const { return CryptoInfo(); }

/*!
* \brief Read the sample asynchronously
Expand Down
Loading

0 comments on commit 91a549c

Please sign in to comment.