Allow specifying protection pattern for pattern encryption
Added --crypt_byte_block, --skip_byte_block to allow users to specify protection pattern other than 1:9 for pattern based encryption scheme, e.g. cbcs and cens. Closes #710. b/147307451 Change-Id: I9f64a7639170c737f138572689b28d17286325c7
This commit is contained in:
parent
1ca873f453
commit
4028bf727b
|
@ -6,6 +6,24 @@ General encryption options
|
||||||
Specify a protection scheme, 'cenc' or 'cbc1' or pattern-based protection
|
Specify a protection scheme, 'cenc' or 'cbc1' or pattern-based protection
|
||||||
schemes 'cens' or 'cbcs'.
|
schemes 'cens' or 'cbcs'.
|
||||||
|
|
||||||
|
--crypt_byte_block
|
||||||
|
|
||||||
|
Specify the count of the encrypted blocks in the protection pattern, where
|
||||||
|
block is of size 16-bytes.
|
||||||
|
|
||||||
|
There are three common patterns (crypt_byte_block:skip_byte_block):
|
||||||
|
1:9 (default), 5:5, 10:0.
|
||||||
|
|
||||||
|
Apply to video streams with 'cbcs' and 'cens' protection schemes only;
|
||||||
|
ignored otherwise.
|
||||||
|
|
||||||
|
--skip_byte_block
|
||||||
|
|
||||||
|
Specify the count of the unencrypted blocks in the protection pattern.
|
||||||
|
|
||||||
|
Apply to video streams with 'cbcs' and 'cens' protection schemes only;
|
||||||
|
ignored otherwise.
|
||||||
|
|
||||||
--vp9_subsample_encryption, --novp9_subsample_encryption
|
--vp9_subsample_encryption, --novp9_subsample_encryption
|
||||||
|
|
||||||
Enable / disable VP9 subsample encryption. Enabled by default.
|
Enable / disable VP9 subsample encryption. Enabled by default.
|
||||||
|
|
|
@ -12,4 +12,33 @@ DEFINE_string(protection_scheme,
|
||||||
"cenc",
|
"cenc",
|
||||||
"Specify a protection scheme, 'cenc' or 'cbc1' or pattern-based "
|
"Specify a protection scheme, 'cenc' or 'cbc1' or pattern-based "
|
||||||
"protection schemes 'cens' or 'cbcs'.");
|
"protection schemes 'cens' or 'cbcs'.");
|
||||||
|
DEFINE_int32(
|
||||||
|
crypt_byte_block,
|
||||||
|
1,
|
||||||
|
"Specify the count of the encrypted blocks in the protection pattern, "
|
||||||
|
"where block is of size 16-bytes. There are three common "
|
||||||
|
"patterns (crypt_byte_block:skip_byte_block): 1:9 (default), 5:5, 10:0. "
|
||||||
|
"Apply to video streams with 'cbcs' and 'cens' protection schemes only; "
|
||||||
|
"ignored otherwise.");
|
||||||
|
DEFINE_int32(
|
||||||
|
skip_byte_block,
|
||||||
|
9,
|
||||||
|
"Specify the count of the unencrypted blocks in the protection pattern. "
|
||||||
|
"Apply to video streams with 'cbcs' and 'cens' protection schemes only; "
|
||||||
|
"ignored otherwise.");
|
||||||
DEFINE_bool(vp9_subsample_encryption, true, "Enable VP9 subsample encryption.");
|
DEFINE_bool(vp9_subsample_encryption, true, "Enable VP9 subsample encryption.");
|
||||||
|
|
||||||
|
bool ValueNotGreaterThanTen(const char* flagname, int32_t value) {
|
||||||
|
if (value > 10) {
|
||||||
|
fprintf(stderr, "ERROR: %s must not be greater than 10.\n", flagname);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (value < 0) {
|
||||||
|
fprintf(stderr, "ERROR: %s must be non-negative.\n", flagname);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DEFINE_validator(crypt_byte_block, &ValueNotGreaterThanTen);
|
||||||
|
DEFINE_validator(skip_byte_block, &ValueNotGreaterThanTen);
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include <gflags/gflags.h>
|
#include <gflags/gflags.h>
|
||||||
|
|
||||||
DECLARE_string(protection_scheme);
|
DECLARE_string(protection_scheme);
|
||||||
|
DECLARE_int32(crypt_byte_block);
|
||||||
|
DECLARE_int32(skip_byte_block);
|
||||||
DECLARE_bool(vp9_subsample_encryption);
|
DECLARE_bool(vp9_subsample_encryption);
|
||||||
|
|
||||||
#endif // PACKAGER_APP_CRYPTO_FLAGS_H_
|
#endif // PACKAGER_APP_CRYPTO_FLAGS_H_
|
||||||
|
|
|
@ -343,6 +343,9 @@ base::Optional<PackagingParams> GetPackagingParams() {
|
||||||
encryption_params.clear_lead_in_seconds = FLAGS_clear_lead;
|
encryption_params.clear_lead_in_seconds = FLAGS_clear_lead;
|
||||||
if (!GetProtectionScheme(&encryption_params.protection_scheme))
|
if (!GetProtectionScheme(&encryption_params.protection_scheme))
|
||||||
return base::nullopt;
|
return base::nullopt;
|
||||||
|
encryption_params.crypt_byte_block = FLAGS_crypt_byte_block;
|
||||||
|
encryption_params.skip_byte_block = FLAGS_skip_byte_block;
|
||||||
|
|
||||||
encryption_params.crypto_period_duration_in_seconds =
|
encryption_params.crypto_period_duration_in_seconds =
|
||||||
FLAGS_crypto_period_duration;
|
FLAGS_crypto_period_duration;
|
||||||
encryption_params.vp9_subsample_encryption = FLAGS_vp9_subsample_encryption;
|
encryption_params.vp9_subsample_encryption = FLAGS_vp9_subsample_encryption;
|
||||||
|
|
|
@ -417,6 +417,8 @@ class PackagerAppTest(unittest.TestCase):
|
||||||
encryption=False,
|
encryption=False,
|
||||||
protection_systems=None,
|
protection_systems=None,
|
||||||
protection_scheme=None,
|
protection_scheme=None,
|
||||||
|
crypt_byte_block=None,
|
||||||
|
skip_byte_block=None,
|
||||||
vp9_subsample_encryption=True,
|
vp9_subsample_encryption=True,
|
||||||
decryption=False,
|
decryption=False,
|
||||||
random_iv=False,
|
random_iv=False,
|
||||||
|
@ -469,6 +471,11 @@ class PackagerAppTest(unittest.TestCase):
|
||||||
|
|
||||||
if protection_scheme:
|
if protection_scheme:
|
||||||
flags += ['--protection_scheme', protection_scheme]
|
flags += ['--protection_scheme', protection_scheme]
|
||||||
|
if crypt_byte_block is not None and skip_byte_block is not None:
|
||||||
|
flags += [
|
||||||
|
'--crypt_byte_block={0}'.format(crypt_byte_block),
|
||||||
|
'--skip_byte_block={0}'.format(skip_byte_block)
|
||||||
|
]
|
||||||
if not vp9_subsample_encryption:
|
if not vp9_subsample_encryption:
|
||||||
flags += ['--vp9_subsample_encryption=false']
|
flags += ['--vp9_subsample_encryption=false']
|
||||||
|
|
||||||
|
@ -1042,6 +1049,18 @@ class PackagerFunctionalTest(PackagerAppTest):
|
||||||
encryption=True, protection_scheme='cbcs', output_dash=True))
|
encryption=True, protection_scheme='cbcs', output_dash=True))
|
||||||
self._CheckTestResults('encryption-cbcs', verify_decryption=True)
|
self._CheckTestResults('encryption-cbcs', verify_decryption=True)
|
||||||
|
|
||||||
|
def testEncryptionCbcsWithFullProtection(self):
|
||||||
|
self.assertPackageSuccess(
|
||||||
|
self._GetStreams(['audio', 'video']),
|
||||||
|
self._GetFlags(
|
||||||
|
encryption=True,
|
||||||
|
protection_scheme='cbcs',
|
||||||
|
crypt_byte_block=10,
|
||||||
|
skip_byte_block=0,
|
||||||
|
output_dash=True))
|
||||||
|
self._CheckTestResults(
|
||||||
|
'encryption-cbcs-with-full-protection', verify_decryption=True)
|
||||||
|
|
||||||
def testEncryptionAndAdCues(self):
|
def testEncryptionAndAdCues(self):
|
||||||
self.assertPackageSuccess(
|
self.assertPackageSuccess(
|
||||||
self._GetStreams(['audio', 'video'], hls=True),
|
self._GetStreams(['audio', 'video'], hls=True),
|
||||||
|
@ -1774,6 +1793,17 @@ class PackagerCommandParsingTest(PackagerAppTest):
|
||||||
# Expect the test to fail but we do not expect a crash.
|
# Expect the test to fail but we do not expect a crash.
|
||||||
self.assertEqual(packaging_result, 1)
|
self.assertEqual(packaging_result, 1)
|
||||||
|
|
||||||
|
def testIncorrectEncryptionPattern(self):
|
||||||
|
packaging_result = self.packager.Package(
|
||||||
|
self._GetStreams(['audio', 'video']),
|
||||||
|
self._GetFlags(
|
||||||
|
encryption=True,
|
||||||
|
protection_scheme='cbcs',
|
||||||
|
crypt_byte_block=12,
|
||||||
|
skip_byte_block=13,
|
||||||
|
output_dash=True))
|
||||||
|
self.assertEqual(packaging_result, 1)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|
BIN
packager/app/test/testdata/encryption-cbcs-with-full-protection/bear-640x360-audio.mp4
vendored
Normal file
BIN
packager/app/test/testdata/encryption-cbcs-with-full-protection/bear-640x360-audio.mp4
vendored
Normal file
Binary file not shown.
BIN
packager/app/test/testdata/encryption-cbcs-with-full-protection/bear-640x360-video.mp4
vendored
Normal file
BIN
packager/app/test/testdata/encryption-cbcs-with-full-protection/bear-640x360-video.mp4
vendored
Normal file
Binary file not shown.
BIN
packager/app/test/testdata/encryption-cbcs-with-full-protection/decrypted-bear-640x360-audio-0.mp4
vendored
Normal file
BIN
packager/app/test/testdata/encryption-cbcs-with-full-protection/decrypted-bear-640x360-audio-0.mp4
vendored
Normal file
Binary file not shown.
BIN
packager/app/test/testdata/encryption-cbcs-with-full-protection/decrypted-bear-640x360-video-0.mp4
vendored
Normal file
BIN
packager/app/test/testdata/encryption-cbcs-with-full-protection/decrypted-bear-640x360-video-0.mp4
vendored
Normal file
Binary file not shown.
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!--Generated with https://github.com/google/shaka-packager version <tag>-<hash>-<test>-->
|
||||||
|
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" minBufferTime="PT2S" type="static" mediaPresentationDuration="PT2.7360665798187256S">
|
||||||
|
<Period id="0">
|
||||||
|
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||||
|
<ContentProtection value="cbcs" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||||
|
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
|
||||||
|
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA==</cenc:pssh>
|
||||||
|
</ContentProtection>
|
||||||
|
<Representation id="0" bandwidth="975825" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||||
|
<BaseURL>bear-640x360-video.mp4</BaseURL>
|
||||||
|
<SegmentBase indexRange="1136-1203" timescale="30000">
|
||||||
|
<Initialization range="0-1135"/>
|
||||||
|
</SegmentBase>
|
||||||
|
</Representation>
|
||||||
|
</AdaptationSet>
|
||||||
|
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
|
||||||
|
<ContentProtection value="cbcs" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||||
|
<ContentProtection schemeIdUri="urn:uuid:1077efec-c0b2-4d02-ace3-3c1e52e2fb4b">
|
||||||
|
<cenc:pssh>AAAANHBzc2gBAAAAEHfv7MCyTQKs4zweUuL7SwAAAAExMjM0NTY3ODkwMTIzNDU2AAAAAA==</cenc:pssh>
|
||||||
|
</ContentProtection>
|
||||||
|
<Representation id="1" bandwidth="133334" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
|
||||||
|
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
|
||||||
|
<BaseURL>bear-640x360-audio.mp4</BaseURL>
|
||||||
|
<SegmentBase indexRange="1012-1079" timescale="44100">
|
||||||
|
<Initialization range="0-1011"/>
|
||||||
|
</SegmentBase>
|
||||||
|
</Representation>
|
||||||
|
</AdaptationSet>
|
||||||
|
</Period>
|
||||||
|
</MPD>
|
|
@ -253,9 +253,8 @@ Status EncryptionHandler::ProcessMediaSample(
|
||||||
void EncryptionHandler::SetupProtectionPattern(StreamType stream_type) {
|
void EncryptionHandler::SetupProtectionPattern(StreamType stream_type) {
|
||||||
if (stream_type == kStreamVideo &&
|
if (stream_type == kStreamVideo &&
|
||||||
IsPatternEncryptionScheme(protection_scheme_)) {
|
IsPatternEncryptionScheme(protection_scheme_)) {
|
||||||
// Use 1:9 pattern.
|
crypt_byte_block_ = encryption_params_.crypt_byte_block;
|
||||||
crypt_byte_block_ = 1u;
|
skip_byte_block_ = encryption_params_.skip_byte_block;
|
||||||
skip_byte_block_ = 9u;
|
|
||||||
} else {
|
} else {
|
||||||
// Audio stream in pattern encryption scheme does not use pattern; it uses
|
// Audio stream in pattern encryption scheme does not use pattern; it uses
|
||||||
// whole-block full sample encryption instead. Non-pattern encryption does
|
// whole-block full sample encryption instead. Non-pattern encryption does
|
||||||
|
|
|
@ -134,6 +134,16 @@ struct EncryptionParams {
|
||||||
static constexpr uint32_t kProtectionSchemeCens = 0x63656E73;
|
static constexpr uint32_t kProtectionSchemeCens = 0x63656E73;
|
||||||
static constexpr uint32_t kProtectionSchemeCbcs = 0x63626373;
|
static constexpr uint32_t kProtectionSchemeCbcs = 0x63626373;
|
||||||
uint32_t protection_scheme = kProtectionSchemeCenc;
|
uint32_t protection_scheme = kProtectionSchemeCenc;
|
||||||
|
/// The count of the encrypted blocks in the protection pattern, where each
|
||||||
|
/// block is of size 16-bytes. There are three common patterns
|
||||||
|
/// (crypt_byte_block:skip_byte_block): 1:9 (default), 5:5, 10:0.
|
||||||
|
/// Applies to video streams with "cbcs" and "cens" protection schemes only;
|
||||||
|
/// Ignored otherwise.
|
||||||
|
uint8_t crypt_byte_block = 1;
|
||||||
|
/// The count of the unencrypted blocks in the protection pattern.
|
||||||
|
/// Applies to video streams with "cbcs" and "cens" protection schemes only;
|
||||||
|
/// Ignored otherwise.
|
||||||
|
uint8_t skip_byte_block = 9;
|
||||||
/// Crypto period duration in seconds. A positive value means key rotation is
|
/// Crypto period duration in seconds. A positive value means key rotation is
|
||||||
/// enabled, the key provider must support key rotation in this case.
|
/// enabled, the key provider must support key rotation in this case.
|
||||||
static constexpr double kNoKeyRotation = 0;
|
static constexpr double kNoKeyRotation = 0;
|
||||||
|
|
Loading…
Reference in New Issue