diff --git a/dom/media/mediasource/MediaSourceDemuxer.cpp b/dom/media/mediasource/MediaSourceDemuxer.cpp index a56fb5cbfe51..23a018c25618 100644 --- a/dom/media/mediasource/MediaSourceDemuxer.cpp +++ b/dom/media/mediasource/MediaSourceDemuxer.cpp @@ -468,8 +468,10 @@ MediaSourceTrackDemuxer::DoSkipToNextRandomAccessPoint(media::TimeUnit aTimeThre buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ); if (buffered.Contains(aTimeThreadshold)) { bool found; - parsed = - mManager->SkipToNextRandomAccessPoint(mType, aTimeThreadshold, found); + parsed = mManager->SkipToNextRandomAccessPoint(mType, + aTimeThreadshold, + MediaSourceDemuxer::EOS_FUZZ, + found); if (found) { return SkipAccessPointPromise::CreateAndResolve(parsed, __func__); } diff --git a/dom/media/mediasource/TrackBuffersManager.cpp b/dom/media/mediasource/TrackBuffersManager.cpp index 0f348ce6e029..17349b676915 100644 --- a/dom/media/mediasource/TrackBuffersManager.cpp +++ b/dom/media/mediasource/TrackBuffersManager.cpp @@ -1896,6 +1896,7 @@ TrackBuffersManager::Seek(TrackInfo::TrackType aTrack, uint32_t TrackBuffersManager::SkipToNextRandomAccessPoint(TrackInfo::TrackType aTrack, const TimeUnit& aTimeThreadshold, + const media::TimeUnit& aFuzz, bool& aFound) { MOZ_ASSERT(OnTaskQueue()); @@ -1904,22 +1905,55 @@ TrackBuffersManager::SkipToNextRandomAccessPoint(TrackInfo::TrackType aTrack, const TrackBuffer& track = GetTrackBuffer(aTrack); aFound = false; - uint32_t nextSampleIndex = trackData.mNextGetSampleIndex.valueOr(0); - for (uint32_t i = nextSampleIndex; i < track.Length(); i++) { - const RefPtr& sample = track[i]; + // SkipToNextRandomAccessPoint can only be called if aTimeThreadshold is known + // to be buffered. + + // So first determine the current position in the track buffer if necessary. + if (trackData.mNextGetSampleIndex.isNothing()) { + if (trackData.mNextSampleTimecode == TimeUnit()) { + // First demux, get first sample. + trackData.mNextGetSampleIndex = Some(0u); + } else { + int32_t pos = FindCurrentPosition(aTrack, aFuzz); + if (pos < 0) { + return 0; + } + trackData.mNextGetSampleIndex = Some(uint32_t(pos)); + } + } + + TimeUnit nextSampleTimecode = trackData.mNextSampleTimecode; + TimeUnit nextSampleTime = trackData.mNextSampleTime; + uint32_t i = trackData.mNextGetSampleIndex.ref(); + + for (; i < track.Length(); i++) { + const MediaRawData* sample = + GetSample(aTrack, + i, + nextSampleTimecode, + nextSampleTime, + aFuzz); + if (!sample) { + break; + } if (sample->mKeyframe && sample->mTime >= aTimeThreadshold.ToMicroseconds()) { - trackData.mNextSampleTimecode = - TimeUnit::FromMicroseconds(sample->mTimecode); - trackData.mNextSampleTime = - TimeUnit::FromMicroseconds(sample->mTime); - trackData.mNextGetSampleIndex = Some(i); aFound = true; break; } + nextSampleTimecode = + TimeUnit::FromMicroseconds(sample->mTimecode + sample->mDuration); + nextSampleTime = TimeUnit::FromMicroseconds(sample->GetEndTime()); parsed++; } + // Adjust the next demux time and index so that the next call to + // SkipToNextRandomAccessPoint will not count again the parsed sample as + // skipped. + trackData.mNextSampleTimecode = nextSampleTimecode; + trackData.mNextSampleTime = nextSampleTime; + trackData.mNextGetSampleIndex = Some(i); + return parsed; } @@ -1930,6 +1964,7 @@ TrackBuffersManager::GetSample(TrackInfo::TrackType aTrack, const TimeUnit& aExpectedPts, const TimeUnit& aFuzz) { + MOZ_ASSERT(OnTaskQueue()); const TrackBuffer& track = GetTrackBuffer(aTrack); if (aIndex >= track.Length()) { @@ -1995,6 +2030,37 @@ TrackBuffersManager::GetSample(TrackInfo::TrackType aTrack, } // Our previous index has been overwritten, attempt to find the new one. + int32_t pos = FindCurrentPosition(aTrack, aFuzz); + if (pos < 0) { + MSE_DEBUG("Couldn't find sample (pts:%lld dts:%lld)", + trackData.mNextSampleTime.ToMicroseconds(), + trackData.mNextSampleTimecode.ToMicroseconds()); + return nullptr; + } + + const RefPtr& sample = track[pos]; + RefPtr p = sample->Clone(); + if (!p) { + // OOM + aError = true; + return nullptr; + } + trackData.mNextGetSampleIndex = Some(uint32_t(pos)+1); + trackData.mNextSampleTimecode = + TimeUnit::FromMicroseconds(sample->mTimecode + sample->mDuration); + trackData.mNextSampleTime = + TimeUnit::FromMicroseconds(sample->GetEndTime()); + return p.forget(); +} + +int32_t +TrackBuffersManager::FindCurrentPosition(TrackInfo::TrackType aTrack, + const TimeUnit& aFuzz) +{ + MOZ_ASSERT(OnTaskQueue()); + auto& trackData = GetTracksData(aTrack); + const TrackBuffer& track = GetTrackBuffer(aTrack); + for (uint32_t i = 0; i < track.Length(); i++) { const RefPtr& sample = track[i]; TimeInterval sampleInterval{ @@ -2003,23 +2069,13 @@ TrackBuffersManager::GetSample(TrackInfo::TrackType aTrack, aFuzz}; if (sampleInterval.ContainsWithStrictEnd(trackData.mNextSampleTimecode)) { - RefPtr p = sample->Clone(); - if (!p) { - // OOM - aError = true; - return nullptr; - } - trackData.mNextGetSampleIndex = Some(i+1); - trackData.mNextSampleTimecode = sampleInterval.mEnd; - trackData.mNextSampleTime = - TimeUnit::FromMicroseconds(sample->GetEndTime()); - return p.forget(); + return i; } } // We couldn't find our sample by decode timestamp. Attempt to find it using // presentation timestamp. There will likely be small jerkiness. - for (uint32_t i = 0; i < track.Length(); i++) { + for (uint32_t i = 0; i < track.Length(); i++) { const RefPtr& sample = track[i]; TimeInterval sampleInterval{ TimeUnit::FromMicroseconds(sample->mTime), @@ -2027,31 +2083,19 @@ TrackBuffersManager::GetSample(TrackInfo::TrackType aTrack, aFuzz}; if (sampleInterval.ContainsWithStrictEnd(trackData.mNextSampleTimecode)) { - RefPtr p = sample->Clone(); - if (!p) { - // OOM - aError = true; - return nullptr; - } - trackData.mNextGetSampleIndex = Some(i+1); - // Estimate decode timestamp of the next sample. - trackData.mNextSampleTimecode = sampleInterval.mEnd; - trackData.mNextSampleTime = - TimeUnit::FromMicroseconds(sample->GetEndTime()); - return p.forget(); + return i; } } - MSE_DEBUG("Couldn't find sample (pts:%lld dts:%lld)", - trackData.mNextSampleTime.ToMicroseconds(), - trackData.mNextSampleTimecode.ToMicroseconds()); - return nullptr; + // Still not found. + return -1; } TimeUnit TrackBuffersManager::GetNextRandomAccessPoint(TrackInfo::TrackType aTrack, const TimeUnit& aFuzz) { + MOZ_ASSERT(OnTaskQueue()); auto& trackData = GetTracksData(aTrack); MOZ_ASSERT(trackData.mNextGetSampleIndex.isSome()); const TrackBuffersManager::TrackBuffer& track = GetTrackBuffer(aTrack); diff --git a/dom/media/mediasource/TrackBuffersManager.h b/dom/media/mediasource/TrackBuffersManager.h index e74c6f895247..68168ff02889 100644 --- a/dom/media/mediasource/TrackBuffersManager.h +++ b/dom/media/mediasource/TrackBuffersManager.h @@ -145,10 +145,13 @@ public: const media::TimeUnit& aFuzz); uint32_t SkipToNextRandomAccessPoint(TrackInfo::TrackType aTrack, const media::TimeUnit& aTimeThreadshold, + const media::TimeUnit& aFuzz, bool& aFound); already_AddRefed GetSample(TrackInfo::TrackType aTrack, const media::TimeUnit& aFuzz, bool& aError); + int32_t FindCurrentPosition(TrackInfo::TrackType aTrack, + const media::TimeUnit& aFuzz); media::TimeUnit GetNextRandomAccessPoint(TrackInfo::TrackType aTrack, const media::TimeUnit& aFuzz);