From 07c1dd125ca68c9baa705ce1ccaf5c1600e40b91 Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Mon, 8 Jan 2024 17:46:10 +0200 Subject: [PATCH 01/17] Add pssh boxes generate function --- include/packager/live_packager.h | 18 ++++++++++ packager/live_packager.cc | 61 ++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) diff --git a/include/packager/live_packager.h b/include/packager/live_packager.h index 16d03004ea7..744cb332734 100644 --- a/include/packager/live_packager.h +++ b/include/packager/live_packager.h @@ -7,7 +7,9 @@ #ifndef PACKAGER_LIVE_PACKAGER_H_ #define PACKAGER_LIVE_PACKAGER_H_ +#include #include + #include #include @@ -86,8 +88,24 @@ struct LiveConfig { std::vector key; std::vector key_id; EncryptionScheme protection_scheme; + + bool include_pssh; +}; + +struct PSSHData { + std::vector cenc_box; + std::vector mspr_box; + std::vector wv_box; }; +struct KeyData { + std::vector curr_key; + std::vector curr_key_id; + std::vector> all_key_ids; +}; + +Status GeneratePSSHData(PSSHData* data, const std::vector& all_keys, const KeyData& current_key, media::FourCC encryption_scheme); + class LivePackager { public: LivePackager(const LiveConfig& config); diff --git a/packager/live_packager.cc b/packager/live_packager.cc index 44b1251c23c..f6a96f1d248 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -15,10 +15,18 @@ #include #include #include + +#include #include #include #include +#include "media/base/common_pssh_generator.h" +#include "media/base/playready_pssh_generator.h" +#include "media/base/protection_system_ids.h" +#include "media/base/pssh_generator.h" +#include "media/base/widevine_pssh_generator.h" + namespace shaka { namespace { @@ -296,6 +304,59 @@ Status LivePackager::Package(const Segment& in, FullSegmentBuffer& out) { return packager.Run(); } +void AddProtectionSystem( + const media::ProtectionSystemSpecificInfo& pssh_info, + PSSHData* data) { + if (const std::vector common_system_id( + media::kCommonSystemId, + media::kCommonSystemId + std::size(media::kCommonSystemId)); + pssh_info.system_id == common_system_id) { + data->cenc_box = pssh_info.psshs; + return; + } + + if (const std::vector widevine_system_id( + media::kWidevineSystemId, + media::kWidevineSystemId + std::size(media::kWidevineSystemId)); + pssh_info.system_id == widevine_system_id) { + data->wv_box = pssh_info.psshs; + return; + } + + if (const std::vector playready_system_id( + media::kPlayReadySystemId, + media::kPlayReadySystemId + std::size(media::kPlayReadySystemId)); + pssh_info.system_id == playready_system_id) { + data->wv_box = pssh_info.psshs; + } +} + +Status GeneratePSSHData( + PSSHData* data, const KeyData& encryption_key, uint32_t protection_scheme) { + std::vector> pssh_generators; + pssh_generators.emplace_back(new media::CommonPsshGenerator()); + pssh_generators.emplace_back(new media::PlayReadyPsshGenerator( + "", static_cast(protection_scheme))); + pssh_generators.emplace_back(new media::WidevinePsshGenerator(static_cast(protection_scheme))); + + for (const auto& pssh_generator : pssh_generators) { + const bool support_multiple_keys = pssh_generator->SupportMultipleKeys(); + if (support_multiple_keys) { + media::ProtectionSystemSpecificInfo info; + RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIds( + encryption_key.all_key_ids, &info)); + AddProtectionSystem(info, data); + } else { + media::ProtectionSystemSpecificInfo info; + RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIdAndKey( + encryption_key.curr_key_id, encryption_key.curr_key, &info)); + AddProtectionSystem(info, data); + } + } + + return Status::OK; +} + SegmentManager::SegmentManager() = default; int64_t SegmentManager::OnSegmentWrite(const std::string& name, From 758f3e0134706de9aafc8799df0ecb8f17da0269 Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Mon, 8 Jan 2024 17:48:23 +0200 Subject: [PATCH 02/17] Fix header --- include/packager/live_packager.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/include/packager/live_packager.h b/include/packager/live_packager.h index 744cb332734..d16a8c16299 100644 --- a/include/packager/live_packager.h +++ b/include/packager/live_packager.h @@ -7,12 +7,8 @@ #ifndef PACKAGER_LIVE_PACKAGER_H_ #define PACKAGER_LIVE_PACKAGER_H_ -#include #include -#include -#include - namespace shaka { class Segment { @@ -104,7 +100,7 @@ struct KeyData { std::vector> all_key_ids; }; -Status GeneratePSSHData(PSSHData* data, const std::vector& all_keys, const KeyData& current_key, media::FourCC encryption_scheme); +Status GeneratePSSHData(PSSHData* data, const std::vector& all_keys, const KeyData& current_key, uint32_t encryption_scheme); class LivePackager { public: From fe3a1fcf8e42d3ee3643810e80638838931c68ee Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Mon, 8 Jan 2024 17:50:43 +0200 Subject: [PATCH 03/17] Add constant val for no headers --- packager/live_packager.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packager/live_packager.cc b/packager/live_packager.cc index f6a96f1d248..90096357e02 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -333,10 +333,12 @@ void AddProtectionSystem( Status GeneratePSSHData( PSSHData* data, const KeyData& encryption_key, uint32_t protection_scheme) { + const std::string no_extra_headers_playready = ""; + std::vector> pssh_generators; pssh_generators.emplace_back(new media::CommonPsshGenerator()); pssh_generators.emplace_back(new media::PlayReadyPsshGenerator( - "", static_cast(protection_scheme))); + no_extra_headers_playready, static_cast(protection_scheme))); pssh_generators.emplace_back(new media::WidevinePsshGenerator(static_cast(protection_scheme))); for (const auto& pssh_generator : pssh_generators) { From 31b809748ce40067fe5ad9bd5ef4b9c54f943efc Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Tue, 9 Jan 2024 14:44:10 +0200 Subject: [PATCH 04/17] Refactor generate function --- include/packager/live_packager.h | 7 +++-- packager/live_packager.cc | 44 ++++++++++---------------------- 2 files changed, 19 insertions(+), 32 deletions(-) diff --git a/include/packager/live_packager.h b/include/packager/live_packager.h index d16a8c16299..9fd86fe259f 100644 --- a/include/packager/live_packager.h +++ b/include/packager/live_packager.h @@ -85,7 +85,7 @@ struct LiveConfig { std::vector key_id; EncryptionScheme protection_scheme; - bool include_pssh; + bool mp4_include_pssh; }; struct PSSHData { @@ -98,9 +98,12 @@ struct KeyData { std::vector curr_key; std::vector curr_key_id; std::vector> all_key_ids; + + // enum for pssh box drm system + // enum for fourcc encryption scheme }; -Status GeneratePSSHData(PSSHData* data, const std::vector& all_keys, const KeyData& current_key, uint32_t encryption_scheme); +Status GeneratePSSHData(const KeyData& encryption_key, uint32_t protection_scheme, PSSHData* data); class LivePackager { public: diff --git a/packager/live_packager.cc b/packager/live_packager.cc index 90096357e02..0815fce1069 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -281,6 +281,7 @@ Status LivePackager::Package(const Segment& in, FullSegmentBuffer& out) { shaka::PackagingParams packaging_params; packaging_params.chunking_params.segment_duration_in_seconds = config_.segment_duration_sec; + packaging_params.mp4_output_params.include_pssh_in_stream = config_.mp4_include_pssh; EncryptionParams& encryption_params = packaging_params.encryption_params; // As a side effect of InitializeEncryption, encryption_params will be @@ -304,56 +305,39 @@ Status LivePackager::Package(const Segment& in, FullSegmentBuffer& out) { return packager.Run(); } -void AddProtectionSystem( - const media::ProtectionSystemSpecificInfo& pssh_info, - PSSHData* data) { - if (const std::vector common_system_id( - media::kCommonSystemId, - media::kCommonSystemId + std::size(media::kCommonSystemId)); - pssh_info.system_id == common_system_id) { +void FillPSSHBoxByDRM(const media::ProtectionSystemSpecificInfo& pssh_info, PSSHData* data) { + if (std::equal(std::begin(media::kCommonSystemId), std::end(media::kCommonSystemId), pssh_info.system_id.begin())) { data->cenc_box = pssh_info.psshs; return; } - if (const std::vector widevine_system_id( - media::kWidevineSystemId, - media::kWidevineSystemId + std::size(media::kWidevineSystemId)); - pssh_info.system_id == widevine_system_id) { + if (std::equal(std::begin(media::kWidevineSystemId), std::end(media::kWidevineSystemId), pssh_info.system_id.begin())) { data->wv_box = pssh_info.psshs; return; } - if (const std::vector playready_system_id( - media::kPlayReadySystemId, - media::kPlayReadySystemId + std::size(media::kPlayReadySystemId)); - pssh_info.system_id == playready_system_id) { - data->wv_box = pssh_info.psshs; + if (std::equal(std::begin(media::kPlayReadySystemId), std::end(media::kPlayReadySystemId), pssh_info.system_id.begin())) { + data->mspr_box = pssh_info.psshs; } } -Status GeneratePSSHData( - PSSHData* data, const KeyData& encryption_key, uint32_t protection_scheme) { - const std::string no_extra_headers_playready = ""; +Status GeneratePSSHData(const KeyData& encryption_key, uint32_t protection_scheme, PSSHData* data) { + const char* kNoExtraHeadersForPlayReady = ""; std::vector> pssh_generators; pssh_generators.emplace_back(new media::CommonPsshGenerator()); pssh_generators.emplace_back(new media::PlayReadyPsshGenerator( - no_extra_headers_playready, static_cast(protection_scheme))); + kNoExtraHeadersForPlayReady, static_cast(protection_scheme))); pssh_generators.emplace_back(new media::WidevinePsshGenerator(static_cast(protection_scheme))); for (const auto& pssh_generator : pssh_generators) { - const bool support_multiple_keys = pssh_generator->SupportMultipleKeys(); - if (support_multiple_keys) { - media::ProtectionSystemSpecificInfo info; - RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIds( - encryption_key.all_key_ids, &info)); - AddProtectionSystem(info, data); + media::ProtectionSystemSpecificInfo info; + if (pssh_generator->SupportMultipleKeys()) { + RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIds(encryption_key.all_key_ids, &info)); } else { - media::ProtectionSystemSpecificInfo info; - RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIdAndKey( - encryption_key.curr_key_id, encryption_key.curr_key, &info)); - AddProtectionSystem(info, data); + RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIdAndKey(encryption_key.curr_key_id, encryption_key.curr_key, &info)); } + FillPSSHBoxByDRM(info, data); } return Status::OK; From 71f317aa7e0689e00d2ea71ef0aae21db3532c80 Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Tue, 9 Jan 2024 14:54:03 +0200 Subject: [PATCH 05/17] Appease linter --- packager/live_packager.cc | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/packager/live_packager.cc b/packager/live_packager.cc index 0815fce1069..42abeef2553 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -16,8 +16,8 @@ #include #include -#include #include +#include #include #include @@ -281,7 +281,8 @@ Status LivePackager::Package(const Segment& in, FullSegmentBuffer& out) { shaka::PackagingParams packaging_params; packaging_params.chunking_params.segment_duration_in_seconds = config_.segment_duration_sec; - packaging_params.mp4_output_params.include_pssh_in_stream = config_.mp4_include_pssh; + packaging_params.mp4_output_params.include_pssh_in_stream = + config_.mp4_include_pssh; EncryptionParams& encryption_params = packaging_params.encryption_params; // As a side effect of InitializeEncryption, encryption_params will be @@ -305,37 +306,50 @@ Status LivePackager::Package(const Segment& in, FullSegmentBuffer& out) { return packager.Run(); } -void FillPSSHBoxByDRM(const media::ProtectionSystemSpecificInfo& pssh_info, PSSHData* data) { - if (std::equal(std::begin(media::kCommonSystemId), std::end(media::kCommonSystemId), pssh_info.system_id.begin())) { +void FillPSSHBoxByDRM(const media::ProtectionSystemSpecificInfo& pssh_info, + PSSHData* data) { + if (std::equal(std::begin(media::kCommonSystemId), + std::end(media::kCommonSystemId), + pssh_info.system_id.begin())) { data->cenc_box = pssh_info.psshs; return; } - if (std::equal(std::begin(media::kWidevineSystemId), std::end(media::kWidevineSystemId), pssh_info.system_id.begin())) { + if (std::equal(std::begin(media::kWidevineSystemId), + std::end(media::kWidevineSystemId), + pssh_info.system_id.begin())) { data->wv_box = pssh_info.psshs; return; } - if (std::equal(std::begin(media::kPlayReadySystemId), std::end(media::kPlayReadySystemId), pssh_info.system_id.begin())) { + if (std::equal(std::begin(media::kPlayReadySystemId), + std::end(media::kPlayReadySystemId), + pssh_info.system_id.begin())) { data->mspr_box = pssh_info.psshs; } } -Status GeneratePSSHData(const KeyData& encryption_key, uint32_t protection_scheme, PSSHData* data) { +Status GeneratePSSHData(const KeyData& encryption_key, + uint32_t protection_scheme, + PSSHData* data) { const char* kNoExtraHeadersForPlayReady = ""; std::vector> pssh_generators; pssh_generators.emplace_back(new media::CommonPsshGenerator()); pssh_generators.emplace_back(new media::PlayReadyPsshGenerator( - kNoExtraHeadersForPlayReady, static_cast(protection_scheme))); - pssh_generators.emplace_back(new media::WidevinePsshGenerator(static_cast(protection_scheme))); + kNoExtraHeadersForPlayReady, + static_cast(protection_scheme))); + pssh_generators.emplace_back(new media::WidevinePsshGenerator( + static_cast(protection_scheme))); for (const auto& pssh_generator : pssh_generators) { media::ProtectionSystemSpecificInfo info; if (pssh_generator->SupportMultipleKeys()) { - RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIds(encryption_key.all_key_ids, &info)); + RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIds( + encryption_key.all_key_ids, &info)); } else { - RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIdAndKey(encryption_key.curr_key_id, encryption_key.curr_key, &info)); + RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIdAndKey( + encryption_key.curr_key_id, encryption_key.curr_key, &info)); } FillPSSHBoxByDRM(info, data); } From 5af753f8677a5fb2aafaed5d056663ee80e9335f Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Tue, 9 Jan 2024 15:04:09 +0200 Subject: [PATCH 06/17] Appease linter --- include/packager/live_packager.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/packager/live_packager.h b/include/packager/live_packager.h index 9fd86fe259f..b298b6ddb8e 100644 --- a/include/packager/live_packager.h +++ b/include/packager/live_packager.h @@ -103,7 +103,9 @@ struct KeyData { // enum for fourcc encryption scheme }; -Status GeneratePSSHData(const KeyData& encryption_key, uint32_t protection_scheme, PSSHData* data); +Status GeneratePSSHData(const KeyData& encryption_key, + uint32_t protection_scheme, + PSSHData* data); class LivePackager { public: From a01d8b573ae791e03203b0edef148cce84bb8f2a Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Wed, 10 Jan 2024 17:39:36 +0200 Subject: [PATCH 07/17] Add tests --- include/packager/live_packager.h | 49 +++++++---- packager/live_packager.cc | 145 ++++++++++++++++++++----------- packager/live_packager_test.cc | 95 ++++++++++++++++++++ 3 files changed, 219 insertions(+), 70 deletions(-) diff --git a/include/packager/live_packager.h b/include/packager/live_packager.h index b298b6ddb8e..d42b50dc657 100644 --- a/include/packager/live_packager.h +++ b/include/packager/live_packager.h @@ -88,25 +88,6 @@ struct LiveConfig { bool mp4_include_pssh; }; -struct PSSHData { - std::vector cenc_box; - std::vector mspr_box; - std::vector wv_box; -}; - -struct KeyData { - std::vector curr_key; - std::vector curr_key_id; - std::vector> all_key_ids; - - // enum for pssh box drm system - // enum for fourcc encryption scheme -}; - -Status GeneratePSSHData(const KeyData& encryption_key, - uint32_t protection_scheme, - PSSHData* data); - class LivePackager { public: LivePackager(const LiveConfig& config); @@ -134,6 +115,36 @@ class LivePackager { LiveConfig config_; }; +struct PSSHData { + std::vector cenc_box; + std::vector mspr_box; + std::vector mspr_pro; + std::vector wv_box; +}; + +enum struct EncryptionSchemeFourCC: uint32_t { + CBCS = 0x63626373, + CENC = 0x63656e63, +}; + +struct PSSHGeneratorInput { + EncryptionSchemeFourCC encryption_scheme; + + // key of a single adaption set for DRM systems that don't support + // multile keys (i.e PlayReady) + std::vector key; + // key id of the key for DRM systems that don't support + // multile keys (i.e PlayReady) + std::vector key_id; + // key ids of all adaptation sets for DRM systems that support + // multiple keys (i.e Widevine, Common Encryption) + std::vector> key_ids; + + Status Validate() const; +}; + +Status GeneratePSSHData(const PSSHGeneratorInput& in, PSSHData* out); + } // namespace shaka #endif // PACKAGER_LIVE_PACKAGER_H_ diff --git a/packager/live_packager.cc b/packager/live_packager.cc index 42abeef2553..510dd55813b 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -306,57 +306,6 @@ Status LivePackager::Package(const Segment& in, FullSegmentBuffer& out) { return packager.Run(); } -void FillPSSHBoxByDRM(const media::ProtectionSystemSpecificInfo& pssh_info, - PSSHData* data) { - if (std::equal(std::begin(media::kCommonSystemId), - std::end(media::kCommonSystemId), - pssh_info.system_id.begin())) { - data->cenc_box = pssh_info.psshs; - return; - } - - if (std::equal(std::begin(media::kWidevineSystemId), - std::end(media::kWidevineSystemId), - pssh_info.system_id.begin())) { - data->wv_box = pssh_info.psshs; - return; - } - - if (std::equal(std::begin(media::kPlayReadySystemId), - std::end(media::kPlayReadySystemId), - pssh_info.system_id.begin())) { - data->mspr_box = pssh_info.psshs; - } -} - -Status GeneratePSSHData(const KeyData& encryption_key, - uint32_t protection_scheme, - PSSHData* data) { - const char* kNoExtraHeadersForPlayReady = ""; - - std::vector> pssh_generators; - pssh_generators.emplace_back(new media::CommonPsshGenerator()); - pssh_generators.emplace_back(new media::PlayReadyPsshGenerator( - kNoExtraHeadersForPlayReady, - static_cast(protection_scheme))); - pssh_generators.emplace_back(new media::WidevinePsshGenerator( - static_cast(protection_scheme))); - - for (const auto& pssh_generator : pssh_generators) { - media::ProtectionSystemSpecificInfo info; - if (pssh_generator->SupportMultipleKeys()) { - RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIds( - encryption_key.all_key_ids, &info)); - } else { - RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIdAndKey( - encryption_key.curr_key_id, encryption_key.curr_key, &info)); - } - FillPSSHBoxByDRM(info, data); - } - - return Status::OK; -} - SegmentManager::SegmentManager() = default; int64_t SegmentManager::OnSegmentWrite(const std::string& name, @@ -443,4 +392,98 @@ Status Aes128EncryptedSegmentManager::InitializeEncryption( } return Status::OK; } + +void FillPSSHBoxByDRM(const media::ProtectionSystemSpecificInfo& pssh_info, + PSSHData* data) { + if (std::equal(std::begin(media::kCommonSystemId), + std::end(media::kCommonSystemId), + pssh_info.system_id.begin())) { + data->cenc_box = pssh_info.psshs; + return; + } + + if (std::equal(std::begin(media::kWidevineSystemId), + std::end(media::kWidevineSystemId), + pssh_info.system_id.begin())) { + data->wv_box = pssh_info.psshs; + return; + } + + if (std::equal(std::begin(media::kPlayReadySystemId), + std::end(media::kPlayReadySystemId), + pssh_info.system_id.begin())) { + data->mspr_box = pssh_info.psshs; + + std::unique_ptr box_builder = media::PsshBoxBuilder::ParseFromBox(pssh_info.psshs.data(), pssh_info.psshs.size()); + data->mspr_pro = box_builder->pssh_data(); + } +} + +Status PSSHGeneratorInput::Validate() const { + if (encryption_scheme != EncryptionSchemeFourCC::CBCS && encryption_scheme != EncryptionSchemeFourCC::CENC) { + LOG(WARNING) << "invalid encryption scheme in PSSH generator input"; + return Status(error::INVALID_ARGUMENT, + "invalid encryption scheme in PSSH generator input"); + } + + if (key.size() != 16) { + LOG(WARNING) << "invalid key lenght in PSSH generator input"; + return Status(error::INVALID_ARGUMENT, + "invalid key lenght in PSSH generator input"); + } + + if (key_id.size() != 16) { + LOG(WARNING) << "invalid key id lenght in PSSH generator input"; + return Status(error::INVALID_ARGUMENT, + "invalid key id lenght in PSSH generator input"); + } + + if (key_ids.empty()) { + LOG(WARNING) << "key ids cannot be empty in PSSH generator input"; + return Status(error::INVALID_ARGUMENT, + "key ids cannot be empty in PSSH generator input"); + } + + for (size_t i = 0; i < key_ids.size(); ++i) { + if (key_ids[i].size() != 16) { + LOG(WARNING) << "invalid key id lenght in key ids array in PSSH generator input, index " + std::to_string(i); + return Status(error::INVALID_ARGUMENT, + "invalid key id lenght in key ids array in PSSH generator input, index " + std::to_string(i)); + } + } + + return Status::OK; +} + +Status GeneratePSSHData(const PSSHGeneratorInput& in, PSSHData* out) { + const char* kNoExtraHeadersForPlayReady = ""; + + RETURN_IF_ERROR(in.Validate()); + if (!out) { + return Status(error::INVALID_ARGUMENT, + "output data cannot be null"); + } + + std::vector> pssh_generators; + pssh_generators.emplace_back(new media::CommonPsshGenerator()); + pssh_generators.emplace_back(new media::PlayReadyPsshGenerator( + kNoExtraHeadersForPlayReady, + static_cast(in.encryption_scheme))); + pssh_generators.emplace_back(new media::WidevinePsshGenerator( + static_cast(in.encryption_scheme))); + + for (const auto& pssh_generator : pssh_generators) { + media::ProtectionSystemSpecificInfo info; + if (pssh_generator->SupportMultipleKeys()) { + RETURN_IF_ERROR( + pssh_generator->GeneratePsshFromKeyIds(in.key_ids, &info)); + } else { + RETURN_IF_ERROR(pssh_generator->GeneratePsshFromKeyIdAndKey( + in.key_id, in.key, &info)); + } + FillPSSHBoxByDRM(info, out); + } + + return Status::OK; +} } // namespace shaka diff --git a/packager/live_packager_test.cc b/packager/live_packager_test.cc index 40404c4467a..330e4dde872 100644 --- a/packager/live_packager_test.cc +++ b/packager/live_packager_test.cc @@ -17,6 +17,8 @@ #include #include +#include "absl/strings/escaping.h" + namespace shaka { namespace { @@ -59,8 +61,101 @@ std::vector ReadTestDataFile(const std::string& name) { return data; } + +uint8_t hex_char_to_int(const char& c) { + unsigned result = 0; + if (c >= '0' && c <= '9') { + result = c - '0'; + } else if (c >= 'A' && c <= 'F') { + result = c - 'A' + 10; + } else if (c >= 'a' && c <= 'f') { + result = c - 'a' + 10; + } else { + throw std::out_of_range("input character is out of hex range"); + } + + return result; +} + +std::vector unhex(const std::string& in) { + std::vector out; + for (std::size_t i = 1; i < in.size(); i+=2) { + out.push_back(16 * hex_char_to_int(in[i-1]) +hex_char_to_int(in[i])); + } + + return out; +} + +std::vector unbase64(const std::string& base64_string) { + std::string str; + std::vector bytes; + if (!absl::Base64Unescape(base64_string, &str)) { + return {}; + } + + bytes.assign(str.begin(), str.end()); + return bytes; +} + } // namespace +TEST(GeneratePSSHData, GeneratesPSSHBoxesAndMSPRObject) { + PSSHGeneratorInput in{ + .encryption_scheme = EncryptionSchemeFourCC::CENC, + .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), + .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), + .key_ids = { + unhex("00000000621f2afe7ab2c868d5fd2e2e"), + unhex("00000000621f2afe7ab2c868d5fd2e2f") + } + }; + + PSSHData expected{ + .cenc_box = unbase64("AAAARHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAIAAAAAYh8q/nqyyGjV/S4uAAAAAGIfKv56ssho1f0uLwAAAAA="), + .mspr_box = unbase64("AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBBAEEAQQBBAEEAQgA5AGkALwBpAHAANgBzAHMAaABvADEAZgAwAHUATABnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+ADQAZgB1AEIAdABEAFUAKwBLAGsARQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA=="), + .mspr_pro = unbase64("BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AQQBBAEEAQQBBAEIAOQBpAC8AaQBwADYAcwBzAGgAbwAxAGYAMAB1AEwAZwA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgA0AGYAdQBCAHQARABVACsASwBrAEUAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA="), + .wv_box = unbase64("AAAASnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAACoSEAAAAABiHyr+erLIaNX9Li4SEAAAAABiHyr+erLIaNX9Li9I49yVmwY=") + }; + PSSHData actual {}; + + ASSERT_EQ(Status::OK, GeneratePSSHData(in, &actual)); + ASSERT_EQ(expected.cenc_box, actual.cenc_box); + ASSERT_EQ(expected.mspr_box, actual.mspr_box); + ASSERT_EQ(expected.mspr_pro, actual.mspr_pro); + ASSERT_EQ(expected.wv_box, actual.wv_box); +} + +TEST(GeneratePSSHData, FailsOnInvalidInput) { + const PSSHGeneratorInput valid_input{ + .encryption_scheme = EncryptionSchemeFourCC::CENC, + .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), + .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), + .key_ids = { + unhex("00000000621f2afe7ab2c868d5fd2e2e"), + unhex("00000000621f2afe7ab2c868d5fd2e2f") + } + }; + + PSSHGeneratorInput in; + ASSERT_EQ(Status(error::INVALID_ARGUMENT, "invalid encryption scheme in PSSH generator input"), GeneratePSSHData(in, nullptr)); + + in.encryption_scheme = valid_input.encryption_scheme; + ASSERT_EQ(Status(error::INVALID_ARGUMENT, "invalid key lenght in PSSH generator input"), GeneratePSSHData(in, nullptr)); + + in.key = valid_input.key; + ASSERT_EQ(Status(error::INVALID_ARGUMENT, "invalid key id lenght in PSSH generator input"), GeneratePSSHData(in, nullptr)); + + in.key_id = valid_input.key_id; + ASSERT_EQ(Status(error::INVALID_ARGUMENT, "key ids cannot be empty in PSSH generator input"), GeneratePSSHData(in, nullptr)); + + in.key_ids = valid_input.key_ids; + in.key_ids[1] = {}; + ASSERT_EQ(Status(error::INVALID_ARGUMENT, "invalid key id lenght in key ids array in PSSH generator input, index 1"), GeneratePSSHData(in, nullptr)); + + in.key_ids = valid_input.key_ids; + ASSERT_EQ(Status(error::INVALID_ARGUMENT, "output data cannot be null"), GeneratePSSHData(in, nullptr)); +} + class LivePackagerBaseTest : public ::testing::Test { public: void SetUp() override { From 21896f8621ac45b2d848abf93c1334eb6ef62568 Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Wed, 10 Jan 2024 17:45:29 +0200 Subject: [PATCH 08/17] Appease linter --- include/packager/live_packager.h | 2 +- packager/live_packager.cc | 18 ++++-- packager/live_packager_test.cc | 94 +++++++++++++++++++++----------- 3 files changed, 76 insertions(+), 38 deletions(-) diff --git a/include/packager/live_packager.h b/include/packager/live_packager.h index 83af3efd53e..d7a119f282d 100644 --- a/include/packager/live_packager.h +++ b/include/packager/live_packager.h @@ -132,7 +132,7 @@ struct PSSHData { std::vector wv_box; }; -enum struct EncryptionSchemeFourCC: uint32_t { +enum struct EncryptionSchemeFourCC : uint32_t { CBCS = 0x63626373, CENC = 0x63656e63, }; diff --git a/packager/live_packager.cc b/packager/live_packager.cc index d89f32d71ef..bacae7624ab 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -450,13 +450,16 @@ void FillPSSHBoxByDRM(const media::ProtectionSystemSpecificInfo& pssh_info, pssh_info.system_id.begin())) { data->mspr_box = pssh_info.psshs; - std::unique_ptr box_builder = media::PsshBoxBuilder::ParseFromBox(pssh_info.psshs.data(), pssh_info.psshs.size()); + std::unique_ptr box_builder = + media::PsshBoxBuilder::ParseFromBox(pssh_info.psshs.data(), + pssh_info.psshs.size()); data->mspr_pro = box_builder->pssh_data(); } } Status PSSHGeneratorInput::Validate() const { - if (encryption_scheme != EncryptionSchemeFourCC::CBCS && encryption_scheme != EncryptionSchemeFourCC::CENC) { + if (encryption_scheme != EncryptionSchemeFourCC::CBCS && + encryption_scheme != EncryptionSchemeFourCC::CENC) { LOG(WARNING) << "invalid encryption scheme in PSSH generator input"; return Status(error::INVALID_ARGUMENT, "invalid encryption scheme in PSSH generator input"); @@ -482,9 +485,13 @@ Status PSSHGeneratorInput::Validate() const { for (size_t i = 0; i < key_ids.size(); ++i) { if (key_ids[i].size() != 16) { - LOG(WARNING) << "invalid key id lenght in key ids array in PSSH generator input, index " + std::to_string(i); + LOG(WARNING) << "invalid key id lenght in key ids array in PSSH " + "generator input, index " + + std::to_string(i); return Status(error::INVALID_ARGUMENT, - "invalid key id lenght in key ids array in PSSH generator input, index " + std::to_string(i)); + "invalid key id lenght in key ids array in PSSH generator " + "input, index " + + std::to_string(i)); } } @@ -496,8 +503,7 @@ Status GeneratePSSHData(const PSSHGeneratorInput& in, PSSHData* out) { RETURN_IF_ERROR(in.Validate()); if (!out) { - return Status(error::INVALID_ARGUMENT, - "output data cannot be null"); + return Status(error::INVALID_ARGUMENT, "output data cannot be null"); } std::vector> pssh_generators; diff --git a/packager/live_packager_test.cc b/packager/live_packager_test.cc index a5f274ab299..851629466ff 100644 --- a/packager/live_packager_test.cc +++ b/packager/live_packager_test.cc @@ -81,8 +81,8 @@ uint8_t hex_char_to_int(const char& c) { std::vector unhex(const std::string& in) { std::vector out; - for (std::size_t i = 1; i < in.size(); i+=2) { - out.push_back(16 * hex_char_to_int(in[i-1]) +hex_char_to_int(in[i])); + for (std::size_t i = 1; i < in.size(); i += 2) { + out.push_back(16 * hex_char_to_int(in[i - 1]) + hex_char_to_int(in[i])); } return out; @@ -273,23 +273,46 @@ void CheckSegment(const LiveConfig& config, const FullSegmentBuffer& buffer) { } // namespace TEST(GeneratePSSHData, GeneratesPSSHBoxesAndMSPRObject) { - PSSHGeneratorInput in{ - .encryption_scheme = EncryptionSchemeFourCC::CENC, - .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), - .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), - .key_ids = { - unhex("00000000621f2afe7ab2c868d5fd2e2e"), - unhex("00000000621f2afe7ab2c868d5fd2e2f") - } - }; + PSSHGeneratorInput in{.encryption_scheme = EncryptionSchemeFourCC::CENC, + .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), + .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), + .key_ids = {unhex("00000000621f2afe7ab2c868d5fd2e2e"), + unhex("00000000621f2afe7ab2c868d5fd2e2f")}}; PSSHData expected{ - .cenc_box = unbase64("AAAARHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAIAAAAAYh8q/nqyyGjV/S4uAAAAAGIfKv56ssho1f0uLwAAAAA="), - .mspr_box = unbase64("AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBIAEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0AYQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAvADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkAbwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQAPgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBOAEYATwA+ADwASwBJAEQAPgBBAEEAQQBBAEEAQgA5AGkALwBpAHAANgBzAHMAaABvADEAZgAwAHUATABnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+ADQAZgB1AEIAdABEAFUAKwBLAGsARQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8ARABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA=="), - .mspr_pro = unbase64("BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0ALwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBkAGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEAVABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2ADwALwBLAEUAWQBMAEUATgA+ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AQQBBAEEAQQBBAEIAOQBpAC8AaQBwADYAcwBzAGgAbwAxAGYAMAB1AEwAZwA9AD0APAAvAEsASQBEAD4APABDAEgARQBDAEsAUwBVAE0APgA0AGYAdQBCAHQARABVACsASwBrAEUAPQA8AC8AQwBIAEUAQwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA="), - .wv_box = unbase64("AAAASnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAACoSEAAAAABiHyr+erLIaNX9Li4SEAAAAABiHyr+erLIaNX9Li9I49yVmwY=") - }; - PSSHData actual {}; + .cenc_box = unbase64("AAAARHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAIAAAAAYh8" + "q/nqyyGjV/S4uAAAAAGIfKv56ssho1f0uLwAAAAA="), + .mspr_box = unbase64( + "AAACJnBzc2gAAAAAmgTweZhAQoarkuZb4IhflQAAAgYGAgAAAQABAPwBPABXAFIATQBI" + "AEUAQQBEAEUAUgAgAHgAbQBsAG4AcwA9ACIAaAB0AHQAcAA6AC8ALwBzAGMAaABlAG0A" + "YQBzAC4AbQBpAGMAcgBvAHMAbwBmAHQALgBjAG8AbQAvAEQAUgBNAC8AMgAwADAANwAv" + "ADAAMwAvAFAAbABhAHkAUgBlAGEAZAB5AEgAZQBhAGQAZQByACIAIAB2AGUAcgBzAGkA" + "bwBuAD0AIgA0AC4AMAAuADAALgAwACIAPgA8AEQAQQBUAEEAPgA8AFAAUgBPAFQARQBD" + "AFQASQBOAEYATwA+" + "ADwASwBFAFkATABFAE4APgAxADYAPAAvAEsARQBZAEwARQBOAD4APABBAEwARwBJAEQA" + "PgBBAEUAUwBDAFQAUgA8AC8AQQBMAEcASQBEAD4APAAvAFAAUgBPAFQARQBDAFQASQBO" + "AEYATwA+" + "ADwASwBJAEQAPgBBAEEAQQBBAEEAQgA5AGkALwBpAHAANgBzAHMAaABvADEAZgAwAHUA" + "TABnAD0APQA8AC8ASwBJAEQAPgA8AEMASABFAEMASwBTAFUATQA+" + "ADQAZgB1AEIAdABEAFUAKwBLAGsARQA9ADwALwBDAEgARQBDAEsAUwBVAE0APgA8AC8A" + "RABBAFQAQQA+ADwALwBXAFIATQBIAEUAQQBEAEUAUgA+AA=="), + .mspr_pro = unbase64( + "BgIAAAEAAQD8ATwAVwBSAE0ASABFAEEARABFAFIAIAB4AG0AbABuAHMAPQAiAGgAdAB0" + "AHAAOgAvAC8AcwBjAGgAZQBtAGEAcwAuAG0AaQBjAHIAbwBzAG8AZgB0AC4AYwBvAG0A" + "LwBEAFIATQAvADIAMAAwADcALwAwADMALwBQAGwAYQB5AFIAZQBhAGQAeQBIAGUAYQBk" + "AGUAcgAiACAAdgBlAHIAcwBpAG8AbgA9ACIANAAuADAALgAwAC4AMAAiAD4APABEAEEA" + "VABBAD4APABQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsARQBZAEwARQBOAD4AMQA2" + "ADwALwBLAEUAWQBMAEUATgA+" + "ADwAQQBMAEcASQBEAD4AQQBFAFMAQwBUAFIAPAAvAEEATABHAEkARAA+" + "ADwALwBQAFIATwBUAEUAQwBUAEkATgBGAE8APgA8AEsASQBEAD4AQQBBAEEAQQBBAEIA" + "OQBpAC8AaQBwADYAcwBzAGgAbwAxAGYAMAB1AEwAZwA9AD0APAAvAEsASQBEAD4APABD" + "AEgARQBDAEsAUwBVAE0APgA0AGYAdQBCAHQARABVACsASwBrAEUAPQA8AC8AQwBIAEUA" + "QwBLAFMAVQBNAD4APAAvAEQAQQBUAEEAPgA8AC8AVwBSAE0ASABFAEEARABFAFIAPgA" + "="), + .wv_box = + unbase64("AAAASnBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAACoSEAAAAABiHyr+" + "erLIaNX9Li4SEAAAAABiHyr+erLIaNX9Li9I49yVmwY=")}; + PSSHData actual{}; ASSERT_EQ(Status::OK, GeneratePSSHData(in, &actual)); ASSERT_EQ(expected.cenc_box, actual.cenc_box); @@ -300,33 +323,42 @@ TEST(GeneratePSSHData, GeneratesPSSHBoxesAndMSPRObject) { TEST(GeneratePSSHData, FailsOnInvalidInput) { const PSSHGeneratorInput valid_input{ - .encryption_scheme = EncryptionSchemeFourCC::CENC, - .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), - .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), - .key_ids = { - unhex("00000000621f2afe7ab2c868d5fd2e2e"), - unhex("00000000621f2afe7ab2c868d5fd2e2f") - } - }; + .encryption_scheme = EncryptionSchemeFourCC::CENC, + .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), + .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), + .key_ids = {unhex("00000000621f2afe7ab2c868d5fd2e2e"), + unhex("00000000621f2afe7ab2c868d5fd2e2f")}}; PSSHGeneratorInput in; - ASSERT_EQ(Status(error::INVALID_ARGUMENT, "invalid encryption scheme in PSSH generator input"), GeneratePSSHData(in, nullptr)); + ASSERT_EQ(Status(error::INVALID_ARGUMENT, + "invalid encryption scheme in PSSH generator input"), + GeneratePSSHData(in, nullptr)); in.encryption_scheme = valid_input.encryption_scheme; - ASSERT_EQ(Status(error::INVALID_ARGUMENT, "invalid key lenght in PSSH generator input"), GeneratePSSHData(in, nullptr)); + ASSERT_EQ(Status(error::INVALID_ARGUMENT, + "invalid key lenght in PSSH generator input"), + GeneratePSSHData(in, nullptr)); in.key = valid_input.key; - ASSERT_EQ(Status(error::INVALID_ARGUMENT, "invalid key id lenght in PSSH generator input"), GeneratePSSHData(in, nullptr)); + ASSERT_EQ(Status(error::INVALID_ARGUMENT, + "invalid key id lenght in PSSH generator input"), + GeneratePSSHData(in, nullptr)); in.key_id = valid_input.key_id; - ASSERT_EQ(Status(error::INVALID_ARGUMENT, "key ids cannot be empty in PSSH generator input"), GeneratePSSHData(in, nullptr)); + ASSERT_EQ(Status(error::INVALID_ARGUMENT, + "key ids cannot be empty in PSSH generator input"), + GeneratePSSHData(in, nullptr)); in.key_ids = valid_input.key_ids; in.key_ids[1] = {}; - ASSERT_EQ(Status(error::INVALID_ARGUMENT, "invalid key id lenght in key ids array in PSSH generator input, index 1"), GeneratePSSHData(in, nullptr)); + ASSERT_EQ(Status(error::INVALID_ARGUMENT, + "invalid key id lenght in key ids array in PSSH generator " + "input, index 1"), + GeneratePSSHData(in, nullptr)); in.key_ids = valid_input.key_ids; - ASSERT_EQ(Status(error::INVALID_ARGUMENT, "output data cannot be null"), GeneratePSSHData(in, nullptr)); + ASSERT_EQ(Status(error::INVALID_ARGUMENT, "output data cannot be null"), + GeneratePSSHData(in, nullptr)); } class LivePackagerBaseTest : public ::testing::Test { From 3c470fe6fc71ef5cc7dced299ff764a32bb9d1c3 Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Fri, 12 Jan 2024 15:45:00 +0200 Subject: [PATCH 09/17] Fix typo --- packager/live_packager.cc | 12 ++++++------ packager/live_packager_test.cc | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packager/live_packager.cc b/packager/live_packager.cc index bacae7624ab..f3e071c3f5e 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -466,15 +466,15 @@ Status PSSHGeneratorInput::Validate() const { } if (key.size() != 16) { - LOG(WARNING) << "invalid key lenght in PSSH generator input"; + LOG(WARNING) << "invalid key length in PSSH generator input"; return Status(error::INVALID_ARGUMENT, - "invalid key lenght in PSSH generator input"); + "invalid key length in PSSH generator input"); } if (key_id.size() != 16) { - LOG(WARNING) << "invalid key id lenght in PSSH generator input"; + LOG(WARNING) << "invalid key id length in PSSH generator input"; return Status(error::INVALID_ARGUMENT, - "invalid key id lenght in PSSH generator input"); + "invalid key id length in PSSH generator input"); } if (key_ids.empty()) { @@ -485,11 +485,11 @@ Status PSSHGeneratorInput::Validate() const { for (size_t i = 0; i < key_ids.size(); ++i) { if (key_ids[i].size() != 16) { - LOG(WARNING) << "invalid key id lenght in key ids array in PSSH " + LOG(WARNING) << "invalid key id length in key ids array in PSSH " "generator input, index " + std::to_string(i); return Status(error::INVALID_ARGUMENT, - "invalid key id lenght in key ids array in PSSH generator " + "invalid key id length in key ids array in PSSH generator " "input, index " + std::to_string(i)); } diff --git a/packager/live_packager_test.cc b/packager/live_packager_test.cc index 851629466ff..af84edc4d90 100644 --- a/packager/live_packager_test.cc +++ b/packager/live_packager_test.cc @@ -336,12 +336,12 @@ TEST(GeneratePSSHData, FailsOnInvalidInput) { in.encryption_scheme = valid_input.encryption_scheme; ASSERT_EQ(Status(error::INVALID_ARGUMENT, - "invalid key lenght in PSSH generator input"), + "invalid key length in PSSH generator input"), GeneratePSSHData(in, nullptr)); in.key = valid_input.key; ASSERT_EQ(Status(error::INVALID_ARGUMENT, - "invalid key id lenght in PSSH generator input"), + "invalid key id length in PSSH generator input"), GeneratePSSHData(in, nullptr)); in.key_id = valid_input.key_id; @@ -352,7 +352,7 @@ TEST(GeneratePSSHData, FailsOnInvalidInput) { in.key_ids = valid_input.key_ids; in.key_ids[1] = {}; ASSERT_EQ(Status(error::INVALID_ARGUMENT, - "invalid key id lenght in key ids array in PSSH generator " + "invalid key id length in key ids array in PSSH generator " "input, index 1"), GeneratePSSHData(in, nullptr)); From a01e569c5c746e137a66bb964aa2fa95f78b7085 Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Fri, 12 Jan 2024 15:49:36 +0200 Subject: [PATCH 10/17] Use make_unique --- packager/live_packager.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packager/live_packager.cc b/packager/live_packager.cc index f3e071c3f5e..112ee9b1456 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -507,11 +507,11 @@ Status GeneratePSSHData(const PSSHGeneratorInput& in, PSSHData* out) { } std::vector> pssh_generators; - pssh_generators.emplace_back(new media::CommonPsshGenerator()); - pssh_generators.emplace_back(new media::PlayReadyPsshGenerator( + pssh_generators.emplace_back(std::make_unique()); + pssh_generators.emplace_back(std::make_unique( kNoExtraHeadersForPlayReady, static_cast(in.encryption_scheme))); - pssh_generators.emplace_back(new media::WidevinePsshGenerator( + pssh_generators.emplace_back(std::make_unique( static_cast(in.encryption_scheme))); for (const auto& pssh_generator : pssh_generators) { From a1e314bb84340bb6b2f577baffef64cdb10013e7 Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Fri, 12 Jan 2024 15:51:28 +0200 Subject: [PATCH 11/17] Remove mp4 pssh include switch --- include/packager/live_packager.h | 2 -- packager/live_packager.cc | 2 -- 2 files changed, 4 deletions(-) diff --git a/include/packager/live_packager.h b/include/packager/live_packager.h index d7a119f282d..af394806f30 100644 --- a/include/packager/live_packager.h +++ b/include/packager/live_packager.h @@ -85,8 +85,6 @@ struct LiveConfig { std::vector key_id; EncryptionScheme protection_scheme; - bool mp4_include_pssh; - /// User-specified segment number. /// For FMP4 output: /// It can be used to set the moof header sequence number if > 0. diff --git a/packager/live_packager.cc b/packager/live_packager.cc index 112ee9b1456..8bcdf5737d9 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -315,8 +315,6 @@ Status LivePackager::Package(const Segment& init_segment, shaka::PackagingParams packaging_params; packaging_params.chunking_params.segment_duration_in_seconds = config_.segment_duration_sec; - packaging_params.mp4_output_params.include_pssh_in_stream = - config_.mp4_include_pssh; packaging_params.mp4_output_params.sequence_number = config_.segment_number; From 4dee600351d56d8d4c8c99c9472f8a82398edb1b Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Fri, 12 Jan 2024 16:01:26 +0200 Subject: [PATCH 12/17] Simplify unhex --- packager/live_packager_test.cc | 22 ++-------------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/packager/live_packager_test.cc b/packager/live_packager_test.cc index af84edc4d90..943d33c48b1 100644 --- a/packager/live_packager_test.cc +++ b/packager/live_packager_test.cc @@ -64,28 +64,10 @@ std::vector ReadTestDataFile(const std::string& name) { return data; } -uint8_t hex_char_to_int(const char& c) { - unsigned result = 0; - if (c >= '0' && c <= '9') { - result = c - '0'; - } else if (c >= 'A' && c <= 'F') { - result = c - 'A' + 10; - } else if (c >= 'a' && c <= 'f') { - result = c - 'a' + 10; - } else { - throw std::out_of_range("input character is out of hex range"); - } - - return result; -} std::vector unhex(const std::string& in) { - std::vector out; - for (std::size_t i = 1; i < in.size(); i += 2) { - out.push_back(16 * hex_char_to_int(in[i - 1]) + hex_char_to_int(in[i])); - } - - return out; + auto converted = absl::HexStringToBytes(in); + return {converted.begin(), converted.end()}; } std::vector unbase64(const std::string& base64_string) { From 94ddbd8d634ebcf4eaf770bed63aed0942a9ab60 Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Fri, 12 Jan 2024 16:08:07 +0200 Subject: [PATCH 13/17] Add constant value for key size --- packager/live_packager.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/packager/live_packager.cc b/packager/live_packager.cc index 8bcdf5737d9..d137f135971 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -456,6 +456,8 @@ void FillPSSHBoxByDRM(const media::ProtectionSystemSpecificInfo& pssh_info, } Status PSSHGeneratorInput::Validate() const { + constexpr int kKeySize = 16; + if (encryption_scheme != EncryptionSchemeFourCC::CBCS && encryption_scheme != EncryptionSchemeFourCC::CENC) { LOG(WARNING) << "invalid encryption scheme in PSSH generator input"; @@ -463,13 +465,13 @@ Status PSSHGeneratorInput::Validate() const { "invalid encryption scheme in PSSH generator input"); } - if (key.size() != 16) { + if (key.size() != kKeySize) { LOG(WARNING) << "invalid key length in PSSH generator input"; return Status(error::INVALID_ARGUMENT, "invalid key length in PSSH generator input"); } - if (key_id.size() != 16) { + if (key_id.size() != kKeySize) { LOG(WARNING) << "invalid key id length in PSSH generator input"; return Status(error::INVALID_ARGUMENT, "invalid key id length in PSSH generator input"); @@ -482,7 +484,7 @@ Status PSSHGeneratorInput::Validate() const { } for (size_t i = 0; i < key_ids.size(); ++i) { - if (key_ids[i].size() != 16) { + if (key_ids[i].size() != kKeySize) { LOG(WARNING) << "invalid key id length in key ids array in PSSH " "generator input, index " + std::to_string(i); From f0b622b322858ad7ded095b269ce934ea846e88a Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Fri, 12 Jan 2024 16:10:22 +0200 Subject: [PATCH 14/17] Appease linter --- packager/live_packager_test.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/packager/live_packager_test.cc b/packager/live_packager_test.cc index 943d33c48b1..304d7f86533 100644 --- a/packager/live_packager_test.cc +++ b/packager/live_packager_test.cc @@ -64,7 +64,6 @@ std::vector ReadTestDataFile(const std::string& name) { return data; } - std::vector unhex(const std::string& in) { auto converted = absl::HexStringToBytes(in); return {converted.begin(), converted.end()}; From eaf27c170ebfb04411889fa105dace29dffcf42a Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Mon, 15 Jan 2024 16:04:47 +0200 Subject: [PATCH 15/17] Remove validation func from header --- include/packager/live_packager.h | 6 ++---- packager/live_packager.cc | 22 +++++++++++----------- packager/live_packager_test.cc | 6 +++--- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/include/packager/live_packager.h b/include/packager/live_packager.h index af394806f30..060bc7afb83 100644 --- a/include/packager/live_packager.h +++ b/include/packager/live_packager.h @@ -130,13 +130,13 @@ struct PSSHData { std::vector wv_box; }; -enum struct EncryptionSchemeFourCC : uint32_t { +enum struct MP4ProtectionSchemeFourCC : uint32_t { CBCS = 0x63626373, CENC = 0x63656e63, }; struct PSSHGeneratorInput { - EncryptionSchemeFourCC encryption_scheme; + MP4ProtectionSchemeFourCC protection_scheme; // key of a single adaption set for DRM systems that don't support // multile keys (i.e PlayReady) @@ -147,8 +147,6 @@ struct PSSHGeneratorInput { // key ids of all adaptation sets for DRM systems that support // multiple keys (i.e Widevine, Common Encryption) std::vector> key_ids; - - Status Validate() const; }; Status GeneratePSSHData(const PSSHGeneratorInput& in, PSSHData* out); diff --git a/packager/live_packager.cc b/packager/live_packager.cc index d137f135971..e5c39614ec2 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -455,36 +455,36 @@ void FillPSSHBoxByDRM(const media::ProtectionSystemSpecificInfo& pssh_info, } } -Status PSSHGeneratorInput::Validate() const { +Status ValidatePSSHGeneratorInput(const PSSHGeneratorInput& input) { constexpr int kKeySize = 16; - if (encryption_scheme != EncryptionSchemeFourCC::CBCS && - encryption_scheme != EncryptionSchemeFourCC::CENC) { + if (input.protection_scheme != MP4ProtectionSchemeFourCC::CBCS && + input.protection_scheme != MP4ProtectionSchemeFourCC::CENC) { LOG(WARNING) << "invalid encryption scheme in PSSH generator input"; return Status(error::INVALID_ARGUMENT, "invalid encryption scheme in PSSH generator input"); } - if (key.size() != kKeySize) { + if (input.key.size() != kKeySize) { LOG(WARNING) << "invalid key length in PSSH generator input"; return Status(error::INVALID_ARGUMENT, "invalid key length in PSSH generator input"); } - if (key_id.size() != kKeySize) { + if (input.key_id.size() != kKeySize) { LOG(WARNING) << "invalid key id length in PSSH generator input"; return Status(error::INVALID_ARGUMENT, "invalid key id length in PSSH generator input"); } - if (key_ids.empty()) { + if (input.key_ids.empty()) { LOG(WARNING) << "key ids cannot be empty in PSSH generator input"; return Status(error::INVALID_ARGUMENT, "key ids cannot be empty in PSSH generator input"); } - for (size_t i = 0; i < key_ids.size(); ++i) { - if (key_ids[i].size() != kKeySize) { + for (size_t i = 0; i < input.key_ids.size(); ++i) { + if (input.key_ids[i].size() != kKeySize) { LOG(WARNING) << "invalid key id length in key ids array in PSSH " "generator input, index " + std::to_string(i); @@ -501,7 +501,7 @@ Status PSSHGeneratorInput::Validate() const { Status GeneratePSSHData(const PSSHGeneratorInput& in, PSSHData* out) { const char* kNoExtraHeadersForPlayReady = ""; - RETURN_IF_ERROR(in.Validate()); + RETURN_IF_ERROR(ValidatePSSHGeneratorInput(in)); if (!out) { return Status(error::INVALID_ARGUMENT, "output data cannot be null"); } @@ -510,9 +510,9 @@ Status GeneratePSSHData(const PSSHGeneratorInput& in, PSSHData* out) { pssh_generators.emplace_back(std::make_unique()); pssh_generators.emplace_back(std::make_unique( kNoExtraHeadersForPlayReady, - static_cast(in.encryption_scheme))); + static_cast(in.protection_scheme))); pssh_generators.emplace_back(std::make_unique( - static_cast(in.encryption_scheme))); + static_cast(in.protection_scheme))); for (const auto& pssh_generator : pssh_generators) { media::ProtectionSystemSpecificInfo info; diff --git a/packager/live_packager_test.cc b/packager/live_packager_test.cc index 304d7f86533..0ce26e436bf 100644 --- a/packager/live_packager_test.cc +++ b/packager/live_packager_test.cc @@ -254,7 +254,7 @@ void CheckSegment(const LiveConfig& config, const FullSegmentBuffer& buffer) { } // namespace TEST(GeneratePSSHData, GeneratesPSSHBoxesAndMSPRObject) { - PSSHGeneratorInput in{.encryption_scheme = EncryptionSchemeFourCC::CENC, + PSSHGeneratorInput in{.protection_scheme = MP4ProtectionSchemeFourCC::CENC, .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), .key_ids = {unhex("00000000621f2afe7ab2c868d5fd2e2e"), @@ -304,7 +304,7 @@ TEST(GeneratePSSHData, GeneratesPSSHBoxesAndMSPRObject) { TEST(GeneratePSSHData, FailsOnInvalidInput) { const PSSHGeneratorInput valid_input{ - .encryption_scheme = EncryptionSchemeFourCC::CENC, + .protection_scheme = MP4ProtectionSchemeFourCC::CENC, .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), .key_ids = {unhex("00000000621f2afe7ab2c868d5fd2e2e"), @@ -315,7 +315,7 @@ TEST(GeneratePSSHData, FailsOnInvalidInput) { "invalid encryption scheme in PSSH generator input"), GeneratePSSHData(in, nullptr)); - in.encryption_scheme = valid_input.encryption_scheme; + in.protection_scheme = valid_input.protection_scheme; ASSERT_EQ(Status(error::INVALID_ARGUMENT, "invalid key length in PSSH generator input"), GeneratePSSHData(in, nullptr)); From 815f9dc6c597985a9b2fe13a7f2c5cb42a96c9fc Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Tue, 16 Jan 2024 15:51:02 +0200 Subject: [PATCH 16/17] Move FourCC enum into input --- include/packager/live_packager.h | 10 +++++----- packager/live_packager.cc | 6 ++++-- packager/live_packager_test.cc | 4 ++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/include/packager/live_packager.h b/include/packager/live_packager.h index 060bc7afb83..37a0f187c97 100644 --- a/include/packager/live_packager.h +++ b/include/packager/live_packager.h @@ -130,12 +130,12 @@ struct PSSHData { std::vector wv_box; }; -enum struct MP4ProtectionSchemeFourCC : uint32_t { - CBCS = 0x63626373, - CENC = 0x63656e63, -}; - struct PSSHGeneratorInput { + enum struct MP4ProtectionSchemeFourCC : uint32_t { + CBCS = 0x63626373, + CENC = 0x63656e63, + }; + MP4ProtectionSchemeFourCC protection_scheme; // key of a single adaption set for DRM systems that don't support diff --git a/packager/live_packager.cc b/packager/live_packager.cc index e5c39614ec2..cb2ec0f2795 100644 --- a/packager/live_packager.cc +++ b/packager/live_packager.cc @@ -458,8 +458,10 @@ void FillPSSHBoxByDRM(const media::ProtectionSystemSpecificInfo& pssh_info, Status ValidatePSSHGeneratorInput(const PSSHGeneratorInput& input) { constexpr int kKeySize = 16; - if (input.protection_scheme != MP4ProtectionSchemeFourCC::CBCS && - input.protection_scheme != MP4ProtectionSchemeFourCC::CENC) { + if (input.protection_scheme != + PSSHGeneratorInput::MP4ProtectionSchemeFourCC::CBCS && + input.protection_scheme != + PSSHGeneratorInput::MP4ProtectionSchemeFourCC::CENC) { LOG(WARNING) << "invalid encryption scheme in PSSH generator input"; return Status(error::INVALID_ARGUMENT, "invalid encryption scheme in PSSH generator input"); diff --git a/packager/live_packager_test.cc b/packager/live_packager_test.cc index 0ce26e436bf..44487c4f0ba 100644 --- a/packager/live_packager_test.cc +++ b/packager/live_packager_test.cc @@ -254,7 +254,7 @@ void CheckSegment(const LiveConfig& config, const FullSegmentBuffer& buffer) { } // namespace TEST(GeneratePSSHData, GeneratesPSSHBoxesAndMSPRObject) { - PSSHGeneratorInput in{.protection_scheme = MP4ProtectionSchemeFourCC::CENC, + PSSHGeneratorInput in{.protection_scheme = PSSHGeneratorInput::MP4ProtectionSchemeFourCC::CENC, .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), .key_ids = {unhex("00000000621f2afe7ab2c868d5fd2e2e"), @@ -304,7 +304,7 @@ TEST(GeneratePSSHData, GeneratesPSSHBoxesAndMSPRObject) { TEST(GeneratePSSHData, FailsOnInvalidInput) { const PSSHGeneratorInput valid_input{ - .protection_scheme = MP4ProtectionSchemeFourCC::CENC, + .protection_scheme = PSSHGeneratorInput::MP4ProtectionSchemeFourCC::CENC, .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), .key_ids = {unhex("00000000621f2afe7ab2c868d5fd2e2e"), From c769f431b1dd05d35c2a685ae12b6db970d71e6e Mon Sep 17 00:00:00 2001 From: Oleksandr Khodos Date: Tue, 16 Jan 2024 18:30:48 +0200 Subject: [PATCH 17/17] Appease linter --- packager/live_packager_test.cc | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packager/live_packager_test.cc b/packager/live_packager_test.cc index 44487c4f0ba..0b3dcdfdaaa 100644 --- a/packager/live_packager_test.cc +++ b/packager/live_packager_test.cc @@ -254,11 +254,12 @@ void CheckSegment(const LiveConfig& config, const FullSegmentBuffer& buffer) { } // namespace TEST(GeneratePSSHData, GeneratesPSSHBoxesAndMSPRObject) { - PSSHGeneratorInput in{.protection_scheme = PSSHGeneratorInput::MP4ProtectionSchemeFourCC::CENC, - .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), - .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), - .key_ids = {unhex("00000000621f2afe7ab2c868d5fd2e2e"), - unhex("00000000621f2afe7ab2c868d5fd2e2f")}}; + PSSHGeneratorInput in{ + .protection_scheme = PSSHGeneratorInput::MP4ProtectionSchemeFourCC::CENC, + .key_id = unhex("00000000621f2afe7ab2c868d5fd2e2e"), + .key = unhex("1af987fa084ff3c0f4ad35a6bdab98e2"), + .key_ids = {unhex("00000000621f2afe7ab2c868d5fd2e2e"), + unhex("00000000621f2afe7ab2c868d5fd2e2f")}}; PSSHData expected{ .cenc_box = unbase64("AAAARHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAIAAAAAYh8"