Bug 1336271 - use MediaByteRangeSet to keep metadata stream in case of invalid 'ftyp' box. r?jya
MozReview-Commit-ID: JruswJ3EpEb
--- a/media/libstagefright/binding/MoofParser.cpp
+++ b/media/libstagefright/binding/MoofParser.cpp
@@ -142,84 +142,85 @@ MoofParser::BlockingReadNextMoof()
byteRanges.Clear();
byteRanges += MediaByteRange(mOffset, box.Range().mEnd);
return RebuildFragmentedIndex(context);
}
}
return false;
}
-void
-MoofParser::ScanForMetadata(mozilla::MediaByteRange& aFtyp,
- mozilla::MediaByteRange& aMoov)
+bool
+MoofParser::ScanForMetadata(mozilla::MediaByteRangeSet& aRanges)
{
+ // TODO:
+ // aRanges should include the box from beginning of streaming
+ // ('ftyp' in most cases) due to stagefright limitation. mInitRange
+ // includes 'moov' only. Once rust parser is enabled, aRanges can be
+ // removed and use mInitRange.
+
int64_t length = std::numeric_limits<int64_t>::max();
mSource->Length(&length);
MediaByteRangeSet byteRanges;
byteRanges += MediaByteRange(0, length);
RefPtr<mp4_demuxer::BlockingStream> stream = new BlockingStream(mSource);
BoxContext context(stream, byteRanges);
for (Box box(&context, mOffset); box.IsAvailable(); box = box.Next()) {
- if (box.IsType("ftyp")) {
- aFtyp = box.Range();
+ CheckedInt<MediaByteBuffer::size_type> boxLength = box.Range().Length();
+ if (!boxLength.isValid() || !boxLength.value()) {
continue;
}
+
+ if (box.IsType("ftyp")) {
+ aRanges += box.Range();
+ }
+
if (box.IsType("moov")) {
- aMoov = box.Range();
- break;
+ aRanges += box.Range();
+ mInitRange = box.Range();
+ return true;
}
}
- mInitRange = aFtyp.Span(aMoov);
+ return false;
}
bool
MoofParser::HasMetadata()
{
- MediaByteRange ftyp;
- MediaByteRange moov;
- ScanForMetadata(ftyp, moov);
- return !!ftyp.Length() && !!moov.Length();
+ MediaByteRangeSet ranges;
+ return ScanForMetadata(ranges);
}
already_AddRefed<mozilla::MediaByteBuffer>
MoofParser::Metadata()
{
- MediaByteRange ftyp;
- MediaByteRange moov;
- ScanForMetadata(ftyp, moov);
- CheckedInt<MediaByteBuffer::size_type> ftypLength = ftyp.Length();
- CheckedInt<MediaByteBuffer::size_type> moovLength = moov.Length();
- if (!ftypLength.isValid() || !moovLength.isValid()
- || !ftypLength.value() || !moovLength.value()) {
- // No ftyp or moov, or they cannot be used as array size.
- return nullptr;
- }
- CheckedInt<MediaByteBuffer::size_type> totalLength = ftypLength + moovLength;
- if (!totalLength.isValid()) {
- // Addition overflow, or sum cannot be used as array size.
- return nullptr;
- }
- RefPtr<MediaByteBuffer> metadata = new MediaByteBuffer();
- if (!metadata->SetLength(totalLength.value(), fallible)) {
- // OOM
+ MediaByteRangeSet ranges;
+ if (!ScanForMetadata(ranges)) {
return nullptr;
}
+ RefPtr<MediaByteBuffer> metadata = new MediaByteBuffer();
RefPtr<mp4_demuxer::BlockingStream> stream = new BlockingStream(mSource);
- size_t read;
- bool rv =
- stream->ReadAt(ftyp.mStart, metadata->Elements(), ftypLength.value(), &read);
- if (!rv || read != ftypLength.value()) {
- return nullptr;
- }
- rv =
- stream->ReadAt(moov.mStart, metadata->Elements() + ftypLength.value(), moovLength.value(), &read);
- if (!rv || read != moovLength.value()) {
- return nullptr;
+ for (const auto& range: ranges) {
+ RefPtr<MediaByteBuffer> buffer = new MediaByteBuffer();
+ if (!buffer->SetLength(range.Length(), fallible)) {
+ // OOM
+ return nullptr;
+ }
+
+ size_t read;
+ bool rv =
+ stream->ReadAt(range.mStart, buffer->Elements(), range.Length(), &read);
+ if (!rv || read != range.Length()) {
+ return nullptr;
+ }
+ if (!metadata->AppendElements(*buffer, fallible)) {
+ // OOM
+ return nullptr;
+ }
}
return metadata.forget();
}
Interval<Microseconds>
MoofParser::GetCompositionRange(const MediaByteRangeSet& aByteRanges)
{
Interval<Microseconds> compositionRange;
--- a/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
+++ b/media/libstagefright/binding/include/mp4_demuxer/MoofParser.h
@@ -294,18 +294,17 @@ public:
Edts mEdts;
Sinf mSinf;
nsTArray<CencSampleEncryptionInfoEntry> mTrackSampleEncryptionInfoEntries;
nsTArray<SampleToGroupEntry> mTrackSampleToGroupEntries;
nsTArray<Moof>& Moofs() { return mMoofs; }
private:
- void ScanForMetadata(mozilla::MediaByteRange& aFtyp,
- mozilla::MediaByteRange& aMoov);
+ bool ScanForMetadata(mozilla::MediaByteRangeSet& aRanges);
nsTArray<Moof> mMoofs;
nsTArray<MediaByteRange> mMediaRanges;
bool mIsAudio;
uint64_t mLastDecodeTime;
};
}
#endif