Add flag for extra PlayReady header data.
Fixes #756 Change-Id: I4fa6328480130675a0257fd2c6663d91729cf72c
This commit is contained in:
parent
665e784cbd
commit
1911c1beaa
|
@ -27,6 +27,9 @@ DEFINE_int32(
|
|||
"Apply to video streams with 'cbcs' and 'cens' protection schemes only; "
|
||||
"ignored otherwise.");
|
||||
DEFINE_bool(vp9_subsample_encryption, true, "Enable VP9 subsample encryption.");
|
||||
DEFINE_string(playready_extra_header_data,
|
||||
"",
|
||||
"Extra XML data to add to PlayReady headers.");
|
||||
|
||||
bool ValueNotGreaterThanTen(const char* flagname, int32_t value) {
|
||||
if (value > 10) {
|
||||
|
@ -40,5 +43,17 @@ bool ValueNotGreaterThanTen(const char* flagname, int32_t value) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool ValueIsXml(const char* flagname, const std::string& value) {
|
||||
if (value.empty())
|
||||
return true;
|
||||
|
||||
if (value[0] != '<' || value[value.size() - 1] != '>') {
|
||||
fprintf(stderr, "ERROR: %s must be valid XML.\n", flagname);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
DEFINE_validator(crypt_byte_block, &ValueNotGreaterThanTen);
|
||||
DEFINE_validator(skip_byte_block, &ValueNotGreaterThanTen);
|
||||
DEFINE_validator(playready_extra_header_data, &ValueIsXml);
|
||||
|
|
|
@ -16,5 +16,6 @@ DECLARE_string(protection_scheme);
|
|||
DECLARE_int32(crypt_byte_block);
|
||||
DECLARE_int32(skip_byte_block);
|
||||
DECLARE_bool(vp9_subsample_encryption);
|
||||
DECLARE_string(playready_extra_header_data);
|
||||
|
||||
#endif // PACKAGER_APP_CRYPTO_FLAGS_H_
|
||||
|
|
|
@ -351,6 +351,8 @@ base::Optional<PackagingParams> GetPackagingParams() {
|
|||
encryption_params.stream_label_func = std::bind(
|
||||
&Packager::DefaultStreamLabelFunction, FLAGS_max_sd_pixels,
|
||||
FLAGS_max_hd_pixels, FLAGS_max_uhd1_pixels, std::placeholders::_1);
|
||||
encryption_params.playready_extra_header_data =
|
||||
FLAGS_playready_extra_header_data;
|
||||
}
|
||||
switch (encryption_params.key_provider) {
|
||||
case KeyProvider::kWidevine: {
|
||||
|
|
|
@ -32,7 +32,7 @@ const std::string kPlayHeaderObject_4_0 =
|
|||
"version=\"4.0.0.0\"><DATA>"
|
||||
"<PROTECTINFO><KEYLEN>16</KEYLEN><ALGID>AESCTR</ALGID></PROTECTINFO>"
|
||||
"<KID>$0</KID><CHECKSUM>$1</CHECKSUM>"
|
||||
"</DATA></WRMHEADER>";
|
||||
"</DATA>$2</WRMHEADER>";
|
||||
|
||||
// For PlayReady clients 4.0+ that support CBC keys.
|
||||
const std::string kPlayHeaderObject_4_3 =
|
||||
|
@ -40,7 +40,7 @@ const std::string kPlayHeaderObject_4_3 =
|
|||
"xmlns=\"http://schemas.microsoft.com/DRM/2007/03/PlayReadyHeader\" "
|
||||
"version=\"4.3.0.0\"><DATA><PROTECTINFO><KIDS>"
|
||||
"<KID ALGID=\"AESCBC\" VALUE=\"$0\"></KID>"
|
||||
"</KIDS></PROTECTINFO></DATA></WRMHEADER>";
|
||||
"</KIDS></PROTECTINFO></DATA>$1</WRMHEADER>";
|
||||
|
||||
// Converts the key_id's endianness.
|
||||
std::vector<uint8_t> ConvertGuidEndianness(const std::vector<uint8_t>& input) {
|
||||
|
@ -64,6 +64,7 @@ std::vector<uint8_t> ConvertGuidEndianness(const std::vector<uint8_t>& input) {
|
|||
// https://docs.microsoft.com/en-us/playready/specifications/playready-header-specification
|
||||
Status GeneratePlayReadyPsshData(const std::vector<uint8_t>& key_id,
|
||||
const std::vector<uint8_t>& key,
|
||||
const std::string& extra_header_data,
|
||||
const FourCC protection_scheme,
|
||||
std::vector<uint8_t>* output) {
|
||||
CHECK(output);
|
||||
|
@ -92,6 +93,8 @@ Status GeneratePlayReadyPsshData(const std::vector<uint8_t>& key_id,
|
|||
playready_header = kPlayHeaderObject_4_3;
|
||||
base::ReplaceFirstSubstringAfterOffset(&playready_header, 0, "$0",
|
||||
base64_key_id);
|
||||
base::ReplaceFirstSubstringAfterOffset(&playready_header, 0, "$1",
|
||||
extra_header_data);
|
||||
break;
|
||||
|
||||
case FOURCC_cenc:
|
||||
|
@ -101,6 +104,8 @@ Status GeneratePlayReadyPsshData(const std::vector<uint8_t>& key_id,
|
|||
base64_key_id);
|
||||
base::ReplaceFirstSubstringAfterOffset(&playready_header, 0, "$1",
|
||||
base64_checksum);
|
||||
base::ReplaceFirstSubstringAfterOffset(&playready_header, 0, "$2",
|
||||
extra_header_data);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -151,10 +156,13 @@ Status GeneratePlayReadyPsshData(const std::vector<uint8_t>& key_id,
|
|||
}
|
||||
} // namespace
|
||||
|
||||
PlayReadyPsshGenerator::PlayReadyPsshGenerator(FourCC protection_scheme)
|
||||
PlayReadyPsshGenerator::PlayReadyPsshGenerator(
|
||||
const std::string& extra_header_data,
|
||||
FourCC protection_scheme)
|
||||
: PsshGenerator(std::vector<uint8_t>(std::begin(kPlayReadySystemId),
|
||||
std::end(kPlayReadySystemId)),
|
||||
kPlayReadyPsshBoxVersion),
|
||||
extra_header_data_(extra_header_data),
|
||||
protection_scheme_(protection_scheme) {}
|
||||
|
||||
PlayReadyPsshGenerator::~PlayReadyPsshGenerator() {}
|
||||
|
@ -168,8 +176,8 @@ PlayReadyPsshGenerator::GeneratePsshDataFromKeyIdAndKey(
|
|||
const std::vector<uint8_t>& key_id,
|
||||
const std::vector<uint8_t>& key) const {
|
||||
std::vector<uint8_t> pssh_data;
|
||||
Status status =
|
||||
GeneratePlayReadyPsshData(key_id, key, protection_scheme_, &pssh_data);
|
||||
Status status = GeneratePlayReadyPsshData(key_id, key, extra_header_data_,
|
||||
protection_scheme_, &pssh_data);
|
||||
if (!status.ok()) {
|
||||
LOG(ERROR) << status.ToString();
|
||||
return base::nullopt;
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#ifndef MEDIA_BASE_PLAYREADY_PSSH_GENERATOR_H_
|
||||
#define MEDIA_BASE_PLAYREADY_PSSH_GENERATOR_H_
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "packager/media/base/fourccs.h"
|
||||
#include "packager/media/base/pssh_generator.h"
|
||||
|
||||
|
@ -15,7 +17,8 @@ namespace media {
|
|||
|
||||
class PlayReadyPsshGenerator : public PsshGenerator {
|
||||
public:
|
||||
explicit PlayReadyPsshGenerator(FourCC protection_scheme);
|
||||
explicit PlayReadyPsshGenerator(const std::string& extra_header_data,
|
||||
FourCC protection_scheme);
|
||||
~PlayReadyPsshGenerator() override;
|
||||
|
||||
/// @name PsshGenerator implemetation overrides.
|
||||
|
@ -36,7 +39,8 @@ class PlayReadyPsshGenerator : public PsshGenerator {
|
|||
const std::vector<uint8_t>& key_id,
|
||||
const std::vector<uint8_t>& key) const override;
|
||||
|
||||
FourCC protection_scheme_ = FOURCC_NULL;
|
||||
const std::string extra_header_data_;
|
||||
const FourCC protection_scheme_;
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
|
|
|
@ -182,6 +182,8 @@ const char kExpectedWidevinePsshCbcs[] = {
|
|||
'\x9B', '\x06',
|
||||
};
|
||||
|
||||
const char kPlayReadyExtraHeaderData[] = "";
|
||||
|
||||
std::vector<uint8_t> GetTestKeyId1() {
|
||||
return std::vector<uint8_t>(std::begin(kTestKeyId1), std::end(kTestKeyId1));
|
||||
}
|
||||
|
@ -201,7 +203,7 @@ TEST(PsshGeneratorTest, GeneratePlayReadyPsshFromKeyIds) {
|
|||
const std::vector<std::vector<uint8_t>> kTestKeyIds = {GetTestKeyId1(),
|
||||
GetTestKeyId2()};
|
||||
std::unique_ptr<PlayReadyPsshGenerator> playready_pssh_generator(
|
||||
new PlayReadyPsshGenerator(FOURCC_cenc));
|
||||
new PlayReadyPsshGenerator(kPlayReadyExtraHeaderData, FOURCC_cenc));
|
||||
ProtectionSystemSpecificInfo info;
|
||||
EXPECT_NOT_OK(
|
||||
playready_pssh_generator->GeneratePsshFromKeyIds(kTestKeyIds, &info));
|
||||
|
@ -212,7 +214,7 @@ TEST(PsshGeneratorTest,
|
|||
const std::vector<uint8_t> kTestKeyId = GetTestKeyId1();
|
||||
const std::vector<uint8_t> kTestKey = GetTestKey1();
|
||||
std::unique_ptr<PlayReadyPsshGenerator> playready_pssh_generator(
|
||||
new PlayReadyPsshGenerator(FOURCC_NULL));
|
||||
new PlayReadyPsshGenerator(kPlayReadyExtraHeaderData, FOURCC_NULL));
|
||||
ProtectionSystemSpecificInfo info;
|
||||
EXPECT_NOT_OK(playready_pssh_generator->GeneratePsshFromKeyIdAndKey(
|
||||
kTestKeyId, kTestKey, &info));
|
||||
|
@ -222,7 +224,7 @@ TEST(PsshGeneratorTest, GeneratePlayReadyPsshFromKeyIdAndKeyUsingCenc) {
|
|||
const std::vector<uint8_t> kTestKeyId = GetTestKeyId1();
|
||||
const std::vector<uint8_t> kTestKey = GetTestKey1();
|
||||
std::unique_ptr<PlayReadyPsshGenerator> playready_pssh_generator(
|
||||
new PlayReadyPsshGenerator(FOURCC_cenc));
|
||||
new PlayReadyPsshGenerator(kPlayReadyExtraHeaderData, FOURCC_cenc));
|
||||
ProtectionSystemSpecificInfo info;
|
||||
EXPECT_OK(playready_pssh_generator->GeneratePsshFromKeyIdAndKey(
|
||||
kTestKeyId, kTestKey, &info));
|
||||
|
@ -236,7 +238,7 @@ TEST(PsshGeneratorTest, GeneratePlayReadyPsshFromKeyIdAndKeyUsingCens) {
|
|||
const std::vector<uint8_t> kTestKeyId = GetTestKeyId1();
|
||||
const std::vector<uint8_t> kTestKey = GetTestKey1();
|
||||
std::unique_ptr<PlayReadyPsshGenerator> playready_pssh_generator(
|
||||
new PlayReadyPsshGenerator(FOURCC_cens));
|
||||
new PlayReadyPsshGenerator("", FOURCC_cens));
|
||||
ProtectionSystemSpecificInfo info;
|
||||
EXPECT_OK(playready_pssh_generator->GeneratePsshFromKeyIdAndKey(
|
||||
kTestKeyId, kTestKey, &info));
|
||||
|
@ -250,7 +252,7 @@ TEST(PsshGeneratorTest, GeneratePlayReadyPsshFromKeyIdAndKeyUsingCbc1) {
|
|||
const std::vector<uint8_t> kTestKeyId = GetTestKeyId1();
|
||||
const std::vector<uint8_t> kTestKey = GetTestKey1();
|
||||
std::unique_ptr<PlayReadyPsshGenerator> playready_pssh_generator(
|
||||
new PlayReadyPsshGenerator(FOURCC_cbc1));
|
||||
new PlayReadyPsshGenerator("", FOURCC_cbc1));
|
||||
ProtectionSystemSpecificInfo info;
|
||||
EXPECT_OK(playready_pssh_generator->GeneratePsshFromKeyIdAndKey(
|
||||
kTestKeyId, kTestKey, &info));
|
||||
|
@ -264,7 +266,7 @@ TEST(PsshGeneratorTest, GeneratePlayReadyPsshFromKeyIdAndKeyUsingCbcs) {
|
|||
const std::vector<uint8_t> kTestKeyId = GetTestKeyId1();
|
||||
const std::vector<uint8_t> kTestKey = GetTestKey1();
|
||||
std::unique_ptr<PlayReadyPsshGenerator> playready_pssh_generator(
|
||||
new PlayReadyPsshGenerator(FOURCC_cbcs));
|
||||
new PlayReadyPsshGenerator(kPlayReadyExtraHeaderData, FOURCC_cbcs));
|
||||
ProtectionSystemSpecificInfo info;
|
||||
EXPECT_OK(playready_pssh_generator->GeneratePsshFromKeyIdAndKey(
|
||||
kTestKeyId, kTestKey, &info));
|
||||
|
|
|
@ -81,6 +81,7 @@ void FillPsshGenerators(
|
|||
if (has_flag(encryption_params.protection_systems,
|
||||
ProtectionSystem::kPlayReady)) {
|
||||
pssh_generators->emplace_back(new PlayReadyPsshGenerator(
|
||||
encryption_params.playready_extra_header_data,
|
||||
static_cast<FourCC>(encryption_params.protection_scheme)));
|
||||
}
|
||||
|
||||
|
|
|
@ -154,6 +154,8 @@ struct EncryptionParams {
|
|||
|
||||
/// The protection systems to generate, multiple can be OR'd together.
|
||||
ProtectionSystem protection_systems;
|
||||
/// Extra XML data to add to PlayReady data.
|
||||
std::string playready_extra_header_data;
|
||||
|
||||
/// Clear lead duration in seconds.
|
||||
double clear_lead_in_seconds = 0;
|
||||
|
|
Loading…
Reference in New Issue