Bug 1118123: Update mediasource duration following sourcebuffer::appendBuffer. r=cajbir
authorJean-Yves Avenard <jyavenard@mozilla.com>
Fri, 09 Jan 2015 12:34:41 +1100
changeset 248670 4cd36b909eef9df1829df8325c42d13f7aa03414
parent 248669 a74e49e232f937764b73b2038cfa90030bacbe3b
child 248671 f56f0268eb5b1f60eb21178f038c50fe0f0e09e6
push id4489
push userraliiev@mozilla.com
push dateMon, 23 Feb 2015 15:17:55 +0000
treeherdermozilla-beta@fd7c3dc24146 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscajbir
bugs1118123
milestone37.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 1118123: Update mediasource duration following sourcebuffer::appendBuffer. r=cajbir
dom/media/mediasource/MediaSource.cpp
dom/media/mediasource/MediaSource.h
dom/media/mediasource/SourceBuffer.cpp
dom/media/mediasource/SourceBuffer.h
--- a/dom/media/mediasource/MediaSource.cpp
+++ b/dom/media/mediasource/MediaSource.cpp
@@ -173,26 +173,34 @@ MediaSource::Duration()
   MOZ_ASSERT(mDecoder);
   return mDecoder->GetMediaSourceDuration();
 }
 
 void
 MediaSource::SetDuration(double aDuration, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
-  MSE_API("MediaSource(%p)::SetDuration(aDuration=%f)", this, aDuration);
+  MSE_API("MediaSource(%p)::SetDuration(aDuration=%f, ErrorResult)", this, aDuration);
   if (aDuration < 0 || IsNaN(aDuration)) {
     aRv.Throw(NS_ERROR_DOM_INVALID_ACCESS_ERR);
     return;
   }
   if (mReadyState != MediaSourceReadyState::Open ||
       mSourceBuffers->AnyUpdating()) {
     aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
     return;
   }
+  SetDuration(aDuration);
+}
+
+void
+MediaSource::SetDuration(double aDuration)
+{
+  MOZ_ASSERT(NS_IsMainThread());
+  MSE_API("MediaSource(%p)::SetDuration(aDuration=%f)", this, aDuration);
   mDecoder->SetMediaSourceDuration(aDuration);
 }
 
 already_AddRefed<SourceBuffer>
 MediaSource::AddSourceBuffer(const nsAString& aType, ErrorResult& aRv)
 {
   MOZ_ASSERT(NS_IsMainThread());
   nsresult rv = mozilla::IsTypeSupported(aType);
--- a/dom/media/mediasource/MediaSource.h
+++ b/dom/media/mediasource/MediaSource.h
@@ -108,29 +108,34 @@ public:
   // aPath must exist.  Debug only, invoke from your favourite debugger.
   void Dump(const char* aPath);
 #endif
 
 private:
   // MediaSourceDecoder uses DurationChange to set the duration
   // without hitting the checks in SetDuration.
   friend class mozilla::MediaSourceDecoder;
+  // SourceBuffer uses SetDuration
+  friend class mozilla::dom::SourceBuffer;
 
   ~MediaSource();
 
   explicit MediaSource(nsPIDOMWindow* aWindow);
 
   friend class AsyncEventRunner<MediaSource>;
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
 
   void DurationChange(double aOldDuration, double aNewDuration);
 
   void InitializationEvent();
 
+  // SetDuration with no checks.
+  void SetDuration(double aDuration);
+
   nsRefPtr<SourceBufferList> mSourceBuffers;
   nsRefPtr<SourceBufferList> mActiveSourceBuffers;
 
   nsRefPtr<MediaSourceDecoder> mDecoder;
   // Ensures the media element remains alive to dispatch progress and
   // durationchanged events.
   nsRefPtr<HTMLMediaElement> mMediaElement;
 
--- a/dom/media/mediasource/SourceBuffer.cpp
+++ b/dom/media/mediasource/SourceBuffer.cpp
@@ -322,16 +322,26 @@ SourceBuffer::AbortUpdating()
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(mUpdating);
   mUpdating = false;
   QueueAsyncSimpleEvent("abort");
   QueueAsyncSimpleEvent("updateend");
 }
 
 void
+SourceBuffer::CheckEndTime()
+{
+  // Check if we need to update mMediaSource duration
+  double endTime = GetBufferedEnd();
+  if (endTime > mMediaSource->Duration()) {
+    mMediaSource->SetDuration(endTime);
+  }
+}
+
+void
 SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv)
 {
   MSE_DEBUG("SourceBuffer(%p)::AppendData(aLength=%u)", this, aLength);
   if (!PrepareAppend(aRv)) {
     return;
   }
   StartUpdating();
 
@@ -344,16 +354,18 @@ SourceBuffer::AppendData(const uint8_t* 
     aRv.Throw(NS_ERROR_FAILURE);
     return;
   }
 
   if (mTrackBuffer->HasInitSegment()) {
     mMediaSource->QueueInitializationEvent();
   }
 
+  CheckEndTime();
+
   // Run the final step of the buffer append algorithm asynchronously to
   // ensure the SourceBuffer's updating flag transition behaves as required
   // by the spec.
   nsCOMPtr<nsIRunnable> event = NS_NewRunnableMethod(this, &SourceBuffer::StopUpdating);
   NS_DispatchToMainThread(event);
 }
 
 bool
--- a/dom/media/mediasource/SourceBuffer.h
+++ b/dom/media/mediasource/SourceBuffer.h
@@ -122,16 +122,21 @@ private:
   void DispatchSimpleEvent(const char* aName);
   void QueueAsyncSimpleEvent(const char* aName);
 
   // Update mUpdating and fire the appropriate events.
   void StartUpdating();
   void StopUpdating();
   void AbortUpdating();
 
+  // If the media segment contains data beyond the current duration,
+  // then run the duration change algorithm with new duration set to the
+  // maximum of the current duration and the group end timestamp.
+  void CheckEndTime();
+
   // Shared implementation of AppendBuffer overloads.
   void AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aRv);
 
   // Implements the "Prepare Append Algorithm".  Returns true if the append
   // may continue, or false (with aRv set) on error.
   bool PrepareAppend(ErrorResult& aRv);
 
   nsRefPtr<MediaSource> mMediaSource;