Bug 687972. Don't count streams whose channel has ended when looking to see if there's any non-suspended stream for a resource. r=cpearce
authorRobert O'Callahan <robert@ocallahan.org>
Thu, 01 Dec 2011 12:09:10 +1300
changeset 82686 4679da64ba71aae08b6578c075d3452b0eddfa43
parent 82685 72e787c04eb669b6c56858af8fe87eb49dd8a39d
child 82687 ab37c20227f8b146fd6a4c986a32ec98a143210e
push idunknown
push userunknown
push dateunknown
reviewerscpearce
bugs687972
milestone11.0a1
Bug 687972. Don't count streams whose channel has ended when looking to see if there's any non-suspended stream for a resource. r=cpearce
content/media/nsMediaCache.cpp
content/media/nsMediaCache.h
--- a/content/media/nsMediaCache.cpp
+++ b/content/media/nsMediaCache.cpp
@@ -1346,16 +1346,17 @@ nsMediaCache::Update()
     nsresult rv = NS_OK;
     switch (actions[i]) {
     case SEEK:
       LOG(PR_LOG_DEBUG, ("Stream %p CacheSeek to %lld (resume=%d)", stream,
            (long long)stream->mChannelOffset, stream->mCacheSuspended));
       rv = stream->mClient->CacheClientSeek(stream->mChannelOffset,
                                             stream->mCacheSuspended);
       stream->mCacheSuspended = false;
+      stream->mChannelEnded = false;
       break;
 
     case RESUME:
       LOG(PR_LOG_DEBUG, ("Stream %p Resumed", stream));
       rv = stream->mClient->CacheClientResume();
       stream->mCacheSuspended = false;
       break;
 
@@ -1849,16 +1850,18 @@ nsMediaCacheStream::NotifyDataEnded(nsre
         stream->mStreamLength = mChannelOffset;
       }
       NS_ASSERTION(!stream->mDidNotifyDataEnded, "Stream already ended!");
       stream->mDidNotifyDataEnded = true;
       stream->mNotifyDataEndedStatus = aStatus;
       stream->mClient->CacheClientNotifyDataEnded(aStatus);
     }
   }
+
+  mChannelEnded = true;
 }
 
 nsMediaCacheStream::~nsMediaCacheStream()
 {
   NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
   NS_ASSERTION(!mPinCount, "Unbalanced Pin");
 
   if (gMediaCache) {
@@ -1888,17 +1891,17 @@ nsMediaCacheStream::IsSeekable()
 }
 
 bool
 nsMediaCacheStream::AreAllStreamsForResourceSuspended()
 {
   ReentrantMonitorAutoEnter mon(gMediaCache->GetReentrantMonitor());
   nsMediaCache::ResourceStreamIterator iter(mResourceID);
   while (nsMediaCacheStream* stream = iter.Next()) {
-    if (!stream->mCacheSuspended)
+    if (!stream->mCacheSuspended && !stream->mChannelEnded)
       return false;
   }
   return true;
 }
 
 void
 nsMediaCacheStream::Close()
 {
@@ -2307,16 +2310,17 @@ nsMediaCacheStream::InitAsClone(nsMediaC
 
   mPrincipal = aOriginal->mPrincipal;
   mStreamLength = aOriginal->mStreamLength;
   mIsSeekable = aOriginal->mIsSeekable;
 
   // Cloned streams are initially suspended, since there is no channel open
   // initially for a clone.
   mCacheSuspended = true;
+  mChannelEnded = true;
 
   if (aOriginal->mDidNotifyDataEnded) {
     mNotifyDataEndedStatus = aOriginal->mNotifyDataEndedStatus;
     mDidNotifyDataEnded = true;
     mClient->CacheClientNotifyDataEnded(mNotifyDataEndedStatus);
   }
 
   for (PRUint32 i = 0; i < aOriginal->mBlocks.Length(); ++i) {
--- a/content/media/nsMediaCache.h
+++ b/content/media/nsMediaCache.h
@@ -224,17 +224,17 @@ public:
   };
 
   // aClient provides the underlying transport that cache will use to read
   // data for this stream.
   nsMediaCacheStream(nsMediaChannelStream* aClient)
     : mClient(aClient), mResourceID(0), mInitialized(false),
       mHasHadUpdate(false),
       mIsSeekable(false), mCacheSuspended(false),
-      mDidNotifyDataEnded(false),
+      mChannelEnded(false), mDidNotifyDataEnded(false),
       mUsingNullPrincipal(false),
       mChannelOffset(0), mStreamLength(-1),  
       mStreamOffset(0), mPlaybackBytesPerSecond(10000),
       mPinCount(0), mCurrentMode(MODE_PLAYBACK),
       mMetadataInPartialBlockBuffer(false),
       mClosed(false) {}
   ~nsMediaCacheStream();
 
@@ -347,17 +347,18 @@ public:
   // 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(PRUint32 aBytesPerSecond);
   // Returns the last set value of SetSeekable.
   bool IsSeekable();
 
-  // Returns true when all streams for this resource are suspended.
+  // 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.
   // This can fail when aWhence is NS_SEEK_END and no stream length
   // is known.
   nsresult Seek(PRInt32 aWhence, PRInt64 aOffset);
@@ -464,16 +465,18 @@ private:
   // only written on the main thread. 
 
   // The last reported seekability state for the underlying channel
   bool mIsSeekable;
   // True if the cache has suspended our channel because the cache is
   // full and the priority of the data that would be received is lower
   // than the priority of the data already in the cache
   bool mCacheSuspended;
+  // True if the channel ended and we haven't seeked it again.
+  bool mChannelEnded;
   // True if CacheClientNotifyDataEnded has been called for this stream.
   bool mDidNotifyDataEnded;
   // True if mPrincipal is a null principal because we saw data from
   // multiple origins
   bool mUsingNullPrincipal;
   // The offset where the next data from the channel will arrive
   PRInt64      mChannelOffset;
   // The reported or discovered length of the data, or -1 if nothing is