Bug 1133625: Return an error when attempting to append too much data. r=cajbir
authorJean-Yves Avenard <jyavenard@mozilla.com>
Fri, 20 Feb 2015 14:19:13 +1300
changeset 229948 661dcf41cef9a2acbb6b4b2dc4af627c750a4b56
parent 229947 25e29e6871e6ee7ed8180d779b5557abc3c972f5
child 229949 af39fc4994cc2c06cce3f11d582b17cd3195cfbb
push id55849
push userjyavenard@mozilla.com
push dateFri, 20 Feb 2015 01:20:02 +0000
treeherdermozilla-inbound@fb6b682a464e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscajbir
bugs1133625
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1133625: Return an error when attempting to append too much data. r=cajbir Implement part 6 of Prepare Append Algorithm: http://w3c.github.io/media-source/#sourcebuffer-prepare-append "If the buffer full flag equals true, then throw a QuotaExceededError exception and abort these step."
dom/media/mediasource/SourceBuffer.cpp
dom/media/mediasource/TrackBuffer.cpp
dom/media/mediasource/TrackBuffer.h
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -554,16 +554,25 @@ SourceBuffer::PrepareAppend(const uint8_
     MSE_DEBUG("AppendData Evict; current buffered start=%f",
               GetBufferedStart());
 
     // We notify that we've evicted from the time range 0 through to
     // the current start point.
     mMediaSource->NotifyEvicted(0.0, newBufferStartTime);
   }
 
+  // See if we have enough free space to append our new data.
+  // As we can only evict once we have playable data, we must give a chance
+  // to the DASH player to provide a complete media segment.
+  if ((mTrackBuffer->GetSize() > mEvictionThreshold - aLength) &&
+      !mTrackBuffer->HasOnlyIncompleteMedia()) {
+    aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
+    return nullptr;
+  }
+
   nsRefPtr<LargeDataBuffer> data = new LargeDataBuffer();
   if (!data->AppendElements(aData, aLength)) {
     aRv.Throw(NS_ERROR_DOM_QUOTA_EXCEEDED_ERR);
     return nullptr;
   }
   // TODO: Test buffer full flag.
   return data.forget();
 }
--- a/dom/media/mediasource/TrackBuffer.cpp
+++ b/dom/media/mediasource/TrackBuffer.cpp
@@ -301,20 +301,17 @@ TrackBuffer::EvictData(double aPlaybackT
 {
   MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
 
   if (!mCurrentDecoder) {
     return false;
   }
 
-  int64_t totalSize = 0;
-  for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
-    totalSize += mDecoders[i]->GetResource()->GetSize();
-  }
+  int64_t totalSize = GetSize();
 
   int64_t toEvict = totalSize - aThreshold;
   if (toEvict <= 0 || mInitializedDecoders.IsEmpty()) {
     return false;
   }
 
   // Get a list of initialized decoders.
   nsTArray<SourceBufferDecoder*> decoders;
@@ -444,16 +441,37 @@ TrackBuffer::RemoveEmptyDecoders(nsTArra
         buffered->GetStartTime() < 0.0 ||
         buffered->GetEndTime() < 0.0) {
       MSE_DEBUG("remove empty decoders=%d", i);
       RemoveDecoder(aDecoders[i]);
     }
   }
 }
 
+int64_t
+TrackBuffer::GetSize()
+{
+  int64_t totalSize = 0;
+  for (uint32_t i = 0; i < mInitializedDecoders.Length(); ++i) {
+    totalSize += mInitializedDecoders[i]->GetResource()->GetSize();
+  }
+  return totalSize;
+}
+
+bool
+TrackBuffer::HasOnlyIncompleteMedia()
+{
+  if (!mCurrentDecoder) {
+    return false;
+  }
+  nsRefPtr<dom::TimeRanges> buffered = new dom::TimeRanges();
+  mCurrentDecoder->GetBuffered(buffered);
+  return mCurrentDecoder->GetResource()->GetSize() && !buffered->Length();
+}
+
 void
 TrackBuffer::EvictBefore(double aTime)
 {
   MOZ_ASSERT(NS_IsMainThread());
   ReentrantMonitorAutoEnter mon(mParentDecoder->GetReentrantMonitor());
   for (uint32_t i = 0; i < mInitializedDecoders.Length(); ++i) {
     int64_t endOffset = mInitializedDecoders[i]->ConvertToByteOffset(aTime);
     if (endOffset > 0) {
--- a/dom/media/mediasource/TrackBuffer.h
+++ b/dom/media/mediasource/TrackBuffer.h
@@ -99,16 +99,23 @@ public:
   // Implementation is only partial, we can only trim a buffer.
   // Returns true if data was evicted.
   // Times are in microseconds.
   bool RangeRemoval(int64_t aStart, int64_t aEnd);
 
   // Abort any pending appendBuffer by rejecting any pending promises.
   void AbortAppendData();
 
+  // Return the size used by all decoders managed by this TrackBuffer.
+  int64_t GetSize();
+
+  // Return true if we have a partial media segment being appended that is
+  // currently not playable.
+  bool HasOnlyIncompleteMedia();
+
 #ifdef MOZ_EME
   nsresult SetCDMProxy(CDMProxy* aProxy);
 #endif
 
 #if defined(DEBUG)
   void Dump(const char* aPath);
 #endif