Bug 1298271 - Make BoxReader use AutoByteReader - r=jya
This is done by moving FlacFrameParsers' AutoByteReader to a more public spot
in libstagefright's bindings.
Using AutoByteReader means there is no more need for explicit calls to
DiscardRemaining(); which means our parsers relying on BoxReader will be more
lenient about boxes that are larger than needed.
MozReview-Commit-ID: 3EERU749WYB
--- a/dom/media/flac/FlacFrameParser.cpp
+++ b/dom/media/flac/FlacFrameParser.cpp
@@ -5,33 +5,21 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "FlacFrameParser.h"
#include "mp4_demuxer/ByteReader.h"
#include "nsTArray.h"
#include "OggCodecState.h"
#include "VideoUtils.h"
+using mp4_demuxer::AutoByteReader;
+
namespace mozilla
{
-class MOZ_RAII AutoByteReader : public mp4_demuxer::ByteReader
-{
-public:
- AutoByteReader(const uint8_t* aData, size_t aSize)
- : mp4_demuxer::ByteReader(aData, aSize)
- {
-
- }
- ~AutoByteReader()
- {
- DiscardRemaining();
- }
-};
-
#define OGG_FLAC_METADATA_TYPE_STREAMINFO 0x7F
#define FLAC_STREAMINFO_SIZE 34
#define BITMASK(x) ((1ULL << x)-1)
enum
{
FLAC_METADATA_TYPE_STREAMINFO = 0,
--- a/media/libstagefright/binding/Box.cpp
+++ b/media/libstagefright/binding/Box.cpp
@@ -2,16 +2,17 @@
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "mp4_demuxer/Box.h"
#include "mp4_demuxer/Stream.h"
#include "mozilla/EndianUtils.h"
+#include "mozilla/Unused.h"
#include <algorithm>
using namespace mozilla;
namespace mp4_demuxer {
// Limit reads to 32MiB max.
// static
@@ -136,20 +137,22 @@ Box::FirstChild() const
{
MOZ_ASSERT(IsAvailable());
if (mChildOffset == mRange.mEnd) {
return Box();
}
return Box(mContext, mChildOffset, this);
}
-bool
-Box::Read(nsTArray<uint8_t>* aDest)
+nsTArray<uint8_t>
+Box::Read()
{
- return Read(aDest, mRange);
+ nsTArray<uint8_t> out;
+ Unused << Read(&out, mRange);
+ return out;
}
bool
Box::Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange)
{
int64_t length;
if (!mContext->mSource->Length(&length)) {
// The HTTP server didn't give us a length to work with.
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -639,18 +639,17 @@ Tkhd::Tkhd(Box& aBox)
} 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();
}
- // More stuff that we don't care about
- reader->DiscardRemaining();
+ // We don't care about whatever else may be in the box.
mValid = true;
}
Mvhd::Mvhd(Box& aBox)
{
BoxReader reader(aBox);
if (!reader->CanReadType<uint32_t>()) {
LOG(Mdhd, "Incomplete Box (missing flags)");
@@ -672,21 +671,19 @@ Mvhd::Mvhd(Box& aBox)
mTimescale = reader->ReadU32();
mDuration = reader->ReadU32();
} else if (version == 1) {
mCreationTime = reader->ReadU64();
mModificationTime = reader->ReadU64();
mTimescale = reader->ReadU32();
mDuration = reader->ReadU64();
} else {
- reader->DiscardRemaining();
return;
}
- // More stuff that we don't care about
- reader->DiscardRemaining();
+ // We don't care about whatever else may be in the box.
if (mTimescale) {
mValid = true;
}
}
Mdhd::Mdhd(Box& aBox)
: Mvhd(aBox)
{
@@ -768,17 +765,16 @@ Tfdt::Tfdt(Box& aBox)
(uint64_t)reader->Remaining(), (uint64_t)need);
return;
}
if (version == 0) {
mBaseMediaDecodeTime = reader->ReadU32();
} else if (version == 1) {
mBaseMediaDecodeTime = reader->ReadU64();
}
- reader->DiscardRemaining();
mValid = true;
}
Edts::Edts(Box& aBox)
: mMediaStart(0)
, mEmptyOffset(0)
{
Box child = aBox.FirstChild();
@@ -849,31 +845,28 @@ Saiz::Saiz(Box& aBox, AtomType aDefaultT
mAuxInfoType = reader->ReadU32();
mAuxInfoTypeParameter = reader->ReadU32();
}
uint8_t defaultSampleInfoSize = reader->ReadU8();
uint32_t count = reader->ReadU32();
if (defaultSampleInfoSize) {
if (!mSampleInfoSize.SetCapacity(count, fallible)) {
LOG(Saiz, "OOM");
- reader->DiscardRemaining();
return;
}
for (int i = 0; i < count; i++) {
MOZ_ALWAYS_TRUE(mSampleInfoSize.AppendElement(defaultSampleInfoSize,
fallible));
}
} else {
if (!reader->ReadArray(mSampleInfoSize, count)) {
LOG(Saiz, "Incomplete Box (OOM or missing count:%u)", count);
- reader->DiscardRemaining();
return;
}
}
- reader->DiscardRemaining();
mValid = true;
}
Saio::Saio(Box& aBox, AtomType aDefaultType)
: mAuxInfoType(aDefaultType)
, mAuxInfoTypeParameter(0)
{
BoxReader reader(aBox);
@@ -897,17 +890,16 @@ Saio::Saio(Box& aBox, AtomType aDefaultT
need = (version ? sizeof(uint64_t) : sizeof(uint32_t)) * count;
if (reader->Remaining() < need) {
LOG(Saio, "Incomplete Box (have:%lld need:%lld)",
(uint64_t)reader->Remaining(), (uint64_t)need);
return;
}
if (!mOffsets.SetCapacity(count, fallible)) {
LOG(Saiz, "OOM");
- reader->DiscardRemaining();
return;
}
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++) {
--- a/media/libstagefright/binding/SinfParser.cpp
+++ b/media/libstagefright/binding/SinfParser.cpp
@@ -36,18 +36,16 @@ SinfParser::ParseSchm(Box& aBox)
BoxReader reader(aBox);
if (reader->Remaining() < 8) {
return;
}
mozilla::Unused << reader->ReadU32(); // flags -- ignore
mSinf.mDefaultEncryptionType = reader->ReadU32();
-
- reader->DiscardRemaining();
}
void
SinfParser::ParseSchi(Box& aBox)
{
for (Box box = aBox.FirstChild(); box.IsAvailable(); box = box.Next()) {
if (box.IsType("tenc")) {
ParseTenc(box);
--- a/media/libstagefright/binding/include/mp4_demuxer/Box.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/Box.h
@@ -43,40 +43,42 @@ public:
uint64_t Length() const { return mRange.mEnd - mRange.mStart; }
uint64_t NextOffset() const { return mRange.mEnd; }
const MediaByteRange& Range() const { return mRange; }
const Box* Parent() const { return mParent; }
bool IsType(const char* aType) const { return mType == AtomType(aType); }
Box Next() const;
Box FirstChild() const;
- bool Read(nsTArray<uint8_t>* aDest);
+ nsTArray<uint8_t> Read();
bool Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange);
static const uint64_t kMAX_BOX_READ;
private:
bool Contains(MediaByteRange aRange) const;
BoxContext* mContext;
mozilla::MediaByteRange mRange;
uint64_t mBodyOffset;
uint64_t mChildOffset;
AtomType mType;
const Box* mParent;
};
+// BoxReader takes a copy of a box contents and serves through an AutoByteReader.
+MOZ_RAII
class BoxReader
{
public:
explicit BoxReader(Box& aBox)
+ : mBuffer(aBox.Read())
+ , mReader(mBuffer.Elements(), mBuffer.Length())
{
- aBox.Read(&mBuffer);
- mReader.SetData(mBuffer);
}
- ByteReader* operator->() { return &mReader; }
- ByteReader mReader;
+ AutoByteReader* operator->() { return &mReader; }
private:
nsTArray<uint8_t> mBuffer;
+ AutoByteReader mReader;
};
}
#endif
--- a/media/libstagefright/binding/include/mp4_demuxer/ByteReader.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/ByteReader.h
@@ -52,17 +52,18 @@ public:
}
size_t Offset()
{
return mLength - mRemaining;
}
// Make it explicit if we're not using the extra bytes.
- void DiscardRemaining() {
+ void DiscardRemaining()
+ {
mRemaining = 0;
}
size_t Remaining() const { return mRemaining; }
bool CanRead8() { return mRemaining >= 1; }
uint8_t ReadU8()
@@ -344,11 +345,29 @@ public:
return true;
}
private:
const uint8_t* mPtr;
size_t mRemaining;
size_t mLength;
};
-}
+
+// A ByteReader that automatically discards remaining data before destruction.
+class MOZ_RAII AutoByteReader : public ByteReader
+{
+public:
+ AutoByteReader(const uint8_t* aData, size_t aSize)
+ : ByteReader(aData, aSize)
+ {
+ }
+ ~AutoByteReader()
+ {
+ ByteReader::DiscardRemaining();
+ }
+
+ // Prevent unneeded DiscardRemaining() calls.
+ void DiscardRemaining() = delete;
+};
+
+} // namespace mp4_demuxer
#endif