Bug 1297036: [MSE] P4. Only report end of stream when reaching the end. r?gerald
MozReview-Commit-ID: 5EWhBVnscXY
--- a/dom/media/mediasource/MediaSourceDemuxer.cpp
+++ b/dom/media/mediasource/MediaSourceDemuxer.cpp
@@ -374,92 +374,99 @@ MediaSourceTrackDemuxer::BreakCycles()
self->mManager = nullptr;
} );
mParent->GetTaskQueue()->Dispatch(task.forget());
}
RefPtr<MediaSourceTrackDemuxer::SeekPromise>
MediaSourceTrackDemuxer::DoSeek(media::TimeUnit aTime)
{
+ typedef TrackBuffersManager::GetSampleResult Result;
+
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__);
+ return SeekPromise::CreateAndReject(DemuxerFailureReason::WAITING_FOR_DATA,
+ __func__);
}
// 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;
}
seekTime = mManager->Seek(mType, seekTime, MediaSourceDemuxer::EOS_FUZZ / 2);
- bool error;
+ Result result;
RefPtr<MediaRawData> sample =
mManager->GetSample(mType,
media::TimeUnit(),
- error);
- MOZ_ASSERT(!error && sample);
+ result);
+ MOZ_ASSERT(result != Result::ERROR && sample);
mNextSample = Some(sample);
mReset = false;
{
MonitorAutoLock mon(mMonitor);
mNextRandomAccessPoint =
mManager->GetNextRandomAccessPoint(mType, MediaSourceDemuxer::EOS_FUZZ);
}
return SeekPromise::CreateAndResolve(seekTime, __func__);
}
RefPtr<MediaSourceTrackDemuxer::SamplesPromise>
MediaSourceTrackDemuxer::DoGetSamples(int32_t aNumSamples)
{
+ typedef TrackBuffersManager::GetSampleResult Result;
+
if (mReset) {
// If a seek (or reset) was recently performed, we ensure that the data
// we are about to retrieve is still available.
TimeIntervals buffered = mManager->Buffered(mType);
buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ);
+ if (!buffered.Length() && mManager->IsEnded()) {
+ return SamplesPromise::CreateAndReject(DemuxerFailureReason::END_OF_STREAM,
+ __func__);
+ }
if (!buffered.Contains(TimeUnit::FromMicroseconds(0))) {
- return SamplesPromise::CreateAndReject(
- mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
- DemuxerFailureReason::WAITING_FOR_DATA, __func__);
+ return SamplesPromise::CreateAndReject(DemuxerFailureReason::WAITING_FOR_DATA,
+ __func__);
}
mReset = false;
}
- bool error = false;
RefPtr<MediaRawData> sample;
if (mNextSample) {
sample = mNextSample.ref();
mNextSample.reset();
} else {
- sample = mManager->GetSample(mType, MediaSourceDemuxer::EOS_FUZZ, error);
+ Result result;
+ sample = mManager->GetSample(mType, MediaSourceDemuxer::EOS_FUZZ, result);
if (!sample) {
- if (error) {
+ if (result == Result::ERROR) {
return SamplesPromise::CreateAndReject(DemuxerFailureReason::DEMUXER_ERROR, __func__);
}
return SamplesPromise::CreateAndReject(
- mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
- DemuxerFailureReason::WAITING_FOR_DATA, __func__);
+ (result == Result::EOS && mManager->IsEnded())
+ ? DemuxerFailureReason::END_OF_STREAM
+ : DemuxerFailureReason::WAITING_FOR_DATA, __func__);
}
}
RefPtr<SamplesHolder> samples = new SamplesHolder;
samples->mSamples.AppendElement(sample);
if (mNextRandomAccessPoint.ToMicroseconds() <= sample->mTime) {
MonitorAutoLock mon(mMonitor);
mNextRandomAccessPoint =
mManager->GetNextRandomAccessPoint(mType, MediaSourceDemuxer::EOS_FUZZ);
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -2133,79 +2133,95 @@ TrackBuffersManager::GetSample(TrackInfo
// TODO, check that we have continuous data based on the sanitized buffered
// range instead.
return nullptr;
}
already_AddRefed<MediaRawData>
TrackBuffersManager::GetSample(TrackInfo::TrackType aTrack,
const TimeUnit& aFuzz,
- bool& aError)
+ GetSampleResult& aResult)
{
MOZ_ASSERT(OnTaskQueue());
auto& trackData = GetTracksData(aTrack);
const TrackBuffer& track = GetTrackBuffer(aTrack);
- aError = false;
+ aResult = GetSampleResult::WAITING_FOR_DATA;
if (!track.Length()) {
+ aResult = GetSampleResult::EOS;
return nullptr;
}
+
if (trackData.mNextGetSampleIndex.isNothing() &&
trackData.mNextSampleTimecode == TimeUnit()) {
// First demux, get first sample.
trackData.mNextGetSampleIndex = Some(0u);
}
if (trackData.mNextGetSampleIndex.isSome()) {
+ if (trackData.mNextGetSampleIndex.ref() >= track.Length()) {
+ aResult = GetSampleResult::EOS;
+ return nullptr;
+ }
const MediaRawData* sample =
GetSample(aTrack,
trackData.mNextGetSampleIndex.ref(),
trackData.mNextSampleTimecode,
trackData.mNextSampleTime,
aFuzz);
if (!sample) {
return nullptr;
}
RefPtr<MediaRawData> p = sample->Clone();
if (!p) {
- aError = true;
+ aResult = GetSampleResult::ERROR;
return nullptr;
}
trackData.mNextGetSampleIndex.ref()++;
// Estimate decode timestamp of the next sample.
trackData.mNextSampleTimecode =
TimeUnit::FromMicroseconds(sample->mTimecode + sample->mDuration);
trackData.mNextSampleTime =
TimeUnit::FromMicroseconds(sample->GetEndTime());
+ aResult = GetSampleResult::NO_ERROR;
return p.forget();
}
+ if (trackData.mNextSampleTimecode.ToMicroseconds() >
+ track.LastElement()->mTimecode + track.LastElement()->mDuration) {
+ // The next element is past our last sample. We're done.
+ trackData.mNextGetSampleIndex = Some(uint32_t(track.Length()));
+ aResult = GetSampleResult::EOS;
+ return nullptr;
+ }
+
// 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<MediaRawData>& sample = track[pos];
RefPtr<MediaRawData> p = sample->Clone();
if (!p) {
// OOM
- aError = true;
+ aResult = GetSampleResult::ERROR;
return nullptr;
}
trackData.mNextGetSampleIndex = Some(uint32_t(pos)+1);
trackData.mNextSampleTimecode =
TimeUnit::FromMicroseconds(sample->mTimecode + sample->mDuration);
trackData.mNextSampleTime =
TimeUnit::FromMicroseconds(sample->GetEndTime());
+ aResult = GetSampleResult::NO_ERROR;
return p.forget();
}
int32_t
TrackBuffersManager::FindCurrentPosition(TrackInfo::TrackType aTrack,
const TimeUnit& aFuzz)
{
MOZ_ASSERT(OnTaskQueue());
--- a/dom/media/mediasource/TrackBuffersManager.h
+++ b/dom/media/mediasource/TrackBuffersManager.h
@@ -148,19 +148,28 @@ public:
}
media::TimeUnit Seek(TrackInfo::TrackType aTrack,
const media::TimeUnit& aTime,
const media::TimeUnit& aFuzz);
uint32_t SkipToNextRandomAccessPoint(TrackInfo::TrackType aTrack,
const media::TimeUnit& aTimeThreadshold,
const media::TimeUnit& aFuzz,
bool& aFound);
+
+ enum class GetSampleResult
+ {
+ NO_ERROR,
+ ERROR,
+ WAITING_FOR_DATA,
+ EOS
+ };
+
already_AddRefed<MediaRawData> GetSample(TrackInfo::TrackType aTrack,
const media::TimeUnit& aFuzz,
- bool& aError);
+ GetSampleResult& aResult);
int32_t FindCurrentPosition(TrackInfo::TrackType aTrack,
const media::TimeUnit& aFuzz);
media::TimeUnit GetNextRandomAccessPoint(TrackInfo::TrackType aTrack,
const media::TimeUnit& aFuzz);
void AddSizeOfResources(MediaSourceDecoder::ResourceSizes* aSizes);
private: