diff --git a/dom/media/MP3Demuxer.cpp b/dom/media/MP3Demuxer.cpp index daeafdc59aa7..941d93d57e40 100644 --- a/dom/media/MP3Demuxer.cpp +++ b/dom/media/MP3Demuxer.cpp @@ -205,7 +205,7 @@ MP3TrackDemuxer::FastSeek(const TimeUnit& aTime) { if (!aTime.ToMicroseconds()) { // Quick seek to the beginning of the stream. mFrameIndex = 0; - } else if (vbr.IsTOCPresent()) { + } else if (vbr.IsTOCPresent() && Duration().ToMicroseconds() > 0) { // Use TOC for more precise seeking. const float durationFrac = static_cast(aTime.ToMicroseconds()) / Duration().ToMicroseconds(); @@ -358,7 +358,9 @@ MP3TrackDemuxer::Duration() const { // Unknown length, we can't estimate duration. return TimeUnit::FromMicroseconds(-1); } - numFrames = (streamLen - mFirstFrameOffset) / AverageFrameLength(); + if (AverageFrameLength() > 0) { + numFrames = (streamLen - mFirstFrameOffset) / AverageFrameLength(); + } } return Duration(numFrames); } @@ -534,7 +536,7 @@ MP3TrackDemuxer::OffsetFromFrameIndex(int64_t aFrameIndex) const { int64_t offset = 0; const auto& vbr = mParser.VBRInfo(); - if (vbr.NumBytes() && vbr.NumAudioFrames()) { + if (vbr.IsValid()) { offset = mFirstFrameOffset + aFrameIndex * vbr.NumBytes().value() / vbr.NumAudioFrames().value(); } else if (AverageFrameLength() > 0) { @@ -550,7 +552,7 @@ MP3TrackDemuxer::FrameIndexFromOffset(int64_t aOffset) const { int64_t frameIndex = 0; const auto& vbr = mParser.VBRInfo(); - if (vbr.NumBytes() && vbr.NumAudioFrames()) { + if (vbr.IsValid()) { frameIndex = static_cast(aOffset - mFirstFrameOffset) / vbr.NumBytes().value() * vbr.NumAudioFrames().value(); frameIndex = std::min(vbr.NumAudioFrames().value(), frameIndex); @@ -626,7 +628,7 @@ MP3TrackDemuxer::AverageFrameLength() const { return static_cast(mTotalFrameLen) / mNumParsedFrames; } const auto& vbr = mParser.VBRInfo(); - if (vbr.NumBytes() && vbr.NumAudioFrames()) { + if (vbr.IsValid() && vbr.NumAudioFrames().value() + 1) { return static_cast(vbr.NumBytes().value()) / (vbr.NumAudioFrames().value() + 1); } @@ -962,6 +964,16 @@ FrameParser::VBRHeader::IsTOCPresent() const { return mTOC.size() == vbr_header::TOC_SIZE; } +bool +FrameParser::VBRHeader::IsValid() const { + return mType != NONE && + mNumAudioFrames.valueOr(0) > 0 && + mNumBytes.valueOr(0) > 0 && + // We don't care about the scale for any computations here. + // mScale < 101 && + true; +} + int64_t FrameParser::VBRHeader::Offset(float aDurationFac) const { if (!IsTOCPresent()) { diff --git a/dom/media/MP3Demuxer.h b/dom/media/MP3Demuxer.h index f42126d764e1..d98cb73566a2 100644 --- a/dom/media/MP3Demuxer.h +++ b/dom/media/MP3Demuxer.h @@ -232,6 +232,9 @@ public: // Returns true iff Xing/Info TOC (table of contents) is present. bool IsTOCPresent() const; + // Returns whether the header is valid (containing reasonable field values). + bool IsValid() const; + // Returns the byte offset for the given duration percentage as a factor // (0: begin, 1.0: end). int64_t Offset(float aDurationFac) const;