Bug 1466606 - P1. Calculate the current GetSample index when needed. r?bryce
The assumption that when calling GetNextRandomAccessPoint the next GetSample index would always be known was incorrect. It assumed that the call to GetNextRandomAccessPoint would always be preceded by a call to GetSample.
This is not always how the MediaSourceDemuxer called it.
MozReview-Commit-ID: H1MyPpDEytk
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -2357,28 +2357,18 @@ TrackBuffersManager::SkipToNextRandomAcc
uint32_t parsed = 0;
auto& trackData = GetTracksData(aTrack);
const TrackBuffer& track = GetTrackBuffer(aTrack);
aFound = false;
// 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));
- }
+ if (NS_FAILED(SetNextGetSampleIndexIfNeeded(aTrack, aFuzz))) {
+ return 0;
}
TimeUnit nextSampleTimecode = trackData.mNextSampleTimecode;
TimeUnit nextSampleTime = trackData.mNextSampleTime;
uint32_t i = trackData.mNextGetSampleIndex.ref();
int32_t originalPos = i;
for (; i < track.Length(); i++) {
@@ -2634,18 +2624,23 @@ TrackBuffersManager::Evictable(TrackInfo
return GetTracksData(aTrack).mEvictionIndex.mEvictable;
}
TimeUnit
TrackBuffersManager::GetNextRandomAccessPoint(TrackInfo::TrackType aTrack,
const TimeUnit& aFuzz)
{
MOZ_ASSERT(OnTaskQueue());
+
+ // So first determine the current position in the track buffer if necessary.
+ if (NS_FAILED(SetNextGetSampleIndexIfNeeded(aTrack, aFuzz))) {
+ return TimeUnit::FromInfinity();
+ }
+
auto& trackData = GetTracksData(aTrack);
- MOZ_ASSERT(trackData.mNextGetSampleIndex.isSome());
const TrackBuffersManager::TrackBuffer& track = GetTrackBuffer(aTrack);
uint32_t i = trackData.mNextGetSampleIndex.ref();
TimeUnit nextSampleTimecode = trackData.mNextSampleTimecode;
TimeUnit nextSampleTime = trackData.mNextSampleTime;
for (; i < track.Length(); i++) {
const MediaRawData* sample =
@@ -2657,16 +2652,55 @@ TrackBuffersManager::GetNextRandomAccess
return sample->mTime;
}
nextSampleTimecode = sample->mTimecode + sample->mDuration;
nextSampleTime = sample->GetEndTime();
}
return TimeUnit::FromInfinity();
}
+nsresult
+TrackBuffersManager::SetNextGetSampleIndexIfNeeded(TrackInfo::TrackType aTrack,
+ const TimeUnit& aFuzz)
+{
+ auto& trackData = GetTracksData(aTrack);
+ const TrackBuffer& track = GetTrackBuffer(aTrack);
+
+ if (trackData.mNextGetSampleIndex.isSome()) {
+ // We already know the next GetSample index.
+ return NS_OK;
+ }
+
+ if (!track.Length()) {
+ // There's nothing to find yet.
+ return NS_ERROR_DOM_MEDIA_END_OF_STREAM;
+ }
+
+ if (trackData.mNextSampleTimecode == TimeUnit()) {
+ // First demux, get first sample.
+ trackData.mNextGetSampleIndex = Some(0u);
+ return NS_OK;
+ }
+
+ if (trackData.mNextSampleTimecode >
+ track.LastElement()->mTimecode + track.LastElement()->mDuration) {
+ // The next element is past our last sample. We're done.
+ trackData.mNextGetSampleIndex = Some(uint32_t(track.Length()));
+ return NS_ERROR_DOM_MEDIA_END_OF_STREAM;
+ }
+
+ int32_t pos = FindCurrentPosition(aTrack, aFuzz);
+ if (pos < 0) {
+ // Not found, must wait for more data.
+ return NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA;
+ }
+ trackData.mNextGetSampleIndex = Some(uint32_t(pos));
+ return NS_OK;
+}
+
void
TrackBuffersManager::TrackData::AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes) const
{
for (const TrackBuffer& buffer : mBuffers) {
for (const MediaRawData* data : buffer) {
aSizes->mByteSize += data->SizeOfIncludingThis(aSizes->mMallocSizeOf);
}
}
--- a/dom/media/mediasource/TrackBuffersManager.h
+++ b/dom/media/mediasource/TrackBuffersManager.h
@@ -155,16 +155,25 @@ public:
const media::TimeUnit& aFuzz,
bool& aFound);
already_AddRefed<MediaRawData> GetSample(TrackInfo::TrackType aTrack,
const media::TimeUnit& aFuzz,
MediaResult& aResult);
int32_t FindCurrentPosition(TrackInfo::TrackType aTrack,
const media::TimeUnit& aFuzz) const;
+
+ // Will set the next GetSample index if needed. This information is determined
+ // through the value of mNextSampleTimecode. Return false if the index
+ // couldn't be determined or if there's nothing more that could be demuxed.
+ // This occurs if either the track buffer doesn't contain the required
+ // timecode or is empty.
+ nsresult SetNextGetSampleIndexIfNeeded(TrackInfo::TrackType aTrack,
+ const media::TimeUnit& aFuzz);
+
media::TimeUnit GetNextRandomAccessPoint(TrackInfo::TrackType aTrack,
const media::TimeUnit& aFuzz);
void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes) const;
private:
typedef MozPromise<bool, MediaResult, /* IsExclusive = */ true> CodedFrameProcessingPromise;