Changeset 102561 in webkit


Ignore:
Timestamp:
Dec 12, 2011 12:10:33 AM (12 years ago)
Author:
noel.gordon@gmail.com
Message:

WebPImageDecoder: Increase image/webp decoding performance 10-20%
https://bugs.webkit.org/show_bug.cgi?id=74263

Reviewed by Adam Barth.

Avoid copying data from the RGB buffer of decoded image output to the
backing pixel store. That is slow - costs 10% of the overall decoding
time at libwebp 0.1.2, and 20% at libwebp 0.1.3.

Instead, instruct the decoder to write the decoded pixels directly to
the backing pixel store.

No new tests. Covered by existing tests. No progressive decoding test
exists in DRT, see https://bugs.webkit.org/show_bug.cgi?id=74062

  • platform/image-decoders/webp/WEBPImageDecoder.cpp:

(outputMode): Define output pixel format. On little-endian machines,
output BGRA pixels to the backing store, for example.
(WebCore::WEBPImageDecoder::WEBPImageDecoder):
(WebCore::WEBPImageDecoder::decode):

  • platform/image-decoders/webp/WEBPImageDecoder.h:
Location:
trunk/Source/WebCore
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r102560 r102561  
     12011-12-12  Noel Gordon  <noel.gordon@gmail.com>
     2
     3        WebPImageDecoder: Increase image/webp decoding performance 10-20%
     4        https://bugs.webkit.org/show_bug.cgi?id=74263
     5
     6        Reviewed by Adam Barth.
     7
     8        Avoid copying data from the RGB buffer of decoded image output to the
     9        backing pixel store. That is slow - costs 10% of the overall decoding
     10        time at libwebp 0.1.2, and 20% at libwebp 0.1.3.
     11
     12        Instead, instruct the decoder to write the decoded pixels directly to
     13        the backing pixel store.
     14
     15        No new tests. Covered by existing tests. No progressive decoding test
     16        exists in DRT, see https://bugs.webkit.org/show_bug.cgi?id=74062
     17
     18        * platform/image-decoders/webp/WEBPImageDecoder.cpp:
     19        (outputMode):  Define output pixel format. On little-endian machines,
     20        output BGRA pixels to the backing store, for example.
     21        (WebCore::WEBPImageDecoder::WEBPImageDecoder):
     22        (WebCore::WEBPImageDecoder::decode):
     23        * platform/image-decoders/webp/WEBPImageDecoder.h:
     24
    1252011-12-11  Zoltan Herczeg  <zherczeg@webkit.org>
    226
  • trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp

    r102519 r102561  
    3434#include "webp/decode.h"
    3535
     36#if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN)
     37inline WEBP_CSP_MODE outputMode() { return MODE_RGBA; }
     38#else // LITTLE_ENDIAN, output BGRA pixels.
     39inline WEBP_CSP_MODE outputMode() { return MODE_BGRA; }
     40#endif
     41
    3642namespace WebCore {
    3743
     
    4046    : ImageDecoder(alphaOption, gammaAndColorProfileOption)
    4147    , m_decoder(0)
    42     , m_lastVisibleRow(0)
    4348{
    4449}
     
    7580}
    7681
    77 
    7882bool WEBPImageDecoder::decode(bool onlySize)
    7983{
    80     // Minimum number of bytes needed to ensure one can parse size information.
    81     static const size_t sizeOfHeader = 30;
    82     // Number of bytes per pixel.
    83     static const int bytesPerPixel = 3;
    84 
    8584    if (failed())
    8685        return false;
     
    9089
    9190    if (!ImageDecoder::isSizeAvailable()) {
    92         if (dataSize < sizeOfHeader)
     91        static const size_t imageHeaderSize = 30;
     92        if (dataSize < imageHeaderSize)
    9393            return false;
    9494        int width, height;
     
    102102    if (onlySize)
    103103        return true;
    104     int width = size().width();
    105     int height = size().height();
    106104
    107     bool allDataReceived = isAllDataReceived();
    108     int stride = width * bytesPerPixel;
    109105    ASSERT(!m_frameBufferCache.isEmpty());
    110106    ImageFrame& buffer = m_frameBufferCache[0];
     107    ASSERT(buffer.status() != ImageFrame::FrameComplete);
    111108
    112109    if (buffer.status() == ImageFrame::FrameEmpty) {
    113         if (!buffer.setSize(width, height))
     110        if (!buffer.setSize(size().width(), size().height()))
    114111            return setFailed();
    115         buffer.setStatus(allDataReceived ? ImageFrame::FrameComplete : ImageFrame::FramePartial);
    116         // FIXME: We currently hard code false below because libwebp doesn't support alpha yet.
    117         buffer.setHasAlpha(false);
     112        buffer.setStatus(ImageFrame::FramePartial);
     113        buffer.setHasAlpha(false); // FIXME: webp does not support alpha yet.
    118114        buffer.setOriginalFrameRect(IntRect(IntPoint(), size()));
    119         m_rgbOutput.resize(height * stride);
    120115    }
    121116
    122     int newLastVisibleRow = 0; // Last completed row.
    123     if (allDataReceived && !m_decoder) {
    124         if (!WebPDecodeRGBInto(dataBytes, dataSize, m_rgbOutput.data(), m_rgbOutput.size(), stride))
     117    if (!m_decoder) {
     118        int rowStride = size().width() * sizeof(ImageFrame::PixelData);
     119        uint8_t* output = reinterpret_cast<uint8_t*>(buffer.getAddr(0, 0));
     120        int outputSize = size().height() * rowStride;
     121        m_decoder = WebPINewRGB(outputMode(), output, outputSize, rowStride);
     122        if (!m_decoder)
    125123            return setFailed();
    126         newLastVisibleRow = height;
    127     } else {
    128         if (!m_decoder) {
    129             m_decoder = WebPINewRGB(MODE_RGB, m_rgbOutput.data(), m_rgbOutput.size(), stride);
    130             if (!m_decoder)
    131                 return setFailed();
    132         }
    133         const VP8StatusCode status = WebPIUpdate(m_decoder, dataBytes, dataSize);
    134         if (status != VP8_STATUS_OK && status != VP8_STATUS_SUSPENDED)
    135             return setFailed();
    136         if (!WebPIDecGetRGB(m_decoder, &newLastVisibleRow, 0, 0, 0))
    137             return false;
    138         ASSERT(newLastVisibleRow >= 0);
    139         ASSERT(newLastVisibleRow <= height);
    140124    }
    141125
    142     // FIXME: remove this data copy.
    143     for (int y = m_lastVisibleRow; y < newLastVisibleRow; ++y) {
    144         const uint8_t* const src = &m_rgbOutput[y * stride];
    145         for (int x = 0; x < width; ++x)
    146             buffer.setRGBA(x, y, src[bytesPerPixel * x + 0], src[bytesPerPixel * x + 1], src[bytesPerPixel * x + 2], 0xff);
     126    switch (WebPIUpdate(m_decoder, dataBytes, dataSize)) {
     127    case VP8_STATUS_OK:
     128        buffer.setStatus(ImageFrame::FrameComplete);
     129        WebPIDelete(m_decoder);
     130        m_decoder = 0;
     131        return true;
     132    case VP8_STATUS_SUSPENDED:
     133        return false;
     134    default:
     135        WebPIDelete(m_decoder);
     136        m_decoder = 0;
     137        return setFailed();
    147138    }
    148 
    149     m_lastVisibleRow = newLastVisibleRow;
    150     if (m_lastVisibleRow == height)
    151          buffer.setStatus(ImageFrame::FrameComplete);
    152     return m_lastVisibleRow == height;
    153139}
    154140
    155 }
     141} // namespace WebCore
    156142
    157143#endif
  • trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h

    r95901 r102561  
    3434#if USE(WEBP)
    3535
    36 // Forward declaration of libwebp's structure. Must be outside the WebCore scope.
    3736typedef struct WebPIDecoder WebPIDecoder;
    3837
     
    4342    WEBPImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption);
    4443    virtual ~WEBPImageDecoder();
     44
    4545    virtual String filenameExtension() const { return "vp8"; }
    4646    virtual bool isSizeAvailable();
     
    4848
    4949private:
    50     // Returns false in case of decoding failure.
    5150    bool decode(bool onlySize);
    5251
    53     WebPIDecoder* m_decoder; // This is only used when we want to decode() but not all data is available yet.
    54     int m_lastVisibleRow;
    55     Vector<uint8_t> m_rgbOutput;
     52    WebPIDecoder* m_decoder;
    5653};
    5754
Note: See TracChangeset for help on using the changeset viewer.