Fix two bugs in 'cbcs' and 'cens' handling and add tests
- BytesOfProtectedData in 'cens' SHALL also be 16-byte aligned - Fix an incorrect box definition bug w.r.t to 'cbcs' and 'cens' - Also add various protection scheme tests Close #77 Close #78 Change-Id: I63c8d8b01ce16ed60affa97ec95fc62bc2da06df
This commit is contained in:
parent
976bf69294
commit
3ff74398df
|
@ -137,6 +137,39 @@ class PackagerAppTest(unittest.TestCase):
|
|||
self._VerifyDecryption(self.output[0], 'bear-640x360-a-golden.mp4')
|
||||
self._VerifyDecryption(self.output[1], 'bear-640x360-v-golden.mp4')
|
||||
|
||||
def testPackageWithEncryptionCbc1(self):
|
||||
self.packager.Package(
|
||||
self._GetStreams(['audio', 'video']),
|
||||
self._GetFlags(encryption=True,
|
||||
protection_scheme='cbc1'))
|
||||
self._DiffGold(self.output[0], 'bear-640x360-a-cbc1-golden.mp4')
|
||||
self._DiffGold(self.output[1], 'bear-640x360-v-cbc1-golden.mp4')
|
||||
self._DiffGold(self.mpd_output, 'bear-640x360-av-cbc1-golden.mpd')
|
||||
self._VerifyDecryption(self.output[0], 'bear-640x360-a-golden.mp4')
|
||||
self._VerifyDecryption(self.output[1], 'bear-640x360-v-golden.mp4')
|
||||
|
||||
def testPackageWithEncryptionCens(self):
|
||||
self.packager.Package(
|
||||
self._GetStreams(['audio', 'video']),
|
||||
self._GetFlags(encryption=True,
|
||||
protection_scheme='cens'))
|
||||
self._DiffGold(self.output[0], 'bear-640x360-a-cenc-golden.mp4')
|
||||
self._DiffGold(self.output[1], 'bear-640x360-v-cens-golden.mp4')
|
||||
self._DiffGold(self.mpd_output, 'bear-640x360-av-cens-golden.mpd')
|
||||
self._VerifyDecryption(self.output[0], 'bear-640x360-a-golden.mp4')
|
||||
self._VerifyDecryption(self.output[1], 'bear-640x360-v-golden.mp4')
|
||||
|
||||
def testPackageWithEncryptionCbcs(self):
|
||||
self.packager.Package(
|
||||
self._GetStreams(['audio', 'video']),
|
||||
self._GetFlags(encryption=True,
|
||||
protection_scheme='cbcs'))
|
||||
self._DiffGold(self.output[0], 'bear-640x360-a-cbc1-golden.mp4')
|
||||
self._DiffGold(self.output[1], 'bear-640x360-v-cbcs-golden.mp4')
|
||||
self._DiffGold(self.mpd_output, 'bear-640x360-av-cbcs-golden.mpd')
|
||||
self._VerifyDecryption(self.output[0], 'bear-640x360-a-golden.mp4')
|
||||
self._VerifyDecryption(self.output[1], 'bear-640x360-v-golden.mp4')
|
||||
|
||||
def testPackageWebmWithEncryption(self):
|
||||
self.packager.Package(
|
||||
self._GetStreams(['video'],
|
||||
|
@ -368,6 +401,7 @@ class PackagerAppTest(unittest.TestCase):
|
|||
|
||||
def _GetFlags(self,
|
||||
encryption=False,
|
||||
protection_scheme=None,
|
||||
decryption=False,
|
||||
random_iv=False,
|
||||
widevine_encryption=False,
|
||||
|
@ -394,6 +428,8 @@ class PackagerAppTest(unittest.TestCase):
|
|||
'--clear_lead=1']
|
||||
if not random_iv:
|
||||
flags.append('--iv=3334353637383930')
|
||||
if protection_scheme:
|
||||
flags += ['--protection_scheme', protection_scheme]
|
||||
|
||||
if decryption:
|
||||
flags += ['--enable_fixed_key_decryption',
|
||||
|
|
Binary file not shown.
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--Generated with https://github.com/google/edash-packager version <tag>-<hash>-<test>-->
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.763174533843994S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="885555" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
<ContentProtection value="cbc1" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<BaseURL>output_video.mp4</BaseURL>
|
||||
<SegmentBase indexRange="1079-1146" timescale="30000">
|
||||
<Initialization range="0-1078"/>
|
||||
</SegmentBase>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
|
||||
<Representation id="1" bandwidth="129127" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
|
||||
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
|
||||
<ContentProtection value="cbc1" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<BaseURL>output_audio.mp4</BaseURL>
|
||||
<SegmentBase indexRange="955-1022" timescale="44100">
|
||||
<Initialization range="0-954"/>
|
||||
</SegmentBase>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
</MPD>
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--Generated with https://github.com/google/edash-packager version <tag>-<hash>-<test>-->
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.763174533843994S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="884365" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
<ContentProtection value="cbcs" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<BaseURL>output_video.mp4</BaseURL>
|
||||
<SegmentBase indexRange="1088-1155" timescale="30000">
|
||||
<Initialization range="0-1087"/>
|
||||
</SegmentBase>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
|
||||
<Representation id="1" bandwidth="129127" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
|
||||
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
|
||||
<ContentProtection value="cbc1" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<BaseURL>output_audio.mp4</BaseURL>
|
||||
<SegmentBase indexRange="955-1022" timescale="44100">
|
||||
<Initialization range="0-954"/>
|
||||
</SegmentBase>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
</MPD>
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--Generated with https://github.com/google/edash-packager version <tag>-<hash>-<test>-->
|
||||
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xlink="http://www.w3.org/1999/xlink" xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 DASH-MPD.xsd" xmlns:cenc="urn:mpeg:cenc:2013" minBufferTime="PT2S" type="static" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT2.763174533843994S">
|
||||
<Period id="0">
|
||||
<AdaptationSet id="0" contentType="video" width="640" height="360" frameRate="30000/1001" subsegmentAlignment="true" par="16:9">
|
||||
<Representation id="0" bandwidth="885555" codecs="avc1.64001e" mimeType="video/mp4" sar="1:1">
|
||||
<ContentProtection value="cens" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<BaseURL>output_video.mp4</BaseURL>
|
||||
<SegmentBase indexRange="1079-1146" timescale="30000">
|
||||
<Initialization range="0-1078"/>
|
||||
</SegmentBase>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
<AdaptationSet id="1" contentType="audio" subsegmentAlignment="true">
|
||||
<Representation id="1" bandwidth="129127" codecs="mp4a.40.2" mimeType="audio/mp4" audioSamplingRate="44100">
|
||||
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
|
||||
<ContentProtection value="cenc" schemeIdUri="urn:mpeg:dash:mp4protection:2011" cenc:default_KID="31323334-3536-3738-3930-313233343536"/>
|
||||
<ContentProtection schemeIdUri="urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed">
|
||||
<cenc:pssh>AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2</cenc:pssh>
|
||||
</ContentProtection>
|
||||
<BaseURL>output_audio.mp4</BaseURL>
|
||||
<SegmentBase indexRange="955-1022" timescale="44100">
|
||||
<Initialization range="0-954"/>
|
||||
</SegmentBase>
|
||||
</Representation>
|
||||
</AdaptationSet>
|
||||
</Period>
|
||||
</MPD>
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -31,7 +31,8 @@ void Box::Write(BufferWriter* writer) {
|
|||
size_t buffer_size_before_write = writer->Size();
|
||||
BoxBuffer buffer(writer);
|
||||
CHECK(ReadWriteInternal(&buffer));
|
||||
DCHECK_EQ(box_size_, writer->Size() - buffer_size_before_write);
|
||||
DCHECK_EQ(box_size_, writer->Size() - buffer_size_before_write)
|
||||
<< FourCCToString(BoxType());
|
||||
}
|
||||
|
||||
void Box::WriteHeader(BufferWriter* writer) {
|
||||
|
|
|
@ -449,6 +449,7 @@ bool TrackEncryption::ReadWriteInternal(BoxBuffer* buffer) {
|
|||
// of |default_is_protected| is not supported.
|
||||
RCHECK(default_is_protected == 0);
|
||||
RCHECK(default_per_sample_iv_size == 0);
|
||||
RCHECK(default_constant_iv.empty());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -482,8 +483,9 @@ bool ProtectionSchemeInfo::ReadWriteInternal(BoxBuffer* buffer) {
|
|||
buffer->PrepareChildren() &&
|
||||
buffer->ReadWriteChild(&format) &&
|
||||
buffer->ReadWriteChild(&type));
|
||||
if (type.type == FOURCC_cenc || type.type == FOURCC_cbc1)
|
||||
RCHECK(buffer->ReadWriteChild(&info));
|
||||
RCHECK(type.type == FOURCC_cenc || type.type == FOURCC_cbc1 ||
|
||||
type.type == FOURCC_cens || type.type == FOURCC_cbcs);
|
||||
RCHECK(buffer->ReadWriteChild(&info));
|
||||
// Other protection schemes are silently ignored. Since the protection scheme
|
||||
// type can't be determined until this box is opened, we return 'true' for
|
||||
// non-CENC protection scheme types. It is the parent box's responsibility to
|
||||
|
@ -1328,18 +1330,8 @@ bool VideoSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
|
|||
|
||||
RCHECK(buffer->PrepareChildren());
|
||||
|
||||
if (format == FOURCC_encv) {
|
||||
if (buffer->Reading()) {
|
||||
// Continue scanning until a recognized protection scheme is found,
|
||||
// or until we run out of protection schemes.
|
||||
while (sinf.type.type != FOURCC_cenc && sinf.type.type != FOURCC_cbc1) {
|
||||
if (!buffer->ReadWriteChild(&sinf))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
RCHECK(buffer->ReadWriteChild(&sinf));
|
||||
}
|
||||
}
|
||||
if (format == FOURCC_encv)
|
||||
RCHECK(buffer->ReadWriteChild(&sinf));
|
||||
|
||||
const FourCC actual_format = GetActualFormat();
|
||||
switch (actual_format) {
|
||||
|
@ -1513,18 +1505,8 @@ bool AudioSampleEntry::ReadWriteInternal(BoxBuffer* buffer) {
|
|||
samplerate >>= 16;
|
||||
|
||||
RCHECK(buffer->PrepareChildren());
|
||||
if (format == FOURCC_enca) {
|
||||
if (buffer->Reading()) {
|
||||
// Continue scanning until a recognized protection scheme is found,
|
||||
// or until we run out of protection schemes.
|
||||
while (sinf.type.type != FOURCC_cenc && sinf.type.type != FOURCC_cbc1) {
|
||||
if (!buffer->ReadWriteChild(&sinf))
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
RCHECK(buffer->ReadWriteChild(&sinf));
|
||||
}
|
||||
}
|
||||
if (format == FOURCC_enca)
|
||||
RCHECK(buffer->ReadWriteChild(&sinf));
|
||||
|
||||
RCHECK(buffer->TryReadWriteChild(&esds));
|
||||
RCHECK(buffer->TryReadWriteChild(&ddts));
|
||||
|
|
|
@ -256,9 +256,11 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
|
|||
// encrypted bytes of each frame within the superframe must be block
|
||||
// aligned so that the counter state can be computed for each frame
|
||||
// within the superframe.
|
||||
// For AES-CBC mode 'cbc1' scheme, clear data is sized appropriately so
|
||||
// that the cipher data is block aligned.
|
||||
if (is_superframe || protection_scheme_ == FOURCC_cbc1) {
|
||||
// ISO/IEC 23001-7:2016 10.2 'cbc1' 10.3 'cens'
|
||||
// The BytesOfProtectedData size SHALL be a multiple of 16 bytes to
|
||||
// avoid partial blocks in Subsamples.
|
||||
if (is_superframe || protection_scheme_ == FOURCC_cbc1 ||
|
||||
protection_scheme_ == FOURCC_cens) {
|
||||
const uint16_t misalign_bytes =
|
||||
subsample.cipher_bytes % kCencBlockSize;
|
||||
subsample.clear_bytes += misalign_bytes;
|
||||
|
@ -298,9 +300,11 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
|
|||
nalu.header_size() + video_slice_header_size;
|
||||
uint64_t cipher_bytes = nalu.payload_size() - video_slice_header_size;
|
||||
|
||||
// For AES-CBC mode 'cbc1' scheme, clear data is sized appropriately
|
||||
// so that the cipher data is block aligned.
|
||||
if (protection_scheme_ == FOURCC_cbc1) {
|
||||
// ISO/IEC 23001-7:2016 10.2 'cbc1' 10.3 'cens'
|
||||
// The BytesOfProtectedData size SHALL be a multiple of 16 bytes to
|
||||
// avoid partial blocks in Subsamples.
|
||||
if (protection_scheme_ == FOURCC_cbc1 ||
|
||||
protection_scheme_ == FOURCC_cens) {
|
||||
const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
|
||||
current_clear_bytes += misalign_bytes;
|
||||
cipher_bytes -= misalign_bytes;
|
||||
|
|
Loading…
Reference in New Issue