Bug 1144617: Part1. Add MediaResource::IsLiveStream() API. r=cpearce
authorJean-Yves Avenard <jyavenard@mozilla.com>
Mon, 23 Mar 2015 21:08:05 +1100
changeset 235035 5a679809898571a7bdbaeeb278fd4f75a259fe3b
parent 235034 2ee1fb53c59c8f434075ac66d55d8d982ad61924
child 235036 6604e8d39fc671b500736ef8c6a891e1a1e70d3a
push id57309
push userjyavenard@mozilla.com
push dateMon, 23 Mar 2015 10:09:49 +0000
treeherdermozilla-inbound@0046e9225bbd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1144617
milestone39.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 1144617: Part1. Add MediaResource::IsLiveStream() API. r=cpearce We can't just rely on the MediaResource size to be -1 with MSE. It needs a dedicated method.
dom/media/MediaDecoderStateMachine.cpp
dom/media/MediaResource.h
dom/media/mediasource/MediaSourceDecoder.cpp
dom/media/mediasource/MediaSourceResource.h
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -2527,17 +2527,17 @@ MediaDecoderStateMachine::SeekCompleted(
   mPlayDuration = newCurrentTime - mStartTime;
 
   mDecoder->StartProgressUpdates();
 
   // Change state to DECODING or COMPLETED now. SeekingStopped will
   // call MediaDecoderStateMachine::Seek to reset our state to SEEKING
   // if we need to seek again.
 
-  bool isLiveStream = mDecoder->GetResource()->GetLength() == -1;
+  bool isLiveStream = mDecoder->GetResource()->IsLiveStream();
   if (mPendingSeek.Exists()) {
     // A new seek target came in while we were processing the old one. No rest
     // for the seeking.
     DECODER_LOG("A new seek came along while we were finishing the old one - staying in SEEKING");
     SetState(DECODER_STATE_SEEKING);
   } else if (GetMediaTime() == mEndTime && !isLiveStream) {
     // Seeked to end of media, move to COMPLETED state. Note we don't do
     // this if we're playing a live stream, since the end of media will advance
@@ -2735,17 +2735,17 @@ nsresult MediaDecoderStateMachine::RunSt
       TimeStamp now = TimeStamp::Now();
       NS_ASSERTION(!mBufferingStart.IsNull(), "Must know buffering start time.");
 
       // With buffering heuristics we will remain in the buffering state if
       // we've not decoded enough data to begin playback, or if we've not
       // downloaded a reasonable amount of data inside our buffering time.
       if (mReader->UseBufferingHeuristics()) {
         TimeDuration elapsed = now - mBufferingStart;
-        bool isLiveStream = resource->GetLength() == -1;
+        bool isLiveStream = resource->IsLiveStream();
         if ((isLiveStream || !mDecoder->CanPlayThrough()) &&
               elapsed < TimeDuration::FromSeconds(mBufferingWait * mPlaybackRate) &&
               (mQuickBuffering ? HasLowDecodedData(mQuickBufferingLowDataThresholdUsecs)
                                : HasLowUndecodedData(mBufferingWait * USECS_PER_S)) &&
               mDecoder->IsExpectingMoreData())
         {
           DECODER_LOG("Buffering: wait %ds, timeout in %.3lfs %s",
                       mBufferingWait, mBufferingWait - elapsed.ToSeconds(),
--- a/dom/media/MediaResource.h
+++ b/dom/media/MediaResource.h
@@ -408,16 +408,22 @@ public:
     return nullptr;
   }
 
   // Return true if the stream is a live stream
   virtual bool IsRealTime() {
     return false;
   }
 
+  // Returns true if the resource is a live stream.
+  virtual bool IsLiveStream()
+  {
+    return GetLength() == -1;
+  }
+
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const {
     return 0;
   }
 
   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const {
     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   }
 
--- a/dom/media/mediasource/MediaSourceDecoder.cpp
+++ b/dom/media/mediasource/MediaSourceDecoder.cpp
@@ -154,16 +154,17 @@ MediaSourceDecoder::OnTrackBufferConfigu
   MOZ_ASSERT(mReader);
   mReader->OnTrackBufferConfigured(aTrackBuffer, aInfo);
 }
 
 void
 MediaSourceDecoder::Ended(bool aEnded)
 {
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
+  static_cast<MediaSourceResource*>(GetResource())->SetEnded(aEnded);
   mReader->Ended(aEnded);
   mon.NotifyAll();
 }
 
 bool
 MediaSourceDecoder::IsExpectingMoreData()
 {
   ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
--- a/dom/media/mediasource/MediaSourceResource.h
+++ b/dom/media/mediasource/MediaSourceResource.h
@@ -3,16 +3,17 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef MOZILLA_MEDIASOURCERESOURCE_H_
 #define MOZILLA_MEDIASOURCERESOURCE_H_
 
 #include "MediaResource.h"
+#include "mozilla/Monitor.h"
 #include "prlog.h"
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* GetMediaSourceLog();
 
 #define MSE_DEBUG(arg, ...) PR_LOG(GetMediaSourceLog(), PR_LOG_DEBUG, ("MediaSourceResource(%p:%s)::%s: " arg, this, mType.get(), __func__, ##__VA_ARGS__))
 #else
 #define MSE_DEBUG(...)
@@ -21,17 +22,20 @@ extern PRLogModuleInfo* GetMediaSourceLo
 #define UNIMPLEMENTED() MSE_DEBUG("UNIMPLEMENTED FUNCTION at %s:%d", __FILE__, __LINE__)
 
 namespace mozilla {
 
 class MediaSourceResource final : public MediaResource
 {
 public:
   explicit MediaSourceResource(nsIPrincipal* aPrincipal = nullptr)
-    : mPrincipal(aPrincipal) {}
+    : mPrincipal(aPrincipal)
+    , mMonitor("MediaSourceResource")
+    , mEnded(false)
+    {}
 
   virtual nsresult Close() override { return NS_OK; }
   virtual void Suspend(bool aCloseImmediately) override { UNIMPLEMENTED(); }
   virtual void Resume() override { UNIMPLEMENTED(); }
   virtual bool CanClone() override { UNIMPLEMENTED(); return false; }
   virtual already_AddRefed<MediaResource> CloneData(MediaDecoder* aDecoder) override { UNIMPLEMENTED(); return nullptr; }
   virtual void SetReadMode(MediaCacheStream::ReadMode aMode) override { UNIMPLEMENTED(); }
   virtual void SetPlaybackRate(uint32_t aBytesPerSecond) override  { UNIMPLEMENTED(); }
@@ -61,32 +65,45 @@ public:
     UNIMPLEMENTED();
     aRanges.AppendElement(MediaByteRange(0, GetLength()));
     return NS_OK;
   }
 
   virtual bool IsTransportSeekable() override { return true; }
   virtual const nsCString& GetContentType() const override { return mType; }
 
+  virtual bool IsLiveStream() override
+  {
+    MonitorAutoLock mon(mMonitor);
+    return !mEnded;
+  }
+  void SetEnded(bool aEnded)
+  {
+    MonitorAutoLock mon(mMonitor);
+    mEnded = aEnded;
+  }
+
 private:
   virtual size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf) const override
   {
     size_t size = MediaResource::SizeOfExcludingThis(aMallocSizeOf);
     size += mType.SizeOfExcludingThisIfUnshared(aMallocSizeOf);
 
     return size;
   }
 
   virtual size_t SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const override
   {
     return aMallocSizeOf(this) + SizeOfExcludingThis(aMallocSizeOf);
   }
 
   nsRefPtr<nsIPrincipal> mPrincipal;
   const nsCString mType;
+  Monitor mMonitor;
+  bool mEnded; // protected by mMonitor
 };
 
 } // namespace mozilla
 
 #undef MSE_DEBUG
 #undef UNIMPLEMENTED
 
 #endif /* MOZILLA_MEDIASOURCERESOURCE_H_ */