Bug 1301307: [MSE] Throw error when sourcebuffer is full and no data could be evicted. r?gerald draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Thu, 08 Sep 2016 19:58:32 +1000
changeset 411608 e58570d948fab9cdc77afd75c7233342b2544299
parent 411607 a331331e839c736c297b00ccf56f2618af2319b2
child 411663 f61c1fb7bf1e3884a5d44b5dccadcefb2340e637
push id28938
push userbmo:jyavenard@mozilla.com
push dateThu, 08 Sep 2016 09:59:26 +0000
reviewersgerald
bugs1301307
milestone51.0a1
Bug 1301307: [MSE] Throw error when sourcebuffer is full and no data could be evicted. r?gerald MozReview-Commit-ID: GWil57B0QBc
dom/media/mediasource/TrackBuffersManager.cpp
dom/media/mediasource/TrackBuffersManager.h
--- 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;