summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/binding/include
diff options
context:
space:
mode:
authorMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
committerMatt A. Tobin <mattatobin@localhost.localdomain>2018-02-02 04:16:08 -0500
commit5f8de423f190bbb79a62f804151bc24824fa32d8 (patch)
tree10027f336435511475e392454359edea8e25895d /media/libstagefright/binding/include
parent49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff)
downloadUXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz
UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip
Add m-esr52 at 52.6.0
Diffstat (limited to 'media/libstagefright/binding/include')
-rw-r--r--media/libstagefright/binding/include/demuxer/TrackDemuxer.h34
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/Adts.h26
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/AnnexB.h55
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/Atom.h27
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/AtomType.h31
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/BitReader.h45
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/Box.h84
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/BufferStream.h46
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/ByteReader.h349
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/ByteWriter.h76
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/DecoderData.h93
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/H264.h372
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/Index.h128
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/Interval.h147
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h54
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/MoofParser.h260
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/ResourceStream.h49
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/SinfParser.h51
-rw-r--r--media/libstagefright/binding/include/mp4_demuxer/Stream.h32
-rw-r--r--media/libstagefright/binding/include/mp4parse.h113
20 files changed, 2072 insertions, 0 deletions
diff --git a/media/libstagefright/binding/include/demuxer/TrackDemuxer.h b/media/libstagefright/binding/include/demuxer/TrackDemuxer.h
new file mode 100644
index 000000000..c3f72648b
--- /dev/null
+++ b/media/libstagefright/binding/include/demuxer/TrackDemuxer.h
@@ -0,0 +1,34 @@
+/* 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/. */
+
+#ifndef TRACK_DEMUXER_H_
+#define TRACK_DEMUXER_H_
+
+template <class T> struct already_AddRefed;
+
+namespace mozilla {
+
+class MediaRawData;
+class MediaByteRange;
+
+class TrackDemuxer {
+public:
+ typedef int64_t Microseconds;
+
+ TrackDemuxer() {}
+ virtual ~TrackDemuxer() {}
+
+ virtual void Seek(Microseconds aTime) = 0;
+
+ // DemuxSample returns nullptr on end of stream or error.
+ virtual already_AddRefed<MediaRawData> DemuxSample() = 0;
+
+ // Returns timestamp of next keyframe, or -1 if demuxer can't
+ // report this.
+ virtual Microseconds GetNextKeyframeTime() = 0;
+};
+
+}
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4_demuxer/Adts.h b/media/libstagefright/binding/include/mp4_demuxer/Adts.h
new file mode 100644
index 000000000..8d03beb4b
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/Adts.h
@@ -0,0 +1,26 @@
+/* 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/. */
+
+#ifndef ADTS_H_
+#define ADTS_H_
+
+#include <stdint.h>
+
+namespace mozilla {
+class MediaRawData;
+}
+
+namespace mp4_demuxer
+{
+
+class Adts
+{
+public:
+ static int8_t GetFrequencyIndex(uint32_t aSamplesPerSecond);
+ static bool ConvertSample(uint16_t aChannelCount, int8_t aFrequencyIndex,
+ int8_t aProfile, mozilla::MediaRawData* aSample);
+};
+}
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4_demuxer/AnnexB.h b/media/libstagefright/binding/include/mp4_demuxer/AnnexB.h
new file mode 100644
index 000000000..879e40c84
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/AnnexB.h
@@ -0,0 +1,55 @@
+/* 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/. */
+
+#ifndef MP4_DEMUXER_ANNEX_B_H_
+#define MP4_DEMUXER_ANNEX_B_H_
+
+template <class T> struct already_AddRefed;
+
+namespace mozilla {
+class MediaRawData;
+class MediaByteBuffer;
+}
+namespace mp4_demuxer
+{
+class ByteReader;
+
+class AnnexB
+{
+public:
+ // All conversions assume size of NAL length field is 4 bytes.
+ // Convert a sample from AVCC format to Annex B.
+ static bool ConvertSampleToAnnexB(mozilla::MediaRawData* aSample, bool aAddSPS = true);
+ // Convert a sample from Annex B to AVCC.
+ // an AVCC extradata must not be set.
+ static bool ConvertSampleToAVCC(mozilla::MediaRawData* aSample);
+ static bool ConvertSampleTo4BytesAVCC(mozilla::MediaRawData* aSample);
+
+ // Parse an AVCC extradata and construct the Annex B sample header.
+ static already_AddRefed<mozilla::MediaByteBuffer> ConvertExtraDataToAnnexB(
+ const mozilla::MediaByteBuffer* aExtraData);
+ // Extract SPS and PPS NALs from aSample, aSample must be in AVCC format.
+ // If aSample already contains an extradata with an SPS, it will be returned
+ // otherwise the SPS/PPS NALs are searched in-band.
+ static already_AddRefed<mozilla::MediaByteBuffer> ExtractExtraData(
+ const mozilla::MediaRawData* aSample);
+ static bool HasSPS(const mozilla::MediaRawData* aSample);
+ static bool HasSPS(const mozilla::MediaByteBuffer* aExtraData);
+ // Returns true if format is AVCC and sample has valid extradata.
+ static bool IsAVCC(const mozilla::MediaRawData* aSample);
+ // Returns true if format is AnnexB.
+ static bool IsAnnexB(const mozilla::MediaRawData* aSample);
+ // Return true if both extradata are equal.
+ static bool CompareExtraData(const mozilla::MediaByteBuffer* aExtraData1,
+ const mozilla::MediaByteBuffer* aExtraData2);
+
+private:
+ // AVCC box parser helper.
+ static void ConvertSPSOrPPS(ByteReader& aReader, uint8_t aCount,
+ mozilla::MediaByteBuffer* aAnnexB);
+};
+
+} // namespace mp4_demuxer
+
+#endif // MP4_DEMUXER_ANNEX_B_H_
diff --git a/media/libstagefright/binding/include/mp4_demuxer/Atom.h b/media/libstagefright/binding/include/mp4_demuxer/Atom.h
new file mode 100644
index 000000000..48f2878d4
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/Atom.h
@@ -0,0 +1,27 @@
+/* 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/. */
+
+#ifndef ATOM_H_
+#define ATOM_H_
+
+namespace mp4_demuxer {
+
+class Atom
+{
+public:
+ Atom()
+ : mValid(false)
+ {
+ }
+ virtual bool IsValid()
+ {
+ return mValid;
+ }
+protected:
+ bool mValid;
+};
+
+}
+
+#endif // ATOM_H_
diff --git a/media/libstagefright/binding/include/mp4_demuxer/AtomType.h b/media/libstagefright/binding/include/mp4_demuxer/AtomType.h
new file mode 100644
index 000000000..95baedfe7
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/AtomType.h
@@ -0,0 +1,31 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef ATOM_TYPE_H_
+#define ATOM_TYPE_H_
+
+#include <stdint.h>
+#include "mozilla/EndianUtils.h"
+
+using namespace mozilla;
+
+namespace mp4_demuxer {
+
+class AtomType
+{
+public:
+ AtomType() : mType(0) { }
+ MOZ_IMPLICIT AtomType(uint32_t aType) : mType(aType) { }
+ MOZ_IMPLICIT AtomType(const char* aType) : mType(BigEndian::readUint32(aType)) { }
+ bool operator==(const AtomType& aType) const { return mType == aType.mType; }
+ bool operator!() const { return !mType; }
+
+private:
+ uint32_t mType;
+};
+}
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4_demuxer/BitReader.h b/media/libstagefright/binding/include/mp4_demuxer/BitReader.h
new file mode 100644
index 000000000..27a10338f
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/BitReader.h
@@ -0,0 +1,45 @@
+/* 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/. */
+
+#ifndef BIT_READER_H_
+#define BIT_READER_H_
+
+#include "nsAutoPtr.h"
+#include "MediaData.h"
+
+namespace stagefright { class ABitReader; }
+
+namespace mp4_demuxer
+{
+
+class BitReader
+{
+public:
+ explicit BitReader(const mozilla::MediaByteBuffer* aBuffer);
+ BitReader(const uint8_t* aBuffer, size_t aLength);
+ ~BitReader();
+ uint32_t ReadBits(size_t aNum);
+ uint32_t ReadBit() { return ReadBits(1); }
+ uint32_t ReadU32() { return ReadBits(32); }
+ uint64_t ReadU64();
+
+ // Read the UTF-8 sequence and convert it to its 64-bit UCS-4 encoded form.
+ // Return 0xfffffffffffffff if sequence was invalid.
+ uint64_t ReadUTF8();
+ // Read unsigned integer Exp-Golomb-coded.
+ uint32_t ReadUE();
+ // Read signed integer Exp-Golomb-coded.
+ int32_t ReadSE();
+
+ // Return the number of bits parsed so far;
+ size_t BitCount() const;
+
+private:
+ nsAutoPtr<stagefright::ABitReader> mBitReader;
+ const size_t mSize;
+};
+
+} // namespace mp4_demuxer
+
+#endif // BIT_READER_H_ \ No newline at end of file
diff --git a/media/libstagefright/binding/include/mp4_demuxer/Box.h b/media/libstagefright/binding/include/mp4_demuxer/Box.h
new file mode 100644
index 000000000..f53404a1d
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/Box.h
@@ -0,0 +1,84 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* 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/. */
+
+#ifndef BOX_H_
+#define BOX_H_
+
+#include <stdint.h>
+#include "nsTArray.h"
+#include "MediaResource.h"
+#include "mozilla/EndianUtils.h"
+#include "mp4_demuxer/AtomType.h"
+#include "mp4_demuxer/ByteReader.h"
+
+using namespace mozilla;
+
+namespace mp4_demuxer {
+
+class Stream;
+
+class BoxContext
+{
+public:
+ BoxContext(Stream* aSource, const MediaByteRangeSet& aByteRanges)
+ : mSource(aSource), mByteRanges(aByteRanges)
+ {
+ }
+
+ RefPtr<Stream> mSource;
+ const MediaByteRangeSet& mByteRanges;
+};
+
+class Box
+{
+public:
+ Box(BoxContext* aContext, uint64_t aOffset, const Box* aParent = nullptr);
+ Box();
+
+ bool IsAvailable() const { return !mRange.IsEmpty(); }
+ uint64_t Offset() const { return mRange.mStart; }
+ 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;
+ 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())
+ {
+ }
+ ByteReader* operator->() { return &mReader; }
+
+private:
+ nsTArray<uint8_t> mBuffer;
+ ByteReader mReader;
+};
+}
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4_demuxer/BufferStream.h b/media/libstagefright/binding/include/mp4_demuxer/BufferStream.h
new file mode 100644
index 000000000..bb703db5d
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/BufferStream.h
@@ -0,0 +1,46 @@
+/* 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/. */
+
+#ifndef BUFFER_STREAM_H_
+#define BUFFER_STREAM_H_
+
+#include "mp4_demuxer/Stream.h"
+#include "nsTArray.h"
+#include "MediaResource.h"
+
+namespace mozilla {
+class MediaByteBuffer;
+}
+
+namespace mp4_demuxer {
+
+class BufferStream : public Stream
+{
+public:
+ /* BufferStream does not take ownership of aData nor does it make a copy.
+ * Therefore BufferStream shouldn't get used after aData is destroyed.
+ */
+ BufferStream();
+ explicit BufferStream(mozilla::MediaByteBuffer* aBuffer);
+
+ virtual bool ReadAt(int64_t aOffset, void* aData, size_t aLength,
+ size_t* aBytesRead) override;
+ virtual bool CachedReadAt(int64_t aOffset, void* aData, size_t aLength,
+ size_t* aBytesRead) override;
+ virtual bool Length(int64_t* aLength) override;
+
+ virtual void DiscardBefore(int64_t aOffset) override;
+
+ bool AppendBytes(const uint8_t* aData, size_t aLength);
+
+ mozilla::MediaByteRange GetByteRange();
+
+private:
+ ~BufferStream();
+ int64_t mStartOffset;
+ RefPtr<mozilla::MediaByteBuffer> mData;
+};
+}
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4_demuxer/ByteReader.h b/media/libstagefright/binding/include/mp4_demuxer/ByteReader.h
new file mode 100644
index 000000000..9c7df04bd
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/ByteReader.h
@@ -0,0 +1,349 @@
+/* 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/. */
+
+#ifndef BYTE_READER_H_
+#define BYTE_READER_H_
+
+#include "mozilla/EndianUtils.h"
+#include "mozilla/Vector.h"
+#include "nsTArray.h"
+#include "MediaData.h"
+
+namespace mp4_demuxer {
+
+class MOZ_RAII ByteReader
+{
+public:
+ ByteReader() : mPtr(nullptr), mRemaining(0) {}
+ explicit ByteReader(const mozilla::Vector<uint8_t>& aData)
+ : mPtr(aData.begin()), mRemaining(aData.length()), mLength(aData.length())
+ {
+ }
+ ByteReader(const uint8_t* aData, size_t aSize)
+ : mPtr(aData), mRemaining(aSize), mLength(aSize)
+ {
+ }
+ template<size_t S>
+ explicit ByteReader(const AutoTArray<uint8_t, S>& aData)
+ : mPtr(aData.Elements()), mRemaining(aData.Length()), mLength(aData.Length())
+ {
+ }
+ explicit ByteReader(const nsTArray<uint8_t>& aData)
+ : mPtr(aData.Elements()), mRemaining(aData.Length()), mLength(aData.Length())
+ {
+ }
+ explicit ByteReader(const mozilla::MediaByteBuffer* aData)
+ : mPtr(aData->Elements()), mRemaining(aData->Length()), mLength(aData->Length())
+ {
+ }
+
+ void SetData(const nsTArray<uint8_t>& aData)
+ {
+ MOZ_ASSERT(!mPtr && !mRemaining);
+ mPtr = aData.Elements();
+ mRemaining = aData.Length();
+ mLength = mRemaining;
+ }
+
+ ~ByteReader()
+ {
+ }
+
+ size_t Offset()
+ {
+ return mLength - mRemaining;
+ }
+
+ size_t Remaining() const { return mRemaining; }
+
+ bool CanRead8() { return mRemaining >= 1; }
+
+ uint8_t ReadU8()
+ {
+ auto ptr = Read(1);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return *ptr;
+ }
+
+ bool CanRead16() { return mRemaining >= 2; }
+
+ uint16_t ReadU16()
+ {
+ auto ptr = Read(2);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return mozilla::BigEndian::readUint16(ptr);
+ }
+
+ int16_t ReadLE16()
+ {
+ auto ptr = Read(2);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return mozilla::LittleEndian::readInt16(ptr);
+ }
+
+ uint32_t ReadU24()
+ {
+ auto ptr = Read(3);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
+ }
+
+ uint32_t Read24()
+ {
+ return (uint32_t)ReadU24();
+ }
+
+ int32_t ReadLE24()
+ {
+ auto ptr = Read(3);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ int32_t result = int32_t(ptr[2] << 16 | ptr[1] << 8 | ptr[0]);
+ if (result & 0x00800000u) {
+ result -= 0x1000000;
+ }
+ return result;
+ }
+
+ bool CanRead32() { return mRemaining >= 4; }
+
+ uint32_t ReadU32()
+ {
+ auto ptr = Read(4);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return mozilla::BigEndian::readUint32(ptr);
+ }
+
+ int32_t Read32()
+ {
+ auto ptr = Read(4);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return mozilla::BigEndian::readInt32(ptr);
+ }
+
+ uint64_t ReadU64()
+ {
+ auto ptr = Read(8);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return mozilla::BigEndian::readUint64(ptr);
+ }
+
+ int64_t Read64()
+ {
+ auto ptr = Read(8);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return mozilla::BigEndian::readInt64(ptr);
+ }
+
+ const uint8_t* Read(size_t aCount)
+ {
+ if (aCount > mRemaining) {
+ mRemaining = 0;
+ return nullptr;
+ }
+ mRemaining -= aCount;
+
+ const uint8_t* result = mPtr;
+ mPtr += aCount;
+
+ return result;
+ }
+
+ const uint8_t* Rewind(size_t aCount)
+ {
+ MOZ_ASSERT(aCount <= Offset());
+ size_t rewind = Offset();
+ if (aCount < rewind) {
+ rewind = aCount;
+ }
+ mRemaining += rewind;
+ mPtr -= rewind;
+ return mPtr;
+ }
+
+ uint8_t PeekU8()
+ {
+ auto ptr = Peek(1);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return *ptr;
+ }
+
+ uint16_t PeekU16()
+ {
+ auto ptr = Peek(2);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return mozilla::BigEndian::readUint16(ptr);
+ }
+
+ uint32_t PeekU24()
+ {
+ auto ptr = Peek(3);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return ptr[0] << 16 | ptr[1] << 8 | ptr[2];
+ }
+
+ uint32_t Peek24()
+ {
+ return (uint32_t)PeekU24();
+ }
+
+ uint32_t PeekU32()
+ {
+ auto ptr = Peek(4);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return mozilla::BigEndian::readUint32(ptr);
+ }
+
+ int32_t Peek32()
+ {
+ auto ptr = Peek(4);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return mozilla::BigEndian::readInt32(ptr);
+ }
+
+ uint64_t PeekU64()
+ {
+ auto ptr = Peek(8);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return mozilla::BigEndian::readUint64(ptr);
+ }
+
+ int64_t Peek64()
+ {
+ auto ptr = Peek(8);
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return mozilla::BigEndian::readInt64(ptr);
+ }
+
+ const uint8_t* Peek(size_t aCount)
+ {
+ if (aCount > mRemaining) {
+ return nullptr;
+ }
+ return mPtr;
+ }
+
+ const uint8_t* Seek(size_t aOffset)
+ {
+ if (aOffset >= mLength) {
+ MOZ_ASSERT(false);
+ return nullptr;
+ }
+
+ mPtr = mPtr - Offset() + aOffset;
+ mRemaining = mLength - aOffset;
+ return mPtr;
+ }
+
+ const uint8_t* Reset()
+ {
+ mPtr -= Offset();
+ mRemaining = mLength;
+ return mPtr;
+ }
+
+ uint32_t Align()
+ {
+ return 4 - ((intptr_t)mPtr & 3);
+ }
+
+ template <typename T> bool CanReadType() { return mRemaining >= sizeof(T); }
+
+ template <typename T> T ReadType()
+ {
+ auto ptr = Read(sizeof(T));
+ if (!ptr) {
+ MOZ_ASSERT(false);
+ return 0;
+ }
+ return *reinterpret_cast<const T*>(ptr);
+ }
+
+ template <typename T>
+ MOZ_MUST_USE bool ReadArray(nsTArray<T>& aDest, size_t aLength)
+ {
+ auto ptr = Read(aLength * sizeof(T));
+ if (!ptr) {
+ return false;
+ }
+
+ aDest.Clear();
+ aDest.AppendElements(reinterpret_cast<const T*>(ptr), aLength);
+ return true;
+ }
+
+ template <typename T>
+ MOZ_MUST_USE bool ReadArray(FallibleTArray<T>& aDest, size_t aLength)
+ {
+ auto ptr = Read(aLength * sizeof(T));
+ if (!ptr) {
+ return false;
+ }
+
+ aDest.Clear();
+ if (!aDest.SetCapacity(aLength, mozilla::fallible)) {
+ return false;
+ }
+ MOZ_ALWAYS_TRUE(aDest.AppendElements(reinterpret_cast<const T*>(ptr),
+ aLength,
+ mozilla::fallible));
+ return true;
+ }
+
+private:
+ const uint8_t* mPtr;
+ size_t mRemaining;
+ size_t mLength;
+};
+
+} // namespace mp4_demuxer
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4_demuxer/ByteWriter.h b/media/libstagefright/binding/include/mp4_demuxer/ByteWriter.h
new file mode 100644
index 000000000..48ebdd460
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/ByteWriter.h
@@ -0,0 +1,76 @@
+/* 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/. */
+
+#ifndef BYTE_WRITER_H_
+#define BYTE_WRITER_H_
+
+#include "mozilla/EndianUtils.h"
+#include "mozilla/Vector.h"
+#include "nsTArray.h"
+
+namespace mp4_demuxer {
+
+class ByteWriter
+{
+public:
+ explicit ByteWriter(mozilla::Vector<uint8_t>& aData)
+ : mPtr(aData)
+ {
+ }
+ ~ByteWriter()
+ {
+ }
+
+ MOZ_MUST_USE bool WriteU8(uint8_t aByte)
+ {
+ return Write(&aByte, 1);
+ }
+
+ MOZ_MUST_USE bool WriteU16(uint16_t aShort)
+ {
+ uint8_t c[2];
+ mozilla::BigEndian::writeUint16(&c[0], aShort);
+ return Write(&c[0], 2);
+ }
+
+ MOZ_MUST_USE bool WriteU32(uint32_t aLong)
+ {
+ uint8_t c[4];
+ mozilla::BigEndian::writeUint32(&c[0], aLong);
+ return Write(&c[0], 4);
+ }
+
+ MOZ_MUST_USE bool Write32(int32_t aLong)
+ {
+ uint8_t c[4];
+ mozilla::BigEndian::writeInt32(&c[0], aLong);
+ return Write(&c[0], 4);
+ }
+
+ MOZ_MUST_USE bool WriteU64(uint64_t aLongLong)
+ {
+ uint8_t c[8];
+ mozilla::BigEndian::writeUint64(&c[0], aLongLong);
+ return Write(&c[0], 8);
+ }
+
+ MOZ_MUST_USE bool Write64(int64_t aLongLong)
+ {
+ uint8_t c[8];
+ mozilla::BigEndian::writeInt64(&c[0], aLongLong);
+ return Write(&c[0], 8);
+ }
+
+ MOZ_MUST_USE bool Write(const uint8_t* aSrc, size_t aCount)
+ {
+ return mPtr.append(aSrc, aCount);
+ }
+
+private:
+ mozilla::Vector<uint8_t>& mPtr;
+};
+
+} // namespace mp4_demuxer
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h b/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
new file mode 100644
index 000000000..87262c26a
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/DecoderData.h
@@ -0,0 +1,93 @@
+/* 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/. */
+
+#ifndef DECODER_DATA_H_
+#define DECODER_DATA_H_
+
+#include "MediaData.h"
+#include "MediaInfo.h"
+#include "mozilla/Types.h"
+#include "mozilla/Vector.h"
+#include "mozilla/RefPtr.h"
+#include "nsString.h"
+#include "nsTArray.h"
+#include "nsString.h"
+
+namespace stagefright
+{
+class MetaData;
+}
+
+#ifdef MOZ_RUST_MP4PARSE
+extern "C" {
+typedef struct mp4parse_track_info mp4parse_track_info;
+typedef struct mp4parse_track_audio_info mp4parse_track_audio_info;
+typedef struct mp4parse_track_video_info mp4parse_track_video_info;
+}
+#endif
+
+namespace mp4_demuxer
+{
+
+class MP4Demuxer;
+
+struct PsshInfo
+{
+ PsshInfo() {}
+ PsshInfo(const PsshInfo& aOther) : uuid(aOther.uuid), data(aOther.data) {}
+ nsTArray<uint8_t> uuid;
+ nsTArray<uint8_t> data;
+};
+
+class CryptoFile
+{
+public:
+ CryptoFile() : valid(false) {}
+ CryptoFile(const CryptoFile& aCryptoFile) : valid(aCryptoFile.valid)
+ {
+ pssh.AppendElements(aCryptoFile.pssh);
+ }
+
+ void Update(const uint8_t* aData, size_t aLength)
+ {
+ valid = DoUpdate(aData, aLength);
+ }
+
+ bool valid;
+ nsTArray<PsshInfo> pssh;
+
+private:
+ bool DoUpdate(const uint8_t* aData, size_t aLength);
+};
+
+class MP4AudioInfo : public mozilla::AudioInfo
+{
+public:
+ MP4AudioInfo() = default;
+
+ void Update(const stagefright::MetaData* aMetaData,
+ const char* aMimeType);
+
+ virtual bool IsValid() const override;
+};
+
+class MP4VideoInfo : public mozilla::VideoInfo
+{
+public:
+ MP4VideoInfo() = default;
+
+ void Update(const stagefright::MetaData* aMetaData,
+ const char* aMimeType);
+
+#ifdef MOZ_RUST_MP4PARSE
+ void Update(const mp4parse_track_info* track,
+ const mp4parse_track_video_info* video);
+#endif
+
+ virtual bool IsValid() const override;
+};
+
+}
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4_demuxer/H264.h b/media/libstagefright/binding/include/mp4_demuxer/H264.h
new file mode 100644
index 000000000..2aa710f61
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/H264.h
@@ -0,0 +1,372 @@
+/* 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/. */
+
+#ifndef MP4_DEMUXER_H264_H_
+#define MP4_DEMUXER_H264_H_
+
+#include "mp4_demuxer/DecoderData.h"
+
+namespace mp4_demuxer
+{
+
+class BitReader;
+
+struct SPSData
+{
+ /* Decoded Members */
+ /*
+ pic_width is the decoded width according to:
+ pic_width = ((pic_width_in_mbs_minus1 + 1) * 16)
+ - (frame_crop_left_offset + frame_crop_right_offset) * 2
+ */
+ uint32_t pic_width;
+ /*
+ pic_height is the decoded height according to:
+ pic_height = (2 - frame_mbs_only_flag) * ((pic_height_in_map_units_minus1 + 1) * 16)
+ - (frame_crop_top_offset + frame_crop_bottom_offset) * 2
+ */
+ uint32_t pic_height;
+
+ bool interlaced;
+
+ /*
+ Displayed size.
+ display_width and display_height are adjusted according to the display
+ sample aspect ratio.
+ */
+ uint32_t display_width;
+ uint32_t display_height;
+
+ float sample_ratio;
+
+ uint32_t crop_left;
+ uint32_t crop_right;
+ uint32_t crop_top;
+ uint32_t crop_bottom;
+
+ /*
+ H264 decoding parameters according to ITU-T H.264 (T-REC-H.264-201402-I/en)
+ http://www.itu.int/rec/T-REC-H.264-201402-I/en
+ */
+
+ bool constraint_set0_flag;
+ bool constraint_set1_flag;
+ bool constraint_set2_flag;
+ bool constraint_set3_flag;
+ bool constraint_set4_flag;
+ bool constraint_set5_flag;
+
+ /*
+ profile_idc and level_idc indicate the profile and level to which the coded
+ video sequence conforms when the SVC sequence parameter set is the active
+ SVC sequence parameter set.
+ */
+ uint8_t profile_idc;
+ uint8_t level_idc;
+
+ /*
+ seq_parameter_set_id identifies the sequence parameter set that is referred
+ to by the picture parameter set. The value of seq_parameter_set_id shall be
+ in the range of 0 to 31, inclusive.
+ */
+ uint8_t seq_parameter_set_id;
+
+ /*
+ chroma_format_idc specifies the chroma sampling relative to the luma
+ sampling as specified in clause 6.2. The value of chroma_format_idc shall be
+ in the range of 0 to 3, inclusive. When chroma_format_idc is not present,
+ it shall be inferred to be equal to 1 (4:2:0 chroma format).
+ When profile_idc is equal to 183, chroma_format_idc shall be equal to 0
+ (4:0:0 chroma format).
+ */
+ uint8_t chroma_format_idc;
+
+ /*
+ separate_colour_plane_flag equal to 1 specifies that the three colour
+ components of the 4:4:4 chroma format are coded separately.
+ separate_colour_plane_flag equal to 0 specifies that the colour components
+ are not coded separately. When separate_colour_plane_flag is not present,
+ it shall be inferred to be equal to 0. When separate_colour_plane_flag is
+ equal to 1, the primary coded picture consists of three separate components,
+ each of which consists of coded samples of one colour plane (Y, Cb or Cr)
+ that each use the monochrome coding syntax. In this case, each colour plane
+ is associated with a specific colour_plane_id value.
+ */
+ bool separate_colour_plane_flag;
+
+ /*
+ log2_max_frame_num_minus4 specifies the value of the variable
+ MaxFrameNum that is used in frame_num related derivations as
+ follows:
+
+ MaxFrameNum = 2( log2_max_frame_num_minus4 + 4 ). The value of
+ log2_max_frame_num_minus4 shall be in the range of 0 to 12, inclusive.
+ */
+ uint8_t log2_max_frame_num;
+
+ /*
+ pic_order_cnt_type specifies the method to decode picture order
+ count (as specified in subclause 8.2.1). The value of
+ pic_order_cnt_type shall be in the range of 0 to 2, inclusive.
+ */
+ uint8_t pic_order_cnt_type;
+
+ /*
+ log2_max_pic_order_cnt_lsb_minus4 specifies the value of the
+ variable MaxPicOrderCntLsb that is used in the decoding
+ process for picture order count as specified in subclause
+ 8.2.1 as follows:
+
+ MaxPicOrderCntLsb = 2( log2_max_pic_order_cnt_lsb_minus4 + 4 )
+
+ The value of log2_max_pic_order_cnt_lsb_minus4 shall be in
+ the range of 0 to 12, inclusive.
+ */
+ uint8_t log2_max_pic_order_cnt_lsb;
+
+ /*
+ delta_pic_order_always_zero_flag equal to 1 specifies that
+ delta_pic_order_cnt[ 0 ] and delta_pic_order_cnt[ 1 ] are
+ not present in the slice headers of the sequence and shall
+ be inferred to be equal to 0.
+ */
+ bool delta_pic_order_always_zero_flag;
+
+ /*
+ offset_for_non_ref_pic is used to calculate the picture
+ order count of a non-reference picture as specified in
+ 8.2.1. The value of offset_for_non_ref_pic shall be in the
+ range of -231 to 231 - 1, inclusive.
+ */
+ int8_t offset_for_non_ref_pic;
+
+ /*
+ offset_for_top_to_bottom_field is used to calculate the
+ picture order count of a bottom field as specified in
+ subclause 8.2.1. The value of offset_for_top_to_bottom_field
+ shall be in the range of -231 to 231 - 1, inclusive.
+ */
+ int8_t offset_for_top_to_bottom_field;
+
+ /*
+ max_num_ref_frames specifies the maximum number of short-term and
+ long-term reference frames, complementary reference field pairs,
+ and non-paired reference fields that may be used by the decoding
+ process for inter prediction of any picture in the
+ sequence. max_num_ref_frames also determines the size of the sliding
+ window operation as specified in subclause 8.2.5.3. The value of
+ max_num_ref_frames shall be in the range of 0 to MaxDpbSize (as
+ specified in subclause A.3.1 or A.3.2), inclusive.
+ */
+ uint32_t max_num_ref_frames;
+
+ /*
+ gaps_in_frame_num_value_allowed_flag specifies the allowed
+ values of frame_num as specified in subclause 7.4.3 and the
+ decoding process in case of an inferred gap between values of
+ frame_num as specified in subclause 8.2.5.2.
+ */
+ bool gaps_in_frame_num_allowed_flag;
+
+ /*
+ pic_width_in_mbs_minus1 plus 1 specifies the width of each
+ decoded picture in units of macroblocks. 16 macroblocks in a row
+ */
+ uint32_t pic_width_in_mbs;
+
+ /*
+ pic_height_in_map_units_minus1 plus 1 specifies the height in
+ slice group map units of a decoded frame or field. 16
+ macroblocks in each column.
+ */
+ uint32_t pic_height_in_map_units;
+
+ /*
+ frame_mbs_only_flag equal to 0 specifies that coded pictures of
+ the coded video sequence may either be coded fields or coded
+ frames. frame_mbs_only_flag equal to 1 specifies that every
+ coded picture of the coded video sequence is a coded frame
+ containing only frame macroblocks.
+ */
+ bool frame_mbs_only_flag;
+
+ /*
+ mb_adaptive_frame_field_flag equal to 0 specifies no
+ switching between frame and field macroblocks within a
+ picture. mb_adaptive_frame_field_flag equal to 1 specifies
+ the possible use of switching between frame and field
+ macroblocks within frames. When mb_adaptive_frame_field_flag
+ is not present, it shall be inferred to be equal to 0.
+ */
+ bool mb_adaptive_frame_field_flag;
+
+ /*
+ frame_cropping_flag equal to 1 specifies that the frame cropping
+ offset parameters follow next in the sequence parameter
+ set. frame_cropping_flag equal to 0 specifies that the frame
+ cropping offset parameters are not present.
+ */
+ bool frame_cropping_flag;
+ uint32_t frame_crop_left_offset;;
+ uint32_t frame_crop_right_offset;
+ uint32_t frame_crop_top_offset;
+ uint32_t frame_crop_bottom_offset;
+
+ // VUI Parameters
+
+ /*
+ vui_parameters_present_flag equal to 1 specifies that the
+ vui_parameters( ) syntax structure as specified in Annex E is
+ present. vui_parameters_present_flag equal to 0 specifies that
+ the vui_parameters( ) syntax structure as specified in Annex E
+ is not present.
+ */
+ bool vui_parameters_present_flag;
+
+ /*
+ aspect_ratio_info_present_flag equal to 1 specifies that
+ aspect_ratio_idc is present. aspect_ratio_info_present_flag
+ equal to 0 specifies that aspect_ratio_idc is not present.
+ */
+ bool aspect_ratio_info_present_flag;
+
+ /*
+ aspect_ratio_idc specifies the value of the sample aspect
+ ratio of the luma samples. Table E-1 shows the meaning of
+ the code. When aspect_ratio_idc indicates Extended_SAR, the
+ sample aspect ratio is represented by sar_width and
+ sar_height. When the aspect_ratio_idc syntax element is not
+ present, aspect_ratio_idc value shall be inferred to be
+ equal to 0.
+ */
+ uint8_t aspect_ratio_idc;
+ uint32_t sar_width;
+ uint32_t sar_height;
+
+ /*
+ video_signal_type_present_flag equal to 1 specifies that video_format,
+ video_full_range_flag and colour_description_present_flag are present.
+ video_signal_type_present_flag equal to 0, specify that video_format,
+ video_full_range_flag and colour_description_present_flag are not present.
+ */
+ bool video_signal_type_present_flag;
+
+ /*
+ overscan_info_present_flag equal to1 specifies that the
+ overscan_appropriate_flag is present. When overscan_info_present_flag is
+ equal to 0 or is not present, the preferred display method for the video
+ signal is unspecified (Unspecified).
+ */
+ bool overscan_info_present_flag;
+ /*
+ overscan_appropriate_flag equal to 1 indicates that the cropped decoded
+ pictures output are suitable for display using overscan.
+ overscan_appropriate_flag equal to 0 indicates that the cropped decoded
+ pictures output contain visually important information in the entire region
+ out to the edges of the cropping rectangle of the picture
+ */
+ bool overscan_appropriate_flag;
+
+ /*
+ video_format indicates the representation of the pictures as specified in
+ Table E-2, before being coded in accordance with this
+ Recommendation | International Standard. When the video_format syntax element
+ is not present, video_format value shall be inferred to be equal to 5.
+ (Unspecified video format)
+ */
+ uint8_t video_format;
+
+ /*
+ video_full_range_flag indicates the black level and range of the luma and
+ chroma signals as derived from E′Y, E′PB, and E′PR or E′R, E′G, and E′B
+ real-valued component signals.
+ When the video_full_range_flag syntax element is not present, the value of
+ video_full_range_flag shall be inferred to be equal to 0.
+ */
+ bool video_full_range_flag;
+
+ /*
+ colour_description_present_flag equal to1 specifies that colour_primaries,
+ transfer_characteristics and matrix_coefficients are present.
+ colour_description_present_flag equal to 0 specifies that colour_primaries,
+ transfer_characteristics and matrix_coefficients are not present.
+ */
+ bool colour_description_present_flag;
+
+ /*
+ colour_primaries indicates the chromaticity coordinates of the source
+ primaries as specified in Table E-3 in terms of the CIE 1931 definition of
+ x and y as specified by ISO 11664-1.
+ When the colour_primaries syntax element is not present, the value of
+ colour_primaries shall be inferred to be equal to 2 (the chromaticity is
+ unspecified or is determined by the application).
+ */
+ uint8_t colour_primaries;
+
+ /*
+ transfer_characteristics indicates the opto-electronic transfer
+ characteristic of the source picture as specified in Table E-4 as a function
+ of a linear optical intensity input Lc with a nominal real-valued range of 0
+ to 1.
+ When the transfer_characteristics syntax element is not present, the value
+ of transfer_characteristics shall be inferred to be equal to 2
+ (the transfer characteristics are unspecified or are determined by the
+ application).
+ */
+ uint8_t transfer_characteristics;
+
+ uint8_t matrix_coefficients;
+ bool chroma_loc_info_present_flag;
+ uint32_t chroma_sample_loc_type_top_field;
+ uint32_t chroma_sample_loc_type_bottom_field;
+ bool timing_info_present_flag;
+ uint32_t num_units_in_tick;
+ uint32_t time_scale;
+ bool fixed_frame_rate_flag;
+
+ SPSData();
+};
+
+class H264
+{
+public:
+ static bool DecodeSPSFromExtraData(const mozilla::MediaByteBuffer* aExtraData, SPSData& aDest);
+
+ /* Extract RAW BYTE SEQUENCE PAYLOAD from NAL content.
+ Returns nullptr if invalid content.
+ This is compliant to ITU H.264 7.3.1 Syntax in tabular form NAL unit syntax
+ */
+ static already_AddRefed<mozilla::MediaByteBuffer> DecodeNALUnit(const mozilla::MediaByteBuffer* aNAL);
+
+ /* Decode SPS NAL RBSP and fill SPSData structure */
+ static bool DecodeSPS(const mozilla::MediaByteBuffer* aSPS, SPSData& aDest);
+
+ // Ensure that SPS data makes sense, Return true if SPS data was, and false
+ // otherwise. If false, then content will be adjusted accordingly.
+ static bool EnsureSPSIsSane(SPSData& aSPS);
+
+ // If the given aExtraData is valid, return the aExtraData.max_num_ref_frames
+ // clamped to be in the range of [4, 16]; otherwise return 4.
+ static uint32_t ComputeMaxRefFrames(const mozilla::MediaByteBuffer* aExtraData);
+
+ enum class FrameType
+ {
+ I_FRAME,
+ OTHER,
+ INVALID,
+ };
+
+ // Returns the frame type. Returns I_FRAME if the sample is an IDR
+ // (Instantaneous Decoding Refresh) Picture.
+ static FrameType GetFrameType(const mozilla::MediaRawData* aSample);
+
+private:
+ static void vui_parameters(BitReader& aBr, SPSData& aDest);
+ // Read HRD parameters, all data is ignored.
+ static void hrd_parameters(BitReader& aBr);
+};
+
+} // namespace mp4_demuxer
+
+#endif // MP4_DEMUXER_H264_H_
diff --git a/media/libstagefright/binding/include/mp4_demuxer/Index.h b/media/libstagefright/binding/include/mp4_demuxer/Index.h
new file mode 100644
index 000000000..d566c9459
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/Index.h
@@ -0,0 +1,128 @@
+/* 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/. */
+
+#ifndef INDEX_H_
+#define INDEX_H_
+
+#include "MediaData.h"
+#include "MediaResource.h"
+#include "TimeUnits.h"
+#include "mp4_demuxer/MoofParser.h"
+#include "mp4_demuxer/Interval.h"
+#include "mp4_demuxer/Stream.h"
+#include "nsISupportsImpl.h"
+
+template<class T> class nsAutoPtr;
+
+namespace mp4_demuxer
+{
+
+class Index;
+
+typedef int64_t Microseconds;
+
+class SampleIterator
+{
+public:
+ explicit SampleIterator(Index* aIndex);
+ ~SampleIterator();
+ already_AddRefed<mozilla::MediaRawData> GetNext();
+ void Seek(Microseconds aTime);
+ Microseconds GetNextKeyframeTime();
+private:
+ Sample* Get();
+ void Next();
+ RefPtr<Index> mIndex;
+ friend class Index;
+ size_t mCurrentMoof;
+ size_t mCurrentSample;
+};
+
+class Index
+{
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Index)
+
+ struct Indice
+ {
+ uint64_t start_offset;
+ uint64_t end_offset;
+ uint64_t start_composition;
+ uint64_t end_composition;
+ uint64_t start_decode;
+ bool sync;
+ };
+
+ struct MP4DataOffset
+ {
+ MP4DataOffset(uint32_t aIndex, int64_t aStartOffset)
+ : mIndex(aIndex)
+ , mStartOffset(aStartOffset)
+ , mEndOffset(0)
+ {}
+
+ bool operator==(int64_t aStartOffset) const {
+ return mStartOffset == aStartOffset;
+ }
+
+ bool operator!=(int64_t aStartOffset) const {
+ return mStartOffset != aStartOffset;
+ }
+
+ bool operator<(int64_t aStartOffset) const {
+ return mStartOffset < aStartOffset;
+ }
+
+ struct EndOffsetComparator {
+ bool Equals(const MP4DataOffset& a, const int64_t& b) const {
+ return a.mEndOffset == b;
+ }
+
+ bool LessThan(const MP4DataOffset& a, const int64_t& b) const {
+ return a.mEndOffset < b;
+ }
+ };
+
+ uint32_t mIndex;
+ int64_t mStartOffset;
+ int64_t mEndOffset;
+ Interval<Microseconds> mTime;
+ };
+
+ Index(const nsTArray<Indice>& aIndex,
+ Stream* aSource,
+ uint32_t aTrackId,
+ bool aIsAudio);
+
+ void UpdateMoofIndex(const mozilla::MediaByteRangeSet& aByteRanges,
+ bool aCanEvict);
+ void UpdateMoofIndex(const mozilla::MediaByteRangeSet& aByteRanges);
+ Microseconds GetEndCompositionIfBuffered(
+ const mozilla::MediaByteRangeSet& aByteRanges);
+ mozilla::media::TimeIntervals ConvertByteRangesToTimeRanges(
+ const mozilla::MediaByteRangeSet& aByteRanges);
+ uint64_t GetEvictionOffset(Microseconds aTime);
+ bool IsFragmented() { return mMoofParser; }
+
+ friend class SampleIterator;
+
+private:
+ ~Index();
+ void RegisterIterator(SampleIterator* aIterator);
+ void UnregisterIterator(SampleIterator* aIterator);
+
+ Stream* mSource;
+ FallibleTArray<Sample> mIndex;
+ FallibleTArray<MP4DataOffset> mDataOffset;
+ nsAutoPtr<MoofParser> mMoofParser;
+ nsTArray<SampleIterator*> mIterators;
+
+ // ConvertByteRangesToTimeRanges cache
+ mozilla::MediaByteRangeSet mLastCachedRanges;
+ mozilla::media::TimeIntervals mLastBufferedRanges;
+ bool mIsAudio;
+};
+}
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4_demuxer/Interval.h b/media/libstagefright/binding/include/mp4_demuxer/Interval.h
new file mode 100644
index 000000000..2c3d0f8af
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/Interval.h
@@ -0,0 +1,147 @@
+/* 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/. */
+
+#ifndef INTERVAL_H_
+#define INTERVAL_H_
+
+#include "nsTArray.h"
+#include <algorithm>
+
+namespace mp4_demuxer
+{
+
+template <typename T>
+struct Interval
+{
+ Interval() : start(0), end(0) {}
+ Interval(T aStart, T aEnd) : start(aStart), end(aEnd)
+ {
+ MOZ_ASSERT(aStart <= aEnd);
+ }
+ T Length() { return end - start; }
+ Interval Intersection(const Interval& aOther) const
+ {
+ T s = start > aOther.start ? start : aOther.start;
+ T e = end < aOther.end ? end : aOther.end;
+ if (s > e) {
+ return Interval();
+ }
+ return Interval(s, e);
+ }
+ bool Contains(const Interval& aOther) const
+ {
+ return aOther.start >= start && aOther.end <= end;
+ }
+ bool operator==(const Interval& aOther) const
+ {
+ return start == aOther.start && end == aOther.end;
+ }
+ bool operator!=(const Interval& aOther) const { return !(*this == aOther); }
+ bool IsNull() const
+ {
+ return end == start;
+ }
+ Interval Extents(const Interval& aOther) const
+ {
+ if (IsNull()) {
+ return aOther;
+ }
+ return Interval(std::min(start, aOther.start),
+ std::max(end, aOther.end));
+ }
+
+ T start;
+ T end;
+
+ static void SemiNormalAppend(nsTArray<Interval<T>>& aIntervals,
+ Interval<T> aInterval)
+ {
+ if (!aIntervals.IsEmpty() &&
+ aIntervals.LastElement().end == aInterval.start) {
+ aIntervals.LastElement().end = aInterval.end;
+ } else {
+ aIntervals.AppendElement(aInterval);
+ }
+ }
+
+ static void Normalize(const nsTArray<Interval<T>>& aIntervals,
+ nsTArray<Interval<T>>* aNormalized)
+ {
+ if (!aNormalized || !aIntervals.Length()) {
+ MOZ_ASSERT(aNormalized);
+ return;
+ }
+ MOZ_ASSERT(aNormalized->IsEmpty());
+
+ nsTArray<Interval<T>> sorted;
+ sorted = aIntervals;
+ sorted.Sort(Compare());
+
+ Interval<T> current = sorted[0];
+ for (size_t i = 1; i < sorted.Length(); i++) {
+ MOZ_ASSERT(sorted[i].start <= sorted[i].end);
+ if (current.Contains(sorted[i])) {
+ continue;
+ }
+ if (current.end >= sorted[i].start) {
+ current.end = sorted[i].end;
+ } else {
+ aNormalized->AppendElement(current);
+ current = sorted[i];
+ }
+ }
+ aNormalized->AppendElement(current);
+ }
+
+ static void Intersection(const nsTArray<Interval<T>>& a0,
+ const nsTArray<Interval<T>>& a1,
+ nsTArray<Interval<T>>* aIntersection)
+ {
+ MOZ_ASSERT(IsNormalized(a0));
+ MOZ_ASSERT(IsNormalized(a1));
+ size_t i0 = 0;
+ size_t i1 = 0;
+ while (i0 < a0.Length() && i1 < a1.Length()) {
+ Interval i = a0[i0].Intersection(a1[i1]);
+ if (i.Length()) {
+ aIntersection->AppendElement(i);
+ }
+ if (a0[i0].end < a1[i1].end) {
+ i0++;
+ // Assert that the array is sorted
+ MOZ_ASSERT(i0 == a0.Length() || a0[i0 - 1].start < a0[i0].start);
+ } else {
+ i1++;
+ // Assert that the array is sorted
+ MOZ_ASSERT(i1 == a1.Length() || a1[i1 - 1].start < a1[i1].start);
+ }
+ }
+ }
+
+ static bool IsNormalized(const nsTArray<Interval<T>>& aIntervals)
+ {
+ for (size_t i = 1; i < aIntervals.Length(); i++) {
+ if (aIntervals[i - 1].end >= aIntervals[i].start) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ struct Compare
+ {
+ bool Equals(const Interval<T>& a0, const Interval<T>& a1) const
+ {
+ return a0.start == a1.start && a0.end == a1.end;
+ }
+
+ bool LessThan(const Interval<T>& a0, const Interval<T>& a1) const
+ {
+ return a0.start < a1.start;
+ }
+ };
+};
+}
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h b/media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h
new file mode 100644
index 000000000..83eca69d3
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/MP4Metadata.h
@@ -0,0 +1,54 @@
+/* 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/. */
+
+#ifndef MP4METADATA_H_
+#define MP4METADATA_H_
+
+#include "mozilla/UniquePtr.h"
+#include "mp4_demuxer/DecoderData.h"
+#include "mp4_demuxer/Index.h"
+#include "MediaData.h"
+#include "MediaInfo.h"
+#include "Stream.h"
+
+namespace mp4_demuxer
+{
+
+class MP4MetadataStagefright;
+class MP4MetadataRust;
+
+class MP4Metadata
+{
+public:
+ explicit MP4Metadata(Stream* aSource);
+ ~MP4Metadata();
+
+ static bool HasCompleteMetadata(Stream* aSource);
+ static already_AddRefed<mozilla::MediaByteBuffer> Metadata(Stream* aSource);
+ uint32_t GetNumberTracks(mozilla::TrackInfo::TrackType aType) const;
+ mozilla::UniquePtr<mozilla::TrackInfo> GetTrackInfo(mozilla::TrackInfo::TrackType aType,
+ size_t aTrackNumber) const;
+ bool CanSeek() const;
+
+ const CryptoFile& Crypto() const;
+
+ bool ReadTrackIndex(FallibleTArray<Index::Indice>& aDest, mozilla::TrackID aTrackID);
+
+private:
+ UniquePtr<MP4MetadataStagefright> mStagefright;
+#ifdef MOZ_RUST_MP4PARSE
+ UniquePtr<MP4MetadataRust> mRust;
+ mutable bool mPreferRust;
+ mutable bool mReportedAudioTrackTelemetry;
+ mutable bool mReportedVideoTrackTelemetry;
+#ifndef RELEASE_OR_BETA
+ mutable bool mRustTestMode;
+#endif
+ bool ShouldPreferRust() const;
+#endif
+};
+
+} // namespace mp4_demuxer
+
+#endif // MP4METADATA_H_
diff --git a/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h b/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
new file mode 100644
index 000000000..814f806fc
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
@@ -0,0 +1,260 @@
+/* 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/. */
+
+#ifndef MOOF_PARSER_H_
+#define MOOF_PARSER_H_
+
+#include "mp4_demuxer/Atom.h"
+#include "mp4_demuxer/AtomType.h"
+#include "mp4_demuxer/SinfParser.h"
+#include "mp4_demuxer/Stream.h"
+#include "mp4_demuxer/Interval.h"
+#include "MediaResource.h"
+
+namespace mp4_demuxer {
+typedef int64_t Microseconds;
+
+class Box;
+class BoxContext;
+class Moof;
+
+class Mvhd : public Atom
+{
+public:
+ Mvhd()
+ : mCreationTime(0)
+ , mModificationTime(0)
+ , mTimescale(0)
+ , mDuration(0)
+ {
+ }
+ explicit Mvhd(Box& aBox);
+
+ Microseconds ToMicroseconds(int64_t aTimescaleUnits)
+ {
+ int64_t major = aTimescaleUnits / mTimescale;
+ int64_t remainder = aTimescaleUnits % mTimescale;
+ return major * 1000000ll + remainder * 1000000ll / mTimescale;
+ }
+
+ uint64_t mCreationTime;
+ uint64_t mModificationTime;
+ uint32_t mTimescale;
+ uint64_t mDuration;
+};
+
+class Tkhd : public Mvhd
+{
+public:
+ Tkhd()
+ : mTrackId(0)
+ {
+ }
+ explicit Tkhd(Box& aBox);
+
+ uint32_t mTrackId;
+};
+
+class Mdhd : public Mvhd
+{
+public:
+ Mdhd() = default;
+ explicit Mdhd(Box& aBox);
+};
+
+class Trex : public Atom
+{
+public:
+ explicit Trex(uint32_t aTrackId)
+ : mFlags(0)
+ , mTrackId(aTrackId)
+ , mDefaultSampleDescriptionIndex(0)
+ , mDefaultSampleDuration(0)
+ , mDefaultSampleSize(0)
+ , mDefaultSampleFlags(0)
+ {
+ }
+
+ explicit Trex(Box& aBox);
+
+ uint32_t mFlags;
+ uint32_t mTrackId;
+ uint32_t mDefaultSampleDescriptionIndex;
+ uint32_t mDefaultSampleDuration;
+ uint32_t mDefaultSampleSize;
+ uint32_t mDefaultSampleFlags;
+};
+
+class Tfhd : public Trex
+{
+public:
+ explicit Tfhd(Trex& aTrex)
+ : Trex(aTrex)
+ , mBaseDataOffset(0)
+ {
+ mValid = aTrex.IsValid();
+ }
+ Tfhd(Box& aBox, Trex& aTrex);
+
+ uint64_t mBaseDataOffset;
+};
+
+class Tfdt : public Atom
+{
+public:
+ Tfdt()
+ : mBaseMediaDecodeTime(0)
+ {
+ }
+ explicit Tfdt(Box& aBox);
+
+ uint64_t mBaseMediaDecodeTime;
+};
+
+class Edts : public Atom
+{
+public:
+ Edts()
+ : mMediaStart(0)
+ , mEmptyOffset(0)
+ {
+ }
+ explicit Edts(Box& aBox);
+ virtual bool IsValid()
+ {
+ // edts is optional
+ return true;
+ }
+
+ int64_t mMediaStart;
+ int64_t mEmptyOffset;
+};
+
+struct Sample
+{
+ mozilla::MediaByteRange mByteRange;
+ mozilla::MediaByteRange mCencRange;
+ Microseconds mDecodeTime;
+ Interval<Microseconds> mCompositionRange;
+ bool mSync;
+};
+
+class Saiz final : public Atom
+{
+public:
+ Saiz(Box& aBox, AtomType aDefaultType);
+
+ AtomType mAuxInfoType;
+ uint32_t mAuxInfoTypeParameter;
+ FallibleTArray<uint8_t> mSampleInfoSize;
+};
+
+class Saio final : public Atom
+{
+public:
+ Saio(Box& aBox, AtomType aDefaultType);
+
+ AtomType mAuxInfoType;
+ uint32_t mAuxInfoTypeParameter;
+ FallibleTArray<uint64_t> mOffsets;
+};
+
+class AuxInfo {
+public:
+ AuxInfo(int64_t aMoofOffset, Saiz& aSaiz, Saio& aSaio);
+
+private:
+ int64_t mMoofOffset;
+ Saiz& mSaiz;
+ Saio& mSaio;
+};
+
+class Moof final : public Atom
+{
+public:
+ Moof(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, Sinf& aSinf, uint64_t* aDecoderTime, bool aIsAudio);
+ bool GetAuxInfo(AtomType aType, nsTArray<MediaByteRange>* aByteRanges);
+ void FixRounding(const Moof& aMoof);
+
+ mozilla::MediaByteRange mRange;
+ mozilla::MediaByteRange mMdatRange;
+ Interval<Microseconds> mTimeRange;
+ FallibleTArray<Sample> mIndex;
+
+ nsTArray<Saiz> mSaizs;
+ nsTArray<Saio> mSaios;
+
+private:
+ // aDecodeTime is updated to the end of the parsed TRAF on return.
+ void ParseTraf(Box& aBox, Trex& aTrex, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, Sinf& aSinf, uint64_t* aDecodeTime, bool aIsAudio);
+ // aDecodeTime is updated to the end of the parsed TRUN on return.
+ bool ParseTrun(Box& aBox, Tfhd& aTfhd, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, uint64_t* aDecodeTime, bool aIsAudio);
+ void ParseSaiz(Box& aBox);
+ void ParseSaio(Box& aBox);
+ bool ProcessCenc();
+ uint64_t mMaxRoundingError;
+};
+
+class MoofParser
+{
+public:
+ MoofParser(Stream* aSource, uint32_t aTrackId, bool aIsAudio)
+ : mSource(aSource)
+ , mOffset(0)
+ , mTrex(aTrackId)
+ , mIsAudio(aIsAudio)
+ , mLastDecodeTime(0)
+ {
+ // Setting the mTrex.mTrackId to 0 is a nasty work around for calculating
+ // the composition range for MSE. We need an array of tracks.
+ }
+ bool RebuildFragmentedIndex(
+ const mozilla::MediaByteRangeSet& aByteRanges);
+ // If *aCanEvict is set to true. then will remove all moofs already parsed
+ // from index then rebuild the index. *aCanEvict is set to true upon return if
+ // some moofs were removed.
+ bool RebuildFragmentedIndex(
+ const mozilla::MediaByteRangeSet& aByteRanges, bool* aCanEvict);
+ bool RebuildFragmentedIndex(BoxContext& aContext);
+ Interval<Microseconds> GetCompositionRange(
+ const mozilla::MediaByteRangeSet& aByteRanges);
+ bool ReachedEnd();
+ void ParseMoov(Box& aBox);
+ void ParseTrak(Box& aBox);
+ void ParseMdia(Box& aBox, Tkhd& aTkhd);
+ void ParseMvex(Box& aBox);
+
+ void ParseMinf(Box& aBox);
+ void ParseStbl(Box& aBox);
+ void ParseStsd(Box& aBox);
+ void ParseEncrypted(Box& aBox);
+ void ParseSinf(Box& aBox);
+
+ bool BlockingReadNextMoof();
+ bool HasMetadata();
+ already_AddRefed<mozilla::MediaByteBuffer> Metadata();
+ MediaByteRange FirstCompleteMediaSegment();
+ MediaByteRange FirstCompleteMediaHeader();
+
+ mozilla::MediaByteRange mInitRange;
+ RefPtr<Stream> mSource;
+ uint64_t mOffset;
+ Mvhd mMvhd;
+ Mdhd mMdhd;
+ Trex mTrex;
+ Tfdt mTfdt;
+ Edts mEdts;
+ Sinf mSinf;
+ nsTArray<Moof>& Moofs() { return mMoofs; }
+private:
+ void ScanForMetadata(mozilla::MediaByteRange& aFtyp,
+ mozilla::MediaByteRange& aMoov);
+ nsTArray<Moof> mMoofs;
+ nsTArray<MediaByteRange> mMediaRanges;
+ bool mIsAudio;
+ uint64_t mLastDecodeTime;
+};
+}
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4_demuxer/ResourceStream.h b/media/libstagefright/binding/include/mp4_demuxer/ResourceStream.h
new file mode 100644
index 000000000..219465f17
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/ResourceStream.h
@@ -0,0 +1,49 @@
+/* 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/. */
+
+#ifndef RESOURCESTREAM_H_
+#define RESOURCESTREAM_H_
+
+#include "MediaResource.h"
+#include "mp4_demuxer/Stream.h"
+#include "mozilla/RefPtr.h"
+
+namespace mp4_demuxer
+{
+
+class ResourceStream : public Stream
+{
+public:
+ explicit ResourceStream(mozilla::MediaResource* aResource);
+
+ virtual bool ReadAt(int64_t offset, void* aBuffer, size_t aCount,
+ size_t* aBytesRead) override;
+ virtual bool CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
+ size_t* aBytesRead) override;
+ virtual bool Length(int64_t* size) override;
+
+ void Pin()
+ {
+ mResource->Pin();
+ ++mPinCount;
+ }
+
+ void Unpin()
+ {
+ mResource->Unpin();
+ MOZ_ASSERT(mPinCount);
+ --mPinCount;
+ }
+
+protected:
+ virtual ~ResourceStream();
+
+private:
+ RefPtr<mozilla::MediaResource> mResource;
+ uint32_t mPinCount;
+};
+
+}
+
+#endif // RESOURCESTREAM_H_
diff --git a/media/libstagefright/binding/include/mp4_demuxer/SinfParser.h b/media/libstagefright/binding/include/mp4_demuxer/SinfParser.h
new file mode 100644
index 000000000..782a87907
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/SinfParser.h
@@ -0,0 +1,51 @@
+/* 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/. */
+
+
+#ifndef SINF_PARSER_H_
+#define SINF_PARSER_H_
+
+#include "mp4_demuxer/Atom.h"
+#include "mp4_demuxer/AtomType.h"
+
+namespace mp4_demuxer {
+
+class Box;
+
+class Sinf : public Atom
+{
+public:
+ Sinf()
+ : mDefaultIVSize(0)
+ , mDefaultEncryptionType()
+ {}
+ explicit Sinf(Box& aBox);
+
+ virtual bool IsValid() override
+ {
+ return !!mDefaultIVSize && !!mDefaultEncryptionType;
+ }
+
+ uint8_t mDefaultIVSize;
+ AtomType mDefaultEncryptionType;
+ uint8_t mDefaultKeyID[16];
+};
+
+class SinfParser
+{
+public:
+ explicit SinfParser(Box& aBox);
+
+ Sinf& GetSinf() { return mSinf; }
+private:
+ void ParseSchm(Box& aBox);
+ void ParseSchi(Box& aBox);
+ void ParseTenc(Box& aBox);
+
+ Sinf mSinf;
+};
+
+}
+
+#endif // SINF_PARSER_H_
diff --git a/media/libstagefright/binding/include/mp4_demuxer/Stream.h b/media/libstagefright/binding/include/mp4_demuxer/Stream.h
new file mode 100644
index 000000000..379478ec7
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4_demuxer/Stream.h
@@ -0,0 +1,32 @@
+/* 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/. */
+
+#ifndef STREAM_H_
+#define STREAM_H_
+
+#include "nsISupportsImpl.h"
+
+namespace mp4_demuxer
+{
+
+class Stream
+{
+public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(Stream);
+
+ virtual bool ReadAt(int64_t offset, void* data, size_t size,
+ size_t* bytes_read) = 0;
+ virtual bool CachedReadAt(int64_t offset, void* data, size_t size,
+ size_t* bytes_read) = 0;
+ virtual bool Length(int64_t* size) = 0;
+
+ virtual void DiscardBefore(int64_t offset) {}
+
+protected:
+ virtual ~Stream() {}
+};
+
+}
+
+#endif
diff --git a/media/libstagefright/binding/include/mp4parse.h b/media/libstagefright/binding/include/mp4parse.h
new file mode 100644
index 000000000..6650661cb
--- /dev/null
+++ b/media/libstagefright/binding/include/mp4parse.h
@@ -0,0 +1,113 @@
+
+#ifndef cheddar_generated_mp4parse_h
+#define cheddar_generated_mp4parse_h
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+
+// THIS FILE IS AUTOGENERATED BY mp4parse-rust/build.rs - DO NOT EDIT
+
+// 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 https://mozilla.org/MPL/2.0/.
+
+typedef enum mp4parse_error {
+ MP4PARSE_OK = 0,
+ MP4PARSE_ERROR_BADARG = 1,
+ MP4PARSE_ERROR_INVALID = 2,
+ MP4PARSE_ERROR_UNSUPPORTED = 3,
+ MP4PARSE_ERROR_EOF = 4,
+ MP4PARSE_ERROR_IO = 5,
+} mp4parse_error;
+
+typedef enum mp4parse_track_type {
+ MP4PARSE_TRACK_TYPE_VIDEO = 0,
+ MP4PARSE_TRACK_TYPE_AUDIO = 1,
+} mp4parse_track_type;
+
+typedef enum mp4parse_codec {
+ MP4PARSE_CODEC_UNKNOWN,
+ MP4PARSE_CODEC_AAC,
+ MP4PARSE_CODEC_FLAC,
+ MP4PARSE_CODEC_OPUS,
+ MP4PARSE_CODEC_AVC,
+ MP4PARSE_CODEC_VP9,
+ MP4PARSE_CODEC_MP3,
+} mp4parse_codec;
+
+typedef struct mp4parse_track_info {
+ mp4parse_track_type track_type;
+ mp4parse_codec codec;
+ uint32_t track_id;
+ uint64_t duration;
+ int64_t media_time;
+} mp4parse_track_info;
+
+typedef struct mp4parse_codec_specific_config {
+ uint32_t length;
+ uint8_t const* data;
+} mp4parse_codec_specific_config;
+
+typedef struct mp4parse_track_audio_info {
+ uint16_t channels;
+ uint16_t bit_depth;
+ uint32_t sample_rate;
+ mp4parse_codec_specific_config codec_specific_config;
+} mp4parse_track_audio_info;
+
+typedef struct mp4parse_track_video_info {
+ uint32_t display_width;
+ uint32_t display_height;
+ uint16_t image_width;
+ uint16_t image_height;
+} mp4parse_track_video_info;
+
+typedef struct mp4parse_fragment_info {
+ uint64_t fragment_duration;
+} mp4parse_fragment_info;
+
+typedef struct mp4parse_parser mp4parse_parser;
+
+typedef struct mp4parse_io {
+ intptr_t (*read)(uint8_t* buffer, uintptr_t size, void* userdata);
+ void* userdata;
+} mp4parse_io;
+
+/// Allocate an `mp4parse_parser*` to read from the supplied `mp4parse_io`.
+mp4parse_parser* mp4parse_new(mp4parse_io const* io);
+
+/// Free an `mp4parse_parser*` allocated by `mp4parse_new()`.
+void mp4parse_free(mp4parse_parser* parser);
+
+/// Run the `mp4parse_parser*` allocated by `mp4parse_new()` until EOF or error.
+mp4parse_error mp4parse_read(mp4parse_parser* parser);
+
+/// Return the number of tracks parsed by previous `mp4parse_read()` call.
+mp4parse_error mp4parse_get_track_count(mp4parse_parser const* parser, uint32_t* count);
+
+/// Fill the supplied `mp4parse_track_info` with metadata for `track`.
+mp4parse_error mp4parse_get_track_info(mp4parse_parser* parser, uint32_t track_index, mp4parse_track_info* info);
+
+/// Fill the supplied `mp4parse_track_audio_info` with metadata for `track`.
+mp4parse_error mp4parse_get_track_audio_info(mp4parse_parser* parser, uint32_t track_index, mp4parse_track_audio_info* info);
+
+/// Fill the supplied `mp4parse_track_video_info` with metadata for `track`.
+mp4parse_error mp4parse_get_track_video_info(mp4parse_parser* parser, uint32_t track_index, mp4parse_track_video_info* info);
+
+mp4parse_error mp4parse_get_fragment_info(mp4parse_parser* parser, mp4parse_fragment_info* info);
+
+mp4parse_error mp4parse_is_fragmented(mp4parse_parser* parser, uint32_t track_id, uint8_t* fragmented);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif