Bug 1320684 - Start metadata decoding when the first data chunk has been received. r=tnikkel
authorAndrew Osmond <aosmond@mozilla.com>
Mon, 28 Nov 2016 08:42:55 -0500
changeset 331393 5186852360d6cf46ad5891b9e903fadcaa8c42c1
parent 331392 0f9e64504f9a7d063e4a096605dd59ce3a50891e
child 331394 28ffe691c195ba3fbb3ead33d28f8fd10f468b25
push id86232
push useraosmond@gmail.com
push dateFri, 27 Jan 2017 12:30:39 +0000
treeherdermozilla-inbound@5186852360d6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel
bugs1320684
milestone54.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 1320684 - Start metadata decoding when the first data chunk has been received. r=tnikkel
image/RasterImage.cpp
image/RasterImage.h
--- a/image/RasterImage.cpp
+++ b/image/RasterImage.cpp
@@ -79,17 +79,18 @@ RasterImage::RasterImage(ImageURL* aURI 
 #ifdef DEBUG
   mFramesNotified(0),
 #endif
   mSourceBuffer(WrapNotNull(new SourceBuffer())),
   mHasSize(false),
   mTransient(false),
   mSyncLoad(false),
   mDiscardable(false),
-  mHasSourceData(false),
+  mSomeSourceData(false),
+  mAllSourceData(false),
   mHasBeenDecoded(false),
   mPendingAnimation(false),
   mAnimationFinished(false),
   mWantFullDecode(false)
 {
 }
 
 //******************************************************************************
@@ -141,24 +142,16 @@ RasterImage::Init(const char* aMimeType,
   }
 
   // Lock this image's surfaces in the SurfaceCache if we're not discardable.
   if (!mDiscardable) {
     mLockCount++;
     SurfaceCache::LockImage(ImageKey(this));
   }
 
-  if (!mSyncLoad) {
-    // Create an async metadata decoder and verify we succeed in doing so.
-    nsresult rv = DecodeMetadata(DECODE_FLAGS_DEFAULT);
-    if (NS_FAILED(rv)) {
-      return NS_ERROR_FAILURE;
-    }
-  }
-
   // Mark us as initialized
   mInitialized = true;
 
   return NS_OK;
 }
 
 //******************************************************************************
 NS_IMETHODIMP_(void)
@@ -354,17 +347,17 @@ RasterImage::LookupFrame(const IntSize& 
   }
 
   MOZ_ASSERT(!result.Surface()->GetIsPaletted(),
              "Should not have a paletted frame");
 
   // Sync decoding guarantees that we got the frame, but if it's owned by an
   // async decoder that's currently running, the contents of the frame may not
   // be available yet. Make sure we get everything.
-  if (mHasSourceData && (aFlags & FLAG_SYNC_DECODE)) {
+  if (mAllSourceData && (aFlags & FLAG_SYNC_DECODE)) {
     result.Surface()->WaitUntilFinished();
   }
 
   // If we could have done some decoding in this function we need to check if
   // that decoding encountered an error and hence aborted the surface. We want
   // to avoid calling IsAborted if we weren't passed any sync decode flag because
   // IsAborted acquires the monitor for the imgFrame.
   if (aFlags & (FLAG_SYNC_DECODE | FLAG_SYNC_DECODE_IF_FAST) &&
@@ -869,17 +862,17 @@ RasterImage::GetImageSpaceInvalidationRe
 
 nsresult
 RasterImage::OnImageDataComplete(nsIRequest*, nsISupports*, nsresult aStatus,
                                  bool aLastPart)
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   // Record that we have all the data we're going to get now.
-  mHasSourceData = true;
+  mAllSourceData = true;
 
   // Let decoders know that there won't be any more data coming.
   mSourceBuffer->Complete(aStatus);
 
   // Allow a synchronous metadata decode if mSyncLoad was set, or if we're
   // running on a single thread (in which case waiting for the async metadata
   // decoder could delay this image's load event quite a bit), or if this image
   // is transient.
@@ -941,16 +934,24 @@ RasterImage::NotifyForLoadEvent(Progress
 nsresult
 RasterImage::OnImageDataAvailable(nsIRequest*,
                                   nsISupports*,
                                   nsIInputStream* aInputStream,
                                   uint64_t,
                                   uint32_t aCount)
 {
   nsresult rv = mSourceBuffer->AppendFromInputStream(aInputStream, aCount);
+  if (NS_SUCCEEDED(rv) && !mSomeSourceData) {
+    mSomeSourceData = true;
+    if (!mSyncLoad) {
+      // Create an async metadata decoder and verify we succeed in doing so.
+      rv = DecodeMetadata(DECODE_FLAGS_DEFAULT);
+    }
+  }
+
   if (NS_FAILED(rv)) {
     DoError();
   }
   return rv;
 }
 
 nsresult
 RasterImage::SetSourceSizeHint(uint32_t aSizeHint)
@@ -1024,17 +1025,17 @@ RasterImage::Discard()
   // Notify that we discarded.
   if (mProgressTracker) {
     mProgressTracker->OnDiscard();
   }
 }
 
 bool
 RasterImage::CanDiscard() {
-  return mHasSourceData &&       // ...have the source data...
+  return mAllSourceData &&       // ...have the source data...
          !mAnimationState;       // Can never discard animated images
 }
 
 NS_IMETHODIMP
 RasterImage::StartDecoding(uint32_t aFlags)
 {
   if (mError) {
     return NS_ERROR_FAILURE;
@@ -1199,17 +1200,17 @@ RasterImage::Decode(const IntSize& aSize
   // Make sure DecoderFactory was able to create a decoder successfully.
   if (!task) {
     return false;
   }
 
   mDecodeCount++;
 
   // We're ready to decode; start the decoder.
-  return LaunchDecodingTask(task, this, aFlags, mHasSourceData);
+  return LaunchDecodingTask(task, this, aFlags, mAllSourceData);
 }
 
 NS_IMETHODIMP
 RasterImage::DecodeMetadata(uint32_t aFlags)
 {
   if (mError) {
     return NS_ERROR_FAILURE;
   }
@@ -1222,17 +1223,17 @@ RasterImage::DecodeMetadata(uint32_t aFl
                                           mSourceBuffer);
 
   // Make sure DecoderFactory was able to create a decoder successfully.
   if (!task) {
     return NS_ERROR_FAILURE;
   }
 
   // We're ready to decode; start the decoder.
-  LaunchDecodingTask(task, this, aFlags, mHasSourceData);
+  LaunchDecodingTask(task, this, aFlags, mAllSourceData);
   return NS_OK;
 }
 
 void
 RasterImage::RecoverFromInvalidFrames(const IntSize& aSize, uint32_t aFlags)
 {
   if (!mHasSize) {
     return;
--- a/image/RasterImage.h
+++ b/image/RasterImage.h
@@ -318,17 +318,16 @@ private:
   // We would like to just check if we have a zero lock count, but we can't do
   // that for animated images because in EnsureAnimExists we lock the image and
   // never unlock so that animated images always have their lock count >= 1. In
   // that case we use our animation consumers count as a proxy for lock count.
   bool IsUnlocked() {
     return (mLockCount == 0 || (mAnimationState && mAnimationConsumers == 0));
   }
 
-
   //////////////////////////////////////////////////////////////////////////////
   // Decoding.
   //////////////////////////////////////////////////////////////////////////////
 
   /**
    * Creates and runs a decoder, either synchronously or asynchronously
    * according to @aFlags. Decodes at the provided target size @aSize, using
    * decode flags @aFlags. Performs a single-frame decode of this image unless
@@ -418,21 +417,22 @@ private: // data
 #ifdef DEBUG
   uint32_t                       mFramesNotified;
 #endif
 
   // The source data for this image.
   NotNull<RefPtr<SourceBuffer>>  mSourceBuffer;
 
   // Boolean flags (clustered together to conserve space):
-  bool                       mHasSize:1;       // Has SetSize() been called?
-  bool                       mTransient:1;     // Is the image short-lived?
-  bool                       mSyncLoad:1;      // Are we loading synchronously?
-  bool                       mDiscardable:1;   // Is container discardable?
-  bool                       mHasSourceData:1; // Do we have source data?
+  bool                       mHasSize:1;        // Has SetSize() been called?
+  bool                       mTransient:1;      // Is the image short-lived?
+  bool                       mSyncLoad:1;       // Are we loading synchronously?
+  bool                       mDiscardable:1;    // Is container discardable?
+  bool                       mSomeSourceData:1; // Do we have some source data?
+  bool                       mAllSourceData:1;  // Do we have all the source data?
   bool                       mHasBeenDecoded:1; // Decoded at least once?
 
   // Whether we're waiting to start animation. If we get a StartAnimation() call
   // but we don't yet have more than one frame, mPendingAnimation is set so that
   // we know to start animation later if/when we have more frames.
   bool                       mPendingAnimation:1;
 
   // Whether the animation can stop, due to running out