Backed out 9 changesets (bug 1554075) for reftest failures in Intervals.h and MP4Interval.h on a CLOSED TREE

Backed out changeset d5543a60f833 (bug 1554075)
Backed out changeset 1ea15f85c789 (bug 1554075)
Backed out changeset a76688ee5b8a (bug 1554075)
Backed out changeset 85482315a53c (bug 1554075)
Backed out changeset c3f3e9e00279 (bug 1554075)
Backed out changeset ac24ec2e0349 (bug 1554075)
Backed out changeset b04fc8b0c07a (bug 1554075)
Backed out changeset 2cce329d894d (bug 1554075)
Backed out changeset 347b7b4eaab1 (bug 1554075)
This commit is contained in:
Oana Pop Rus 2019-06-11 09:52:43 +03:00
Родитель 4463ad6a27
Коммит 9fdfa8a955
13 изменённых файлов: 60 добавлений и 271 удалений

Просмотреть файл

@ -225,12 +225,6 @@ class Interval {
(aOther.mStart - aOther.mFuzz <= mEnd + mFuzz); (aOther.mStart - aOther.mFuzz <= mEnd + mFuzz);
} }
// Returns true if the two intervals intersect with this being on the right
// of aOther, ignoring fuzz.
bool TouchesOnRightStrict(const SelfType& aOther) const {
return aOther.mStart <= mStart && mStart <= aOther.mEnd;
}
T mStart; T mStart;
T mEnd; T mEnd;
T mFuzz; T mFuzz;
@ -306,12 +300,8 @@ class IntervalSet {
} }
SelfType& Add(const SelfType& aIntervals) { SelfType& Add(const SelfType& aIntervals) {
if (aIntervals.mIntervals.Length() == 1) { mIntervals.AppendElements(aIntervals.mIntervals);
Add(aIntervals.mIntervals[0]); Normalize();
} else {
mIntervals.AppendElements(aIntervals.mIntervals);
Normalize();
}
return *this; return *this;
} }
@ -389,26 +379,12 @@ class IntervalSet {
} }
// Excludes an interval from an IntervalSet. // Excludes an interval from an IntervalSet.
// This is done by inverting aInterval within the bounds of mIntervals
// and then doing the intersection.
SelfType& operator-=(const ElemType& aInterval) { SelfType& operator-=(const ElemType& aInterval) {
if (aInterval.IsEmpty() || mIntervals.IsEmpty()) { if (aInterval.IsEmpty() || mIntervals.IsEmpty()) {
return *this; return *this;
} }
if (mIntervals.Length() == 1 &&
mIntervals[0].TouchesOnRightStrict(aInterval)) {
// Fast path when we're removing from the front of a set with a
// single interval. This is common for the buffered time ranges
// we see on Twitch.
if (aInterval.mEnd >= mIntervals[0].mEnd) {
mIntervals.RemoveElementAt(0);
} else {
mIntervals[0].mStart = aInterval.mEnd;
mIntervals[0].mFuzz = std::max(mIntervals[0].mFuzz, aInterval.mFuzz);
}
return *this;
}
// General case performed by inverting aInterval within the bounds of
// mIntervals and then doing the intersection.
T firstEnd = std::max(mIntervals[0].mStart, aInterval.mStart); T firstEnd = std::max(mIntervals[0].mStart, aInterval.mStart);
T secondStart = std::min(mIntervals.LastElement().mEnd, aInterval.mEnd); T secondStart = std::min(mIntervals.LastElement().mEnd, aInterval.mEnd);
ElemType startInterval(mIntervals[0].mStart, firstEnd); ElemType startInterval(mIntervals[0].mStart, firstEnd);
@ -633,7 +609,7 @@ class IntervalSet {
for (auto& interval : mIntervals) { for (auto& interval : mIntervals) {
interval.SetFuzz(aFuzz); interval.SetFuzz(aFuzz);
} }
MergeOverlappingIntervals(); Normalize();
} }
static const IndexType NoIndex = IndexType(-1); static const IndexType NoIndex = IndexType(-1);
@ -677,32 +653,27 @@ class IntervalSet {
private: private:
void Normalize() { void Normalize() {
if (mIntervals.Length() < 2) { if (mIntervals.Length() >= 2) {
return; ContainerType normalized;
}
mIntervals.Sort(CompareIntervals());
MergeOverlappingIntervals();
}
void MergeOverlappingIntervals() { mIntervals.Sort(CompareIntervals());
if (mIntervals.Length() < 2) {
return;
}
// This merges the intervals in place. // This merges the intervals.
IndexType read = 0; ElemType current(mIntervals[0]);
IndexType write = 0; for (IndexType i = 1; i < mIntervals.Length(); i++) {
while (read < mIntervals.Length()) { ElemType& interval = mIntervals[i];
ElemType current(mIntervals[read]); if (current.Touches(interval)) {
read++; current = current.Span(interval);
while (read < mIntervals.Length() && current.Touches(mIntervals[read])) { } else {
current = current.Span(mIntervals[read]); normalized.AppendElement(std::move(current));
read++; current = std::move(interval);
}
} }
mIntervals[write] = current; normalized.AppendElement(std::move(current));
write++;
mIntervals.Clear();
mIntervals.AppendElements(std::move(normalized));
} }
mIntervals.SetLength(write);
} }
struct CompareIntervals { struct CompareIntervals {

Просмотреть файл

@ -2615,7 +2615,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mAbstractMainThread(aDecoder->AbstractMainThread()), mAbstractMainThread(aDecoder->AbstractMainThread()),
mFrameStats(&aDecoder->GetFrameStatistics()), mFrameStats(&aDecoder->GetFrameStatistics()),
mVideoFrameContainer(aDecoder->GetVideoFrameContainer()), mVideoFrameContainer(aDecoder->GetVideoFrameContainer()),
mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::MDSM), mTaskQueue(new TaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK),
"MDSM::mTaskQueue", "MDSM::mTaskQueue",
/* aSupportsTailDispatch = */ true)), /* aSupportsTailDispatch = */ true)),
mWatchManager(this, mTaskQueue), mWatchManager(this, mTaskQueue),

Просмотреть файл

@ -206,7 +206,6 @@ bool IsValidVideoRegion(const gfx::IntSize& aFrame,
already_AddRefed<SharedThreadPool> GetMediaThreadPool(MediaThreadType aType) { already_AddRefed<SharedThreadPool> GetMediaThreadPool(MediaThreadType aType) {
const char* name; const char* name;
uint32_t threads = 4;
switch (aType) { switch (aType) {
case MediaThreadType::PLATFORM_DECODER: case MediaThreadType::PLATFORM_DECODER:
name = "MediaPDecoder"; name = "MediaPDecoder";
@ -217,10 +216,6 @@ already_AddRefed<SharedThreadPool> GetMediaThreadPool(MediaThreadType aType) {
case MediaThreadType::WEBRTC_DECODER: case MediaThreadType::WEBRTC_DECODER:
name = "WebRTCPD"; name = "WebRTCPD";
break; break;
case MediaThreadType::MDSM:
name = "MediaDecoderStateMachine";
threads = 1;
break;
default: default:
MOZ_FALLTHROUGH_ASSERT("Unexpected MediaThreadType"); MOZ_FALLTHROUGH_ASSERT("Unexpected MediaThreadType");
case MediaThreadType::PLAYBACK: case MediaThreadType::PLAYBACK:
@ -228,8 +223,9 @@ already_AddRefed<SharedThreadPool> GetMediaThreadPool(MediaThreadType aType) {
break; break;
} }
RefPtr<SharedThreadPool> pool = static const uint32_t kMediaThreadPoolDefaultCount = 4;
SharedThreadPool::Get(nsDependentCString(name), threads); RefPtr<SharedThreadPool> pool = SharedThreadPool::Get(
nsDependentCString(name), kMediaThreadPoolDefaultCount);
// Ensure a larger stack for platform decoder threads // Ensure a larger stack for platform decoder threads
if (aType == MediaThreadType::PLATFORM_DECODER) { if (aType == MediaThreadType::PLATFORM_DECODER) {

Просмотреть файл

@ -184,8 +184,7 @@ enum class MediaThreadType {
PLAYBACK, // MediaDecoderStateMachine and MediaFormatReader PLAYBACK, // MediaDecoderStateMachine and MediaFormatReader
PLATFORM_DECODER, // MediaDataDecoder PLATFORM_DECODER, // MediaDataDecoder
MSG_CONTROL, MSG_CONTROL,
WEBRTC_DECODER, WEBRTC_DECODER
MDSM,
}; };
// Returns the thread pool that is shared amongst all decoder state machines // Returns the thread pool that is shared amongst all decoder state machines
// for decoding streams. // for decoding streams.

Просмотреть файл

@ -329,7 +329,6 @@ class MP4Stream : public ByteStream, public DecoderDoctorLifeLogger<MP4Stream> {
bool CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount, bool CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
size_t* aBytesRead) override; size_t* aBytesRead) override;
bool Length(int64_t* aSize) override; bool Length(int64_t* aSize) override;
const uint8_t* GetContiguousAccess(int64_t aOffset, size_t aSize) override;
private: private:
RefPtr<SourceBufferResource> mResource; RefPtr<SourceBufferResource> mResource;
@ -360,10 +359,6 @@ bool MP4Stream::CachedReadAt(int64_t aOffset, void* aBuffer, size_t aCount,
return true; return true;
} }
const uint8_t* MP4Stream::GetContiguousAccess(int64_t aOffset, size_t aSize) {
return mResource->GetContiguousAccess(aOffset, aSize);
}
bool MP4Stream::Length(int64_t* aSize) { bool MP4Stream::Length(int64_t* aSize) {
if (mResource->GetLength() < 0) return false; if (mResource->GetLength() < 0) return false;
*aSize = mResource->GetLength(); *aSize = mResource->GetLength();

Просмотреть файл

@ -24,8 +24,7 @@ extern mozilla::LogModule* GetSourceBufferResourceLog();
namespace mozilla { namespace mozilla {
ResourceItem::ResourceItem(MediaByteBuffer* aData, uint64_t aOffset) ResourceItem::ResourceItem(MediaByteBuffer* aData) : mData(aData) {}
: mData(aData), mOffset(aOffset) {}
size_t ResourceItem::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const { size_t ResourceItem::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
// size including this // size including this
@ -50,26 +49,13 @@ uint64_t ResourceQueue::GetOffset() { return mOffset; }
uint64_t ResourceQueue::GetLength() { return mLogicalLength; } uint64_t ResourceQueue::GetLength() { return mLogicalLength; }
const uint8_t* ResourceQueue::GetContiguousAccess(int64_t aOffset,
size_t aSize) {
uint32_t offset = 0;
uint32_t start = GetAtOffset(aOffset, &offset);
if (start >= GetSize()) {
return nullptr;
}
ResourceItem* item = ResourceAt(start);
if (offset + aSize > item->mData->Length()) {
return nullptr;
}
return item->mData->Elements() + offset;
}
void ResourceQueue::CopyData(uint64_t aOffset, uint32_t aCount, char* aDest) { void ResourceQueue::CopyData(uint64_t aOffset, uint32_t aCount, char* aDest) {
uint32_t offset = 0; uint32_t offset = 0;
uint32_t start = GetAtOffset(aOffset, &offset); uint32_t start = GetAtOffset(aOffset, &offset);
size_t i = start; uint32_t end =
while (i < uint32_t(GetSize()) && aCount > 0) { std::min(GetAtOffset(aOffset + aCount, nullptr) + 1, uint32_t(GetSize()));
ResourceItem* item = ResourceAt(i++); for (uint32_t i = start; i < end; ++i) {
ResourceItem* item = ResourceAt(i);
uint32_t bytes = std::min(aCount, uint32_t(item->mData->Length() - offset)); uint32_t bytes = std::min(aCount, uint32_t(item->mData->Length() - offset));
if (bytes != 0) { if (bytes != 0) {
memcpy(aDest, &(*item->mData)[offset], bytes); memcpy(aDest, &(*item->mData)[offset], bytes);
@ -81,9 +67,8 @@ void ResourceQueue::CopyData(uint64_t aOffset, uint32_t aCount, char* aDest) {
} }
void ResourceQueue::AppendItem(MediaByteBuffer* aData) { void ResourceQueue::AppendItem(MediaByteBuffer* aData) {
uint64_t offset = mLogicalLength;
mLogicalLength += aData->Length(); mLogicalLength += aData->Length();
Push(new ResourceItem(aData, offset)); Push(new ResourceItem(aData));
} }
uint32_t ResourceQueue::Evict(uint64_t aOffset, uint32_t aSizeToEvict, uint32_t ResourceQueue::Evict(uint64_t aOffset, uint32_t aSizeToEvict,
@ -112,7 +97,7 @@ uint32_t ResourceQueue::EvictBefore(uint64_t aOffset, ErrorResult& aRv) {
aRv.Throw(NS_ERROR_OUT_OF_MEMORY); aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
return 0; return 0;
} }
item->mOffset += offset;
item->mData = data; item->mData = data;
break; break;
} }
@ -171,29 +156,22 @@ ResourceItem* ResourceQueue::ResourceAt(uint32_t aIndex) const {
} }
uint32_t ResourceQueue::GetAtOffset(uint64_t aOffset, uint32_t ResourceQueue::GetAtOffset(uint64_t aOffset,
uint32_t* aResourceOffset) const { uint32_t* aResourceOffset) {
MOZ_RELEASE_ASSERT(aOffset >= mOffset); MOZ_RELEASE_ASSERT(aOffset >= mOffset);
uint64_t offset = mOffset;
size_t hi = GetSize(); for (uint32_t i = 0; i < uint32_t(GetSize()); ++i) {
size_t lo = 0; ResourceItem* item = ResourceAt(i);
while (lo < hi) { // If the item contains the start of the offset we want to
size_t mid = lo + (hi - lo) / 2; // break out of the loop.
const ResourceItem* resource = ResourceAt(mid); if (item->mData->Length() + offset > aOffset) {
if (resource->mOffset <= aOffset &&
aOffset < resource->mOffset + resource->mData->Length()) {
if (aResourceOffset) { if (aResourceOffset) {
*aResourceOffset = aOffset - resource->mOffset; *aResourceOffset = aOffset - offset;
} }
return uint32_t(mid); return i;
}
if (resource->mOffset + resource->mData->Length() <= aOffset) {
lo = mid + 1;
} else {
hi = mid;
} }
offset += item->mData->Length();
} }
return GetSize();
return uint32_t(GetSize());
} }
ResourceItem* ResourceQueue::PopFront() { ResourceItem* ResourceQueue::PopFront() {

Просмотреть файл

@ -26,10 +26,9 @@ class ErrorResult;
// timepoint. // timepoint.
struct ResourceItem { struct ResourceItem {
ResourceItem(MediaByteBuffer* aData, uint64_t aOffset); explicit ResourceItem(MediaByteBuffer* aData);
size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const; size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const;
RefPtr<MediaByteBuffer> mData; RefPtr<MediaByteBuffer> mData;
uint64_t mOffset;
}; };
class ResourceQueue : private nsDeque { class ResourceQueue : private nsDeque {
@ -62,8 +61,6 @@ class ResourceQueue : private nsDeque {
void Dump(const char* aPath); void Dump(const char* aPath);
#endif #endif
const uint8_t* GetContiguousAccess(int64_t aOffset, size_t aSize);
private: private:
ResourceItem* ResourceAt(uint32_t aIndex) const; ResourceItem* ResourceAt(uint32_t aIndex) const;
@ -72,7 +69,7 @@ class ResourceQueue : private nsDeque {
// the resource at the given index returned if it is not null. If // the resource at the given index returned if it is not null. If
// no such resource exists, returns GetSize() and aOffset is // no such resource exists, returns GetSize() and aOffset is
// untouched. // untouched.
uint32_t GetAtOffset(uint64_t aOffset, uint32_t* aResourceOffset) const; uint32_t GetAtOffset(uint64_t aOffset, uint32_t* aResourceOffset);
ResourceItem* PopFront(); ResourceItem* PopFront();

Просмотреть файл

@ -110,10 +110,6 @@ class SourceBufferResource final
return mInputBuffer.GetLength() - mInputBuffer.GetOffset(); return mInputBuffer.GetLength() - mInputBuffer.GetOffset();
} }
const uint8_t* GetContiguousAccess(int64_t aOffset, size_t aSize) {
return mInputBuffer.GetContiguousAccess(aOffset, aSize);
}
#if defined(DEBUG) #if defined(DEBUG)
void Dump(const char* aPath) { mInputBuffer.Dump(aPath); } void Dump(const char* aPath) { mInputBuffer.Dump(aPath); }
#endif #endif

Просмотреть файл

@ -68,6 +68,7 @@ Box::Box(BoxContext* aContext, uint64_t aOffset, const Box* aParent)
bytes != sizeof(header)) { bytes != sizeof(header)) {
return; return;
} }
mHeader.AppendElements(header, sizeof(header));
uint64_t size = BigEndian::readUint32(header); uint64_t size = BigEndian::readUint32(header);
if (size == 1) { if (size == 1) {
@ -86,6 +87,7 @@ Box::Box(BoxContext* aContext, uint64_t aOffset, const Box* aParent)
} }
size = BigEndian::readUint64(bigLength); size = BigEndian::readUint64(bigLength);
mBodyOffset = bigLengthRange.mEnd; mBodyOffset = bigLengthRange.mEnd;
mHeader.AppendElements(bigLength, sizeof(bigLength));
} else if (size == 0) { } else if (size == 0) {
// box extends to end of file. // box extends to end of file.
size = mContext->mByteRanges.LastInterval().mEnd - aOffset; size = mContext->mByteRanges.LastInterval().mEnd - aOffset;
@ -132,21 +134,6 @@ Box Box::FirstChild() const {
return Box(mContext, mChildOffset, this); return Box(mContext, mChildOffset, this);
} }
nsTArray<uint8_t> Box::ReadCompleteBox() const {
const size_t length = mRange.mEnd - mRange.mStart;
nsTArray<uint8_t> out(length);
out.SetLength(length);
size_t bytesRead = 0;
if (!mContext->mSource->CachedReadAt(mRange.mStart, out.Elements(), length,
&bytesRead) ||
bytesRead != length) {
// Byte ranges are being reported incorrectly
NS_WARNING("Read failed in mozilla::Box::ReadCompleteBox()");
return nsTArray<uint8_t>(0);
}
return out;
}
nsTArray<uint8_t> Box::Read() const { nsTArray<uint8_t> Box::Read() const {
nsTArray<uint8_t> out; nsTArray<uint8_t> out;
Unused << Read(&out, mRange); Unused << Read(&out, mRange);
@ -174,56 +161,4 @@ bool Box::Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange) const {
} }
return true; return true;
} }
ByteSlice Box::ReadAsSlice() {
if (!mContext) {
return ByteSlice{nullptr, 0};
}
int64_t length;
if (!mContext->mSource->Length(&length)) {
// The HTTP server didn't give us a length to work with.
// Limit the read to kMAX_BOX_READ max.
length = std::min(mRange.mEnd - mChildOffset, kMAX_BOX_READ);
} else {
length = mRange.mEnd - mChildOffset;
}
const uint8_t* data =
mContext->mSource->GetContiguousAccess(mChildOffset, length);
if (data) {
// We can direct access the underlying storage of the ByteStream.
return ByteSlice{data, size_t(length)};
}
uint8_t* p = mContext->mAllocator.Allocate(size_t(length));
size_t bytes;
if (!mContext->mSource->CachedReadAt(mChildOffset, p, length, &bytes) ||
bytes != length) {
// Byte ranges are being reported incorrectly
NS_WARNING("Read failed in mozilla::Box::ReadAsSlice()");
return ByteSlice{nullptr, 0};
}
return ByteSlice{p, size_t(length)};
}
const size_t BLOCK_CAPACITY = 16 * 1024;
uint8_t* BumpAllocator::Allocate(size_t aNumBytes) {
if (aNumBytes > BLOCK_CAPACITY) {
mBuffers.AppendElement(nsTArray<uint8_t>(aNumBytes));
mBuffers.LastElement().SetLength(aNumBytes);
return mBuffers.LastElement().Elements();
}
for (nsTArray<uint8_t>& buffer : mBuffers) {
if (buffer.Length() + aNumBytes < BLOCK_CAPACITY) {
size_t offset = buffer.Length();
buffer.SetLength(buffer.Length() + aNumBytes);
return buffer.Elements() + offset;
}
}
mBuffers.AppendElement(nsTArray<uint8_t>(BLOCK_CAPACITY));
mBuffers.LastElement().SetLength(aNumBytes);
return mBuffers.LastElement().Elements();
}
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -17,14 +17,6 @@
namespace mozilla { namespace mozilla {
class ByteStream; class ByteStream;
class BumpAllocator {
public:
uint8_t* Allocate(size_t aNumBytes);
private:
nsTArray<nsTArray<uint8_t>> mBuffers;
};
class BoxContext { class BoxContext {
public: public:
BoxContext(ByteStream* aSource, const MediaByteRangeSet& aByteRanges) BoxContext(ByteStream* aSource, const MediaByteRangeSet& aByteRanges)
@ -32,12 +24,6 @@ class BoxContext {
RefPtr<ByteStream> mSource; RefPtr<ByteStream> mSource;
const MediaByteRangeSet& mByteRanges; const MediaByteRangeSet& mByteRanges;
BumpAllocator mAllocator;
};
struct ByteSlice {
const uint8_t* mBytes;
size_t mSize;
}; };
class Box { class Box {
@ -55,20 +41,12 @@ class Box {
Box Next() const; Box Next() const;
Box FirstChild() const; Box FirstChild() const;
// Reads the box contents, excluding the header.
nsTArray<uint8_t> Read() const; nsTArray<uint8_t> Read() const;
// Reads the complete box; its header and body.
nsTArray<uint8_t> ReadCompleteBox() const;
// Reads from the content of the box, excluding header.
bool Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange) const; bool Read(nsTArray<uint8_t>* aDest, const MediaByteRange& aRange) const;
static const uint64_t kMAX_BOX_READ; static const uint64_t kMAX_BOX_READ;
// Returns a slice, pointing to the data of this box. The lifetime of const nsTArray<uint8_t>& Header() const { return mHeader; }
// the memory this slice points to matches the box's context's lifetime.
ByteSlice ReadAsSlice();
private: private:
bool Contains(MediaByteRange aRange) const; bool Contains(MediaByteRange aRange) const;
@ -77,22 +55,20 @@ class Box {
uint64_t mBodyOffset; uint64_t mBodyOffset;
uint64_t mChildOffset; uint64_t mChildOffset;
AtomType mType; AtomType mType;
nsTArray<uint8_t> mHeader;
const Box* mParent; const Box* mParent;
}; };
// BoxReader serves box data through an AutoByteReader. The box data is // BoxReader takes a copy of a box contents and serves through an
// stored either in the box's context's bump allocator, or in the ByteStream // AutoByteReader.
// itself if the ByteStream implements the Access() method.
// NOTE: The data the BoxReader reads may be stored in the Box's BoxContext.
// Ensure that the BoxReader doesn't outlive the BoxContext!
class MOZ_RAII BoxReader { class MOZ_RAII BoxReader {
public: public:
explicit BoxReader(Box& aBox) explicit BoxReader(Box& aBox)
: mData(aBox.ReadAsSlice()), mReader(mData.mBytes, mData.mSize) {} : mBuffer(aBox.Read()), mReader(mBuffer.Elements(), mBuffer.Length()) {}
BufferReader* operator->() { return &mReader; } BufferReader* operator->() { return &mReader; }
private: private:
ByteSlice mData; nsTArray<uint8_t> mBuffer;
BufferReader mReader; BufferReader mReader;
}; };
} // namespace mozilla } // namespace mozilla

Просмотреть файл

@ -24,14 +24,6 @@ class ByteStream : public DecoderDoctorLifeLogger<ByteStream> {
virtual void DiscardBefore(int64_t offset) {} virtual void DiscardBefore(int64_t offset) {}
// If this ByteStream's underlying storage of media is in-memory, this
// function returns a pointer to the in-memory storage of data at offset.
// Note that even if a ByteStream stores data in memory, it may not be
// stored contiguously, in which case this returns nullptr.
virtual const uint8_t* GetContiguousAccess(int64_t aOffset, size_t aSize) {
return nullptr;
}
protected: protected:
virtual ~ByteStream() {} virtual ~ByteStream() {}
}; };

Просмотреть файл

@ -36,11 +36,6 @@ namespace mozilla {
const uint32_t kKeyIdSize = 16; const uint32_t kKeyIdSize = 16;
// We ensure there are no gaps in samples' CTS between the last sample in a
// Moof, and the first sample in the next Moof, if they're within these many
// Microseconds of each other.
const Microseconds CROSS_MOOF_CTS_MERGE_THRESHOLD = 1;
bool MoofParser::RebuildFragmentedIndex(const MediaByteRangeSet& aByteRanges) { bool MoofParser::RebuildFragmentedIndex(const MediaByteRangeSet& aByteRanges) {
BoxContext context(mSource, aByteRanges); BoxContext context(mSource, aByteRanges);
return RebuildFragmentedIndex(context); return RebuildFragmentedIndex(context);
@ -76,7 +71,7 @@ bool MoofParser::RebuildFragmentedIndex(BoxContext& aContext) {
ParseMoov(box); ParseMoov(box);
} else if (box.IsType("moof")) { } else if (box.IsType("moof")) {
Moof moof(box, mTrackParseMode, mTrex, mMvhd, mMdhd, mEdts, mSinf, Moof moof(box, mTrackParseMode, mTrex, mMvhd, mMdhd, mEdts, mSinf,
&mLastDecodeTime, mIsAudio, mTracksEndCts); &mLastDecodeTime, mIsAudio);
if (!moof.IsValid() && !box.Next().IsAvailable()) { if (!moof.IsValid() && !box.Next().IsAvailable()) {
// Moof isn't valid abort search for now. // Moof isn't valid abort search for now.
@ -427,8 +422,7 @@ class CtsComparator {
Moof::Moof(Box& aBox, const TrackParseMode& aTrackParseMode, Trex& aTrex, Moof::Moof(Box& aBox, const TrackParseMode& aTrackParseMode, Trex& aTrex,
Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, Sinf& aSinf, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, Sinf& aSinf,
uint64_t* aDecodeTime, bool aIsAudio, uint64_t* aDecodeTime, bool aIsAudio)
nsTArray<TrackEndCts>& aTracksEndCts)
: mRange(aBox.Range()), mTfhd(aTrex), mMaxRoundingError(35000) { : mRange(aBox.Range()), mTfhd(aTrex), mMaxRoundingError(35000) {
LOG_DEBUG( LOG_DEBUG(
Moof, Moof,
@ -461,7 +455,8 @@ Moof::Moof(Box& aBox, const TrackParseMode& aTrackParseMode, Trex& aTrex,
mPsshes.AppendElement(); mPsshes.AppendElement();
} }
nsTArray<uint8_t>& pssh = mPsshes.LastElement(); nsTArray<uint8_t>& pssh = mPsshes.LastElement();
pssh.AppendElements(std::move(box.ReadCompleteBox())); pssh.AppendElements(box.Header());
pssh.AppendElements(box.Read());
} }
if (IsValid()) { if (IsValid()) {
@ -478,35 +473,6 @@ Moof::Moof(Box& aBox, const TrackParseMode& aTrackParseMode, Trex& aTrex,
ctsOrder[i]->mCompositionRange.start; ctsOrder[i]->mCompositionRange.start;
} }
// Ensure that there are no gaps between the first sample in this
// Moof and the preceeding Moof.
if (!ctsOrder.IsEmpty()) {
bool found = false;
// Track ID of the track we're parsing.
const uint32_t trackId = aTrex.mTrackId;
// Find the previous CTS end time of Moof preceeding the Moofs we just
// parsed, for the track we're parsing.
for (auto& prevCts : aTracksEndCts) {
if (prevCts.mTrackId == trackId) {
// We have previously parsed a Moof for this track. Smooth the gap
// between samples for this track across the Moof bounary.
if (ctsOrder[0]->mCompositionRange.start - prevCts.mCtsEndTime <=
CROSS_MOOF_CTS_MERGE_THRESHOLD) {
ctsOrder[0]->mCompositionRange.start = prevCts.mCtsEndTime;
}
prevCts.mCtsEndTime = ctsOrder.LastElement()->mCompositionRange.end;
found = true;
break;
}
}
if (!found) {
// We've not parsed a Moof for this track yet. Save its CTS end
// time for the next Moof we parse.
aTracksEndCts.AppendElement(TrackEndCts(
trackId, ctsOrder.LastElement()->mCompositionRange.end));
}
}
// In MP4, the duration of a sample is defined as the delta between two // In MP4, the duration of a sample is defined as the delta between two
// decode timestamps. The operation above has updated the duration of each // decode timestamps. The operation above has updated the duration of each
// sample as a Sample's duration is mCompositionRange.end - // sample as a Sample's duration is mCompositionRange.end -

Просмотреть файл

@ -23,16 +23,6 @@ class BoxContext;
class BoxReader; class BoxReader;
class Moof; class Moof;
// Used to track the CTS end time of the last sample of a track
// in the preceeding Moof, so that we can smooth tracks' timestamps
// across Moofs.
struct TrackEndCts {
TrackEndCts(uint32_t aTrackId, Microseconds aCtsEndTime)
: mTrackId(aTrackId), mCtsEndTime(aCtsEndTime) {}
uint32_t mTrackId;
Microseconds mCtsEndTime;
};
class Mvhd : public Atom { class Mvhd : public Atom {
public: public:
Mvhd() Mvhd()
@ -244,8 +234,7 @@ class Moof final : public Atom {
public: public:
Moof(Box& aBox, const TrackParseMode& aTrackParseMode, Trex& aTrex, Moof(Box& aBox, const TrackParseMode& aTrackParseMode, Trex& aTrex,
Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, Sinf& aSinf, Mvhd& aMvhd, Mdhd& aMdhd, Edts& aEdts, Sinf& aSinf,
uint64_t* aDecodeTime, bool aIsAudio, uint64_t* aDecodeTime, bool aIsAudio);
nsTArray<TrackEndCts>& aTracksEndCts);
bool GetAuxInfo(AtomType aType, FallibleTArray<MediaByteRange>* aByteRanges); bool GetAuxInfo(AtomType aType, FallibleTArray<MediaByteRange>* aByteRanges);
void FixRounding(const Moof& aMoof); void FixRounding(const Moof& aMoof);
@ -348,7 +337,6 @@ class MoofParser : public DecoderDoctorLifeLogger<MoofParser> {
void ScanForMetadata(mozilla::MediaByteRange& aMoov); void ScanForMetadata(mozilla::MediaByteRange& aMoov);
nsTArray<Moof> mMoofs; nsTArray<Moof> mMoofs;
nsTArray<MediaByteRange> mMediaRanges; nsTArray<MediaByteRange> mMediaRanges;
nsTArray<TrackEndCts> mTracksEndCts;
bool mIsAudio; bool mIsAudio;
uint64_t mLastDecodeTime; uint64_t mLastDecodeTime;
// Either a ParseAllTracks if in multitrack mode, or an integer representing // Either a ParseAllTracks if in multitrack mode, or an integer representing