Bug 1415069 - Add a member to ChannelMediaResource to remember seekability of the channel. r=bechen,gerald
authorJW Wang <jwwang@mozilla.com>
Tue, 07 Nov 2017 14:26:10 +0800
changeset 444180 2f059a9dbd9d0b76230f53a78bf29dfad1e56d06
parent 444179 b12b1f6beb496de17cfcaa8af70d7216853b2866
child 444181 798de42346d14e277a4f2de2189d4e1870eeef8e
push id1618
push userCallek@gmail.com
push dateThu, 11 Jan 2018 17:45:48 +0000
treeherdermozilla-release@882ca853e05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbechen, gerald
bugs1415069
milestone58.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 1415069 - Add a member to ChannelMediaResource to remember seekability of the channel. r=bechen,gerald So it doesn't need to call mCacheStream.IsTransportSeekable() which needs to take the lock and might block the main thread. MozReview-Commit-ID: 99QVcSxzjCz
dom/media/ChannelMediaResource.cpp
dom/media/ChannelMediaResource.h
dom/media/MediaCache.cpp
dom/media/MediaCache.h
--- a/dom/media/ChannelMediaResource.cpp
+++ b/dom/media/ChannelMediaResource.cpp
@@ -289,16 +289,17 @@ ChannelMediaResource::OnStartRequest(nsI
   }
 
   // Update principals before OnDataAvailable() putting the data in the cache.
   // This is important, we want to make sure all principals are updated before
   // any consumer can see the new data.
   UpdatePrincipal();
 
   mCacheStream.NotifyDataStarted(mLoadID, startOffset, seekable);
+  mIsTransportSeekable = seekable;
   mChannelStatistics.Start();
   mReopenOnError = false;
 
   mSuspendAgent.UpdateSuspendedStatusIfNeeded();
 
   // Fires an initial progress event.
   owner->DownloadProgressed();
 
@@ -313,17 +314,18 @@ ChannelMediaResource::OnStartRequest(nsI
   }
 
   return NS_OK;
 }
 
 bool
 ChannelMediaResource::IsTransportSeekable()
 {
-  return mCacheStream.IsTransportSeekable();
+  MOZ_ASSERT(NS_IsMainThread());
+  return mIsTransportSeekable;
 }
 
 nsresult
 ChannelMediaResource::ParseContentRangeHeader(nsIHttpChannel * aHttpChan,
                                               int64_t& aRangeStart,
                                               int64_t& aRangeEnd,
                                               int64_t& aRangeTotal)
 {
@@ -382,17 +384,17 @@ ChannelMediaResource::OnStopRequest(nsIR
   // --- even in situations where the server cut us off because we were
   // suspended. So we need to "reopen on error" in that case too. The only
   // cases where we don't need to reopen are when *we* closed the stream.
   // But don't reopen if we need to seek and we don't think we can... that would
   // cause us to just re-read the stream, which would be really bad.
   if (mReopenOnError && aStatus != NS_ERROR_PARSED_DATA_CACHED &&
       aStatus != NS_BINDING_ABORTED &&
       (GetOffset() == 0 || (GetLength() > 0 && GetOffset() != GetLength() &&
-                            mCacheStream.IsTransportSeekable()))) {
+                            mIsTransportSeekable))) {
     // If the stream did close normally, restart the channel if we're either
     // at the start of the resource, or if the server is seekable and we're
     // not at the end of stream. We don't restart the stream if we're at the
     // end because not all web servers handle this case consistently; see:
     // https://bugzilla.mozilla.org/show_bug.cgi?id=1373618#c36
     nsresult rv = Seek(GetOffset(), false);
     if (NS_SUCCEEDED(rv)) {
       return rv;
@@ -595,16 +597,18 @@ already_AddRefed<BaseMediaResource>
 ChannelMediaResource::CloneData(MediaResourceCallback* aCallback)
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   NS_ASSERTION(mCacheStream.IsAvailableForSharing(), "Stream can't be cloned");
 
   RefPtr<ChannelMediaResource> resource =
     new ChannelMediaResource(aCallback, nullptr, mURI, mChannelStatistics);
 
+  resource->mIsTransportSeekable = mIsTransportSeekable;
+
   // Initially the clone is treated as suspended by the cache, because
   // we don't have a channel. If the cache needs to read data from the clone
   // it will call CacheClientResume (or CacheClientSeek with aResume true)
   // which will recreate the channel. This way, if all of the media data
   // is already in the cache we don't create an unnecessary HTTP channel
   // and perform a useless HTTP transaction.
   resource->mCacheStream.InitAsClone(&mCacheStream);
   // mSuspendAgent.Suspend() accesses mCacheStream which is not ready
@@ -687,17 +691,17 @@ ChannelMediaResource::Suspend(bool aClos
     return;
   }
 
   MediaDecoderOwner* owner = mCallback->GetMediaOwner();
   MOZ_DIAGNOSTIC_ASSERT(owner);
   dom::HTMLMediaElement* element = owner->GetMediaElement();
   MOZ_DIAGNOSTIC_ASSERT(element);
 
-  if (mChannel && aCloseImmediately && mCacheStream.IsTransportSeekable()) {
+  if (mChannel && aCloseImmediately && mIsTransportSeekable) {
     CloseChannel();
     element->DownloadSuspended();
   }
 
   if (mSuspendAgent.Suspend()) {
     if (mChannel) {
       mChannelStatistics.Stop();
       element->DownloadSuspended();
--- a/dom/media/ChannelMediaResource.h
+++ b/dom/media/ChannelMediaResource.h
@@ -242,16 +242,18 @@ protected:
                                      const char* aFromSegment,
                                      uint32_t aToOffset,
                                      uint32_t aCount,
                                      uint32_t* aWriteCount);
 
   // Main thread access only
   // True if Close() has been called.
   bool mClosed = false;
+  // The last reported seekability state for the underlying channel
+  bool mIsTransportSeekable = false;
   RefPtr<Listener> mListener;
   // A mono-increasing integer to uniquely identify the channel we are loading.
   uint32_t mLoadID = 0;
   // Used by the cache to store the offset to seek to when we are resumed.
   // -1 means no seek initiated by the cache is waiting.
   int64_t mPendingSeekOffset = -1;
   // When this flag is set, if we get a network error we should silently
   // reopen the stream.
--- a/dom/media/MediaCache.cpp
+++ b/dom/media/MediaCache.cpp
@@ -2196,23 +2196,16 @@ MediaCacheStream::~MediaCacheStream()
       "MEDIACACHESTREAM_LENGTH_KB=%" PRIu32,
       this,
       lengthKb);
   Telemetry::Accumulate(Telemetry::HistogramID::MEDIACACHESTREAM_LENGTH_KB,
                         lengthKb);
 }
 
 bool
-MediaCacheStream::IsTransportSeekable()
-{
-  ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
-  return mIsTransportSeekable;
-}
-
-bool
 MediaCacheStream::AreAllStreamsForResourceSuspended()
 {
   ReentrantMonitorAutoEnter mon(mMediaCache->GetReentrantMonitor());
   MediaCache::ResourceStreamIterator iter(mMediaCache, mResourceID);
   // Look for a stream that's able to read the data we need
   int64_t dataOffset = -1;
   while (MediaCacheStream* stream = iter.Next()) {
     if (stream->mCacheSuspended || stream->mChannelEnded || stream->mClosed) {
--- a/dom/media/MediaCache.h
+++ b/dom/media/MediaCache.h
@@ -324,18 +324,16 @@ public:
   bool IsDataCachedToEndOfStream(int64_t aOffset);
   // The mode is initially MODE_PLAYBACK.
   void SetReadMode(ReadMode aMode);
   // This is the client's estimate of the playback rate assuming
   // the media plays continuously. The cache can't guess this itself
   // because it doesn't know when the decoder was paused, buffering, etc.
   // Do not pass zero.
   void SetPlaybackRate(uint32_t aBytesPerSecond);
-  // Returns the last set value of SetTransportSeekable.
-  bool IsTransportSeekable();
 
   // Returns true when all streams for this resource are suspended or their
   // channel has ended.
   bool AreAllStreamsForResourceSuspended();
 
   // These methods must be called on a different thread from the main
   // thread. They should always be called on the same thread for a given
   // stream.