summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/binding/MoofParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'media/libstagefright/binding/MoofParser.cpp')
-rw-r--r--media/libstagefright/binding/MoofParser.cpp479
1 files changed, 407 insertions, 72 deletions
diff --git a/media/libstagefright/binding/MoofParser.cpp b/media/libstagefright/binding/MoofParser.cpp
index ced054282..771be3428 100644
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -27,6 +27,8 @@ namespace mp4_demuxer
using namespace stagefright;
using namespace mozilla;
+const uint32_t kKeyIdSize = 16;
+
bool
MoofParser::RebuildFragmentedIndex(const MediaByteRangeSet& aByteRanges)
{
@@ -330,6 +332,18 @@ MoofParser::ParseStbl(Box& aBox)
for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
if (box.IsType("stsd")) {
ParseStsd(box);
+ } else if (box.IsType("sgpd")) {
+ Sgpd sgpd(box);
+ if (sgpd.IsValid() && sgpd.mGroupingType == "seig") {
+ mTrackSampleEncryptionInfoEntries.Clear();
+ mTrackSampleEncryptionInfoEntries.AppendElements(sgpd.mEntries);
+ }
+ } else if (box.IsType("sbgp")) {
+ Sbgp sbgp(box);
+ if (sbgp.IsValid() && sbgp.mGroupingType == "seig") {
+ mTrackSampleToGroupEntries.Clear();
+ mTrackSampleToGroupEntries.AppendElements(sbgp.mEntries);
+ }
}
}
}
@@ -495,12 +509,25 @@ Moof::ParseTraf(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, S
MOZ_ASSERT(aDecodeTime);
Tfhd tfhd(aTrex);
Tfdt tfdt;
+
for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
if (box.IsType("tfhd")) {
tfhd = Tfhd(box, aTrex);
} else if (!aTrex.mTrackId || tfhd.mTrackId == aTrex.mTrackId) {
if (box.IsType("tfdt")) {
tfdt = Tfdt(box);
+ } else if (box.IsType("sgpd")) {
+ Sgpd sgpd(box);
+ if (sgpd.IsValid() && sgpd.mGroupingType == "seig") {
+ mFragmentSampleEncryptionInfoEntries.Clear();
+ mFragmentSampleEncryptionInfoEntries.AppendElements(sgpd.mEntries);
+ }
+ } else if (box.IsType("sbgp")) {
+ Sbgp sbgp(box);
+ if (sbgp.IsValid() && sbgp.mGroupingType == "seig") {
+ mFragmentSampleToGroupEntries.Clear();
+ mFragmentSampleToGroupEntries.AppendElements(sbgp.mEntries);
+ }
} else if (box.IsType("saiz")) {
mSaizs.AppendElement(Saiz(box, aSinf.mDefaultEncryptionType));
} else if (box.IsType("saio")) {
@@ -550,14 +577,20 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, u
LOG(Moof, "Incomplete Box (missing flags)");
return false;
}
- uint32_t flags = reader->ReadU32();
+ uint32_t flags;
+ if (!reader->ReadU32(flags)) {
+ return false;
+ }
uint8_t version = flags >> 24;
if (!reader->CanReadType<uint32_t>()) {
LOG(Moof, "Incomplete Box (missing sampleCount)");
return false;
}
- uint32_t sampleCount = reader->ReadU32();
+ uint32_t sampleCount;
+ if (!reader->ReadU32(sampleCount)) {
+ return false;
+ }
if (sampleCount == 0) {
return true;
}
@@ -577,9 +610,21 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, u
return false;
}
- uint64_t offset = aTfhd.mBaseDataOffset + (flags & 1 ? reader->ReadU32() : 0);
- uint32_t firstSampleFlags =
- flags & 4 ? reader->ReadU32() : aTfhd.mDefaultSampleFlags;
+ uint64_t offset = aTfhd.mBaseDataOffset;
+ if (flags & 1) {
+ uint32_t baseOffset;
+ if (!reader->ReadU32(baseOffset)) {
+ return false;
+ }
+ offset += baseOffset;
+ }
+ uint32_t firstSampleFlags = aTfhd.mDefaultSampleFlags;
+ if (flags & 4) {
+ if (!reader->ReadU32(firstSampleFlags)) {
+ return false;
+ }
+ }
+
uint64_t decodeTime = *aDecodeTime;
nsTArray<Interval<Microseconds>> timeRanges;
@@ -589,16 +634,29 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, u
}
for (size_t i = 0; i < sampleCount; i++) {
- uint32_t sampleDuration =
- flags & 0x100 ? reader->ReadU32() : aTfhd.mDefaultSampleDuration;
- uint32_t sampleSize =
- flags & 0x200 ? reader->ReadU32() : aTfhd.mDefaultSampleSize;
- uint32_t sampleFlags =
- flags & 0x400 ? reader->ReadU32()
- : i ? aTfhd.mDefaultSampleFlags : firstSampleFlags;
+ uint32_t sampleDuration = aTfhd.mDefaultSampleDuration;
+ if (flags & 0x100) {
+ if (!reader->ReadU32(sampleDuration)) {
+ return false;
+ }
+ }
+ uint32_t sampleSize = aTfhd.mDefaultSampleSize;
+ if (flags & 0x200) {
+ if (!reader->ReadU32(sampleSize)) {
+ return false;
+ }
+ }
+ uint32_t sampleFlags = i ? aTfhd.mDefaultSampleFlags : firstSampleFlags;
+ if (flags & 0x400) {
+ if (!reader->ReadU32(sampleFlags)) {
+ return false;
+ }
+ }
int32_t ctsOffset = 0;
if (flags & 0x800) {
- ctsOffset = reader->Read32();
+ if (!reader->Read32(ctsOffset)) {
+ return false;
+ }
}
Sample sample;
@@ -635,7 +693,10 @@ Tkhd::Tkhd(Box& aBox)
LOG(Tkhd, "Incomplete Box (missing flags)");
return;
}
- uint32_t flags = reader->ReadU32();
+ uint32_t flags;
+ if (!reader->ReadU32(flags)) {
+ return;
+ }
uint8_t version = flags >> 24;
size_t need =
3*(version ? sizeof(int64_t) : sizeof(int32_t)) + 2*sizeof(int32_t);
@@ -645,19 +706,30 @@ Tkhd::Tkhd(Box& aBox)
return;
}
if (version == 0) {
- mCreationTime = reader->ReadU32();
- mModificationTime = reader->ReadU32();
- mTrackId = reader->ReadU32();
- uint32_t reserved = reader->ReadU32();
+ uint32_t createTime, modificationTime, trackId, reserved, duration;
+ if (!reader->ReadU32(createTime) ||
+ !reader->ReadU32(modificationTime) ||
+ !reader->ReadU32(trackId) ||
+ !reader->ReadU32(reserved) ||
+ !reader->ReadU32(duration)) {
+ return;
+ }
NS_ASSERTION(!reserved, "reserved should be 0");
- mDuration = reader->ReadU32();
+ mCreationTime = createTime;
+ mModificationTime = modificationTime;
+ mTrackId = trackId;
+ mDuration = duration;
} else if (version == 1) {
- mCreationTime = reader->ReadU64();
- mModificationTime = reader->ReadU64();
- mTrackId = reader->ReadU32();
- uint32_t reserved = reader->ReadU32();
+ uint32_t trackId, reserved;
+ if (!reader->ReadU64(mCreationTime) ||
+ !reader->ReadU64(mModificationTime) ||
+ !reader->ReadU32(trackId) ||
+ !reader->ReadU32(reserved) ||
+ !reader->ReadU64(mDuration)) {
+ return;
+ }
NS_ASSERTION(!reserved, "reserved should be 0");
- mDuration = reader->ReadU64();
+ mTrackId = trackId;
}
// We don't care about whatever else may be in the box.
mValid = true;
@@ -670,10 +742,13 @@ Mvhd::Mvhd(Box& aBox)
LOG(Mdhd, "Incomplete Box (missing flags)");
return;
}
- uint32_t flags = reader->ReadU32();
+ uint32_t flags;
+ if (!reader->ReadU32(flags)) {
+ return;
+ }
uint8_t version = flags >> 24;
size_t need =
- 3*(version ? sizeof(int64_t) : sizeof(int32_t)) + sizeof(uint32_t);
+ 3 * (version ? sizeof(int64_t) : sizeof(int32_t)) + sizeof(uint32_t);
if (reader->Remaining() < need) {
LOG(Mvhd, "Incomplete Box (have:%lld need:%lld)",
(uint64_t)reader->Remaining(), (uint64_t)need);
@@ -681,15 +756,23 @@ Mvhd::Mvhd(Box& aBox)
}
if (version == 0) {
- mCreationTime = reader->ReadU32();
- mModificationTime = reader->ReadU32();
- mTimescale = reader->ReadU32();
- mDuration = reader->ReadU32();
+ uint32_t createTime, modificationTime, duration;
+ if (!reader->ReadU32(createTime) ||
+ !reader->ReadU32(modificationTime) ||
+ !reader->ReadU32(mTimescale) ||
+ !reader->ReadU32(duration)) {
+ return;
+ }
+ mCreationTime = createTime;
+ mModificationTime = modificationTime;
+ mDuration = duration;
} else if (version == 1) {
- mCreationTime = reader->ReadU64();
- mModificationTime = reader->ReadU64();
- mTimescale = reader->ReadU32();
- mDuration = reader->ReadU64();
+ if (!reader->ReadU64(mCreationTime) ||
+ !reader->ReadU64(mModificationTime) ||
+ !reader->ReadU32(mTimescale) ||
+ !reader->ReadU64(mDuration)) {
+ return;
+ }
} else {
return;
}
@@ -707,18 +790,19 @@ Mdhd::Mdhd(Box& aBox)
Trex::Trex(Box& aBox)
{
BoxReader reader(aBox);
- if (reader->Remaining() < 6*sizeof(uint32_t)) {
+ if (reader->Remaining() < 6 * sizeof(uint32_t)) {
LOG(Trex, "Incomplete Box (have:%lld need:%lld)",
(uint64_t)reader->Remaining(), (uint64_t)6*sizeof(uint32_t));
return;
}
- mFlags = reader->ReadU32();
- mTrackId = reader->ReadU32();
- mDefaultSampleDescriptionIndex = reader->ReadU32();
- mDefaultSampleDuration = reader->ReadU32();
- mDefaultSampleSize = reader->ReadU32();
- mDefaultSampleFlags = reader->ReadU32();
- mValid = true;
+ if (!reader->ReadU32(mFlags) ||
+ !reader->ReadU32(mTrackId) ||
+ !reader->ReadU32(mDefaultSampleDescriptionIndex) ||
+ !reader->ReadU32(mDefaultSampleDuration) ||
+ !reader->ReadU32(mDefaultSampleSize) ||
+ !reader->ReadU32(mDefaultSampleFlags)) {
+ return;
+ }
}
Tfhd::Tfhd(Box& aBox, Trex& aTrex)
@@ -733,7 +817,9 @@ Tfhd::Tfhd(Box& aBox, Trex& aTrex)
LOG(Tfhd, "Incomplete Box (missing flags)");
return;
}
- mFlags = reader->ReadU32();
+ if (!reader->ReadU32(mFlags)) {
+ return;
+ }
size_t need = sizeof(uint32_t) /* trackid */;
uint8_t flag[] = { 1, 2, 8, 0x10, 0x20, 0 };
uint8_t flagSize[] = { sizeof(uint64_t), sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t), sizeof(uint32_t) };
@@ -747,20 +833,34 @@ Tfhd::Tfhd(Box& aBox, Trex& aTrex)
(uint64_t)reader->Remaining(), (uint64_t)need);
return;
}
- mTrackId = reader->ReadU32();
- mBaseDataOffset =
- mFlags & 1 ? reader->ReadU64() : aBox.Parent()->Parent()->Offset();
+ if (!reader->ReadU32(mTrackId)) {
+ return;
+ }
+ mBaseDataOffset = aBox.Parent()->Parent()->Offset();
+ if (mFlags & 1) {
+ if (!reader->ReadU64(mBaseDataOffset)) {
+ return;
+ }
+ }
if (mFlags & 2) {
- mDefaultSampleDescriptionIndex = reader->ReadU32();
+ if (!reader->ReadU32(mDefaultSampleDescriptionIndex)) {
+ return;
+ }
}
if (mFlags & 8) {
- mDefaultSampleDuration = reader->ReadU32();
+ if (!reader->ReadU32(mDefaultSampleDuration)) {
+ return;
+ }
}
if (mFlags & 0x10) {
- mDefaultSampleSize = reader->ReadU32();
+ if (!reader->ReadU32(mDefaultSampleSize)) {
+ return;
+ }
}
if (mFlags & 0x20) {
- mDefaultSampleFlags = reader->ReadU32();
+ if (!reader->ReadU32(mDefaultSampleFlags)) {
+ return;
+ }
}
mValid = true;
}
@@ -772,7 +872,10 @@ Tfdt::Tfdt(Box& aBox)
LOG(Tfdt, "Incomplete Box (missing flags)");
return;
}
- uint32_t flags = reader->ReadU32();
+ uint32_t flags;
+ if (!reader->ReadU32(flags)) {
+ return;
+ }
uint8_t version = flags >> 24;
size_t need = version ? sizeof(uint64_t) : sizeof(uint32_t) ;
if (reader->Remaining() < need) {
@@ -781,9 +884,15 @@ Tfdt::Tfdt(Box& aBox)
return;
}
if (version == 0) {
- mBaseMediaDecodeTime = reader->ReadU32();
+ uint32_t baseDecodeTime;
+ if (!reader->ReadU32(baseDecodeTime)) {
+ return;
+ }
+ mBaseMediaDecodeTime = baseDecodeTime;
} else if (version == 1) {
- mBaseMediaDecodeTime = reader->ReadU64();
+ if (!reader->ReadU64(mBaseMediaDecodeTime)) {
+ return;
+ }
}
mValid = true;
}
@@ -802,7 +911,10 @@ Edts::Edts(Box& aBox)
LOG(Edts, "Incomplete Box (missing flags)");
return;
}
- uint32_t flags = reader->ReadU32();
+ uint32_t flags;
+ if (!reader->ReadU32(flags)) {
+ return;
+ }
uint8_t version = flags >> 24;
size_t need =
sizeof(uint32_t) + 2*(version ? sizeof(int64_t) : sizeof(uint32_t));
@@ -812,16 +924,27 @@ Edts::Edts(Box& aBox)
return;
}
bool emptyEntry = false;
- uint32_t entryCount = reader->ReadU32();
+ uint32_t entryCount;
+ if (!reader->ReadU32(entryCount)) {
+ return;
+ }
for (uint32_t i = 0; i < entryCount; i++) {
uint64_t segment_duration;
int64_t media_time;
if (version == 1) {
- segment_duration = reader->ReadU64();
- media_time = reader->Read64();
+ if (!reader->ReadU64(segment_duration) ||
+ !reader->Read64(media_time)) {
+ return;
+ }
} else {
- segment_duration = reader->ReadU32();
- media_time = reader->Read32();
+ uint32_t duration;
+ int32_t time;
+ if (!reader->ReadU32(duration) ||
+ !reader->Read32(time)) {
+ return;
+ }
+ segment_duration = duration;
+ media_time = time;
}
if (media_time == -1 && i) {
LOG(Edts, "Multiple empty edit, not handled");
@@ -834,8 +957,12 @@ Edts::Edts(Box& aBox)
} else {
mMediaStart = media_time;
}
- reader->ReadU32(); // media_rate_integer and media_rate_fraction
+ // media_rate_integer and media_rate_fraction
+ if (!reader->Skip(4)) {
+ return;
+ }
}
+ mValid = true;
}
Saiz::Saiz(Box& aBox, AtomType aDefaultType)
@@ -847,7 +974,10 @@ Saiz::Saiz(Box& aBox, AtomType aDefaultType)
LOG(Saiz, "Incomplete Box (missing flags)");
return;
}
- uint32_t flags = reader->ReadU32();
+ uint32_t flags;
+ if (!reader->ReadU32(flags)) {
+ return;
+ }
uint8_t version = flags >> 24;
size_t need =
((flags & 1) ? 2*sizeof(uint32_t) : 0) + sizeof(uint8_t) + sizeof(uint32_t);
@@ -857,11 +987,19 @@ Saiz::Saiz(Box& aBox, AtomType aDefaultType)
return;
}
if (flags & 1) {
- mAuxInfoType = reader->ReadU32();
- mAuxInfoTypeParameter = reader->ReadU32();
+ uint32_t auxType;
+ if (!reader->ReadU32(auxType) ||
+ !reader->ReadU32(mAuxInfoTypeParameter)) {
+ return;
+ }
+ mAuxInfoType = auxType;
+ }
+ uint8_t defaultSampleInfoSize;
+ uint32_t count;
+ if (!reader->ReadU8(defaultSampleInfoSize) ||
+ !reader->ReadU32(count)) {
+ return;
}
- uint8_t defaultSampleInfoSize = reader->ReadU8();
- uint32_t count = reader->ReadU32();
if (defaultSampleInfoSize) {
if (!mSampleInfoSize.SetLength(count, fallible)) {
LOG(Saiz, "OOM");
@@ -886,19 +1024,29 @@ Saio::Saio(Box& aBox, AtomType aDefaultType)
LOG(Saio, "Incomplete Box (missing flags)");
return;
}
- uint32_t flags = reader->ReadU32();
+ uint32_t flags;
+ if (!reader->ReadU32(flags)) {
+ return;
+ }
uint8_t version = flags >> 24;
- size_t need = ((flags & 1) ? (2*sizeof(uint32_t)) : 0) + sizeof(uint32_t);
+ size_t need = ((flags & 1) ? (2 * sizeof(uint32_t)) : 0) + sizeof(uint32_t);
if (reader->Remaining() < need) {
LOG(Saio, "Incomplete Box (have:%lld need:%lld)",
(uint64_t)reader->Remaining(), (uint64_t)need);
return;
}
if (flags & 1) {
- mAuxInfoType = reader->ReadU32();
- mAuxInfoTypeParameter = reader->ReadU32();
+ uint32_t auxType;
+ if (!reader->ReadU32(auxType) ||
+ !reader->ReadU32(mAuxInfoTypeParameter)) {
+ return;
+ }
+ mAuxInfoType = auxType;
+ }
+ uint32_t count;
+ if (!reader->ReadU32(count)) {
+ return;
}
- size_t count = reader->ReadU32();
need = (version ? sizeof(uint64_t) : sizeof(uint32_t)) * count;
if (reader->Remaining() < need) {
LOG(Saio, "Incomplete Box (have:%lld need:%lld)",
@@ -910,16 +1058,203 @@ Saio::Saio(Box& aBox, AtomType aDefaultType)
return;
}
if (version == 0) {
+ uint32_t offset;
for (size_t i = 0; i < count; i++) {
- MOZ_ALWAYS_TRUE(mOffsets.AppendElement(reader->ReadU32(), fallible));
+ if (!reader->ReadU32(offset)) {
+ return;
+ }
+ MOZ_ALWAYS_TRUE(mOffsets.AppendElement(offset, fallible));
}
} else {
+ uint64_t offset;
for (size_t i = 0; i < count; i++) {
- MOZ_ALWAYS_TRUE(mOffsets.AppendElement(reader->ReadU64(), fallible));
+ if (!reader->ReadU64(offset)) {
+ return;
+ }
+ MOZ_ALWAYS_TRUE(mOffsets.AppendElement(offset, fallible));
+ }
+ }
+ mValid = true;
+}
+
+Sbgp::Sbgp(Box& aBox)
+{
+ BoxReader reader(aBox);
+
+ if (!reader->CanReadType<uint32_t>()) {
+ LOG(Sbgp, "Incomplete Box (missing flags)");
+ return;
+ }
+
+ uint32_t flags;
+ if (!reader->ReadU32(flags)) {
+ return;
+ }
+ const uint8_t version = flags >> 24;
+ flags = flags & 0xffffff;
+
+ // Make sure we have enough bytes to read as far as the count.
+ uint32_t need = (version == 1 ? sizeof(uint32_t) : 0) + sizeof(uint32_t) * 2;
+ if (reader->Remaining() < need) {
+ LOG(Sbgp, "Incomplete Box (have:%lld, need:%lld)",
+ (uint64_t)reader->Remaining(), (uint64_t)need);
+ return;
+ }
+
+ uint32_t groupType;
+ if (!reader->ReadU32(groupType)) {
+ return;
+ }
+ mGroupingType = groupType;
+
+ if (version == 1) {
+ if (reader->ReadU32(mGroupingTypeParam)) {
+ false;
+ }
+ }
+
+ uint32_t count;
+ if (!reader->ReadU32(count)) {
+ return;
+ }
+
+ // Make sure we can read all the entries.
+ need = sizeof(uint32_t) * 2 * count;
+ if (reader->Remaining() < need) {
+ LOG(Sbgp, "Incomplete Box (have:%lld, need:%lld). Failed to read entries",
+ (uint64_t)reader->Remaining(), (uint64_t)need);
+ return;
+ }
+
+ for (uint32_t i = 0; i < count; i++) {
+ uint32_t sampleCount;
+ uint32_t groupDescriptionIndex;
+ if (!reader->ReadU32(sampleCount) ||
+ !reader->ReadU32(groupDescriptionIndex)) {
+ return;
}
+
+ SampleToGroupEntry entry(sampleCount, groupDescriptionIndex);
+ mEntries.AppendElement(entry);
}
+
mValid = true;
}
+Sgpd::Sgpd(Box& aBox)
+{
+ BoxReader reader(aBox);
+
+ if (!reader->CanReadType<uint32_t>()) {
+ LOG(Sgpd, "Incomplete Box (missing flags)");
+ return;
+ }
+
+ uint32_t flags;
+ if (!reader->ReadU32(flags)) {
+ return;
+ }
+ const uint8_t version = flags >> 24;
+ flags = flags & 0xffffff;
+
+ uint32_t need = ((flags & 1) ? sizeof(uint32_t) : 0) + sizeof(uint32_t) * 2;
+ if (reader->Remaining() < need) {
+ LOG(Sgpd, "Incomplete Box (have:%lld need:%lld)",
+ (uint64_t)reader->Remaining(), (uint64_t)need);
+ return;
+ }
+
+ uint32_t groupType;
+ if (!reader->ReadU32(groupType)) {
+ return;
+ }
+ mGroupingType = groupType;
+
+ const uint32_t entrySize = sizeof(uint32_t) + kKeyIdSize;
+ uint32_t defaultLength = 0;
+
+ if (version == 1) {
+ if (!reader->ReadU32(defaultLength)) {
+ return;
+ }
+ if (defaultLength < entrySize && defaultLength != 0) {
+ return;
+ }
+ }
+
+ uint32_t count;
+ if (!reader->ReadU32(count)) {
+ return;
+ }
+
+ // Make sure we have sufficient remaining bytes to read the entries.
+ need =
+ count * (sizeof(uint32_t) * (version == 1 && defaultLength == 0 ? 2 : 1) +
+ kKeyIdSize * sizeof(uint8_t));
+ if (reader->Remaining() < need) {
+ LOG(Sgpd, "Incomplete Box (have:%lld need:%lld). Failed to read entries",
+ (uint64_t)reader->Remaining(), (uint64_t)need);
+ return;
+ }
+ for (uint32_t i = 0; i < count; ++i) {
+ if (version == 1 && defaultLength == 0) {
+ uint32_t descriptionLength;
+ if (!reader->ReadU32(descriptionLength)) {
+ return;
+ }
+ if (descriptionLength < entrySize) {
+ return;
+ }
+ }
+
+ CencSampleEncryptionInfoEntry entry;
+ bool valid = entry.Init(reader);
+ if (!valid) {
+ return;
+ }
+ mEntries.AppendElement(entry);
+ }
+
+ mValid = true;
+}
+
+bool CencSampleEncryptionInfoEntry::Init(BoxReader& aReader)
+{
+ // Skip a reserved byte.
+ uint8_t skip;
+ if (!aReader->ReadU8(skip)) {
+ return false;
+ }
+
+ uint8_t possiblePatternInfo;
+ uint8_t flag;
+ if (!aReader->ReadU8(possiblePatternInfo) ||
+ !aReader->ReadU8(flag) ||
+ !aReader->ReadU8(mIVSize)) {
+ return false;
+ }
+
+ // Read the key id.
+ uint8_t key;
+ for (uint32_t i = 0; i < kKeyIdSize; ++i) {
+ if (!aReader->ReadU8(key)) {
+ return false;
+ }
+ mKeyId.AppendElement(key);
+ }
+
+ mIsEncrypted = flag != 0;
+
+ if (mIsEncrypted) {
+ if (mIVSize != 8 && mIVSize != 16) {
+ return false;
+ }
+ } else if (mIVSize != 0) {
+ return false;
+ }
+
+ return true;
+}
+
#undef LOG
}