Bug 1301307: [MSE] Throw error when sourcebuffer is full and no data could be evicted. r?gerald
MozReview-Commit-ID: GWil57B0QBc
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -98,17 +98,17 @@ TrackBuffersManager::TrackBuffersManager
, mProcessedInput(0)
, mTaskQueue(aParentDecoder->GetDemuxer()->GetTaskQueue())
, mParentDecoder(new nsMainThreadPtrHolder<MediaSourceDecoder>(aParentDecoder, false /* strict */))
, mEnded(false)
, mVideoEvictionThreshold(Preferences::GetUint("media.mediasource.eviction_threshold.video",
100 * 1024 * 1024))
, mAudioEvictionThreshold(Preferences::GetUint("media.mediasource.eviction_threshold.audio",
30 * 1024 * 1024))
- , mEvictionOccurred(false)
+ , mEvictionState(EvictionState::NO_EVICTION_NEEDED)
, mMonitor("TrackBuffersManager")
{
MOZ_ASSERT(NS_IsMainThread(), "Must be instanciated on the main thread");
}
TrackBuffersManager::~TrackBuffersManager()
{
ShutdownDemuxers();
@@ -273,29 +273,33 @@ TrackBuffersManager::EvictData(const Tim
return EvictDataResult::BUFFER_FULL;
}
const int64_t toEvict = GetSize() + aSize - EvictionThreshold();
MSE_DEBUG("buffered=%lldkb, eviction threshold=%ukb, evict=%lldkb",
GetSize() / 1024, EvictionThreshold() / 1024, toEvict / 1024);
if (toEvict <= 0) {
+ mEvictionState = EvictionState::NO_EVICTION_NEEDED;
return EvictDataResult::NO_DATA_EVICTED;
}
if (toEvict <= 512*1024) {
// Don't bother evicting less than 512KB.
+ mEvictionState = EvictionState::NO_EVICTION_NEEDED;
return EvictDataResult::CANT_EVICT;
}
- if (mBufferFull && mEvictionOccurred) {
+ if (mBufferFull && mEvictionState == EvictionState::EVICTION_COMPLETED) {
return EvictDataResult::BUFFER_FULL;
}
MSE_DEBUG("Reaching our size limit, schedule eviction of %lld bytes", toEvict);
+ mEvictionState = EvictionState::EVICTION_NEEDED;
+
QueueTask(new EvictDataTask(aPlaybackTime, toEvict));
return EvictDataResult::NO_DATA_EVICTED;
}
TimeIntervals
TrackBuffersManager::Buffered()
{
@@ -406,16 +410,18 @@ TrackBuffersManager::EvictionThreshold()
}
void
TrackBuffersManager::DoEvictData(const TimeUnit& aPlaybackTime,
int64_t aSizeToEvict)
{
MOZ_ASSERT(OnTaskQueue());
+ mEvictionState = EvictionState::EVICTION_COMPLETED;
+
// Video is what takes the most space, only evict there if we have video.
const auto& track = HasVideo() ? mVideoTracks : mAudioTracks;
const auto& buffer = track.mBuffers.LastElement();
// Remove any data we've already played, or before the next sample to be
// demuxed whichever is lowest.
TimeUnit lowerLimit = std::min(track.mNextSampleTime, aPlaybackTime);
uint32_t lastKeyFrameIndex = 0;
int64_t toEvict = aSizeToEvict;
@@ -558,17 +564,16 @@ TrackBuffersManager::CodedFrameRemoval(T
// Update our reported total size.
mSizeSourceBuffer = mVideoTracks.mSizeBuffer + mAudioTracks.mSizeBuffer;
// 4. If buffer full flag equals true and this object is ready to accept more bytes, then set the buffer full flag to false.
if (mBufferFull && mSizeSourceBuffer < EvictionThreshold()) {
mBufferFull = false;
}
- mEvictionOccurred = true;
return dataRemoved;
}
void
TrackBuffersManager::UpdateBufferedRanges()
{
MonitorAutoLock mon(mMonitor);
@@ -1264,17 +1269,16 @@ TrackBuffersManager::CompleteCodedFrameP
// Update our reported total size.
mSizeSourceBuffer = mVideoTracks.mSizeBuffer + mAudioTracks.mSizeBuffer;
// Return to step 6.4 of Segment Parser Loop algorithm
// 4. If this SourceBuffer is full and cannot accept more media data, then set the buffer full flag to true.
if (mSizeSourceBuffer >= EvictionThreshold()) {
mBufferFull = true;
- mEvictionOccurred = false;
}
// 5. If the input buffer does not contain a complete media segment, then jump to the need more data step below.
if (mParser->MediaSegmentRange().IsEmpty()) {
ResolveProcessing(true, __func__);
return;
}
--- a/dom/media/mediasource/TrackBuffersManager.h
+++ b/dom/media/mediasource/TrackBuffersManager.h
@@ -430,17 +430,23 @@ private:
// Set to true if mediasource state changed to ended.
Atomic<bool> mEnded;
// Global size of this source buffer content.
Atomic<int64_t> mSizeSourceBuffer;
const int64_t mVideoEvictionThreshold;
const int64_t mAudioEvictionThreshold;
- Atomic<bool> mEvictionOccurred;
+ enum class EvictionState
+ {
+ NO_EVICTION_NEEDED,
+ EVICTION_NEEDED,
+ EVICTION_COMPLETED,
+ };
+ Atomic<EvictionState> mEvictionState;
// Monitor to protect following objects accessed across multipple threads.
mutable Monitor mMonitor;
// Stable audio and video track time ranges.
media::TimeIntervals mVideoBufferedRanges;
media::TimeIntervals mAudioBufferedRanges;
// MediaInfo of the first init segment read.
MediaInfo mInfo;