Title: [151957] trunk/Source/WebCore
Revision
151957
Author
[email protected]
Date
2013-06-25 01:44:38 -0700 (Tue, 25 Jun 2013)

Log Message

Checking if frame is complete and access duration doesn't need a decode
https://bugs.webkit.org/show_bug.cgi?id=116041

Reviewed by Allan Sandfeld Jensen.

This change is to avoid image decoding for these two operations:
1. frameIsCompleteAtIndex
2. frameDurationAtIndex
These two operations are moved to ImageDecoder interface and are now const
to prevent future regression.

We are now able to check if a frame is complete by parsing the entire GIF file
without decoding. This also provides information like frame duration such that
controller the animation doesn't require any decoding.

Based on the Blink patch by Hin-Chung Lam <[email protected]>
https://src.chromium.org/viewvc/blink?revision=149883&view=revision

* platform/graphics/BitmapImage.cpp:
(WebCore::BitmapImage::frameIsCompleteAtIndex):
(WebCore::BitmapImage::frameDurationAtIndex):
* platform/graphics/ImageSource.cpp:
(WebCore::ImageSource::frameDurationAtIndex):
(WebCore::ImageSource::frameHasAlphaAtIndex):
(WebCore::ImageSource::frameIsCompleteAtIndex):
* platform/graphics/ImageSource.h:
* platform/image-decoders/ImageDecoder.cpp:
(WebCore::ImageDecoder::frameHasAlphaAtIndex):
(WebCore::ImageDecoder::frameIsCompleteAtIndex):
* platform/image-decoders/ImageDecoder.h:
(WebCore::ImageDecoder::frameDurationAtIndex):
* platform/image-decoders/gif/GIFImageDecoder.cpp:
(WebCore::GIFImageDecoder::frameIsCompleteAtIndex):
(WebCore::GIFImageDecoder::frameDurationAtIndex):
(WebCore::GIFImageDecoder::haveDecodedRow):
(WebCore::GIFImageDecoder::gifComplete):
(WebCore::GIFImageDecoder::decode):
(WebCore::GIFImageDecoder::initFrameBuffer):
* platform/image-decoders/gif/GIFImageDecoder.h:
* platform/image-decoders/gif/GIFImageReader.h:
(GIFImageReader::frameContext):
(GIFImageReader::parseCompleted):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (151956 => 151957)


--- trunk/Source/WebCore/ChangeLog	2013-06-25 06:28:00 UTC (rev 151956)
+++ trunk/Source/WebCore/ChangeLog	2013-06-25 08:44:38 UTC (rev 151957)
@@ -1,3 +1,48 @@
+2013-06-25  Csaba Osztrogonác  <[email protected]>
+
+        Checking if frame is complete and access duration doesn't need a decode
+        https://bugs.webkit.org/show_bug.cgi?id=116041
+
+        Reviewed by Allan Sandfeld Jensen.
+
+        This change is to avoid image decoding for these two operations:
+        1. frameIsCompleteAtIndex
+        2. frameDurationAtIndex
+        These two operations are moved to ImageDecoder interface and are now const
+        to prevent future regression.
+
+        We are now able to check if a frame is complete by parsing the entire GIF file
+        without decoding. This also provides information like frame duration such that
+        controller the animation doesn't require any decoding.
+
+        Based on the Blink patch by Hin-Chung Lam <[email protected]>
+        https://src.chromium.org/viewvc/blink?revision=149883&view=revision
+
+        * platform/graphics/BitmapImage.cpp:
+        (WebCore::BitmapImage::frameIsCompleteAtIndex):
+        (WebCore::BitmapImage::frameDurationAtIndex):
+        * platform/graphics/ImageSource.cpp:
+        (WebCore::ImageSource::frameDurationAtIndex):
+        (WebCore::ImageSource::frameHasAlphaAtIndex):
+        (WebCore::ImageSource::frameIsCompleteAtIndex):
+        * platform/graphics/ImageSource.h:
+        * platform/image-decoders/ImageDecoder.cpp:
+        (WebCore::ImageDecoder::frameHasAlphaAtIndex):
+        (WebCore::ImageDecoder::frameIsCompleteAtIndex):
+        * platform/image-decoders/ImageDecoder.h:
+        (WebCore::ImageDecoder::frameDurationAtIndex):
+        * platform/image-decoders/gif/GIFImageDecoder.cpp:
+        (WebCore::GIFImageDecoder::frameIsCompleteAtIndex):
+        (WebCore::GIFImageDecoder::frameDurationAtIndex):
+        (WebCore::GIFImageDecoder::haveDecodedRow):
+        (WebCore::GIFImageDecoder::gifComplete):
+        (WebCore::GIFImageDecoder::decode):
+        (WebCore::GIFImageDecoder::initFrameBuffer):
+        * platform/image-decoders/gif/GIFImageDecoder.h:
+        * platform/image-decoders/gif/GIFImageReader.h:
+        (GIFImageReader::frameContext):
+        (GIFImageReader::parseCompleted):
+
 2013-06-24  Christophe Dumez  <[email protected]>
 
         Update AbstractWorker, Worker and SharedWorker to match the specification

Modified: trunk/Source/WebCore/platform/graphics/BitmapImage.cpp (151956 => 151957)


--- trunk/Source/WebCore/platform/graphics/BitmapImage.cpp	2013-06-25 06:28:00 UTC (rev 151956)
+++ trunk/Source/WebCore/platform/graphics/BitmapImage.cpp	2013-06-25 08:44:38 UTC (rev 151957)
@@ -305,16 +305,16 @@
 
 bool BitmapImage::frameIsCompleteAtIndex(size_t index)
 {
-    if (!ensureFrameIsCached(index))
-        return false;
-    return m_frames[index].m_isComplete;
+    if (index < m_frames.size() && m_frames[index].m_haveMetadata && m_frames[index].m_isComplete)
+        return true;
+    return m_source.frameIsCompleteAtIndex(index);
 }
 
 float BitmapImage::frameDurationAtIndex(size_t index)
 {
-    if (!ensureFrameIsCached(index))
-        return 0;
-    return m_frames[index].m_duration;
+    if (index < m_frames.size() && m_frames[index].m_haveMetadata)
+        return m_frames[index].m_duration;
+    return m_source.frameDurationAtIndex(index);
 }
 
 PassNativeImagePtr BitmapImage::nativeImageForCurrentFrame()

Modified: trunk/Source/WebCore/platform/graphics/ImageSource.cpp (151956 => 151957)


--- trunk/Source/WebCore/platform/graphics/ImageSource.cpp	2013-06-25 06:28:00 UTC (rev 151956)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.cpp	2013-06-25 08:44:38 UTC (rev 151957)
@@ -155,20 +155,16 @@
     return buffer->asNewNativeImage();
 }
 
-float ImageSource::frameDurationAtIndex(size_t index)
+float ImageSource::frameDurationAtIndex(size_t index) const
 {
     if (!m_decoder)
         return 0;
 
-    ImageFrame* buffer = m_decoder->frameBufferAtIndex(index);
-    if (!buffer || buffer->status() == ImageFrame::FrameEmpty)
-        return 0;
-
     // Many annoying ads specify a 0 duration to make an image flash as quickly as possible.
     // We follow Firefox's behavior and use a duration of 100 ms for any frames that specify
     // a duration of <= 10 ms. See <rdar://problem/7689300> and <http://webkit.org/b/36082>
     // for more information.
-    const float duration = buffer->duration() / 1000.0f;
+    const float duration = m_decoder->frameDurationAtIndex(index) / 1000.0f;
     if (duration < 0.011f)
         return 0.100f;
     return duration;
@@ -179,20 +175,14 @@
     return m_decoder ? m_decoder->orientation() : DefaultImageOrientation;
 }
 
-bool ImageSource::frameHasAlphaAtIndex(size_t index)
+bool ImageSource::frameHasAlphaAtIndex(size_t index) const
 {
-    if (!m_decoder)
-        return true;
-    return m_decoder->frameHasAlphaAtIndex(index);
+    return !m_decoder || m_decoder->frameHasAlphaAtIndex(index);
 }
 
-bool ImageSource::frameIsCompleteAtIndex(size_t index)
+bool ImageSource::frameIsCompleteAtIndex(size_t index) const
 {
-    if (!m_decoder)
-        return false;
-
-    ImageFrame* buffer = m_decoder->frameBufferAtIndex(index);
-    return buffer && buffer->status() == ImageFrame::FrameComplete;
+    return m_decoder && m_decoder->frameIsCompleteAtIndex(index);
 }
 
 unsigned ImageSource::frameBytesAtIndex(size_t index) const

Modified: trunk/Source/WebCore/platform/graphics/ImageSource.h (151956 => 151957)


--- trunk/Source/WebCore/platform/graphics/ImageSource.h	2013-06-25 06:28:00 UTC (rev 151956)
+++ trunk/Source/WebCore/platform/graphics/ImageSource.h	2013-06-25 08:44:38 UTC (rev 151957)
@@ -147,9 +147,9 @@
     // see comments on clear() above.
     PassNativeImagePtr createFrameAtIndex(size_t);
 
-    float frameDurationAtIndex(size_t);
-    bool frameHasAlphaAtIndex(size_t); // Whether or not the frame actually used any alpha.
-    bool frameIsCompleteAtIndex(size_t); // Whether or not the frame is completely decoded.
+    float frameDurationAtIndex(size_t) const;
+    bool frameHasAlphaAtIndex(size_t) const; // Whether or not the frame actually used any alpha.
+    bool frameIsCompleteAtIndex(size_t) const; // Whether or not the frame is completely decoded.
     ImageOrientation orientationAtIndex(size_t) const; // EXIF image orientation
 
     // Return the number of bytes in the decoded frame. If the frame is not yet

Modified: trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp (151956 => 151957)


--- trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp	2013-06-25 06:28:00 UTC (rev 151956)
+++ trunk/Source/WebCore/platform/graphics/cg/ImageSourceCG.cpp	2013-06-25 08:44:38 UTC (rev 151957)
@@ -312,7 +312,7 @@
     return maskedImage.leakRef();
 }
 
-bool ImageSource::frameIsCompleteAtIndex(size_t index)
+bool ImageSource::frameIsCompleteAtIndex(size_t index) const
 {
     ASSERT(frameCount());
 
@@ -332,7 +332,7 @@
     return frameStatus == kCGImageStatusComplete;
 }
 
-float ImageSource::frameDurationAtIndex(size_t index)
+float ImageSource::frameDurationAtIndex(size_t index) const
 {
     if (!initialized())
         return 0;
@@ -361,7 +361,7 @@
     return duration;
 }
 
-bool ImageSource::frameHasAlphaAtIndex(size_t index)
+bool ImageSource::frameHasAlphaAtIndex(size_t index) const
 {
     if (!m_decoder)
         return false; // FIXME: why doesn't this return true?

Modified: trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp (151956 => 151957)


--- trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp	2013-06-25 06:28:00 UTC (rev 151956)
+++ trunk/Source/WebCore/platform/image-decoders/ImageDecoder.cpp	2013-06-25 08:44:38 UTC (rev 151957)
@@ -267,13 +267,14 @@
 
 bool ImageDecoder::frameHasAlphaAtIndex(size_t index) const
 {
-    if (m_frameBufferCache.size() <= index)
-        return true;
-    if (m_frameBufferCache[index].status() == ImageFrame::FrameComplete)
-        return m_frameBufferCache[index].hasAlpha();
-    return true;
+    return !frameIsCompleteAtIndex(index) || m_frameBufferCache[index].hasAlpha();
 }
 
+bool ImageDecoder::frameIsCompleteAtIndex(size_t index) const
+{
+    return (index < m_frameBufferCache.size()) && (m_frameBufferCache[index].status() == ImageFrame::FrameComplete);
+}
+
 unsigned ImageDecoder::frameBytesAtIndex(size_t index) const
 {
     if (m_frameBufferCache.size() <= index)

Modified: trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h (151956 => 151957)


--- trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h	2013-06-25 06:28:00 UTC (rev 151956)
+++ trunk/Source/WebCore/platform/image-decoders/ImageDecoder.h	2013-06-25 08:44:38 UTC (rev 151957)
@@ -274,6 +274,12 @@
         // Make the best effort guess to check if the requested frame has alpha channel.
         virtual bool frameHasAlphaAtIndex(size_t) const;
 
+        // Whether or not the frame is fully received.
+        virtual bool frameIsCompleteAtIndex(size_t) const;
+
+        // Duration for displaying a frame in seconds. This method is used by animated images only.
+        virtual float frameDurationAtIndex(size_t) const { return 0; }
+
         // Number of bytes in the decoded frame requested. Return 0 if not yet decoded.
         virtual unsigned frameBytesAtIndex(size_t) const;
 

Modified: trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp (151956 => 151957)


--- trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp	2013-06-25 06:28:00 UTC (rev 151956)
+++ trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.cpp	2013-06-25 08:44:38 UTC (rev 151957)
@@ -127,6 +127,19 @@
     return &frame;
 }
 
+
+bool GIFImageDecoder::frameIsCompleteAtIndex(size_t index) const
+{
+    return m_reader && (index < m_reader->imagesCount()) && m_reader->frameContext(index)->isComplete();
+}
+
+float GIFImageDecoder::frameDurationAtIndex(size_t index) const
+{
+    return (m_reader && (index < m_reader->imagesCount()) && m_reader->frameContext(index)->isHeaderDefined())
+        ? m_reader->frameContext(index)->delayTime : 0;
+}
+
+
 bool GIFImageDecoder::setFailed()
 {
     m_reader.clear();
@@ -185,7 +198,7 @@
 
 bool GIFImageDecoder::haveDecodedRow(unsigned frameIndex, const Vector<unsigned char>& rowBuffer, size_t width, size_t rowNumber, unsigned repeatCount, bool writeTransparentPixels)
 {
-    const GIFFrameContext* frameContext = m_reader->frameContext();
+    const GIFFrameContext* frameContext = m_reader->frameContext(frameIndex);
     // The pixel data and coordinates supplied to us are relative to the frame's
     // origin within the entire image size, i.e.
     // (frameContext->xOffset, frameContext->yOffset). There is no guarantee
@@ -297,8 +310,6 @@
     // Cache the repetition count, which is now as authoritative as it's ever
     // going to be.
     repetitionCount();
-
-    m_reader.clear();
 }
 
 void GIFImageDecoder::decode(unsigned haltAtFrame, GIFQuery query)
@@ -335,16 +346,16 @@
         return;
     }
 
-    // It is also a fatal error if all data is received but we failed to decode
-    // all frames completely.
-    if (isAllDataReceived() && haltAtFrame >= m_frameBufferCache.size() && m_reader)
+    // It is also a fatal error if all data is received and we have decoded all
+    // frames available but the file is truncated.
+    if (haltAtFrame >= m_frameBufferCache.size() && isAllDataReceived() && m_reader && !m_reader->parseCompleted())
         setFailed();
 }
 
 bool GIFImageDecoder::initFrameBuffer(unsigned frameIndex)
 {
     // Initialize the frame rect in our buffer.
-    const GIFFrameContext* frameContext = m_reader->frameContext();
+    const GIFFrameContext* frameContext = m_reader->frameContext(frameIndex);
     IntRect frameRect(frameContext->xOffset, frameContext->yOffset, frameContext->width, frameContext->height);
 
     // Make sure the frameRect doesn't extend outside the buffer.

Modified: trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h (151956 => 151957)


--- trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h	2013-06-25 06:28:00 UTC (rev 151956)
+++ trunk/Source/WebCore/platform/image-decoders/gif/GIFImageDecoder.h	2013-06-25 08:44:38 UTC (rev 151957)
@@ -49,6 +49,8 @@
         virtual size_t frameCount();
         virtual int repetitionCount() const;
         virtual ImageFrame* frameBufferAtIndex(size_t index);
+        virtual bool frameIsCompleteAtIndex(size_t) const;
+        virtual float frameDurationAtIndex(size_t) const;
         // CAUTION: setFailed() deletes |m_reader|.  Be careful to avoid
         // accessing deleted memory, especially when calling this from inside
         // GIFImageReader!

Modified: trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h (151956 => 151957)


--- trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h	2013-06-25 06:28:00 UTC (rev 151956)
+++ trunk/Source/WebCore/platform/image-decoders/gif/GIFImageReader.h	2013-06-25 08:44:38 UTC (rev 151957)
@@ -282,11 +282,13 @@
         return frame->isLocalColormapDefined ? frame->localColormapSize : 0;
     }
 
-    const GIFFrameContext* frameContext() const
+    const GIFFrameContext* frameContext(size_t index) const
     {
-        return m_currentDecodingFrame < m_frames.size() ? m_frames[m_currentDecodingFrame].get() : 0;
+        return index < m_frames.size() ? m_frames[index].get() : 0;
     }
 
+    bool parseCompleted() const { return m_parseCompleted; }
+
 private:
     bool parse(size_t dataPosition, size_t len, bool parseSizeOnly);
     void setRemainingBytes(size_t);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to