Bug 1000608 - Implement seeking on MediaSourceDecoder - r=kinetik
authorcajbir <cajbir.bugzilla@cd.pn>
Wed, 23 Apr 2014 19:46:00 +1200
changeset 180405 a336e673aaf5
parent 180404 1e21f55bcc9d
child 180406 f398aa51c65a
push id26663
push userryanvm@gmail.com
push dateSun, 27 Apr 2014 01:52:51 +0000
treeherdermozilla-central@fcf19894d9f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskinetik
bugs1000608
milestone31.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 1000608 - Implement seeking on MediaSourceDecoder - r=kinetik
content/media/mediasource/MediaSourceDecoder.cpp
--- a/content/media/mediasource/MediaSourceDecoder.cpp
+++ b/content/media/mediasource/MediaSourceDecoder.cpp
@@ -15,16 +15,17 @@
 #include "mozilla/dom/TimeRanges.h"
 #include "mozilla/mozalloc.h"
 #include "nsISupports.h"
 #include "nsIThread.h"
 #include "prlog.h"
 #include "MediaSource.h"
 #include "SubBufferDecoder.h"
 #include "SourceBufferResource.h"
+#include "SourceBufferList.h"
 #include "VideoUtils.h"
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gMediaSourceLog;
 #define MSE_DEBUG(...) PR_LOG(gMediaSourceLog, PR_LOG_DEBUG, (__VA_ARGS__))
 #else
 #define MSE_DEBUG(...)
 #endif
@@ -35,20 +36,21 @@ namespace dom {
 
 class TimeRanges;
 
 } // namespace dom
 
 class MediaSourceReader : public MediaDecoderReader
 {
 public:
-  MediaSourceReader(MediaSourceDecoder* aDecoder)
+  MediaSourceReader(MediaSourceDecoder* aDecoder, dom::MediaSource* aSource)
     : MediaDecoderReader(aDecoder)
     , mActiveVideoDecoder(-1)
     , mActiveAudioDecoder(-1)
+    , mMediaSource(aSource)
   {
   }
 
   nsresult Init(MediaDecoderReader* aCloneDonor) MOZ_OVERRIDE
   {
     // Although we technically don't implement anything here, we return NS_OK
     // so that when the state machine initializes and calls this function
     // we don't return an error code back to the media element.
@@ -120,34 +122,19 @@ public:
   }
 
   bool HasAudio() MOZ_OVERRIDE
   {
     return mInfo.HasAudio();
   }
 
   nsresult ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags) MOZ_OVERRIDE;
-
   nsresult Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
-                int64_t aCurrentTime) MOZ_OVERRIDE
-  {
-    return NS_ERROR_NOT_IMPLEMENTED;
-  }
-
-  nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime) MOZ_OVERRIDE
-  {
-    for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
-      nsRefPtr<dom::TimeRanges> r = new dom::TimeRanges();
-      mDecoders[i]->GetBuffered(r);
-      aBuffered->Add(r->GetStartTime(), r->GetEndTime());
-    }
-    aBuffered->Normalize();
-    return NS_OK;
-  }
-
+                int64_t aCurrentTime) MOZ_OVERRIDE;
+  nsresult GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime) MOZ_OVERRIDE;
   already_AddRefed<SubBufferDecoder> CreateSubDecoder(const nsACString& aType,
                                                       MediaSourceDecoder* aParentDecoder);
 
   void CallDecoderInitialization();
 
 private:
   bool SwitchVideoReaders(int64_t aTimeThreshold) {
     MOZ_ASSERT(mActiveVideoDecoder != -1);
@@ -193,16 +180,17 @@ private:
   nsresult EnqueueDecoderInitialization();
   void WaitForPendingDecoders();
 
   nsTArray<nsRefPtr<SubBufferDecoder>> mPendingDecoders;
   nsTArray<nsRefPtr<SubBufferDecoder>> mDecoders;
 
   int32_t mActiveVideoDecoder;
   int32_t mActiveAudioDecoder;
+  dom::MediaSource* mMediaSource;
 
   nsCOMPtr<nsIThread> mWorkQueue;
 };
 
 class MediaSourceStateMachine : public MediaDecoderStateMachine
 {
 public:
   MediaSourceStateMachine(MediaDecoder* aDecoder,
@@ -239,17 +227,17 @@ MediaSourceDecoder::Clone()
 {
   // TODO: Sort out cloning.
   return nullptr;
 }
 
 MediaDecoderStateMachine*
 MediaSourceDecoder::CreateStateMachine()
 {
-  return new MediaSourceStateMachine(this, new MediaSourceReader(this));
+  return new MediaSourceStateMachine(this, new MediaSourceReader(this, mMediaSource));
 }
 
 nsresult
 MediaSourceDecoder::Load(nsIStreamListener**, MediaDecoder*)
 {
   MOZ_ASSERT(!mDecoderStateMachine);
   mDecoderStateMachine = CreateStateMachine();
   if (!mDecoderStateMachine) {
@@ -423,16 +411,52 @@ MediaSourceReader::CreateSubDecoder(cons
   decoder->SetReader(reader.forget());
   mPendingDecoders.AppendElement(decoder);
   EnqueueDecoderInitialization();
   mDecoder->NotifyWaitingForResourcesStatusChanged();
   return decoder.forget();
 }
 
 nsresult
+MediaSourceReader::Seek(int64_t aTime, int64_t aStartTime, int64_t aEndTime,
+                        int64_t aCurrentTime)
+{
+  ResetDecode();
+
+  dom::SourceBufferList* sbl = mMediaSource->ActiveSourceBuffers();
+  if (sbl->ContainsTime (aTime / USECS_PER_S)) {
+    if (GetAudioReader()) {
+      nsresult rv = GetAudioReader()->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+    }
+    if (GetVideoReader()) {
+      nsresult rv = GetVideoReader()->Seek(aTime, aStartTime, aEndTime, aCurrentTime);
+      if (NS_FAILED(rv)) {
+        return rv;
+      }
+    }
+  }
+  return NS_OK;
+}
+
+nsresult
+MediaSourceReader::GetBuffered(dom::TimeRanges* aBuffered, int64_t aStartTime)
+{
+  for (uint32_t i = 0; i < mDecoders.Length(); ++i) {
+    nsRefPtr<dom::TimeRanges> r = new dom::TimeRanges();
+    mDecoders[i]->GetBuffered(r);
+    aBuffered->Add(r->GetStartTime(), r->GetEndTime());
+  }
+  aBuffered->Normalize();
+  return NS_OK;
+}
+
+nsresult
 MediaSourceReader::ReadMetadata(MediaInfo* aInfo, MetadataTags** aTags)
 {
   mDecoder->SetMediaSeekable(true);
   mDecoder->SetTransportSeekable(false);
 
   MSE_DEBUG("%p: MSR::ReadMetadata pending=%u", this, mPendingDecoders.Length());
 
   WaitForPendingDecoders();