Changeset 102561 in webkit
- Timestamp:
- Dec 12, 2011 12:10:33 AM (12 years ago)
- Location:
- trunk/Source/WebCore
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebCore/ChangeLog
r102560 r102561 1 2011-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 1 25 2011-12-11 Zoltan Herczeg <zherczeg@webkit.org> 2 26 -
trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
r102519 r102561 34 34 #include "webp/decode.h" 35 35 36 #if CPU(BIG_ENDIAN) || CPU(MIDDLE_ENDIAN) 37 inline WEBP_CSP_MODE outputMode() { return MODE_RGBA; } 38 #else // LITTLE_ENDIAN, output BGRA pixels. 39 inline WEBP_CSP_MODE outputMode() { return MODE_BGRA; } 40 #endif 41 36 42 namespace WebCore { 37 43 … … 40 46 : ImageDecoder(alphaOption, gammaAndColorProfileOption) 41 47 , m_decoder(0) 42 , m_lastVisibleRow(0)43 48 { 44 49 } … … 75 80 } 76 81 77 78 82 bool WEBPImageDecoder::decode(bool onlySize) 79 83 { 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 85 84 if (failed()) 86 85 return false; … … 90 89 91 90 if (!ImageDecoder::isSizeAvailable()) { 92 if (dataSize < sizeOfHeader) 91 static const size_t imageHeaderSize = 30; 92 if (dataSize < imageHeaderSize) 93 93 return false; 94 94 int width, height; … … 102 102 if (onlySize) 103 103 return true; 104 int width = size().width();105 int height = size().height();106 104 107 bool allDataReceived = isAllDataReceived();108 int stride = width * bytesPerPixel;109 105 ASSERT(!m_frameBufferCache.isEmpty()); 110 106 ImageFrame& buffer = m_frameBufferCache[0]; 107 ASSERT(buffer.status() != ImageFrame::FrameComplete); 111 108 112 109 if (buffer.status() == ImageFrame::FrameEmpty) { 113 if (!buffer.setSize( width, height))110 if (!buffer.setSize(size().width(), size().height())) 114 111 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. 118 114 buffer.setOriginalFrameRect(IntRect(IntPoint(), size())); 119 m_rgbOutput.resize(height * stride);120 115 } 121 116 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) 125 123 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);140 124 } 141 125 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(); 147 138 } 148 149 m_lastVisibleRow = newLastVisibleRow;150 if (m_lastVisibleRow == height)151 buffer.setStatus(ImageFrame::FrameComplete);152 return m_lastVisibleRow == height;153 139 } 154 140 155 } 141 } // namespace WebCore 156 142 157 143 #endif -
trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.h
r95901 r102561 34 34 #if USE(WEBP) 35 35 36 // Forward declaration of libwebp's structure. Must be outside the WebCore scope.37 36 typedef struct WebPIDecoder WebPIDecoder; 38 37 … … 43 42 WEBPImageDecoder(ImageSource::AlphaOption, ImageSource::GammaAndColorProfileOption); 44 43 virtual ~WEBPImageDecoder(); 44 45 45 virtual String filenameExtension() const { return "vp8"; } 46 46 virtual bool isSizeAvailable(); … … 48 48 49 49 private: 50 // Returns false in case of decoding failure.51 50 bool decode(bool onlySize); 52 51 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; 56 53 }; 57 54
Note: See TracChangeset
for help on using the changeset viewer.