Bug 1297036: [MSE] P2. Make seek always succeed when attempting to seek past the end time. r?gerald
MozReview-Commit-ID: H2YJu7vY0aP
--- a/dom/media/mediasource/MediaSourceDemuxer.cpp
+++ b/dom/media/mediasource/MediaSourceDemuxer.cpp
@@ -380,24 +380,31 @@ RefPtr<MediaSourceTrackDemuxer::SeekProm
MediaSourceTrackDemuxer::DoSeek(media::TimeUnit aTime)
{
TimeIntervals buffered = mManager->Buffered(mType);
// Fuzz factor represents a +/- threshold. So when seeking it allows the gap
// to be twice as big as the fuzz value. We only want to allow EOS_FUZZ gap.
buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ / 2);
TimeUnit seekTime = std::max(aTime - mPreRoll, TimeUnit::FromMicroseconds(0));
+ if (mManager->IsEnded() && seekTime >= buffered.GetEnd()) {
+ // We're attempting to seek past the end time. Cap seekTime so that we seek
+ // to the last sample instead.
+ seekTime =
+ std::max(mManager->HighestStartTime(mType) - mPreRoll,
+ TimeUnit::FromMicroseconds(0));
+ }
if (!buffered.Contains(seekTime)) {
if (!buffered.Contains(aTime)) {
// We don't have the data to seek to.
return SeekPromise::CreateAndReject(
mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
DemuxerFailureReason::WAITING_FOR_DATA, __func__);
}
- // Theorically we should reject the promise with WAITING_FOR_DATA,
+ // Theoretically we should reject the promise with WAITING_FOR_DATA,
// however, to avoid unwanted regressions we assume that if at this time
// we don't have the wanted data it won't come later.
// Instead of using the pre-rolled time, use the earliest time available in
// the interval.
TimeIntervals::IndexType index = buffered.Find(aTime);
MOZ_ASSERT(index != TimeIntervals::NoIndex);
seekTime = buffered[index].mStart;
}
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -1888,16 +1888,23 @@ TrackBuffersManager::GetMetadata()
const TimeIntervals&
TrackBuffersManager::Buffered(TrackInfo::TrackType aTrack)
{
MOZ_ASSERT(OnTaskQueue());
return GetTracksData(aTrack).mBufferedRanges;
}
+const media::TimeUnit&
+TrackBuffersManager::HighestStartTime(TrackInfo::TrackType aTrack)
+{
+ MOZ_ASSERT(OnTaskQueue());
+ return GetTracksData(aTrack).mHighestStartTimestamp;
+}
+
TimeIntervals
TrackBuffersManager::SafeBuffered(TrackInfo::TrackType aTrack) const
{
MonitorAutoLock mon(mMonitor);
return aTrack == TrackInfo::kVideoTrack
? mVideoBufferedRanges
: mAudioBufferedRanges;
}
@@ -1976,18 +1983,18 @@ TrackBuffersManager::Seek(TrackInfo::Tra
uint32_t i = 0;
if (aTime != TimeUnit()) {
// Determine the interval of samples we're attempting to seek to.
TimeIntervals buffered = trackBuffer.mBufferedRanges;
buffered.SetFuzz(aFuzz);
TimeIntervals::IndexType index = buffered.Find(aTime);
- MOZ_ASSERT(index != TimeIntervals::NoIndex);
-
+ MOZ_ASSERT(index != TimeIntervals::NoIndex,
+ "We shouldn't be called if aTime isn't buffered");
TimeInterval target = buffered[index];
i = FindSampleIndex(track, target);
}
Maybe<TimeUnit> lastKeyFrameTime;
TimeUnit lastKeyFrameTimecode;
uint32_t lastKeyFrameIndex = 0;
for (; i < track.Length(); i++) {
--- a/dom/media/mediasource/TrackBuffersManager.h
+++ b/dom/media/mediasource/TrackBuffersManager.h
@@ -135,16 +135,17 @@ public:
void Detach();
int64_t EvictionThreshold() const;
// Interface for MediaSourceDemuxer
MediaInfo GetMetadata();
const TrackBuffer& GetTrackBuffer(TrackInfo::TrackType aTrack);
const media::TimeIntervals& Buffered(TrackInfo::TrackType);
+ const media::TimeUnit& HighestStartTime(TrackInfo::TrackType);
media::TimeIntervals SafeBuffered(TrackInfo::TrackType) const;
bool IsEnded() const
{
return mEnded;
}
media::TimeUnit Seek(TrackInfo::TrackType aTrack,
const media::TimeUnit& aTime,
const media::TimeUnit& aFuzz);