diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /media/libstagefright/binding/include | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-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')
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 |