Skip to content

Commit

Permalink
Begin refactor of wvdecrypter, sample-aes-cbc support
Browse files Browse the repository at this point in the history
  • Loading branch information
glennguy committed Jan 23, 2022
1 parent e484fb4 commit da26852
Show file tree
Hide file tree
Showing 6 changed files with 90 additions and 33 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ set(ADP_HEADERS
src/main.h
src/oscompat.h
src/SSD_dll.h
src/common/AdaptiveDecrypter.h
src/common/AdaptiveStream.h
src/common/AdaptiveTree.h
src/common/RepresentationChooser.h
Expand Down
14 changes: 7 additions & 7 deletions src/SSD_dll.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

//Functionality wich is supported by the Decrypter
class AP4_CencSingleSampleDecrypter;
class Adaptive_CencSingleSampleDecrypter;
class AP4_DataBuffer;

namespace SSD
Expand Down Expand Up @@ -182,15 +182,15 @@ namespace SSD
// Return supported URN if type matches to capabilities, otherwise null
virtual const char *SelectKeySytem(const char* keySystem) = 0;
virtual bool OpenDRMSystem(const char *licenseURL, const AP4_DataBuffer &serverCertificate, const uint8_t config) = 0;
virtual AP4_CencSingleSampleDecrypter *CreateSingleSampleDecrypter(AP4_DataBuffer &pssh, const char *optionalKeyParameter, const uint8_t *defaultkeyid, bool skipSessionMessage) = 0;
virtual void DestroySingleSampleDecrypter(AP4_CencSingleSampleDecrypter* decrypter) = 0;
virtual Adaptive_CencSingleSampleDecrypter *CreateSingleSampleDecrypter(AP4_DataBuffer &pssh, const char *optionalKeyParameter, const uint8_t *defaultkeyid, bool skipSessionMessage) = 0;
virtual void DestroySingleSampleDecrypter(Adaptive_CencSingleSampleDecrypter* decrypter) = 0;

virtual void GetCapabilities(AP4_CencSingleSampleDecrypter* decrypter, const uint8_t *keyid, uint32_t media, SSD_DECRYPTER::SSD_CAPS &caps) = 0;
virtual bool HasLicenseKey(AP4_CencSingleSampleDecrypter* decrypter, const uint8_t *keyid) = 0;
virtual void GetCapabilities(Adaptive_CencSingleSampleDecrypter* decrypter, const uint8_t *keyid, uint32_t media, SSD_DECRYPTER::SSD_CAPS &caps) = 0;
virtual bool HasLicenseKey(Adaptive_CencSingleSampleDecrypter* decrypter, const uint8_t *keyid) = 0;
virtual bool HasCdmSession() = 0;
virtual std::string GetChallengeB64Data(AP4_CencSingleSampleDecrypter* decrypter) = 0;
virtual std::string GetChallengeB64Data(Adaptive_CencSingleSampleDecrypter* decrypter) = 0;

virtual bool OpenVideoDecoder(AP4_CencSingleSampleDecrypter* decrypter, const SSD_VIDEOINITDATA *initData) = 0;
virtual bool OpenVideoDecoder(Adaptive_CencSingleSampleDecrypter* decrypter, const SSD_VIDEOINITDATA *initData) = 0;
virtual SSD_DECODE_RETVAL DecodeVideo(void* instance, SSD_SAMPLE *sample, SSD_PICTURE *picture) = 0;
virtual void ResetVideo() = 0;
};
Expand Down
20 changes: 20 additions & 0 deletions src/common/AdaptiveDecrypter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include <bento4/Ap4.h>

enum class ENCRYPTION_SCHEME
{
NONE,
CENC,
CBCS
};

class Adaptive_CencSingleSampleDecrypter : public AP4_CencSingleSampleDecrypter
{
public:

Adaptive_CencSingleSampleDecrypter() : AP4_CencSingleSampleDecrypter(0) {};

void SetCrypto(AP4_UI08 cryptBlocks, AP4_UI08 skipBlocks) { m_CryptBlocks = cryptBlocks; m_SkipBlocks = skipBlocks; };
virtual void SetEncryptionScheme(ENCRYPTION_SCHEME encryptionScheme) {};
AP4_UI08 m_CryptBlocks = 0;
AP4_UI08 m_SkipBlocks = 0;
};
26 changes: 20 additions & 6 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1113,7 +1113,7 @@ class ATTR_DLL_LOCAL FragmentedSampleReader : public SampleReader, public AP4_Li
AP4_Movie* movie,
AP4_Track* track,
AP4_UI32 streamId,
AP4_CencSingleSampleDecrypter* ssd,
Adaptive_CencSingleSampleDecrypter* ssd,
const SSD::SSD_DECRYPTER::SSD_CAPS& dcaps)
: AP4_LinearReader(*movie, input),
m_track(track),
Expand Down Expand Up @@ -1492,6 +1492,20 @@ class ATTR_DLL_LOCAL FragmentedSampleReader : public SampleReader, public AP4_Li
AP4_CencSampleDecrypter::Create(sample_table, algorithm_id, 0, 0, 0, reset_iv,
m_singleSampleDecryptor, m_decrypter)))
return result;

// Inform decrypter of pattern decryption (CBCS)
AP4_UI08 cryptBlocks = sample_table->GetCryptByteBlock();
AP4_UI08 skipBlocks = sample_table->GetSkipByteBlock();

if (cryptBlocks > 0 && skipBlocks > 0)
{
m_singleSampleDecryptor->SetCrypto(cryptBlocks, skipBlocks);
m_singleSampleDecryptor->SetEncryptionScheme(ENCRYPTION_SCHEME::CBCS);
}
else if (m_protectedDesc->GetSchemeType() == AP4_PROTECTION_SCHEME_TYPE_CBCS)
m_singleSampleDecryptor->SetEncryptionScheme(ENCRYPTION_SCHEME::CBCS);
else
m_singleSampleDecryptor->SetEncryptionScheme(ENCRYPTION_SCHEME::CENC);
}
}
SUCCESS:
Expand Down Expand Up @@ -1575,7 +1589,7 @@ class ATTR_DLL_LOCAL FragmentedSampleReader : public SampleReader, public AP4_Li
const AP4_UI08* m_defaultKey;

AP4_ProtectedSampleDescription* m_protectedDesc;
AP4_CencSingleSampleDecrypter* m_singleSampleDecryptor;
Adaptive_CencSingleSampleDecrypter* m_singleSampleDecryptor;
AP4_CencSampleDecrypter* m_decrypter;
uint64_t m_nextDuration, m_nextTimestamp;
};
Expand Down Expand Up @@ -2700,14 +2714,14 @@ bool Session::InitializeDRM()
AP4_FormatHex(reinterpret_cast<const AP4_UI08*>(defkid), 16, hexkid), hexkid[32] = 0;
kodi::Log(ADDON_LOG_DEBUG, "Initializing stream with KID: %s", hexkid);

for (unsigned int i(1); i < ses; ++i)
/*for (unsigned int i(1); i < ses; ++i)
if (decrypter_->HasLicenseKey(cdm_sessions_[i].single_sample_decryptor_,
(const uint8_t*)defkid))
{
session.single_sample_decryptor_ = cdm_sessions_[i].single_sample_decryptor_;
session.shared_single_sample_decryptor_ = true;
break;
}
}*/
}
else if (!defkid)
{
Expand Down Expand Up @@ -3296,7 +3310,7 @@ const AP4_UI08* Session::GetDefaultKeyId(const uint16_t index) const
return default_key;
}

AP4_CencSingleSampleDecrypter* Session::GetSingleSampleDecrypter(std::string sessionId)
Adaptive_CencSingleSampleDecrypter* Session::GetSingleSampleDecrypter(std::string sessionId)
{
for (std::vector<CDMSESSION>::iterator b(cdm_sessions_.begin() + 1), e(cdm_sessions_.end());
b != e; ++b)
Expand Down Expand Up @@ -4151,7 +4165,7 @@ bool CVideoCodecAdaptive::Open(const kodi::addon::VideoCodecInitdata& initData)
m_name += ".decoder";

std::string sessionId(initData.GetCryptoSession().GetSessionId());
AP4_CencSingleSampleDecrypter* ssd(m_session->GetSingleSampleDecrypter(sessionId));
Adaptive_CencSingleSampleDecrypter* ssd(m_session->GetSingleSampleDecrypter(sessionId));

return m_session->GetDecrypter()->OpenVideoDecoder(
ssd, reinterpret_cast<const SSD::SSD_VIDEOINITDATA*>(initData.GetCStructure()));
Expand Down
7 changes: 4 additions & 3 deletions src/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <kodi/addon-instance/Inputstream.h>
#include <kodi/tools/DllHelper.h>

#include "common/AdaptiveDecrypter.h"
#include "common/AdaptiveTree.h"
#include "common/AdaptiveStream.h"
#include "common/RepresentationChooser.h"
Expand Down Expand Up @@ -164,9 +165,9 @@ class ATTR_DLL_LOCAL Session : public adaptive::AdaptiveStreamObserver
unsigned int GetStreamCount() const { return streams_.size(); };
const char *GetCDMSession(int nSet) { return cdm_sessions_[nSet].cdm_session_str_; };;
uint8_t GetMediaTypeMask() const { return media_type_mask_; };
AP4_CencSingleSampleDecrypter * GetSingleSampleDecryptor(unsigned int nIndex)const{ return cdm_sessions_[nIndex].single_sample_decryptor_; };
Adaptive_CencSingleSampleDecrypter * GetSingleSampleDecryptor(unsigned int nIndex)const{ return cdm_sessions_[nIndex].single_sample_decryptor_; };
SSD::SSD_DECRYPTER *GetDecrypter() { return decrypter_; };
AP4_CencSingleSampleDecrypter *GetSingleSampleDecrypter(std::string sessionId);
Adaptive_CencSingleSampleDecrypter *GetSingleSampleDecrypter(std::string sessionId);
const SSD::SSD_DECRYPTER::SSD_CAPS &GetDecrypterCaps(unsigned int nIndex) const{ return cdm_sessions_[nIndex].decrypter_caps_; };
uint64_t GetTotalTimeMs()const { return adaptiveTree_->overallSeconds_ * 1000; };
uint64_t GetElapsedTimeMs()const { return elapsed_time_ / 1000; };
Expand Down Expand Up @@ -219,7 +220,7 @@ class ATTR_DLL_LOCAL Session : public adaptive::AdaptiveStreamObserver
struct CDMSESSION
{
SSD::SSD_DECRYPTER::SSD_CAPS decrypter_caps_;
AP4_CencSingleSampleDecrypter *single_sample_decryptor_;
Adaptive_CencSingleSampleDecrypter *single_sample_decryptor_;
const char* cdm_session_str_ = nullptr;
bool shared_single_sample_decryptor_ = false;
};
Expand Down
55 changes: 38 additions & 17 deletions wvdecrypter/wvdecrypter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "../src/helpers.h"
#include "../src/SSD_dll.h"
#include "../src/md5.h"
#include "../src/common/AdaptiveDecrypter.h"
#include "jsmn.h"
#include <bento4/Ap4.h>

Expand Down Expand Up @@ -165,14 +166,15 @@ class CdmFixedBuffer : public cdm::Buffer {
+---------------------------------------------------------------------*/
class WV_DRM;

class WV_CencSingleSampleDecrypter : public AP4_CencSingleSampleDecrypter
class WV_CencSingleSampleDecrypter : public Adaptive_CencSingleSampleDecrypter
{
public:
// methods
WV_CencSingleSampleDecrypter(WV_DRM &drm, AP4_DataBuffer &pssh, const uint8_t *defaultKeyId, bool skipSessionMessage);
virtual ~WV_CencSingleSampleDecrypter();

void GetCapabilities(const uint8_t* key, uint32_t media, SSD_DECRYPTER::SSD_CAPS &caps);
void GetCapabilities(const uint8_t* key, uint32_t media, SSD_DECRYPTER::SSD_CAPS &caps);
bool CanDecode(AP4_UI32 pool_id, 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);
virtual const char *GetSessionId() override;
void SetSessionActive();
void CloseSessionId();
Expand Down Expand Up @@ -214,7 +216,9 @@ class WV_CencSingleSampleDecrypter : public AP4_CencSingleSampleDecrypter

bool OpenVideoDecoder(const SSD_VIDEOINITDATA *initData);
SSD_DECODE_RETVAL DecodeVideo(void* hostInstance, SSD_SAMPLE *sample, SSD_PICTURE *picture);
void ResetVideo();
void ResetVideo();

virtual void SetEncryptionScheme(ENCRYPTION_SCHEME encryptionScheme) override;

private:
void CheckLicenseRenewal();
Expand Down Expand Up @@ -254,6 +258,7 @@ class WV_CencSingleSampleDecrypter : public AP4_CencSingleSampleDecrypter

std::list<media::CdmVideoFrame> videoFrames_;
std::mutex renewal_lock_;
cdm::EncryptionScheme m_EncryptionScheme = cdm::EncryptionScheme::kCenc;
};


Expand Down Expand Up @@ -406,8 +411,7 @@ void WV_DRM::OnCDMMessage(const char* session, uint32_t session_size, CDMADPMSG
+---------------------------------------------------------------------*/

WV_CencSingleSampleDecrypter::WV_CencSingleSampleDecrypter(WV_DRM &drm, AP4_DataBuffer &pssh, const uint8_t *defaultKeyId, bool skipSessionMessage)
: AP4_CencSingleSampleDecrypter(0)
, drm_(drm)
: drm_(drm)
, pssh_(pssh)
, hdcp_version_(99)
, hdcp_limit_(0)
Expand Down Expand Up @@ -536,7 +540,6 @@ void WV_CencSingleSampleDecrypter::GetCapabilities(const uint8_t* key, uint32_t
{
AP4_UI32 poolid(AddPool());
fragment_pool_[poolid].key_ = key ? key : reinterpret_cast<const uint8_t*>(keys_.front().keyid.data());

AP4_DataBuffer in, out;
AP4_UI32 encb[2] = { 1,1 };
AP4_UI16 clearb[2] = { 5,5 };
Expand Down Expand Up @@ -1226,9 +1229,9 @@ AP4_Result WV_CencSingleSampleDecrypter::DecryptSampleData(AP4_UI32 pool_id,
cdm_in.key_id = fragInfo.key_;
cdm_in.key_id_size = 16;
cdm_in.subsamples = subsample_buffer_decrypt_;
cdm_in.encryption_scheme = cdm::EncryptionScheme::kCenc;
cdm_in.encryption_scheme = m_EncryptionScheme;
cdm_in.timestamp = 0;
cdm_in.pattern = { 0,0 };
cdm_in.pattern = { m_CryptBlocks, m_SkipBlocks };

CdmBuffer buf((useSingleDecrypt) ? &decrypt_out_ : &data_out);
CdmDecryptedBlock cdm_out;
Expand Down Expand Up @@ -1271,7 +1274,7 @@ bool WV_CencSingleSampleDecrypter::OpenVideoDecoder(const SSD_VIDEOINITDATA *ini
vconfig.format = static_cast<cdm::VideoFormat> (initData->videoFormats[0]);
vconfig.profile = static_cast<cdm::VideoCodecProfile>(initData->codecProfile);
vconfig.color_space = { 2, 2, 2, cdm::ColorRange::kInvalid };
vconfig.encryption_scheme = cdm::EncryptionScheme::kCenc;
vconfig.encryption_scheme = m_EncryptionScheme;

cdm::Status ret = drm_.GetCdmAdapter()->InitializeVideoDecoder(vconfig);
videoFrames_.clear();
Expand Down Expand Up @@ -1320,8 +1323,8 @@ SSD_DECODE_RETVAL WV_CencSingleSampleDecrypter::DecodeVideo(void* hostInstance,
cdm_in.iv = sample->iv;
cdm_in.iv_size = sample->iv ? 16 : 0;
cdm_in.timestamp = sample->pts;
cdm_in.encryption_scheme = sample->kid ? cdm::EncryptionScheme::kCenc : cdm::EncryptionScheme::kUnencrypted;
cdm_in.pattern = { 0,0 };
cdm_in.encryption_scheme = sample->kid ? m_EncryptionScheme : cdm::EncryptionScheme::kUnencrypted;
cdm_in.pattern = { m_CryptBlocks, m_SkipBlocks };

uint8_t unencryptedKID [] = { 0 };
cdm_in.key_id = sample->kid ? sample->kid : unencryptedKID;
Expand Down Expand Up @@ -1407,6 +1410,24 @@ void WV_CencSingleSampleDecrypter::ResetVideo()
drained_ = true;
}

void WV_CencSingleSampleDecrypter::SetEncryptionScheme(ENCRYPTION_SCHEME encryptionScheme)
{
switch (encryptionScheme)
{
case ENCRYPTION_SCHEME::NONE:
m_EncryptionScheme = cdm::EncryptionScheme::kUnencrypted;
break;
case ENCRYPTION_SCHEME::CENC:
m_EncryptionScheme = cdm::EncryptionScheme::kCenc;
break;
case ENCRYPTION_SCHEME::CBCS:
m_EncryptionScheme = cdm::EncryptionScheme::kCbcs;
break;
default:
m_EncryptionScheme = cdm::EncryptionScheme::kCenc;
}
}

/*********************************************************************************************/

class WVDecrypter : public SSD_DECRYPTER
Expand Down Expand Up @@ -1434,7 +1455,7 @@ class WVDecrypter : public SSD_DECRYPTER
return cdmsession_->GetCdmAdapter() != nullptr;
}

virtual AP4_CencSingleSampleDecrypter *CreateSingleSampleDecrypter(AP4_DataBuffer &pssh, const char *optionalKeyParameter, const uint8_t *defaultkeyid, bool skipSessionMessage) override
virtual Adaptive_CencSingleSampleDecrypter *CreateSingleSampleDecrypter(AP4_DataBuffer &pssh, const char *optionalKeyParameter, const uint8_t *defaultkeyid, bool skipSessionMessage) override
{
WV_CencSingleSampleDecrypter *decrypter = new WV_CencSingleSampleDecrypter(*cdmsession_, pssh, defaultkeyid, skipSessionMessage);
if (!decrypter->GetSessionId())
Expand All @@ -1445,7 +1466,7 @@ class WVDecrypter : public SSD_DECRYPTER
return decrypter;
}

virtual void DestroySingleSampleDecrypter(AP4_CencSingleSampleDecrypter* decrypter) override
virtual void DestroySingleSampleDecrypter(Adaptive_CencSingleSampleDecrypter* decrypter) override
{
if (decrypter)
{
Expand All @@ -1455,7 +1476,7 @@ class WVDecrypter : public SSD_DECRYPTER
}
}

virtual void GetCapabilities(AP4_CencSingleSampleDecrypter* decrypter, const uint8_t *keyid, uint32_t media, SSD_DECRYPTER::SSD_CAPS &caps) override
virtual void GetCapabilities(Adaptive_CencSingleSampleDecrypter* decrypter, const uint8_t *keyid, uint32_t media, SSD_DECRYPTER::SSD_CAPS &caps) override
{
if (!decrypter)
{
Expand All @@ -1466,7 +1487,7 @@ class WVDecrypter : public SSD_DECRYPTER
static_cast<WV_CencSingleSampleDecrypter*>(decrypter)->GetCapabilities(keyid, media, caps);
}

virtual bool HasLicenseKey(AP4_CencSingleSampleDecrypter* decrypter, const uint8_t *keyid) override
virtual bool HasLicenseKey(Adaptive_CencSingleSampleDecrypter* decrypter, const uint8_t *keyid) override
{
if (decrypter)
return static_cast<WV_CencSingleSampleDecrypter*>(decrypter)->HasKeyId(keyid);
Expand All @@ -1478,7 +1499,7 @@ class WVDecrypter : public SSD_DECRYPTER
return cdmsession_ != nullptr;
}

virtual std::string GetChallengeB64Data(AP4_CencSingleSampleDecrypter* decrypter) override
virtual std::string GetChallengeB64Data(Adaptive_CencSingleSampleDecrypter* decrypter) override
{
if (!decrypter)
return nullptr;
Expand All @@ -1488,7 +1509,7 @@ class WVDecrypter : public SSD_DECRYPTER
return b64_encode(challengeData.GetData(), challengeData.GetDataSize(), true);
}

virtual bool OpenVideoDecoder(AP4_CencSingleSampleDecrypter* decrypter, const SSD_VIDEOINITDATA *initData) override
virtual bool OpenVideoDecoder(Adaptive_CencSingleSampleDecrypter* decrypter, const SSD_VIDEOINITDATA *initData) override
{
if (!decrypter || !initData)
return false;
Expand Down

0 comments on commit da26852

Please sign in to comment.