--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -701,196 +701,241 @@ Moof::ParseTrun(Box& aBox, Tfhd& aTfhd,
*aDecodeTime = decodeTime;
return true;
}
Tkhd::Tkhd(Box& aBox)
{
+ if (Parse(aBox)) {
+ mValid = true;
+ }
+}
+
+bool
+Tkhd::Parse(Box& aBox)
+{
BoxReader reader(aBox);
if (!reader->CanReadType<uint32_t>()) {
LOG(Tkhd, "Incomplete Box (missing flags)");
- return;
+ return false;
}
uint32_t flags = reader->ReadU32();
uint8_t version = flags >> 24;
size_t need =
3*(version ? sizeof(int64_t) : sizeof(int32_t)) + 2*sizeof(int32_t);
if (reader->Remaining() < need) {
LOG(Tkhd, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
if (version == 0) {
mCreationTime = reader->ReadU32();
mModificationTime = reader->ReadU32();
mTrackId = reader->ReadU32();
uint32_t reserved = reader->ReadU32();
NS_ASSERTION(!reserved, "reserved should be 0");
mDuration = reader->ReadU32();
} else if (version == 1) {
mCreationTime = reader->ReadU64();
mModificationTime = reader->ReadU64();
mTrackId = reader->ReadU32();
uint32_t reserved = reader->ReadU32();
NS_ASSERTION(!reserved, "reserved should be 0");
mDuration = reader->ReadU64();
}
- // We don't care about whatever else may be in the box.
- mValid = true;
+ return true;
}
Mvhd::Mvhd(Box& aBox)
{
+ if (Parse(aBox)) {
+ mValid = true;
+ }
+}
+
+bool
+Mvhd::Parse(Box& aBox)
+{
BoxReader reader(aBox);
if (!reader->CanReadType<uint32_t>()) {
LOG(Mdhd, "Incomplete Box (missing flags)");
- return;
+ return false;
}
uint32_t flags = reader->ReadU32();
uint8_t version = flags >> 24;
size_t need =
3*(version ? sizeof(int64_t) : sizeof(int32_t)) + sizeof(uint32_t);
if (reader->Remaining() < need) {
LOG(Mvhd, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
if (version == 0) {
mCreationTime = reader->ReadU32();
mModificationTime = reader->ReadU32();
mTimescale = reader->ReadU32();
mDuration = reader->ReadU32();
} else if (version == 1) {
mCreationTime = reader->ReadU64();
mModificationTime = reader->ReadU64();
mTimescale = reader->ReadU32();
mDuration = reader->ReadU64();
} else {
- return;
+ return false;
}
- // We don't care about whatever else may be in the box.
- if (mTimescale) {
- mValid = true;
- }
+ return true;
}
Mdhd::Mdhd(Box& aBox)
: Mvhd(aBox)
{
}
Trex::Trex(Box& aBox)
{
+ if (Parse(aBox)) {
+ mValid = true;
+ }
+}
+
+bool
+Trex::Parse(Box& aBox)
+{
BoxReader reader(aBox);
if (reader->Remaining() < 6*sizeof(uint32_t)) {
LOG(Trex, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
(uint64_t)reader->Remaining(), (uint64_t)6*sizeof(uint32_t));
- return;
+ return false;
}
mFlags = reader->ReadU32();
mTrackId = reader->ReadU32();
mDefaultSampleDescriptionIndex = reader->ReadU32();
mDefaultSampleDuration = reader->ReadU32();
mDefaultSampleSize = reader->ReadU32();
mDefaultSampleFlags = reader->ReadU32();
- mValid = true;
+ return true;
}
Tfhd::Tfhd(Box& aBox, Trex& aTrex)
: Trex(aTrex)
{
+ if (Parse(aBox)) {
+ mValid = true;
+ }
+}
+
+bool
+Tfhd::Parse(Box& aBox)
+{
MOZ_ASSERT(aBox.IsType("tfhd"));
MOZ_ASSERT(aBox.Parent()->IsType("traf"));
MOZ_ASSERT(aBox.Parent()->Parent()->IsType("moof"));
BoxReader reader(aBox);
if (!reader->CanReadType<uint32_t>()) {
LOG(Tfhd, "Incomplete Box (missing flags)");
- return;
+ return false;
}
mFlags = reader->ReadU32();
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) };
for (size_t i = 0; flag[i]; i++) {
if (mFlags & flag[i]) {
need += flagSize[i];
}
}
if (reader->Remaining() < need) {
LOG(Tfhd, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
mTrackId = reader->ReadU32();
mBaseDataOffset =
mFlags & 1 ? reader->ReadU64() : aBox.Parent()->Parent()->Offset();
if (mFlags & 2) {
mDefaultSampleDescriptionIndex = reader->ReadU32();
}
if (mFlags & 8) {
mDefaultSampleDuration = reader->ReadU32();
}
if (mFlags & 0x10) {
mDefaultSampleSize = reader->ReadU32();
}
if (mFlags & 0x20) {
mDefaultSampleFlags = reader->ReadU32();
}
- mValid = true;
+
+ return true;
}
Tfdt::Tfdt(Box& aBox)
{
+ if (Parse(aBox)) {
+ mValid = true;
+ }
+}
+
+bool
+Tfdt::Parse(Box& aBox)
+{
BoxReader reader(aBox);
if (!reader->CanReadType<uint32_t>()) {
LOG(Tfdt, "Incomplete Box (missing flags)");
- return;
+ return false;
}
uint32_t flags = reader->ReadU32();
uint8_t version = flags >> 24;
size_t need = version ? sizeof(uint64_t) : sizeof(uint32_t) ;
if (reader->Remaining() < need) {
LOG(Tfdt, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
if (version == 0) {
mBaseMediaDecodeTime = reader->ReadU32();
} else if (version == 1) {
mBaseMediaDecodeTime = reader->ReadU64();
}
- mValid = true;
+ return true;
}
Edts::Edts(Box& aBox)
: mMediaStart(0)
, mEmptyOffset(0)
{
+ if (Parse(aBox)) {
+ mValid = true;
+ }
+}
+
+bool
+Edts::Parse(Box& aBox)
+{
Box child = aBox.FirstChild();
if (!child.IsType("elst")) {
- return;
+ return false;
}
BoxReader reader(child);
if (!reader->CanReadType<uint32_t>()) {
LOG(Edts, "Incomplete Box (missing flags)");
- return;
+ return false;
}
uint32_t flags = reader->ReadU32();
uint8_t version = flags >> 24;
size_t need =
sizeof(uint32_t) + 2*(version ? sizeof(int64_t) : sizeof(uint32_t));
if (reader->Remaining() < need) {
LOG(Edts, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
bool emptyEntry = false;
uint32_t entryCount = reader->ReadU32();
for (uint32_t i = 0; i < entryCount; i++) {
uint64_t segment_duration;
int64_t media_time;
if (version == 1) {
segment_duration = reader->ReadU64();
@@ -907,215 +952,247 @@ Edts::Edts(Box& aBox)
} else if (i > 1 || (i > 0 && !emptyEntry)) {
LOG(Edts, "More than one edit entry, not handled. A/V sync will be wrong");
break;
} else {
mMediaStart = media_time;
}
reader->ReadU32(); // media_rate_integer and media_rate_fraction
}
+
+ return true;
}
Saiz::Saiz(Box& aBox, AtomType aDefaultType)
: mAuxInfoType(aDefaultType)
, mAuxInfoTypeParameter(0)
{
+ if (Parse(aBox)) {
+ mValid = true;
+ }
+}
+
+bool
+Saiz::Parse(Box& aBox)
+{
BoxReader reader(aBox);
if (!reader->CanReadType<uint32_t>()) {
LOG(Saiz, "Incomplete Box (missing flags)");
- return;
+ return false;
}
uint32_t flags = reader->ReadU32();
uint8_t version = flags >> 24;
size_t need =
((flags & 1) ? 2*sizeof(uint32_t) : 0) + sizeof(uint8_t) + sizeof(uint32_t);
if (reader->Remaining() < need) {
LOG(Saiz, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
if (flags & 1) {
mAuxInfoType = reader->ReadU32();
mAuxInfoTypeParameter = reader->ReadU32();
}
uint8_t defaultSampleInfoSize = reader->ReadU8();
uint32_t count = reader->ReadU32();
if (defaultSampleInfoSize) {
if (!mSampleInfoSize.SetLength(count, fallible)) {
LOG(Saiz, "OOM");
- return;
+ return false;
}
memset(mSampleInfoSize.Elements(), defaultSampleInfoSize, mSampleInfoSize.Length());
} else {
if (!reader->ReadArray(mSampleInfoSize, count)) {
LOG(Saiz, "Incomplete Box (OOM or missing count:%u)", count);
- return;
+ return false;
}
}
- mValid = true;
+ return true;
}
Saio::Saio(Box& aBox, AtomType aDefaultType)
: mAuxInfoType(aDefaultType)
, mAuxInfoTypeParameter(0)
{
+ if (Parse(aBox)) {
+ mValid = true;
+ }
+}
+
+bool
+Saio::Parse(Box& aBox)
+{
BoxReader reader(aBox);
if (!reader->CanReadType<uint32_t>()) {
LOG(Saio, "Incomplete Box (missing flags)");
- return;
+ return false;
}
uint32_t flags = reader->ReadU32();
uint8_t version = flags >> 24;
size_t need = ((flags & 1) ? (2*sizeof(uint32_t)) : 0) + sizeof(uint32_t);
if (reader->Remaining() < need) {
LOG(Saio, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
if (flags & 1) {
mAuxInfoType = reader->ReadU32();
mAuxInfoTypeParameter = reader->ReadU32();
}
size_t count = reader->ReadU32();
need = (version ? sizeof(uint64_t) : sizeof(uint32_t)) * count;
if (reader->Remaining() < need) {
LOG(Saio, "Incomplete Box (have:%" PRIu64 " need:%" PRIu64 ")",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
if (!mOffsets.SetCapacity(count, fallible)) {
LOG(Saiz, "OOM");
- return;
+ return false;
}
if (version == 0) {
for (size_t i = 0; i < count; i++) {
MOZ_ALWAYS_TRUE(mOffsets.AppendElement(reader->ReadU32(), fallible));
}
} else {
for (size_t i = 0; i < count; i++) {
MOZ_ALWAYS_TRUE(mOffsets.AppendElement(reader->ReadU64(), fallible));
}
}
- mValid = true;
+ return true;
}
Sbgp::Sbgp(Box& aBox)
{
+ if (Parse(aBox)) {
+ mValid = true;
+ }
+}
+
+bool
+Sbgp::Parse(Box& aBox)
+{
BoxReader reader(aBox);
if (!reader->CanReadType<uint32_t>()) {
LOG(Sbgp, "Incomplete Box (missing flags)");
- return;
+ return false;
}
uint32_t flags = reader->ReadU32();
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:%" PRIu64 ", need:%" PRIu64 ")",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
mGroupingType = reader->ReadU32();
if (version == 1) {
mGroupingTypeParam = reader->Read32();
}
uint32_t count = reader->ReadU32();
// Make sure we can read all the entries.
need = sizeof(uint32_t) * 2 * count;
if (reader->Remaining() < need) {
LOG(Sbgp, "Incomplete Box (have:%" PRIu64 ", need:%" PRIu64 "). Failed to read entries",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
for (uint32_t i = 0; i < count; i++) {
uint32_t sampleCount = reader->ReadU32();
uint32_t groupDescriptionIndex = reader->ReadU32();
SampleToGroupEntry entry(sampleCount, groupDescriptionIndex);
if (!mEntries.AppendElement(entry, mozilla::fallible)) {
LOG(Sbgp, "OOM");
- return;
+ return false;
}
}
-
- mValid = true;
+ return true;
}
Sgpd::Sgpd(Box& aBox)
{
+ if (Parse(aBox)) {
+ mValid = true;
+ }
+}
+
+bool
+Sgpd::Parse(Box& aBox)
+{
BoxReader reader(aBox);
if (!reader->CanReadType<uint32_t>()) {
LOG(Sgpd, "Incomplete Box (missing flags)");
- return;
+ return false;
}
uint32_t flags = reader->ReadU32();
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:%" PRIu64 " need:%" PRIu64 ")",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
mGroupingType = reader->ReadU32();
const uint32_t entrySize = sizeof(uint32_t) + kKeyIdSize;
uint32_t defaultLength = 0;
if (version == 1) {
defaultLength = reader->ReadU32();
if (defaultLength < entrySize && defaultLength != 0) {
- return;
+ return false;
}
}
uint32_t count = reader->ReadU32();
// 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:%" PRIu64 " need:%" PRIu64 "). Failed to read entries",
(uint64_t)reader->Remaining(), (uint64_t)need);
- return;
+ return false;
}
for (uint32_t i = 0; i < count; ++i) {
if (version == 1 && defaultLength == 0) {
uint32_t descriptionLength = reader->ReadU32();
if (descriptionLength < entrySize) {
- return;
+ return false;
}
}
CencSampleEncryptionInfoEntry entry;
bool valid = entry.Init(reader);
if (!valid) {
- return;
+ return false;
}
if (!mEntries.AppendElement(entry, mozilla::fallible)) {
LOG(Sgpd, "OOM");
- return;
+ return false;
}
}
-
- mValid = true;
+ return true;
}
bool CencSampleEncryptionInfoEntry::Init(BoxReader& aReader)
{
// Skip a reserved byte.
aReader->ReadU8();
uint8_t possiblePatternInfo = aReader->ReadU8();
--- a/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
@@ -38,28 +38,34 @@ public:
int64_t remainder = aTimescaleUnits % mTimescale;
return major * 1000000ll + remainder * 1000000ll / mTimescale;
}
uint64_t mCreationTime;
uint64_t mModificationTime;
uint32_t mTimescale;
uint64_t mDuration;
+
+protected:
+ bool Parse(Box& aBox);
};
class Tkhd : public Mvhd
{
public:
Tkhd()
: mTrackId(0)
{
}
explicit Tkhd(Box& aBox);
uint32_t mTrackId;
+
+protected:
+ bool Parse(Box& aBox);
};
class Mdhd : public Mvhd
{
public:
Mdhd() = default;
explicit Mdhd(Box& aBox);
};
@@ -80,42 +86,51 @@ public:
explicit Trex(Box& aBox);
uint32_t mFlags;
uint32_t mTrackId;
uint32_t mDefaultSampleDescriptionIndex;
uint32_t mDefaultSampleDuration;
uint32_t mDefaultSampleSize;
uint32_t mDefaultSampleFlags;
+
+protected:
+ bool Parse(Box& aBox);
};
class Tfhd : public Trex
{
public:
explicit Tfhd(Trex& aTrex)
: Trex(aTrex)
, mBaseDataOffset(0)
{
mValid = aTrex.IsValid();
}
Tfhd(Box& aBox, Trex& aTrex);
uint64_t mBaseDataOffset;
+
+protected:
+ bool Parse(Box& aBox);
};
class Tfdt : public Atom
{
public:
Tfdt()
: mBaseMediaDecodeTime(0)
{
}
explicit Tfdt(Box& aBox);
uint64_t mBaseMediaDecodeTime;
+
+protected:
+ bool Parse(Box& aBox);
};
class Edts : public Atom
{
public:
Edts()
: mMediaStart(0)
, mEmptyOffset(0)
@@ -125,16 +140,19 @@ public:
virtual bool IsValid()
{
// edts is optional
return true;
}
int64_t mMediaStart;
int64_t mEmptyOffset;
+
+protected:
+ bool Parse(Box& aBox);
};
struct Sample
{
mozilla::MediaByteRange mByteRange;
mozilla::MediaByteRange mCencRange;
Microseconds mDecodeTime;
Interval<Microseconds> mCompositionRange;
@@ -144,26 +162,32 @@ struct Sample
class Saiz final : public Atom
{
public:
Saiz(Box& aBox, AtomType aDefaultType);
AtomType mAuxInfoType;
uint32_t mAuxInfoTypeParameter;
FallibleTArray<uint8_t> mSampleInfoSize;
+
+protected:
+ bool Parse(Box& aBox);
};
class Saio final : public Atom
{
public:
Saio(Box& aBox, AtomType aDefaultType);
AtomType mAuxInfoType;
uint32_t mAuxInfoTypeParameter;
FallibleTArray<uint64_t> mOffsets;
+
+protected:
+ bool Parse(Box& aBox);
};
struct SampleToGroupEntry
{
public:
static const uint32_t kTrackGroupDescriptionIndexBase = 0;
static const uint32_t kFragmentGroupDescriptionIndexBase = 0x10000;
@@ -180,16 +204,19 @@ public:
class Sbgp final : public Atom // SampleToGroup box.
{
public:
explicit Sbgp(Box& aBox);
AtomType mGroupingType;
uint32_t mGroupingTypeParam;
FallibleTArray<SampleToGroupEntry> mEntries;
+
+protected:
+ bool Parse(Box& aBox);
};
struct CencSampleEncryptionInfoEntry final
{
public:
CencSampleEncryptionInfoEntry() { }
bool Init(BoxReader& aReader);
@@ -201,16 +228,19 @@ public:
class Sgpd final : public Atom // SampleGroupDescription box.
{
public:
explicit Sgpd(Box& aBox);
AtomType mGroupingType;
FallibleTArray<CencSampleEncryptionInfoEntry> mEntries;
+
+protected:
+ bool Parse(Box& aBox);
};
class AuxInfo {
public:
AuxInfo(int64_t aMoofOffset, Saiz& aSaiz, Saio& aSaio);
private:
int64_t mMoofOffset;