diff options
Diffstat (limited to 'dom/media/mp4/SinfParser.cpp')
-rw-r--r-- | dom/media/mp4/SinfParser.cpp | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/dom/media/mp4/SinfParser.cpp b/dom/media/mp4/SinfParser.cpp new file mode 100644 index 0000000000..4ea14adaaa --- /dev/null +++ b/dom/media/mp4/SinfParser.cpp @@ -0,0 +1,95 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "mozilla/Unused.h" +#include "SinfParser.h" +#include "AtomType.h" +#include "Box.h" +#include "ByteStream.h" + +namespace mozilla { + +Sinf::Sinf(Box& aBox) : mDefaultIVSize(0), mDefaultEncryptionType() { + SinfParser parser(aBox); + if (parser.GetSinf().IsValid()) { + *this = parser.GetSinf(); + } +} + +SinfParser::SinfParser(Box& aBox) { + for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) { + if (box.IsType("schm")) { + mozilla::Unused << ParseSchm(box); + } else if (box.IsType("schi")) { + mozilla::Unused << ParseSchi(box); + } + } +} + +Result<Ok, nsresult> SinfParser::ParseSchm(Box& aBox) { + BoxReader reader(aBox); + + if (reader->Remaining() < 8) { + return Err(NS_ERROR_FAILURE); + } + + MOZ_TRY(reader->ReadU32()); // flags -- ignore + MOZ_TRY_VAR(mSinf.mDefaultEncryptionType, reader->ReadU32()); + return Ok(); +} + +Result<Ok, nsresult> SinfParser::ParseSchi(Box& aBox) { + for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) { + if (box.IsType("tenc") && ParseTenc(box).isErr()) { + return Err(NS_ERROR_FAILURE); + } + } + return Ok(); +} + +Result<Ok, nsresult> SinfParser::ParseTenc(Box& aBox) { + BoxReader reader(aBox); + + if (reader->Remaining() < 24) { + return Err(NS_ERROR_FAILURE); + } + + uint32_t flags; + MOZ_TRY_VAR(flags, reader->ReadU32()); + uint8_t version = flags >> 24; + + // Skip reserved byte + MOZ_TRY(reader->ReadU8()); + if (version >= 1) { + uint8_t pattern; + MOZ_TRY_VAR(pattern, reader->ReadU8()); + mSinf.mDefaultCryptByteBlock = pattern >> 4; + mSinf.mDefaultSkipByteBlock = pattern & 0x0f; + } else { + // Reserved if version is less than 1 + MOZ_TRY(reader->ReadU8()); + mSinf.mDefaultCryptByteBlock = 0; + mSinf.mDefaultSkipByteBlock = 0; + } + + uint8_t isEncrypted; + MOZ_TRY_VAR(isEncrypted, reader->ReadU8()); + MOZ_TRY_VAR(mSinf.mDefaultIVSize, reader->ReadU8()); + memcpy(mSinf.mDefaultKeyID, reader->Read(16), 16); + + if (isEncrypted && mSinf.mDefaultIVSize == 0) { + uint8_t defaultConstantIVSize; + MOZ_TRY_VAR(defaultConstantIVSize, reader->ReadU8()); + if (!mSinf.mDefaultConstantIV.SetLength(defaultConstantIVSize, + mozilla::fallible)) { + return Err(NS_ERROR_FAILURE); + } + for (uint8_t i = 0; i < defaultConstantIVSize; i++) { + MOZ_TRY_VAR(mSinf.mDefaultConstantIV.ElementAt(i), reader->ReadU8()); + } + } + return Ok(); +} + +} // namespace mozilla |