diff --git a/packager/app/test/packager_test.py b/packager/app/test/packager_test.py index c0af87b428..584a17b7f4 100755 --- a/packager/app/test/packager_test.py +++ b/packager/app/test/packager_test.py @@ -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', diff --git a/packager/app/test/testdata/bear-640x360-a-cbc1-golden.mp4 b/packager/app/test/testdata/bear-640x360-a-cbc1-golden.mp4 new file mode 100644 index 0000000000..1bc6c9d2a6 Binary files /dev/null and b/packager/app/test/testdata/bear-640x360-a-cbc1-golden.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-av-cbc1-golden.mpd b/packager/app/test/testdata/bear-640x360-av-cbc1-golden.mpd new file mode 100644 index 0000000000..afa02f3cfd --- /dev/null +++ b/packager/app/test/testdata/bear-640x360-av-cbc1-golden.mpd @@ -0,0 +1,31 @@ + + + + + + + + + AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2 + + output_video.mp4 + + + + + + + + + + + AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2 + + output_audio.mp4 + + + + + + + diff --git a/packager/app/test/testdata/bear-640x360-av-cbcs-golden.mpd b/packager/app/test/testdata/bear-640x360-av-cbcs-golden.mpd new file mode 100644 index 0000000000..abb3213d34 --- /dev/null +++ b/packager/app/test/testdata/bear-640x360-av-cbcs-golden.mpd @@ -0,0 +1,31 @@ + + + + + + + + + AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2 + + output_video.mp4 + + + + + + + + + + + AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2 + + output_audio.mp4 + + + + + + + diff --git a/packager/app/test/testdata/bear-640x360-av-cens-golden.mpd b/packager/app/test/testdata/bear-640x360-av-cens-golden.mpd new file mode 100644 index 0000000000..3f79f1d0fa --- /dev/null +++ b/packager/app/test/testdata/bear-640x360-av-cens-golden.mpd @@ -0,0 +1,31 @@ + + + + + + + + + AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2 + + output_video.mp4 + + + + + + + + + + + AAAAMHBzc2gAAAAA7e+LqXnWSs6jyCfc1R0h7QAAABAxMjM0NTY3ODkwMTIzNDU2 + + output_audio.mp4 + + + + + + + diff --git a/packager/app/test/testdata/bear-640x360-v-cbc1-golden.mp4 b/packager/app/test/testdata/bear-640x360-v-cbc1-golden.mp4 new file mode 100644 index 0000000000..0d86a63191 Binary files /dev/null and b/packager/app/test/testdata/bear-640x360-v-cbc1-golden.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-v-cbcs-golden.mp4 b/packager/app/test/testdata/bear-640x360-v-cbcs-golden.mp4 new file mode 100644 index 0000000000..af6474058a Binary files /dev/null and b/packager/app/test/testdata/bear-640x360-v-cbcs-golden.mp4 differ diff --git a/packager/app/test/testdata/bear-640x360-v-cens-golden.mp4 b/packager/app/test/testdata/bear-640x360-v-cens-golden.mp4 new file mode 100644 index 0000000000..8cc823884b Binary files /dev/null and b/packager/app/test/testdata/bear-640x360-v-cens-golden.mp4 differ diff --git a/packager/media/formats/mp4/box.cc b/packager/media/formats/mp4/box.cc index 4b42e0c054..2771887081 100644 --- a/packager/media/formats/mp4/box.cc +++ b/packager/media/formats/mp4/box.cc @@ -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) { diff --git a/packager/media/formats/mp4/box_definitions.cc b/packager/media/formats/mp4/box_definitions.cc index 4900dbfb75..9d4cb61e71 100644 --- a/packager/media/formats/mp4/box_definitions.cc +++ b/packager/media/formats/mp4/box_definitions.cc @@ -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)); diff --git a/packager/media/formats/mp4/encrypting_fragmenter.cc b/packager/media/formats/mp4/encrypting_fragmenter.cc index 5d8a4ebb66..3080388f90 100644 --- a/packager/media/formats/mp4/encrypting_fragmenter.cc +++ b/packager/media/formats/mp4/encrypting_fragmenter.cc @@ -256,9 +256,11 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr 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 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;