diff --git a/dom/html/HTMLMediaElement.cpp b/dom/html/HTMLMediaElement.cpp
index 94f343f00f..1fbb2af62c 100644
--- a/dom/html/HTMLMediaElement.cpp
+++ b/dom/html/HTMLMediaElement.cpp
@@ -1467,10 +1467,12 @@ HTMLMediaElement::Seek(double aTime,
// Clamp the seek target to inside the seekable ranges.
nsRefPtr seekable = new dom::TimeRanges();
- if (NS_FAILED(mDecoder->GetSeekable(seekable))) {
+ media::TimeIntervals seekableIntervals = mDecoder->GetSeekable();
+ if (seekableIntervals.IsInvalid()) {
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return;
}
+ seekableIntervals.ToTimeRanges(seekable);
uint32_t length = 0;
seekable->GetLength(&length);
if (!length) {
@@ -1590,9 +1592,8 @@ HTMLMediaElement::Seekable() const
{
nsRefPtr ranges = new TimeRanges();
if (mDecoder && mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) {
- mDecoder->GetSeekable(ranges);
+ mDecoder->GetSeekable().ToTimeRanges(ranges);
}
- ranges->Normalize();
return ranges.forget();
}
@@ -4127,12 +4128,12 @@ HTMLMediaElement::Buffered() const
nsRefPtr ranges = new TimeRanges();
if (mReadyState > nsIDOMHTMLMediaElement::HAVE_NOTHING) {
if (mDecoder) {
- // If GetBuffered fails we ignore the error result and just return the
- // time ranges we found up till the error.
- mDecoder->GetBuffered(ranges);
+ media::TimeIntervals buffered = mDecoder->GetBuffered();
+ if (!buffered.IsInvalid()) {
+ buffered.ToTimeRanges(ranges);
+ }
}
}
- ranges->Normalize();
return ranges.forget();
}
diff --git a/dom/media/Intervals.h b/dom/media/Intervals.h
index ad0263f5eb..ccf2930066 100644
--- a/dom/media/Intervals.h
+++ b/dom/media/Intervals.h
@@ -514,8 +514,8 @@ public:
void Shift(const T& aOffset)
{
for (auto& interval : mIntervals) {
- interval.mStart += aOffset;
- interval.mEnd += aOffset;
+ interval.mStart = interval.mStart + aOffset;
+ interval.mEnd = interval.mEnd + aOffset;
}
}
diff --git a/dom/media/MediaDecoder.cpp b/dom/media/MediaDecoder.cpp
index 3694c88f25..92f6235530 100644
--- a/dom/media/MediaDecoder.cpp
+++ b/dom/media/MediaDecoder.cpp
@@ -12,7 +12,6 @@
#include "nsTArray.h"
#include "VideoUtils.h"
#include "MediaDecoderStateMachine.h"
-#include "mozilla/dom/TimeRanges.h"
#include "ImageContainer.h"
#include "MediaResource.h"
#include "nsError.h"
@@ -1466,22 +1465,21 @@ bool MediaDecoder::IsMediaSeekable()
return mMediaSeekable;
}
-nsresult MediaDecoder::GetSeekable(dom::TimeRanges* aSeekable)
+media::TimeIntervals MediaDecoder::GetSeekable()
{
- double initialTime = 0.0;
-
// We can seek in buffered range if the media is seekable. Also, we can seek
// in unbuffered ranges if the transport level is seekable (local file or the
// server supports range requests, etc.)
if (!IsMediaSeekable()) {
- return NS_OK;
+ return media::TimeIntervals();
} else if (!IsTransportSeekable()) {
- return GetBuffered(aSeekable);
+ return GetBuffered();
} else {
- double end = IsInfinite() ? std::numeric_limits::infinity()
- : initialTime + GetDuration();
- aSeekable->Add(initialTime, end);
- return NS_OK;
+ return media::TimeIntervals(
+ media::TimeInterval(media::TimeUnit::FromMicroseconds(0),
+ IsInfinite() ?
+ media::TimeUnit::FromInfinity() :
+ media::TimeUnit::FromSeconds(GetDuration())));
}
}
@@ -1623,9 +1621,9 @@ void MediaDecoder::Invalidate()
// Constructs the time ranges representing what segments of the media
// are buffered and playable.
-nsresult MediaDecoder::GetBuffered(dom::TimeRanges* aBuffered) {
- NS_ENSURE_TRUE(mDecoderStateMachine && !mShuttingDown, NS_ERROR_FAILURE);
- return mDecoderStateMachine->GetBuffered(aBuffered);
+media::TimeIntervals MediaDecoder::GetBuffered() {
+ NS_ENSURE_TRUE(mDecoderStateMachine && !mShuttingDown, media::TimeIntervals::Invalid());
+ return mDecoderStateMachine->GetBuffered();
}
size_t MediaDecoder::SizeOfVideoQueue() {
diff --git a/dom/media/MediaDecoder.h b/dom/media/MediaDecoder.h
index 85a2e070e6..365f9fb5f5 100644
--- a/dom/media/MediaDecoder.h
+++ b/dom/media/MediaDecoder.h
@@ -197,16 +197,11 @@ destroying the MediaDecoder object.
#include "MediaStreamGraph.h"
#include "AbstractMediaDecoder.h"
#include "necko-config.h"
+#include "TimeUnits.h"
class nsIStreamListener;
class nsIPrincipal;
-namespace mozilla {
-namespace dom {
-class TimeRanges;
-}
-}
-
namespace mozilla {
namespace layers {
class Image;
@@ -625,7 +620,7 @@ public:
virtual bool IsTransportSeekable() override;
// Return the time ranges that can be seeked into.
- virtual nsresult GetSeekable(dom::TimeRanges* aSeekable);
+ virtual media::TimeIntervals GetSeekable();
// Set the end time of the media resource. When playback reaches
// this point the media pauses. aTime is in seconds.
@@ -680,7 +675,7 @@ public:
// Constructs the time ranges representing what segments of the media
// are buffered and playable.
- virtual nsresult GetBuffered(dom::TimeRanges* aBuffered);
+ virtual media::TimeIntervals GetBuffered();
// Returns the size, in bytes, of the heap memory used by the currently
// queued decoded video and audio data.
diff --git a/dom/media/MediaDecoderReader.cpp b/dom/media/MediaDecoderReader.cpp
index 8a7dcf6cd2..67ae9b0f93 100644
--- a/dom/media/MediaDecoderReader.cpp
+++ b/dom/media/MediaDecoderReader.cpp
@@ -162,8 +162,8 @@ MediaDecoderReader::SetStartTime(int64_t aStartTime)
mStartTime = aStartTime;
}
-nsresult
-MediaDecoderReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered)
+media::TimeIntervals
+MediaDecoderReader::GetBuffered()
{
AutoPinned stream(mDecoder->GetResource());
int64_t durationUs = 0;
@@ -171,8 +171,7 @@ MediaDecoderReader::GetBuffered(mozilla::dom::TimeRanges* aBuffered)
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
durationUs = mDecoder->GetMediaDuration();
}
- GetEstimatedBufferedTimeRanges(stream, durationUs, aBuffered);
- return NS_OK;
+ return GetEstimatedBufferedTimeRanges(stream, durationUs);
}
int64_t
diff --git a/dom/media/MediaDecoderReader.h b/dom/media/MediaDecoderReader.h
index f63cda624e..11b1a17ad4 100644
--- a/dom/media/MediaDecoderReader.h
+++ b/dom/media/MediaDecoderReader.h
@@ -12,13 +12,10 @@
#include "MediaPromise.h"
#include "MediaQueue.h"
#include "AudioCompactor.h"
+#include "TimeUnits.h"
namespace mozilla {
-namespace dom {
-class TimeRanges;
-}
-
class MediaDecoderReader;
class SharedDecoderManager;
@@ -226,7 +223,7 @@ public:
// The OggReader relies on this base implementation not performing I/O,
// since in FirefoxOS we can't do I/O on the main thread, where this is
// called.
- virtual nsresult GetBuffered(dom::TimeRanges* aBuffered);
+ virtual media::TimeIntervals GetBuffered();
virtual int64_t ComputeStartTime(const VideoData* aVideo, const AudioData* aAudio);
diff --git a/dom/media/MediaDecoderStateMachine.cpp b/dom/media/MediaDecoderStateMachine.cpp
index bea2af9e66..79602bddee 100644
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -21,7 +21,7 @@
#include "mozilla/MathAlgorithms.h"
#include "mozilla/mozalloc.h"
#include "VideoUtils.h"
-#include "mozilla/dom/TimeRanges.h"
+#include "TimeUnits.h"
#include "nsDeque.h"
#include "AudioSegment.h"
#include "VideoSegment.h"
@@ -1686,17 +1686,13 @@ void MediaDecoderStateMachine::NotifyDataArrived(const char* aBuffer,
//
// Make sure to only do this if we have a start time, otherwise the reader
// doesn't know how to compute GetBuffered.
- nsRefPtr buffered = new dom::TimeRanges();
- if (mDecoder->IsInfinite() && (mStartTime != -1) &&
- NS_SUCCEEDED(mDecoder->GetBuffered(buffered)))
- {
- uint32_t length = 0;
- buffered->GetLength(&length);
- if (length) {
- double end = 0;
- buffered->End(length - 1, &end);
+ media::TimeIntervals buffered{mDecoder->GetBuffered()};
+ if (mDecoder->IsInfinite() && (mStartTime != -1) && !buffered.IsInvalid()) {
+ bool exists;
+ media::TimeUnit end{buffered.GetEnd(&exists)};
+ if (exists) {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
- mEndTime = std::max(mEndTime, end * USECS_PER_S);
+ mEndTime = std::max(mEndTime, end.ToMicroseconds());
}
}
}
@@ -2117,9 +2113,10 @@ bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs)
return false;
}
- nsRefPtr buffered = new dom::TimeRanges();
- nsresult rv = mReader->GetBuffered(buffered.get());
- NS_ENSURE_SUCCESS(rv, false);
+ media::TimeIntervals buffered{mReader->GetBuffered()};
+ if (buffered.IsInvalid()) {
+ return false;
+ }
int64_t endOfDecodedVideoData = INT64_MAX;
if (HasVideo() && !VideoQueue().AtEndOfStream()) {
@@ -2134,9 +2131,13 @@ bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs)
}
int64_t endOfDecodedData = std::min(endOfDecodedVideoData, endOfDecodedAudioData);
- return endOfDecodedData != INT64_MAX &&
- !buffered->Contains(static_cast(endOfDecodedData) / USECS_PER_S,
- static_cast(std::min(endOfDecodedData + aUsecs, GetDuration())) / USECS_PER_S);
+ if (GetDuration() < endOfDecodedData) {
+ // Our duration is not up to date. No point buffering.
+ return false;
+ }
+ media::TimeInterval interval(media::TimeUnit::FromMicroseconds(endOfDecodedData),
+ media::TimeUnit::FromMicroseconds(std::min(endOfDecodedData + aUsecs, GetDuration())));
+ return endOfDecodedData != INT64_MAX && !buffered.Contains(interval);
}
void
diff --git a/dom/media/MediaDecoderStateMachine.h b/dom/media/MediaDecoderStateMachine.h
index 7cf45e78be..325bf793dc 100644
--- a/dom/media/MediaDecoderStateMachine.h
+++ b/dom/media/MediaDecoderStateMachine.h
@@ -297,16 +297,16 @@ public:
return mState == DECODER_STATE_SEEKING;
}
- nsresult GetBuffered(dom::TimeRanges* aBuffered) {
+ media::TimeIntervals GetBuffered() {
// It's possible for JS to query .buffered before we've determined the start
// time from metadata, in which case the reader isn't ready to be asked this
// question.
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mStartTime < 0) {
- return NS_OK;
+ return media::TimeIntervals();
}
- return mReader->GetBuffered(aBuffered);
+ return mReader->GetBuffered();
}
void SetPlaybackRate(double aPlaybackRate);
diff --git a/dom/media/MediaFormatReader.cpp b/dom/media/MediaFormatReader.cpp
index 6a87db7a86..c4281e73be 100644
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -5,7 +5,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/dom/HTMLMediaElement.h"
-#include "mozilla/dom/TimeRanges.h"
#include "mozilla/Preferences.h"
#include "nsPrintfCString.h"
#include "nsSize.h"
@@ -1177,8 +1176,8 @@ MediaFormatReader::GetEvictionOffset(double aTime)
return std::min(audioOffset, videoOffset);
}
-nsresult
-MediaFormatReader::GetBuffered(dom::TimeRanges* aBuffered)
+media::TimeIntervals
+MediaFormatReader::GetBuffered()
{
media::TimeIntervals videoti;
media::TimeIntervals audioti;
@@ -1202,14 +1201,14 @@ MediaFormatReader::GetBuffered(dom::TimeRanges* aBuffered)
}
if (HasAudio() && HasVideo()) {
videoti.Intersection(audioti);
- videoti.ToTimeRanges(aBuffered);
+ return videoti;
} else if (HasAudio()) {
- audioti.ToTimeRanges(aBuffered);
+ return audioti;
} else if (HasVideo()) {
- videoti.ToTimeRanges(aBuffered);
+ return videoti;
}
- return NS_OK;
+ return media::TimeIntervals();
}
bool MediaFormatReader::IsDormantNeeded()
diff --git a/dom/media/MediaFormatReader.h b/dom/media/MediaFormatReader.h
index a5b862cdb6..c34c5acacb 100644
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -17,10 +17,6 @@
namespace mozilla {
-namespace dom {
-class TimeRanges;
-}
-
#if defined(MOZ_GONK_MEDIACODEC) || defined(XP_WIN) || defined(MOZ_APPLEMEDIA) || defined(MOZ_FFMPEG)
#define READER_DORMANT_HEURISTIC
#else
@@ -81,7 +77,7 @@ public:
uint32_t aLength,
int64_t aOffset) override;
- virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) override;
+ virtual media::TimeIntervals GetBuffered() override;
// For Media Resource Management
virtual void SetIdle() override;
diff --git a/dom/media/TimeUnits.h b/dom/media/TimeUnits.h
index 693092dc2c..f478481415 100644
--- a/dom/media/TimeUnits.h
+++ b/dom/media/TimeUnits.h
@@ -8,7 +8,6 @@
#define TIME_UNITS_H
#include "Intervals.h"
-#include "VideoUtils.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/FloatingPoint.h"
#include "mozilla/dom/TimeRanges.h"
@@ -16,6 +15,15 @@
namespace mozilla {
namespace media {
+// Number of microseconds per second. 1e6.
+static const int64_t USECS_PER_S = 1000000;
+
+// Number of microseconds per millisecond.
+static const int64_t USECS_PER_MS = 1000;
+
+// Number of nanoseconds per second. 1e9.
+static const int64_t NSECS_PER_S = 1000000000;
+
struct Microseconds {
Microseconds()
: mValue(0)
@@ -89,6 +97,10 @@ public:
return TimeUnit(aValue.mValue);
}
+ static TimeUnit FromNanoseconds(int64_t aValue) {
+ return TimeUnit(aValue / 1000);
+ }
+
static TimeUnit FromInfinity() {
return TimeUnit(INT64_MAX);
}
@@ -97,6 +109,10 @@ public:
return mValue.value();
}
+ int64_t ToNanoseconds() const {
+ return mValue.value() * 1000;
+ }
+
double ToSeconds() const {
if (IsInfinite()) {
return PositiveInfinity();
@@ -198,6 +214,17 @@ public:
: BaseType(Move(aOther))
{}
+ static TimeIntervals Invalid()
+ {
+ return TimeIntervals(TimeInterval(TimeUnit::FromMicroseconds(INT64_MIN),
+ TimeUnit::FromMicroseconds(INT64_MIN)));
+ }
+ bool IsInvalid()
+ {
+ return Length() == 1 && Start(0).ToMicroseconds() == INT64_MIN &&
+ End(0).ToMicroseconds() == INT64_MIN;
+ }
+
TimeIntervals() = default;
// Make TimeIntervals interchangeable with dom::TimeRanges.
diff --git a/dom/media/VideoUtils.cpp b/dom/media/VideoUtils.cpp
index 22424d155e..d16a505ad7 100644
--- a/dom/media/VideoUtils.cpp
+++ b/dom/media/VideoUtils.cpp
@@ -4,7 +4,7 @@
#include "VideoUtils.h"
#include "MediaResource.h"
-#include "mozilla/dom/TimeRanges.h"
+#include "TimeUnits.h"
#include "nsMathUtils.h"
#include "nsSize.h"
#include "VorbisUtils.h"
@@ -70,18 +70,20 @@ static int64_t BytesToTime(int64_t offset, int64_t length, int64_t durationUs) {
return int64_t(double(durationUs) * r);
}
-void GetEstimatedBufferedTimeRanges(mozilla::MediaResource* aStream,
- int64_t aDurationUsecs,
- mozilla::dom::TimeRanges* aOutBuffered)
+media::TimeIntervals GetEstimatedBufferedTimeRanges(mozilla::MediaResource* aStream,
+ int64_t aDurationUsecs)
{
+ media::TimeIntervals buffered;
// Nothing to cache if the media takes 0us to play.
- if (aDurationUsecs <= 0 || !aStream || !aOutBuffered)
- return;
+ if (aDurationUsecs <= 0 || !aStream)
+ return buffered;
// Special case completely cached files. This also handles local files.
if (aStream->IsDataCachedToEndOfResource(0)) {
- aOutBuffered->Add(0, double(aDurationUsecs) / USECS_PER_S);
- return;
+ buffered +=
+ media::TimeInterval(media::TimeUnit::FromMicroseconds(0),
+ media::TimeUnit::FromMicroseconds(aDurationUsecs));
+ return buffered;
}
int64_t totalBytes = aStream->GetLength();
@@ -90,7 +92,7 @@ void GetEstimatedBufferedTimeRanges(mozilla::MediaResource* aStream,
// buffered. This will put us in a state of eternally-low-on-undecoded-data
// which is not great, but about the best we can do.
if (totalBytes <= 0)
- return;
+ return buffered;
int64_t startOffset = aStream->GetNextCachedData(0);
while (startOffset >= 0) {
@@ -102,12 +104,14 @@ void GetEstimatedBufferedTimeRanges(mozilla::MediaResource* aStream,
int64_t startUs = BytesToTime(startOffset, totalBytes, aDurationUsecs);
int64_t endUs = BytesToTime(endOffset, totalBytes, aDurationUsecs);
if (startUs != endUs) {
- aOutBuffered->Add(double(startUs) / USECS_PER_S,
- double(endUs) / USECS_PER_S);
+ buffered +=
+ media::TimeInterval(media::TimeUnit::FromMicroseconds(startUs),
+
+ media::TimeUnit::FromMicroseconds(endUs));
}
startOffset = aStream->GetNextCachedData(endOffset);
}
- return;
+ return buffered;
}
int DownmixAudioToStereo(mozilla::AudioDataValue* buffer,
diff --git a/dom/media/VideoUtils.h b/dom/media/VideoUtils.h
index e11087f6c6..950cf85536 100644
--- a/dom/media/VideoUtils.h
+++ b/dom/media/VideoUtils.h
@@ -21,6 +21,7 @@
#include "prtime.h"
#include "AudioSampleFormat.h"
#include "mozilla/RefPtr.h"
+#include "TimeUnits.h"
using mozilla::CheckedInt64;
using mozilla::CheckedUint64;
@@ -116,19 +117,14 @@ void DeleteOnMainThread(nsAutoPtr& aObject) {
class MediaResource;
-namespace dom {
-class TimeRanges;
-}
-
// Estimates the buffered ranges of a MediaResource using a simple
// (byteOffset/length)*duration method. Probably inaccurate, but won't
// do file I/O, and can be used when we don't have detailed knowledge
// of the byte->time mapping of a resource. aDurationUsecs is the duration
// of the media in microseconds. Estimated buffered ranges are stored in
// aOutBuffered. Ranges are 0-normalized, i.e. in the range of (0,duration].
-void GetEstimatedBufferedTimeRanges(mozilla::MediaResource* aStream,
- int64_t aDurationUsecs,
- mozilla::dom::TimeRanges* aOutBuffered);
+media::TimeIntervals GetEstimatedBufferedTimeRanges(mozilla::MediaResource* aStream,
+ int64_t aDurationUsecs);
// Converts from number of audio frames (aFrames) to microseconds, given
// the specified audio rate (aRate). Stores result in aOutUsecs. Returns true
diff --git a/dom/media/android/AndroidMediaPluginHost.cpp b/dom/media/android/AndroidMediaPluginHost.cpp
index 2d95f59bfd..5e390ce73c 100644
--- a/dom/media/android/AndroidMediaPluginHost.cpp
+++ b/dom/media/android/AndroidMediaPluginHost.cpp
@@ -4,7 +4,6 @@
* 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/. */
#include "mozilla/Preferences.h"
-#include "mozilla/dom/TimeRanges.h"
#include "MediaResource.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "AndroidMediaPluginHost.h"
diff --git a/dom/media/android/AndroidMediaReader.cpp b/dom/media/android/AndroidMediaReader.cpp
index 90be487b6e..847da8db5b 100644
--- a/dom/media/android/AndroidMediaReader.cpp
+++ b/dom/media/android/AndroidMediaReader.cpp
@@ -5,7 +5,6 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AndroidMediaReader.h"
#include "mozilla/TimeStamp.h"
-#include "mozilla/dom/TimeRanges.h"
#include "mozilla/gfx/Point.h"
#include "MediaResource.h"
#include "VideoUtils.h"
diff --git a/dom/media/fmp4/MP4Reader.cpp b/dom/media/fmp4/MP4Reader.cpp
index 3e38c7d710..bd02743012 100644
--- a/dom/media/fmp4/MP4Reader.cpp
+++ b/dom/media/fmp4/MP4Reader.cpp
@@ -18,7 +18,6 @@
#include "SharedThreadPool.h"
#include "mozilla/Preferences.h"
#include "mozilla/Telemetry.h"
-#include "mozilla/dom/TimeRanges.h"
#include "mp4_demuxer/AnnexB.h"
#include "mp4_demuxer/H264.h"
#include "SharedDecoderManager.h"
@@ -1017,12 +1016,13 @@ MP4Reader::GetEvictionOffset(double aTime)
return mDemuxer->GetEvictionOffset(aTime * 1000000.0);
}
-nsresult
-MP4Reader::GetBuffered(dom::TimeRanges* aBuffered)
+media::TimeIntervals
+MP4Reader::GetBuffered()
{
MonitorAutoLock mon(mDemuxerMonitor);
+ media::TimeIntervals buffered;
if (!mIndexReady) {
- return NS_OK;
+ return buffered;
}
UpdateIndex();
MOZ_ASSERT(mStartTime != -1, "Need to finish metadata decode first");
@@ -1035,12 +1035,13 @@ MP4Reader::GetBuffered(dom::TimeRanges* aBuffered)
nsTArray> timeRanges;
mDemuxer->ConvertByteRangesToTime(ranges, &timeRanges);
for (size_t i = 0; i < timeRanges.Length(); i++) {
- aBuffered->Add((timeRanges[i].start - mStartTime) / 1000000.0,
- (timeRanges[i].end - mStartTime) / 1000000.0);
+ buffered += media::TimeInterval(
+ media::TimeUnit::FromMicroseconds(timeRanges[i].start - mStartTime),
+ media::TimeUnit::FromMicroseconds(timeRanges[i].end - mStartTime));
}
}
- return NS_OK;
+ return buffered;
}
bool MP4Reader::IsDormantNeeded()
diff --git a/dom/media/fmp4/MP4Reader.h b/dom/media/fmp4/MP4Reader.h
index 0bca2da881..413f24d4f8 100644
--- a/dom/media/fmp4/MP4Reader.h
+++ b/dom/media/fmp4/MP4Reader.h
@@ -19,10 +19,6 @@
namespace mozilla {
-namespace dom {
-class TimeRanges;
-}
-
typedef std::deque> MediaSampleQueue;
class MP4Stream;
@@ -68,7 +64,7 @@ public:
virtual int64_t GetEvictionOffset(double aTime) override;
virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) override;
- virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) override;
+ virtual media::TimeIntervals GetBuffered() override;
// For Media Resource Management
virtual void SetIdle() override;
diff --git a/dom/media/gstreamer/GStreamerReader.cpp b/dom/media/gstreamer/GStreamerReader.cpp
index 27b1eafb2d..2104cb83c7 100644
--- a/dom/media/gstreamer/GStreamerReader.cpp
+++ b/dom/media/gstreamer/GStreamerReader.cpp
@@ -13,7 +13,6 @@
#include "GStreamerAllocator.h"
#include "GStreamerFormatHelper.h"
#include "VideoUtils.h"
-#include "mozilla/dom/TimeRanges.h"
#include "mozilla/Endian.h"
#include "mozilla/Preferences.h"
#include "mozilla/unused.h"
@@ -804,10 +803,11 @@ GStreamerReader::Seek(int64_t aTarget, int64_t aEndTime)
return SeekPromise::CreateAndResolve(aTarget, __func__);
}
-nsresult GStreamerReader::GetBuffered(dom::TimeRanges* aBuffered)
+media::TimeIntervals GStreamerReader::GetBuffered()
{
+ media::TimeIntervals buffered;
if (!mInfo.HasValidMedia()) {
- return NS_OK;
+ return buffered;
}
AutoPinned resource(mDecoder->GetResource());
@@ -823,11 +823,12 @@ nsresult GStreamerReader::GetBuffered(dom::TimeRanges* aBuffered)
duration = mDecoder->GetMediaDuration();
}
- double end = (double) duration / GST_MSECOND;
LOG(PR_LOG_DEBUG, "complete range [0, %f] for [0, %li]",
- end, GetDataLength());
- aBuffered->Add(0, end);
- return NS_OK;
+ (double) duration / GST_MSECOND, GetDataLength());
+ buffered +=
+ media::TimeInterval(media::TimeUnit::FromMicroseconds(0),
+ media::TimeUnit::FromMicroseconds(duration));
+ return buffered;
}
for(uint32_t index = 0; index < ranges.Length(); index++) {
@@ -842,14 +843,16 @@ nsresult GStreamerReader::GetBuffered(dom::TimeRanges* aBuffered)
endOffset, GST_FORMAT_TIME, &endTime))
continue;
- double start = (double) GST_TIME_AS_USECONDS (startTime) / GST_MSECOND;
- double end = (double) GST_TIME_AS_USECONDS (endTime) / GST_MSECOND;
LOG(PR_LOG_DEBUG, "adding range [%f, %f] for [%li %li] size %li",
- start, end, startOffset, endOffset, GetDataLength());
- aBuffered->Add(start, end);
+ (double) GST_TIME_AS_USECONDS (startTime) / GST_MSECOND,
+ (double) GST_TIME_AS_USECONDS (endTime) / GST_MSECOND,
+ startOffset, endOffset, GetDataLength());
+ buffered +=
+ media::TimeInterval(media::TimeUnit::FromMicroseconds(GST_TIME_AS_USECONDS(startTime)),
+ media::TimeUnit::FromMicroseconds(GST_TIME_AS_USECONDS(endTime)));
}
- return NS_OK;
+ return buffered;
}
void GStreamerReader::ReadAndPushData(guint aLength)
diff --git a/dom/media/gstreamer/GStreamerReader.h b/dom/media/gstreamer/GStreamerReader.h
index 4e430d9ae5..fd6bfc3122 100644
--- a/dom/media/gstreamer/GStreamerReader.h
+++ b/dom/media/gstreamer/GStreamerReader.h
@@ -29,10 +29,6 @@ struct GstURIDecodeBin;
namespace mozilla {
-namespace dom {
-class TimeRanges;
-}
-
class AbstractMediaDecoder;
typedef enum {
@@ -59,7 +55,7 @@ public:
MetadataTags** aTags) override;
virtual nsRefPtr
Seek(int64_t aTime, int64_t aEndTime) override;
- virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) override;
+ virtual media::TimeIntervals GetBuffered() override;
virtual void NotifyDataArrived(const char *aBuffer,
uint32_t aLength,
diff --git a/dom/media/gtest/TestMP4Reader.cpp b/dom/media/gtest/TestMP4Reader.cpp
index c2cde8fb68..9959ddd0b8 100644
--- a/dom/media/gtest/TestMP4Reader.cpp
+++ b/dom/media/gtest/TestMP4Reader.cpp
@@ -10,7 +10,7 @@
#include "MockMediaResource.h"
#include "MockMediaDecoderOwner.h"
#include "mozilla/Preferences.h"
-#include "mozilla/dom/TimeRanges.h"
+#include "TimeUnits.h"
using namespace mozilla;
using namespace mozilla::dom;
@@ -83,15 +83,10 @@ TEST(MP4Reader, BufferedRange)
// Video 3-4 sec, audio 2.986666-4.010666 sec
b->resource->MockAddBufferedRange(248400, 327455);
- nsRefPtr ranges = new TimeRanges();
- EXPECT_EQ(NS_OK, b->reader->GetBuffered(ranges));
- EXPECT_EQ(1U, ranges->Length());
- double start = 0;
- EXPECT_EQ(NS_OK, ranges->Start(0, &start));
- EXPECT_NEAR(270000 / 90000.0, start, 0.000001);
- double end = 0;
- EXPECT_EQ(NS_OK, ranges->End(0, &end));
- EXPECT_NEAR(360000 / 90000.0, end, 0.000001);
+ media::TimeIntervals ranges = b->reader->GetBuffered();
+ EXPECT_EQ(1U, ranges.Length());
+ EXPECT_NEAR(270000 / 90000.0, ranges.Start(0).ToSeconds(), 0.000001);
+ EXPECT_NEAR(360000 / 90000.0, ranges.End(0).ToSeconds(), 0.000001);
}
TEST(MP4Reader, BufferedRangeMissingLastByte)
@@ -104,15 +99,10 @@ TEST(MP4Reader, BufferedRangeMissingLastByte)
b->resource->MockAddBufferedRange(248400, 324912);
b->resource->MockAddBufferedRange(324913, 327455);
- nsRefPtr ranges = new TimeRanges();
- EXPECT_EQ(NS_OK, b->reader->GetBuffered(ranges));
- EXPECT_EQ(1U, ranges->Length());
- double start = 0;
- EXPECT_EQ(NS_OK, ranges->Start(0, &start));
- EXPECT_NEAR(270000.0 / 90000.0, start, 0.000001);
- double end = 0;
- EXPECT_EQ(NS_OK, ranges->End(0, &end));
- EXPECT_NEAR(357000 / 90000.0, end, 0.000001);
+ media::TimeIntervals ranges = b->reader->GetBuffered();
+ EXPECT_EQ(1U, ranges.Length());
+ EXPECT_NEAR(270000.0 / 90000.0, ranges.Start(0).ToSeconds(), 0.000001);
+ EXPECT_NEAR(357000 / 90000.0, ranges.End(0).ToSeconds(), 0.000001);
}
TEST(MP4Reader, BufferedRangeSyncFrame)
@@ -125,15 +115,10 @@ TEST(MP4Reader, BufferedRangeSyncFrame)
b->resource->MockClearBufferedRanges();
b->resource->MockAddBufferedRange(146336, 327455);
- nsRefPtr ranges = new TimeRanges();
- EXPECT_EQ(NS_OK, b->reader->GetBuffered(ranges));
- EXPECT_EQ(1U, ranges->Length());
- double start = 0;
- EXPECT_EQ(NS_OK, ranges->Start(0, &start));
- EXPECT_NEAR(270000.0 / 90000.0, start, 0.000001);
- double end = 0;
- EXPECT_EQ(NS_OK, ranges->End(0, &end));
- EXPECT_NEAR(360000 / 90000.0, end, 0.000001);
+ media::TimeIntervals ranges = b->reader->GetBuffered();
+ EXPECT_EQ(1U, ranges.Length());
+ EXPECT_NEAR(270000.0 / 90000.0, ranges.Start(0).ToSeconds(), 0.000001);
+ EXPECT_NEAR(360000 / 90000.0, ranges.End(0).ToSeconds(), 0.000001);
}
TEST(MP4Reader, CompositionOrder)
@@ -183,23 +168,14 @@ TEST(MP4Reader, CompositionOrder)
b->resource->MockAddBufferedRange(12616, 13196);
b->resource->MockAddBufferedRange(13220, 13901);
- nsRefPtr ranges = new TimeRanges();
- EXPECT_EQ(NS_OK, b->reader->GetBuffered(ranges));
- EXPECT_EQ(2U, ranges->Length());
+ media::TimeIntervals ranges = b->reader->GetBuffered();
+ EXPECT_EQ(2U, ranges.Length());
- double start = 0;
- EXPECT_EQ(NS_OK, ranges->Start(0, &start));
- EXPECT_NEAR(166.0 / 2500.0, start, 0.000001);
- double end = 0;
- EXPECT_EQ(NS_OK, ranges->End(0, &end));
- EXPECT_NEAR(332.0 / 2500.0, end, 0.000001);
+ EXPECT_NEAR(166.0 / 2500.0, ranges.Start(0).ToSeconds(), 0.000001);
+ EXPECT_NEAR(332.0 / 2500.0, ranges.End(0).ToSeconds(), 0.000001);
- start = 0;
- EXPECT_EQ(NS_OK, ranges->Start(1, &start));
- EXPECT_NEAR(581.0 / 2500.0, start, 0.000001);
- end = 0;
- EXPECT_EQ(NS_OK, ranges->End(1, &end));
- EXPECT_NEAR(11255.0 / 44100.0, end, 0.000001);
+ EXPECT_NEAR(581.0 / 2500.0, ranges.Start(1).ToSeconds(), 0.000001);
+ EXPECT_NEAR(11255.0 / 44100.0, ranges.End(1).ToSeconds(), 0.000001);
}
TEST(MP4Reader, Normalised)
@@ -233,14 +209,9 @@ TEST(MP4Reader, Normalised)
b->resource->MockClearBufferedRanges();
b->resource->MockAddBufferedRange(48, 13901);
- nsRefPtr ranges = new TimeRanges();
- EXPECT_EQ(NS_OK, b->reader->GetBuffered(ranges));
- EXPECT_EQ(1U, ranges->Length());
+ media::TimeIntervals ranges = b->reader->GetBuffered();
+ EXPECT_EQ(1U, ranges.Length());
- double start = 0;
- EXPECT_EQ(NS_OK, ranges->Start(0, &start));
- EXPECT_NEAR(166.0 / 2500.0, start, 0.000001);
- double end = 0;
- EXPECT_EQ(NS_OK, ranges->End(0, &end));
- EXPECT_NEAR(11255.0 / 44100.0, end, 0.000001);
+ EXPECT_NEAR(166.0 / 2500.0, ranges.Start(0).ToSeconds(), 0.000001);
+ EXPECT_NEAR(11255.0 / 44100.0, ranges.End(0).ToSeconds(), 0.000001);
}
diff --git a/dom/media/mediasource/MediaSource.cpp b/dom/media/mediasource/MediaSource.cpp
index ef5e9a2c74..3831b83eee 100644
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -16,7 +16,6 @@
#include "mozilla/Preferences.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/HTMLMediaElement.h"
-#include "mozilla/dom/TimeRanges.h"
#include "mozilla/mozalloc.h"
#include "nsContentTypeParser.h"
#include "nsDebug.h"
diff --git a/dom/media/mediasource/MediaSourceDecoder.cpp b/dom/media/mediasource/MediaSourceDecoder.cpp
index 4ed1edc84d..d52fedcdf1 100644
--- a/dom/media/mediasource/MediaSourceDecoder.cpp
+++ b/dom/media/mediasource/MediaSourceDecoder.cpp
@@ -7,7 +7,6 @@
#include "prlog.h"
#include "mozilla/dom/HTMLMediaElement.h"
-#include "mozilla/dom/TimeRanges.h"
#include "MediaDecoderStateMachine.h"
#include "MediaSource.h"
#include "MediaSourceReader.h"
@@ -68,26 +67,30 @@ MediaSourceDecoder::Load(nsIStreamListener**, MediaDecoder*)
return ScheduleStateMachineThread();
}
-nsresult
-MediaSourceDecoder::GetSeekable(dom::TimeRanges* aSeekable)
+media::TimeIntervals
+MMediaSourceDecoder::GetSeekable()
{
MOZ_ASSERT(NS_IsMainThread());
if (!mMediaSource) {
- return NS_ERROR_FAILURE;
+ NS_WARNING("MediaSource element isn't attached");
+ return media::TimeIntervals::Invalid();
}
+ media::TimeIntervals seekable;
double duration = mMediaSource->Duration();
if (IsNaN(duration)) {
// Return empty range.
} else if (duration > 0 && mozilla::IsInfinite(duration)) {
- nsRefPtr bufferedRanges = new dom::TimeRanges();
- mReader->GetBuffered(bufferedRanges);
- aSeekable->Add(bufferedRanges->GetStartTime(), bufferedRanges->GetEndTime());
+ media::TimeIntervals buffered = mReader->GetBuffered();
+ if (buffered.Length()) {
+ seekable += media::TimeInterval(buffered.GetStart(), buffered.GetEnd());
+ }
} else {
- aSeekable->Add(0, duration);
+ seekable += media::TimeInterval(media::TimeUnit::FromSeconds(0),
+ media::TimeUnit::FromSeconds(duration));
}
- MSE_DEBUG("ranges=%s", DumpTimeRanges(aSeekable).get());
- return NS_OK;
+ MSE_DEBUG("ranges=%s", DumpTimeRanges(seekable).get());
+ return seekable;
}
void
@@ -316,22 +319,25 @@ MediaSourceDecoder::SelectDecoder(int64_t aTarget,
{
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
+ media::TimeUnit target{media::TimeUnit::FromMicroseconds(aTarget)};
+ media::TimeUnit tolerance{media::TimeUnit::FromMicroseconds(aTolerance + aTarget)};
+
+ // aTolerance gives a slight bias toward the start of a range only.
// Consider decoders in order of newest to oldest, as a newer decoder
// providing a given buffered range is expected to replace an older one.
for (int32_t i = aTrackDecoders.Length() - 1; i >= 0; --i) {
nsRefPtr newDecoder = aTrackDecoders[i];
- nsRefPtr ranges = new dom::TimeRanges();
- newDecoder->GetBuffered(ranges);
- if (ranges->Find(double(aTarget) / USECS_PER_S,
- double(aTolerance) / USECS_PER_S) == dom::TimeRanges::NoIndex) {
- MSE_DEBUGV("SelectDecoder(%lld fuzz:%lld) newDecoder=%p (%d/%d) target not in ranges=%s",
- aTarget, aTolerance, newDecoder.get(), i+1,
- aTrackDecoders.Length(), DumpTimeRanges(ranges).get());
- continue;
+ media::TimeIntervals ranges = newDecoder->GetBuffered();
+ for (uint32_t j = 0; j < ranges.Length(); j++) {
+ if (target < ranges.End(j) && tolerance >= ranges.Start(j)) {
+ return newDecoder.forget();
+ }
}
- return newDecoder.forget();
+ MSE_DEBUGV("SelectDecoder(%lld fuzz:%lld) newDecoder=%p (%d/%d) target not in ranges=%s",
+ aTarget, aTolerance, newDecoder.get(), i+1,
+ aTrackDecoders.Length(), DumpTimeRanges(ranges).get());
}
return nullptr;
diff --git a/dom/media/mediasource/MediaSourceDecoder.h b/dom/media/mediasource/MediaSourceDecoder.h
index eae671581a..287fd06065 100644
--- a/dom/media/mediasource/MediaSourceDecoder.h
+++ b/dom/media/mediasource/MediaSourceDecoder.h
@@ -38,7 +38,7 @@ public:
virtual MediaDecoder* Clone() override;
virtual MediaDecoderStateMachine* CreateStateMachine() override;
virtual nsresult Load(nsIStreamListener**, MediaDecoder*) override;
- virtual nsresult GetSeekable(dom::TimeRanges* aSeekable) override;
+ virtual media::TimeIntervals GetSeekable() override;
virtual void Shutdown() override;
diff --git a/dom/media/mediasource/MediaSourceReader.cpp b/dom/media/mediasource/MediaSourceReader.cpp
index c1ae4a462c..385bdb051c 100644
--- a/dom/media/mediasource/MediaSourceReader.cpp
+++ b/dom/media/mediasource/MediaSourceReader.cpp
@@ -7,7 +7,6 @@
#include
#include "prlog.h"
-#include "mozilla/dom/TimeRanges.h"
#include "DecoderTraits.h"
#include "MediaDecoderOwner.h"
#include "MediaFormatReader.h"
@@ -41,8 +40,6 @@ extern PRLogModuleInfo* GetMediaSourceLog();
// default value used in Blink, kDefaultBufferDurationInMs.
#define EOS_FUZZ_US 125000
-using mozilla::dom::TimeRanges;
-
namespace mozilla {
MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder)
@@ -230,10 +227,9 @@ static void
AdjustEndTime(int64_t* aEndTime, SourceBufferDecoder* aDecoder)
{
if (aDecoder) {
- nsRefPtr ranges = new dom::TimeRanges();
- aDecoder->GetBuffered(ranges);
- if (ranges->Length() > 0) {
- int64_t end = std::ceil(ranges->GetEndTime() * USECS_PER_S);
+ media::TimeIntervals ranges = aDecoder->GetBuffered();
+ if (ranges.Length()) {
+ int64_t end = ranges.GetEnd().ToMicroseconds();
*aEndTime = std::max(*aEndTime, end);
}
}
@@ -585,9 +581,8 @@ MediaSourceReader::SwitchAudioSource(int64_t* aTarget)
// A decoder buffered range is continuous. We would have failed the exact
// search but succeeded the fuzzy one if our target was shortly before
// start time.
- nsRefPtr ranges = new dom::TimeRanges();
- newDecoder->GetBuffered(ranges);
- int64_t startTime = ranges->GetStartTime() * USECS_PER_S;
+ media::TimeIntervals ranges = newDecoder->GetBuffered();
+ int64_t startTime = ranges.GetStart().ToMicroseconds();
if (*aTarget < startTime) {
*aTarget = startTime;
}
@@ -631,9 +626,8 @@ MediaSourceReader::SwitchVideoSource(int64_t* aTarget)
// A decoder buffered range is continuous. We would have failed the exact
// search but succeeded the fuzzy one if our target was shortly before
// start time.
- nsRefPtr ranges = new dom::TimeRanges();
- newDecoder->GetBuffered(ranges);
- int64_t startTime = ranges->GetStartTime() * USECS_PER_S;
+ media::TimeIntervals ranges = newDecoder->GetBuffered();
+ int64_t startTime = ranges.GetStart().ToMicroseconds();
if (*aTarget < startTime) {
*aTarget = startTime;
}
@@ -982,44 +976,39 @@ MediaSourceReader::DoVideoSeek()
MSE_DEBUG("reader=%p", GetVideoReader());
}
-nsresult
-MediaSourceReader::GetBuffered(dom::TimeRanges* aBuffered)
+media::TimeIntervals
+MediaSourceReader::GetBuffered()
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
- MOZ_ASSERT(aBuffered->Length() == 0);
- if (mTrackBuffers.IsEmpty()) {
- return NS_OK;
+ media::TimeIntervals buffered;
+
+ media::TimeUnit highestEndTime;
+ nsTArray activeRanges;
+ // Must set the capacity of the nsTArray first: bug #1164444
+ activeRanges.SetCapacity(mTrackBuffers.Length());
+
+ for (const auto& trackBuffer : mTrackBuffers) {
+ activeRanges.AppendElement(trackBuffer->Buffered());
+ highestEndTime = std::max(highestEndTime, activeRanges.LastElement().GetEnd());
}
- double highestEndTime = 0;
+ buffered +=
+ media::TimeInterval(media::TimeUnit::FromMicroseconds(0), highestEndTime);
- nsTArray> activeRanges;
- for (uint32_t i = 0; i < mTrackBuffers.Length(); ++i) {
- nsRefPtr r = new TimeRanges();
- mTrackBuffers[i]->Buffered(r);
- activeRanges.AppendElement(r);
- highestEndTime = std::max(highestEndTime, activeRanges.LastElement()->GetEndTime());
- }
-
- TimeRanges* intersectionRanges = aBuffered;
- intersectionRanges->Add(0, highestEndTime);
-
- for (uint32_t i = 0; i < activeRanges.Length(); ++i) {
- TimeRanges* sourceRanges = activeRanges[i];
-
- if (IsEnded()) {
+ for (auto& range : activeRanges) {
+ if (IsEnded() && range.Length()) {
// Set the end time on the last range to highestEndTime by adding a
// new range spanning the current end time to highestEndTime, which
// Normalize() will then merge with the old last range.
- sourceRanges->Add(sourceRanges->GetEndTime(), highestEndTime);
- sourceRanges->Normalize();
+ range +=
+ media::TimeInterval(range.GetEnd(), highestEndTime);
}
- intersectionRanges->Intersection(sourceRanges);
+ buffered.Intersection(range);
}
- MSE_DEBUG("ranges=%s", DumpTimeRanges(intersectionRanges).get());
- return NS_OK;
+ MSE_DEBUG("ranges=%s", DumpTimeRanges(buffered).get());
+ return buffered;
}
already_AddRefed
@@ -1035,15 +1024,14 @@ MediaSourceReader::FirstDecoder(MediaData::Type aType)
}
nsRefPtr firstDecoder;
- double lowestStartTime = PositiveInfinity();
+ media::TimeUnit lowestStartTime{media::TimeUnit::FromInfinity()};
for (uint32_t i = 0; i < decoders.Length(); ++i) {
- nsRefPtr r = new TimeRanges();
- decoders[i]->GetBuffered(r);
- double start = r->GetStartTime();
- if (start < 0) {
+ media::TimeIntervals r = decoders[i]->GetBuffered();
+ if (!r.Length()) {
continue;
}
+ media::TimeUnit start = r.GetStart();
if (start < lowestStartTime) {
firstDecoder = decoders[i];
lowestStartTime = start;
@@ -1203,9 +1191,8 @@ MediaSourceReader::IsNearEnd(MediaData::Type aType, int64_t aTime)
}
TrackBuffer* trackBuffer =
aType == MediaData::AUDIO_DATA ? mAudioTrack : mVideoTrack;
- nsRefPtr buffered = new dom::TimeRanges();
- trackBuffer->Buffered(buffered);
- return aTime >= (buffered->GetEndTime() * USECS_PER_S - EOS_FUZZ_US);
+ media::TimeIntervals buffered = trackBuffer->Buffered();
+ return aTime >= buffered.GetEnd().ToMicroseconds() - EOS_FUZZ_US;
}
int64_t
@@ -1214,10 +1201,9 @@ MediaSourceReader::LastSampleTime(MediaData::Type aType)
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
TrackBuffer* trackBuffer =
- aType == MediaData::AUDIO_DATA ? mAudioTrack : mVideoTrack;
- nsRefPtr buffered = new dom::TimeRanges();
- trackBuffer->Buffered(buffered);
- return buffered->GetEndTime() * USECS_PER_S - 1;
+ aType == MediaData::AUDIO_DATA ? mAudioTrack : mVideoTrack;
+ media::TimeIntervals buffered = trackBuffer->Buffered();
+ return buffered.GetEnd().ToMicroseconds() - 1;
}
void
@@ -1238,8 +1224,7 @@ MediaSourceReader::GetMozDebugReaderData(nsAString& aString)
for (int32_t i = mAudioTrack->Decoders().Length() - 1; i >= 0; --i) {
nsRefPtr newReader = mAudioTrack->Decoders()[i]->GetReader();
- nsRefPtr ranges = new dom::TimeRanges();
- mAudioTrack->Decoders()[i]->GetBuffered(ranges);
+ media::TimeIntervals ranges = mAudioTrack->Decoders()[i]->GetBuffered();
result += nsPrintfCString("\t\tReader %d: %p ranges=%s active=%s size=%lld\n",
i, newReader.get(), DumpTimeRanges(ranges).get(),
newReader.get() == GetAudioReader() ? "true" : "false",
@@ -1252,8 +1237,7 @@ MediaSourceReader::GetMozDebugReaderData(nsAString& aString)
for (int32_t i = mVideoTrack->Decoders().Length() - 1; i >= 0; --i) {
nsRefPtr newReader = mVideoTrack->Decoders()[i]->GetReader();
- nsRefPtr ranges = new dom::TimeRanges();
- mVideoTrack->Decoders()[i]->GetBuffered(ranges);
+ media::TimeIntervals ranges = mVideoTrack->Decoders()[i]->GetBuffered();
result += nsPrintfCString("\t\tReader %d: %p ranges=%s active=%s size=%lld\n",
i, newReader.get(), DumpTimeRanges(ranges).get(),
newReader.get() == GetVideoReader() ? "true" : "false",
diff --git a/dom/media/mediasource/MediaSourceReader.h b/dom/media/mediasource/MediaSourceReader.h
index 9bddc341a9..981e503cc3 100644
--- a/dom/media/mediasource/MediaSourceReader.h
+++ b/dom/media/mediasource/MediaSourceReader.h
@@ -112,7 +112,7 @@ public:
nsresult ResetDecode() override;
// Acquires the decoder monitor, and is thus callable on any thread.
- nsresult GetBuffered(dom::TimeRanges* aBuffered) override;
+ media::TimeIntervals GetBuffered() override;
already_AddRefed CreateSubDecoder(const nsACString& aType,
int64_t aTimestampOffset /* microseconds */);
diff --git a/dom/media/mediasource/MediaSourceUtils.cpp b/dom/media/mediasource/MediaSourceUtils.cpp
index 83bba60011..ec88728aba 100644
--- a/dom/media/mediasource/MediaSourceUtils.cpp
+++ b/dom/media/mediasource/MediaSourceUtils.cpp
@@ -6,24 +6,24 @@
#include "MediaSourceUtils.h"
#include "prlog.h"
-#include "mozilla/dom/TimeRanges.h"
#include "nsPrintfCString.h"
namespace mozilla {
nsCString
-DumpTimeRanges(dom::TimeRanges* aRanges)
+DumpTimeRanges(const media::TimeIntervals& aRanges)
{
nsCString dump;
dump = "[";
- for (uint32_t i = 0; i < aRanges->Length(); ++i) {
+ for (uint32_t i = 0; i < aRanges.Length(); ++i) {
if (i > 0) {
dump += ", ";
}
- ErrorResult dummy;
- dump += nsPrintfCString("(%f, %f)", aRanges->Start(i, dummy), aRanges->End(i, dummy));
+ dump += nsPrintfCString("(%f, %f)",
+ aRanges.Start(i).ToSeconds(),
+ aRanges.End(i).ToSeconds());
}
dump += "]";
diff --git a/dom/media/mediasource/MediaSourceUtils.h b/dom/media/mediasource/MediaSourceUtils.h
index 35365eb1a6..2bda99f1b9 100644
--- a/dom/media/mediasource/MediaSourceUtils.h
+++ b/dom/media/mediasource/MediaSourceUtils.h
@@ -8,14 +8,11 @@
#define MOZILLA_MEDIASOURCEUTILS_H_
#include "nsString.h"
+#include "TimeUnits.h"
namespace mozilla {
-namespace dom {
- class TimeRanges;
-} // namespace dom
-
-nsCString DumpTimeRanges(dom::TimeRanges* aRanges);
+nsCString DumpTimeRanges(const media::TimeIntervals& aRanges);
} // namespace mozilla
diff --git a/dom/media/mediasource/SourceBuffer.cpp b/dom/media/mediasource/SourceBuffer.cpp
index eaa9bf2945..c05b9ea02c 100644
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -146,17 +146,14 @@ SourceBuffer::GetBuffered(ErrorResult& aRv)
aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
return nullptr;
}
- nsRefPtr ranges = new TimeRanges();
- double highestEndTime = mTrackBuffer->Buffered(ranges);
- if (mMediaSource->ReadyState() == MediaSourceReadyState::Ended) {
- // Set the end time on the last range to highestEndTime by adding a
- // new range spanning the current end time to highestEndTime, which
- // Normalize() will then merge with the old last range.
- ranges->Add(ranges->GetEndTime(), highestEndTime);
- ranges->Normalize();
- }
+ // We only manage a single trackbuffer in our source buffer.
+ // As such, there's no need to adjust the end of the trackbuffers as per
+ // Step 4: http://w3c.github.io/media-source/index.html#widl-SourceBuffer-buffered
+ media::TimeIntervals ranges = mTrackBuffer->Buffered();
MSE_DEBUGV("ranges=%s", DumpTimeRanges(ranges).get());
- return ranges.forget();
+ nsRefPtr tr = new dom::TimeRanges();
+ ranges.ToTimeRanges(tr);
+ return tr.forget();
}
void
@@ -287,8 +284,8 @@ SourceBuffer::DoRangeRemoval(double aStart, double aEnd)
{
MSE_DEBUG("DoRangeRemoval(%f, %f)", aStart, aEnd);
if (mTrackBuffer && !IsInfinite(aStart)) {
- mTrackBuffer->RangeRemoval(media::Microseconds::FromSeconds(aStart),
- media::Microseconds::FromSeconds(aEnd));
+ mTrackBuffer->RangeRemoval(media::TimeUnit::FromSeconds(aStart),
+ media::TimeUnit::FromSeconds(aEnd));
}
}
diff --git a/dom/media/mediasource/SourceBufferDecoder.cpp b/dom/media/mediasource/SourceBufferDecoder.cpp
index b511a30925..878cefeeb6 100644
--- a/dom/media/mediasource/SourceBufferDecoder.cpp
+++ b/dom/media/mediasource/SourceBufferDecoder.cpp
@@ -9,7 +9,6 @@
#include "prlog.h"
#include "AbstractMediaDecoder.h"
#include "MediaDecoderReader.h"
-#include "mozilla/dom/TimeRanges.h"
#ifdef PR_LOGGING
extern PRLogModuleInfo* GetMediaSourceLog();
@@ -238,24 +237,23 @@ SourceBufferDecoder::NotifyDataArrived(const char* aBuffer, uint32_t aLength, in
mParentDecoder->NotifyDataArrived(nullptr, 0, 0);
}
-nsresult
-SourceBufferDecoder::GetBuffered(dom::TimeRanges* aBuffered)
+media::TimeIntervals
+SourceBufferDecoder::GetBuffered()
{
- nsresult rv = mReader->GetBuffered(aBuffered);
- if (NS_FAILED(rv)) {
- return rv;
+ media::TimeIntervals buffered = mReader->GetBuffered();
+ if (buffered.IsInvalid()) {
+ return buffered;
}
// Adjust buffered range according to timestamp offset.
- aBuffered->Shift((double)mTimestampOffset / USECS_PER_S);
+ buffered.Shift(media::TimeUnit::FromMicroseconds(mTimestampOffset));
if (!WasTrimmed()) {
- return NS_OK;
+ return buffered;
}
- nsRefPtr tr = new dom::TimeRanges();
- tr->Add(0, mTrimmedOffset);
- aBuffered->Intersection(tr);
- return NS_OK;
+ media::TimeInterval filter(media::TimeUnit::FromSeconds(0),
+ media::TimeUnit::FromSeconds(mTrimmedOffset));
+ return buffered.Intersection(filter);
}
int64_t
diff --git a/dom/media/mediasource/SourceBufferDecoder.h b/dom/media/mediasource/SourceBufferDecoder.h
index 5bf0791ec8..e52f694c72 100644
--- a/dom/media/mediasource/SourceBufferDecoder.h
+++ b/dom/media/mediasource/SourceBufferDecoder.h
@@ -18,12 +18,6 @@ namespace mozilla {
class MediaResource;
class MediaDecoderReader;
-namespace dom {
-
-class TimeRanges;
-
-} // namespace dom
-
class SourceBufferDecoder final : public AbstractMediaDecoder
{
public:
@@ -69,7 +63,7 @@ public:
// Warning: this mirrors GetBuffered in MediaDecoder, but this class's base is
// AbstractMediaDecoder, which does not supply this interface.
- nsresult GetBuffered(dom::TimeRanges* aBuffered);
+ media::TimeIntervals GetBuffered();
void SetReader(MediaDecoderReader* aReader)
{
diff --git a/dom/media/mediasource/TrackBuffer.cpp b/dom/media/mediasource/TrackBuffer.cpp
index 3c23d97bcf..1234bf4c0f 100644
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -276,24 +276,18 @@ class DecoderSorter
public:
bool LessThan(SourceBufferDecoder* aFirst, SourceBufferDecoder* aSecond) const
{
- nsRefPtr first = new dom::TimeRanges();
- aFirst->GetBuffered(first);
+ media::TimeIntervals first = aFirst->GetBuffered();
+ media::TimeIntervals second = aSecond->GetBuffered();
- nsRefPtr second = new dom::TimeRanges();
- aSecond->GetBuffered(second);
-
- return first->GetStartTime() < second->GetStartTime();
+ return first.GetStart() < second.GetStart();
}
bool Equals(SourceBufferDecoder* aFirst, SourceBufferDecoder* aSecond) const
{
- nsRefPtr first = new dom::TimeRanges();
- aFirst->GetBuffered(first);
+ media::TimeIntervals first = aFirst->GetBuffered();
+ media::TimeIntervals second = aSecond->GetBuffered();
- nsRefPtr second = new dom::TimeRanges();
- aSecond->GetBuffered(second);
-
- return first->GetStartTime() == second->GetStartTime();
+ return first.GetStart() == second.GetStart();
}
};
@@ -323,8 +317,7 @@ TrackBuffer::EvictData(double aPlaybackTime,
// First try to evict data before the current play position, starting
// with the oldest decoder.
for (uint32_t i = 0; i < decoders.Length() && toEvict > 0; ++i) {
- nsRefPtr buffered = new dom::TimeRanges();
- decoders[i]->GetBuffered(buffered);
+ media::TimeIntervals buffered = decoders[i]->GetBuffered();
MSE_DEBUG("Step1. decoder=%u/%u threshold=%u toEvict=%lld",
i, decoders.Length(), aThreshold, toEvict);
@@ -333,22 +326,24 @@ TrackBuffer::EvictData(double aPlaybackTime,
// we apply a threshold of a few seconds back and evict data up to
// that point.
if (aPlaybackTime > MSE_EVICT_THRESHOLD_TIME) {
- double time = aPlaybackTime - MSE_EVICT_THRESHOLD_TIME;
+ media::TimeUnit time = media::TimeUnit::FromSeconds(aPlaybackTime) -
+ media::TimeUnit::FromSeconds(MSE_EVICT_THRESHOLD_TIME);
bool isActive = decoders[i] == mCurrentDecoder ||
mParentDecoder->IsActiveReader(decoders[i]->GetReader());
- if (!isActive && buffered->GetEndTime() < time) {
+ if (!isActive && buffered.GetEnd() < time) {
// The entire decoder is contained before our current playback time.
// It can be fully evicted.
MSE_DEBUG("evicting all bufferedEnd=%f "
"aPlaybackTime=%f time=%f, size=%lld",
- buffered->GetEndTime(), aPlaybackTime, time,
+ buffered.GetEnd().ToSeconds(), aPlaybackTime, time,
decoders[i]->GetResource()->GetSize());
toEvict -= decoders[i]->GetResource()->EvictAll();
} else {
- int64_t playbackOffset = decoders[i]->ConvertToByteOffset(time);
+ int64_t playbackOffset =
+ decoders[i]->ConvertToByteOffset(time.ToMicroseconds());
MSE_DEBUG("evicting some bufferedEnd=%f "
"aPlaybackTime=%f time=%f, playbackOffset=%lld size=%lld",
- buffered->GetEndTime(), aPlaybackTime, time,
+ buffered.GetEnd().ToSeconds(), aPlaybackTime, time,
playbackOffset, decoders[i]->GetResource()->GetSize());
if (playbackOffset > 0) {
toEvict -= decoders[i]->GetResource()->EvictData(playbackOffset,
@@ -368,13 +363,12 @@ TrackBuffer::EvictData(double aPlaybackTime,
if (decoders[i] == mCurrentDecoder) {
continue;
}
- nsRefPtr buffered = new dom::TimeRanges();
- decoders[i]->GetBuffered(buffered);
+ media::TimeIntervals buffered = decoders[i]->GetBuffered();
// Remove data from older decoders than the current one.
MSE_DEBUG("evicting all "
"bufferedStart=%f bufferedEnd=%f aPlaybackTime=%f size=%lld",
- buffered->GetStartTime(), buffered->GetEndTime(),
+ buffered.GetStart().ToSeconds(), buffered.GetEnd().ToSeconds(),
aPlaybackTime, decoders[i]->GetResource()->GetSize());
toEvict -= decoders[i]->GetResource()->EvictAll();
}
@@ -398,10 +392,9 @@ TrackBuffer::EvictData(double aPlaybackTime,
// Find the next decoder we're likely going to play with.
nsRefPtr nextPlayingDecoder = nullptr;
if (playingDecoder) {
- nsRefPtr buffered = new dom::TimeRanges();
- playingDecoder->GetBuffered(buffered);
+ media::TimeIntervals buffered = playingDecoder->GetBuffered();
nextPlayingDecoder =
- mParentDecoder->SelectDecoder(buffered->GetEndTime() * USECS_PER_S + 1,
+ mParentDecoder->SelectDecoder(buffered.GetEnd().ToMicroseconds() + 1,
EOS_FUZZ_US,
mInitializedDecoders);
}
@@ -416,12 +409,11 @@ TrackBuffer::EvictData(double aPlaybackTime,
decoders[i] == mCurrentDecoder) {
continue;
}
- nsRefPtr buffered = new dom::TimeRanges();
- decoders[i]->GetBuffered(buffered);
+ media::TimeIntervals buffered = decoders[i]->GetBuffered();
MSE_DEBUG("evicting all "
"bufferedStart=%f bufferedEnd=%f aPlaybackTime=%f size=%lld",
- buffered->GetStartTime(), buffered->GetEndTime(),
+ buffered.GetStart().ToSeconds(), buffered.GetEnd().ToSeconds(),
aPlaybackTime, decoders[i]->GetResource()->GetSize());
toEvict -= decoders[i]->GetResource()->EvictAll();
}
@@ -431,9 +423,8 @@ TrackBuffer::EvictData(double aPlaybackTime,
bool evicted = toEvict < (totalSize - aThreshold);
if (evicted) {
if (playingDecoder) {
- nsRefPtr ranges = new dom::TimeRanges();
- playingDecoder->GetBuffered(ranges);
- *aBufferStartTime = std::max(0.0, ranges->GetStartTime());
+ media::TimeIntervals ranges = playingDecoder->GetBuffered();
+ *aBufferStartTime = std::max(0.0, ranges.GetStart().ToSeconds());
} else {
// We do not currently have data to play yet.
// Avoid evicting anymore data to minimize rebuffering time.
@@ -451,20 +442,18 @@ TrackBuffer::RemoveEmptyDecoders(nsTArray& aDecod
// Remove decoders that have no data in them
for (uint32_t i = 0; i < aDecoders.Length(); ++i) {
- nsRefPtr buffered = new dom::TimeRanges();
- aDecoders[i]->GetBuffered(buffered);
+ media::TimeIntervals buffered = aDecoders[i]->GetBuffered();
MSE_DEBUG("maybe remove empty decoders=%d "
"size=%lld start=%f end=%f",
i, aDecoders[i]->GetResource()->GetSize(),
- buffered->GetStartTime(), buffered->GetEndTime());
+ buffered.GetStart().ToSeconds(), buffered.GetEnd().ToSeconds());
if (aDecoders[i] == mCurrentDecoder ||
mParentDecoder->IsActiveReader(aDecoders[i]->GetReader())) {
continue;
}
- if (aDecoders[i]->GetResource()->GetSize() == 0 ||
- buffered->GetStartTime() < 0.0 ||
- buffered->GetEndTime() < 0.0) {
+ if (aDecoders[i]->GetResource()->GetSize() == 0 || !buffered.Length() ||
+ buffered[0].IsEmpty()) {
MSE_DEBUG("remove empty decoders=%d", i);
RemoveDecoder(aDecoders[i]);
}
@@ -487,12 +476,11 @@ TrackBuffer::HasOnlyIncompleteMedia()
if (!mCurrentDecoder) {
return false;
}
- nsRefPtr buffered = new dom::TimeRanges();
- mCurrentDecoder->GetBuffered(buffered);
+ media::TimeIntervals buffered = mCurrentDecoder->GetBuffered();
MSE_DEBUG("mCurrentDecoder.size=%lld, start=%f end=%f",
mCurrentDecoder->GetResource()->GetSize(),
- buffered->GetStartTime(), buffered->GetEndTime());
- return mCurrentDecoder->GetResource()->GetSize() && !buffered->Length();
+ buffered.GetStart(), buffered.GetEnd());
+ return mCurrentDecoder->GetResource()->GetSize() && !buffered.Length();
}
void
@@ -510,23 +498,23 @@ TrackBuffer::EvictBefore(double aTime)
}
}
-double
-TrackBuffer::Buffered(dom::TimeRanges* aRanges)
+media::TimeIntervals
+TrackBuffer::Buffered()
{
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
- double highestEndTime = 0;
+ media::TimeIntervals buffered;
- for (uint32_t i = 0; i < mInitializedDecoders.Length(); ++i) {
- nsRefPtr r = new dom::TimeRanges();
- mInitializedDecoders[i]->GetBuffered(r);
- if (r->Length() > 0) {
- highestEndTime = std::max(highestEndTime, r->GetEndTime());
- aRanges->Union(r, double(mParser->GetRoundingError()) / USECS_PER_S);
- }
+ for (auto& decoder : mInitializedDecoders) {
+ buffered += decoder->GetBuffered();
+ }
+ // mParser may not be initialized yet, and will only be so if we have a
+ // buffered range.
+ if (buffered.Length()) {
+ buffered.SetFuzz(media::TimeUnit::FromMicroseconds(mParser->GetRoundingError()));
}
- return highestEndTime;
+ return buffered;
}
already_AddRefed
@@ -883,10 +871,11 @@ TrackBuffer::ContainsTime(int64_t aTime, int64_t aTolerance)
{
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
for (uint32_t i = 0; i < mInitializedDecoders.Length(); ++i) {
- nsRefPtr r = new dom::TimeRanges();
- mInitializedDecoders[i]->GetBuffered(r);
- if (r->Find(double(aTime) / USECS_PER_S,
- double(aTolerance) / USECS_PER_S) != dom::TimeRanges::NoIndex) {
+ media::TimeUnit time{media::TimeUnit::FromMicroseconds(aTime)};
+ for (auto& decoder : mInitializedDecoders) {
+ media::TimeIntervals r = decoder->GetBuffered();
+ r.SetFuzz(media::TimeUnit::FromMicroseconds(aTolerance));
+ if (r.Contains(time)) {
return true;
}
}
@@ -1026,17 +1015,17 @@ TrackBuffer::RemoveDecoder(SourceBufferDecoder* aDecoder)
}
bool
-TrackBuffer::RangeRemoval(media::Microseconds aStart,
- media::Microseconds aEnd)
+TrackBuffer::RangeRemoval(media::TimeUnit aStart,
+ media::TimeUnit aEnd)
{
MOZ_ASSERT(NS_IsMainThread());
ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
- nsRefPtr buffered = new dom::TimeRanges();
- media::Microseconds bufferedEnd = media::Microseconds::FromSeconds(Buffered(buffered));
- media::Microseconds bufferedStart = media::Microseconds::FromSeconds(buffered->GetStartTime());
+ media::TimeIntervals buffered = Buffered();
+ media::TimeUnit bufferedStart = buffered.GetStart();
+ media::TimeUnit bufferedEnd = buffered.GetEnd();
- if (bufferedStart < media::Microseconds(0) || aStart > bufferedEnd || aEnd < bufferedStart) {
+ if (!buffered.Length() || aStart > bufferedEnd || aEnd < bufferedStart) {
// Nothing to remove.
return false;
}
@@ -1054,18 +1043,17 @@ TrackBuffer::RangeRemoval(media::Microseconds aStart,
if (aStart <= bufferedStart && aEnd < bufferedEnd) {
// Evict data from beginning.
for (size_t i = 0; i < decoders.Length(); ++i) {
- nsRefPtr buffered = new dom::TimeRanges();
- decoders[i]->GetBuffered(buffered);
- if (media::Microseconds::FromSeconds(buffered->GetEndTime()) < aEnd) {
+ media::TimeIntervals buffered = decoders[i]->GetBuffered();
+ if (buffered.GetEnd() < aEnd) {
// Can be fully removed.
MSE_DEBUG("remove all bufferedEnd=%f size=%lld",
- buffered->GetEndTime(),
+ buffered.GetEnd().ToSeconds(),
decoders[i]->GetResource()->GetSize());
decoders[i]->GetResource()->EvictAll();
} else {
int64_t offset = decoders[i]->ConvertToByteOffset(aEnd.ToSeconds());
MSE_DEBUG("removing some bufferedEnd=%f offset=%lld size=%lld",
- buffered->GetEndTime(), offset,
+ buffered.GetEnd().ToSeconds(), offset,
decoders[i]->GetResource()->GetSize());
if (offset > 0) {
decoders[i]->GetResource()->EvictData(offset, offset);
@@ -1075,11 +1063,11 @@ TrackBuffer::RangeRemoval(media::Microseconds aStart,
} else {
// Only trimming existing buffers.
for (size_t i = 0; i < decoders.Length(); ++i) {
- if (aStart <= media::Microseconds::FromSeconds(buffered->GetStartTime())) {
+ if (aStart <= buffered.GetStart()) {
// It will be entirely emptied, can clear all data.
decoders[i]->GetResource()->EvictAll();
} else {
- decoders[i]->Trim(aStart.mValue);
+ decoders[i]->Trim(aStart.ToMicroseconds());
}
}
}
diff --git a/dom/media/mediasource/TrackBuffer.h b/dom/media/mediasource/TrackBuffer.h
index e8d16422cc..cba7fb6185 100644
--- a/dom/media/mediasource/TrackBuffer.h
+++ b/dom/media/mediasource/TrackBuffer.h
@@ -24,12 +24,6 @@ class ContainerParser;
class MediaSourceDecoder;
class MediaLargeByteBuffer;
-namespace dom {
-
-class TimeRanges;
-
-} // namespace dom
-
class TrackBuffer final {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TrackBuffer);
@@ -56,10 +50,9 @@ public:
// of the buffer through to aTime.
void EvictBefore(double aTime);
- // Returns the highest end time of all of the buffered ranges in the
- // decoders managed by this TrackBuffer, and returns the union of the
- // decoders buffered ranges in aRanges. This may be called on any thread.
- double Buffered(dom::TimeRanges* aRanges);
+ // Returns the union of the decoders buffered ranges in aRanges.
+ // This may be called on any thread.
+ media::TimeIntervals Buffered();
// Mark the current decoder's resource as ended, clear mCurrentDecoder and
// reset mLast{Start,End}Timestamp. Main thread only.
@@ -99,8 +92,8 @@ public:
// Implementation is only partial, we can only trim a buffer.
// Returns true if data was evicted.
// Times are in microseconds.
- bool RangeRemoval(mozilla::media::Microseconds aStart,
- mozilla::media::Microseconds aEnd);
+ bool RangeRemoval(mozilla::media::TimeUnit aStart,
+ mozilla::media::TimeUnit aEnd);
// Abort any pending appendBuffer by rejecting any pending promises.
void AbortAppendData();
diff --git a/dom/media/ogg/OggReader.cpp b/dom/media/ogg/OggReader.cpp
index cc08b1b58b..8729c63de3 100644
--- a/dom/media/ogg/OggReader.cpp
+++ b/dom/media/ogg/OggReader.cpp
@@ -17,7 +17,6 @@
extern "C" {
#include "opus/opus_multistream.h"
}
-#include "mozilla/dom/TimeRanges.h"
#include "mozilla/TimeStamp.h"
#include "VorbisUtils.h"
#include "MediaMetadataManager.h"
@@ -1859,29 +1858,31 @@ nsresult OggReader::SeekBisection(int64_t aTarget,
return NS_OK;
}
-nsresult OggReader::GetBuffered(dom::TimeRanges* aBuffered)
+media::TimeIntervals OggReader::GetBuffered()
{
MOZ_ASSERT(mStartTime != -1, "Need to finish metadata decode first");
{
mozilla::ReentrantMonitorAutoEnter mon(mMonitor);
- if (mIsChained)
- return NS_ERROR_FAILURE;
+ if (mIsChained) {
+ return media::TimeIntervals::Invalid();
+ }
}
#ifdef OGG_ESTIMATE_BUFFERED
- return MediaDecoderReader::GetBuffered(aBuffered);
+ return MediaDecoderReader::GetBuffered();
#else
+ media::TimeIntervals buffered;
// HasAudio and HasVideo are not used here as they take a lock and cause
// a deadlock. Accessing mInfo doesn't require a lock - it doesn't change
// after metadata is read.
if (!mInfo.HasValidMedia()) {
// No need to search through the file if there are no audio or video tracks
- return NS_OK;
+ return buffered;
}
AutoPinned resource(mDecoder->GetResource());
nsTArray ranges;
nsresult res = resource->GetCachedRanges(ranges);
- NS_ENSURE_SUCCESS(res, res);
+ NS_ENSURE_SUCCESS(res, media::TimeIntervals::Invalid());
// Traverse across the buffered byte ranges, determining the time ranges
// they contain. MediaResource::GetNextCachedData(offset) returns -1 when
@@ -1915,7 +1916,7 @@ nsresult OggReader::GetBuffered(dom::TimeRanges* aBuffered)
&page,
discard);
if (res == PAGE_SYNC_ERROR) {
- return NS_ERROR_FAILURE;
+ return media::TimeIntervals::Invalid();
} else if (res == PAGE_SYNC_END_OF_RANGE) {
// Hit the end of range without reading a page, give up trying to
// find a start time for this buffered range, skip onto the next one.
@@ -1955,7 +1956,7 @@ nsresult OggReader::GetBuffered(dom::TimeRanges* aBuffered)
// prevents us searching through the rest of the media when we
// may not be able to extract timestamps from it.
SetChained(true);
- return NS_OK;
+ return buffered;
}
}
@@ -1963,14 +1964,15 @@ nsresult OggReader::GetBuffered(dom::TimeRanges* aBuffered)
// We were able to find a start time for that range, see if we can
// find an end time.
int64_t endTime = RangeEndTime(startOffset, endOffset, true);
- if (endTime != -1) {
- aBuffered->Add((startTime - mStartTime) / static_cast(USECS_PER_S),
- (endTime - mStartTime) / static_cast(USECS_PER_S));
+ if (endTime > startTime) {
+ buffered += media::TimeInterval(
+ media::TimeUnit::FromMicroseconds(startTime - mStartTime),
+ media::TimeUnit::FromMicroseconds(endTime - mStartTime));
}
}
}
- return NS_OK;
+ return buffered;
#endif
}
diff --git a/dom/media/ogg/OggReader.h b/dom/media/ogg/OggReader.h
index 84a241987c..fef0c68695 100644
--- a/dom/media/ogg/OggReader.h
+++ b/dom/media/ogg/OggReader.h
@@ -18,12 +18,6 @@
#include "VideoUtils.h"
#include "mozilla/Monitor.h"
-namespace mozilla {
-namespace dom {
-class TimeRanges;
-}
-}
-
namespace mozilla {
// Thread safe container to store the codec information and the serial for each
@@ -77,7 +71,7 @@ public:
MetadataTags** aTags) override;
virtual nsRefPtr
Seek(int64_t aTime, int64_t aEndTime) override;
- virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) override;
+ virtual media::TimeIntervals GetBuffered() override;
virtual bool IsMediaSeekable() override;
diff --git a/dom/media/omx/MediaOmxReader.cpp b/dom/media/omx/MediaOmxReader.cpp
index 0f839da17b..cda592ddf6 100644
--- a/dom/media/omx/MediaOmxReader.cpp
+++ b/dom/media/omx/MediaOmxReader.cpp
@@ -8,7 +8,6 @@
#include "MediaDecoderStateMachine.h"
#include "mozilla/TimeStamp.h"
-#include "mozilla/dom/TimeRanges.h"
#include "MediaResource.h"
#include "VideoUtils.h"
#include "MediaOmxDecoder.h"
diff --git a/dom/media/omx/RtspMediaCodecReader.h b/dom/media/omx/RtspMediaCodecReader.h
index 57b8cd47a9..e5ac6eaed3 100644
--- a/dom/media/omx/RtspMediaCodecReader.h
+++ b/dom/media/omx/RtspMediaCodecReader.h
@@ -11,10 +11,6 @@
namespace mozilla {
-namespace dom {
- class TimeRanges;
-}
-
class AbstractMediaDecoder;
class RtspMediaResource;
@@ -48,8 +44,8 @@ public:
// we returned are not useful for the MediaDecodeStateMachine. Unlike the
// ChannelMediaResource, it has a "cache" that can store the whole streaming
// data so the |GetBuffered| function can retrieve useful time ranges.
- virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) override {
- return NS_ERROR_NOT_IMPLEMENTED;
+ virtual media::TimeIntervals GetBuffered() override {
+ return media::TimeIntervals::Invalid();
}
virtual void SetIdle() override;
diff --git a/dom/media/omx/RtspOmxReader.h b/dom/media/omx/RtspOmxReader.h
index c8ffd31e9d..8c31b51ea8 100644
--- a/dom/media/omx/RtspOmxReader.h
+++ b/dom/media/omx/RtspOmxReader.h
@@ -58,8 +58,8 @@ public:
// we returned are not useful for the MediaDecodeStateMachine. Unlike the
// ChannelMediaResource, it has a "cache" that can store the whole streaming
// data so the |GetBuffered| function can retrieve useful time ranges.
- virtual nsresult GetBuffered(mozilla::dom::TimeRanges* aBuffered) final override {
- return NS_ERROR_NOT_IMPLEMENTED;
+ virtual media::TimeIntervals GetBuffered() final override {
+ return media::TimeIntervals::Invalid();
}
virtual void SetIdle() override;
diff --git a/dom/media/raw/RawReader.cpp b/dom/media/raw/RawReader.cpp
index 93b4e8e0ad..d46affee43 100644
--- a/dom/media/raw/RawReader.cpp
+++ b/dom/media/raw/RawReader.cpp
@@ -289,7 +289,7 @@ nsresult RawReader::SeekInternal(int64_t aTime)
return NS_OK;
}
-nsresult RawReader::GetBuffered(dom::TimeRanges* aBuffered)
+media::TimeIntervals RawReader::GetBuffered()
{
- return NS_OK;
+ return media::TimeIntervals();
}
diff --git a/dom/media/raw/RawReader.h b/dom/media/raw/RawReader.h
index 636ec41d95..65d5195bb5 100644
--- a/dom/media/raw/RawReader.h
+++ b/dom/media/raw/RawReader.h
@@ -42,7 +42,7 @@ public:
virtual nsRefPtr
Seek(int64_t aTime, int64_t aEndTime) override;
- virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) override;
+ virtual media::TimeIntervals GetBuffered() override;
virtual bool IsMediaSeekable() override;
diff --git a/dom/media/wave/WaveReader.cpp b/dom/media/wave/WaveReader.cpp
index fc1b557391..53f630912f 100644
--- a/dom/media/wave/WaveReader.cpp
+++ b/dom/media/wave/WaveReader.cpp
@@ -7,7 +7,6 @@
#include "AbstractMediaDecoder.h"
#include "MediaResource.h"
#include "WaveReader.h"
-#include "mozilla/dom/TimeRanges.h"
#include "MediaDecoderStateMachine.h"
#include "VideoUtils.h"
#include "nsISeekableStream.h"
@@ -280,15 +279,12 @@ WaveReader::Seek(int64_t aTarget, int64_t aEndTime)
}
}
-static double RoundToUsecs(double aSeconds) {
- return floor(aSeconds * USECS_PER_S) / USECS_PER_S;
-}
-
-nsresult WaveReader::GetBuffered(dom::TimeRanges* aBuffered)
+media::TimeIntervals WaveReader::GetBuffered()
{
if (!mInfo.HasAudio()) {
- return NS_OK;
+ return media::TimeIntervals();
}
+ media::TimeIntervals buffered;
AutoPinned resource(mDecoder->GetResource());
int64_t startOffset = resource->GetNextCachedData(mWavePCMOffset);
while (startOffset >= 0) {
@@ -300,11 +296,12 @@ nsresult WaveReader::GetBuffered(dom::TimeRanges* aBuffered)
// We need to round the buffered ranges' times to microseconds so that they
// have the same precision as the currentTime and duration attribute on
// the media element.
- aBuffered->Add(RoundToUsecs(BytesToTime(startOffset - mWavePCMOffset)),
- RoundToUsecs(BytesToTime(endOffset - mWavePCMOffset)));
+ buffered += media::TimeInterval(
+ media::TimeUnit::FromSeconds(BytesToTime(startOffset - mWavePCMOffset)),
+ media::TimeUnit::FromSeconds(BytesToTime(endOffset - mWavePCMOffset)));
startOffset = resource->GetNextCachedData(endOffset);
}
- return NS_OK;
+ return buffered;
}
bool
diff --git a/dom/media/wave/WaveReader.h b/dom/media/wave/WaveReader.h
index 4b2eb89647..f7d539d75d 100644
--- a/dom/media/wave/WaveReader.h
+++ b/dom/media/wave/WaveReader.h
@@ -9,12 +9,6 @@
#include "MediaDecoderReader.h"
#include "mozilla/dom/HTMLMediaElement.h"
-namespace mozilla {
-namespace dom {
-class TimeRanges;
-}
-}
-
namespace mozilla {
class WaveReader : public MediaDecoderReader
@@ -46,7 +40,7 @@ public:
virtual nsRefPtr
Seek(int64_t aTime, int64_t aEndTime) override;
- virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) override;
+ virtual media::TimeIntervals GetBuffered() override;
virtual bool IsMediaSeekable() override;
diff --git a/dom/media/webm/SoftwareWebMVideoDecoder.cpp b/dom/media/webm/SoftwareWebMVideoDecoder.cpp
index b1a9ade38a..1d1b73d496 100644
--- a/dom/media/webm/SoftwareWebMVideoDecoder.cpp
+++ b/dom/media/webm/SoftwareWebMVideoDecoder.cpp
@@ -8,9 +8,9 @@
#include "gfx2DGlue.h"
#include "MediaDecoderStateMachine.h"
#include "MediaResource.h"
-#include "mozilla/dom/TimeRanges.h"
#include "nsError.h"
#include "OggReader.h"
+#include "TimeUnits.h"
#include "VorbisUtils.h"
#include "WebMBufferedParser.h"
diff --git a/dom/media/webm/WebMBufferedParser.cpp b/dom/media/webm/WebMBufferedParser.cpp
index ff3087e2c2..42a298f708 100644
--- a/dom/media/webm/WebMBufferedParser.cpp
+++ b/dom/media/webm/WebMBufferedParser.cpp
@@ -6,7 +6,6 @@
#include "nsAlgorithm.h"
#include "WebMBufferedParser.h"
-#include "mozilla/dom/TimeRanges.h"
#include "nsThreadUtils.h"
#include
diff --git a/dom/media/webm/WebMReader.cpp b/dom/media/webm/WebMReader.cpp
index 53c777a8be..8f2ba69767 100644
--- a/dom/media/webm/WebMReader.cpp
+++ b/dom/media/webm/WebMReader.cpp
@@ -10,7 +10,6 @@
#include "SoftwareWebMVideoDecoder.h"
#include "WebMReader.h"
#include "WebMBufferedParser.h"
-#include "mozilla/dom/TimeRanges.h"
#include "VorbisUtils.h"
#include "gfx2DGlue.h"
#include "Layers.h"
@@ -1102,21 +1101,21 @@ nsresult WebMReader::SeekInternal(int64_t aTarget)
return NS_OK;
}
-nsresult WebMReader::GetBuffered(dom::TimeRanges* aBuffered)
+media::TimeIntervals WebMReader::GetBuffered()
{
MOZ_ASSERT(mStartTime != -1, "Need to finish metadata decode first");
- if (aBuffered->Length() != 0) {
- return NS_ERROR_FAILURE;
- }
-
AutoPinned resource(mDecoder->GetResource());
+ media::TimeIntervals buffered;
// Special case completely cached files. This also handles local files.
if (mContext && resource->IsDataCachedToEndOfResource(0)) {
uint64_t duration = 0;
if (nestegg_duration(mContext, &duration) == 0) {
- aBuffered->Add(0, duration / NS_PER_S);
- return NS_OK;
+ buffered +=
+ media::TimeInterval(media::TimeUnit::FromSeconds(0),
+ media::TimeUnit::FromSeconds(duration / NS_PER_S));
+ return buffered;
+ }
}
}
@@ -1124,7 +1123,7 @@ nsresult WebMReader::GetBuffered(dom::TimeRanges* aBuffered)
// the WebM bitstream.
nsTArray ranges;
nsresult res = resource->GetCachedRanges(ranges);
- NS_ENSURE_SUCCESS(res, res);
+ NS_ENSURE_SUCCESS(res, media::TimeIntervals::Invalid());
for (uint32_t index = 0; index < ranges.Length(); index++) {
uint64_t start, end;
@@ -1150,11 +1149,12 @@ nsresult WebMReader::GetBuffered(dom::TimeRanges* aBuffered)
}
}
- aBuffered->Add(startTime, endTime);
+ buffered += media::TimeInterval(media::TimeUnit::FromSeconds(startTime),
+ media::TimeUnit::FromSeconds(endTime));
}
}
- return NS_OK;
+ return buffered;
}
void WebMReader::NotifyDataArrived(const char* aBuffer, uint32_t aLength,
diff --git a/dom/media/webm/WebMReader.h b/dom/media/webm/WebMReader.h
index a95b92af56..d45b108d1d 100644
--- a/dom/media/webm/WebMReader.h
+++ b/dom/media/webm/WebMReader.h
@@ -158,7 +158,7 @@ public:
virtual nsRefPtr
Seek(int64_t aTime, int64_t aEndTime) override;
- virtual nsresult GetBuffered(dom::TimeRanges* aBuffered) override;
+ virtual media::TimeIntervals GetBuffered() override;
virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength,
int64_t aOffset) override;
virtual int64_t GetEvictionOffset(double aTime) override;
diff --git a/dom/media/wmf/WMFReader.cpp b/dom/media/wmf/WMFReader.cpp
index 660fbb1999..c331909ae1 100644
--- a/dom/media/wmf/WMFReader.cpp
+++ b/dom/media/wmf/WMFReader.cpp
@@ -10,7 +10,6 @@
#include "WMFByteStream.h"
#include "WMFSourceReaderCallback.h"
#include "mozilla/ArrayUtils.h"
-#include "mozilla/dom/TimeRanges.h"
#include "mozilla/dom/HTMLMediaElement.h"
#include "mozilla/Preferences.h"
#include "DXVA2Manager.h"