Changeset 223754 in webkit
- Timestamp:
- Oct 20, 2017 4:08:12 AM (7 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r223753 r223754 1 2017-10-20 Miguel Gomez <magomez@igalia.com> 2 3 [GTK][WPE] Fix review comments on WEBPImageDecoder 4 https://bugs.webkit.org/show_bug.cgi?id=178080 5 6 Reviewed by Said Abou-Hallawa. 7 8 Adjusted test duration. 9 10 * fast/images/animated-webp.html: 11 1 12 2017-10-20 Zan Dobersek <zdobersek@igalia.com> 2 13 -
trunk/LayoutTests/fast/images/animated-webp.html
r222841 r223754 13 13 if (window.testRunner) 14 14 testRunner.notifyDone(); 15 }, 500);15 }, 300); 16 16 } 17 17 </script> -
trunk/Source/WebCore/ChangeLog
r223752 r223754 1 2017-10-20 Miguel Gomez <magomez@igalia.com> 2 3 [GTK][WPE] Fix review comments on WEBPImageDecoder 4 https://bugs.webkit.org/show_bug.cgi?id=178080 5 6 Reviewed by Said Abou-Hallawa. 7 8 Properly free the demuxer in case of error, improve the code to detect the first 9 required frame to decode, fix the usage of the DecodingStatus and some styling 10 changes. 11 12 Covered by existent tests. 13 14 * platform/image-decoders/webp/WEBPImageDecoder.cpp: 15 (WebCore::webpFrameAtIndex): 16 (WebCore::WEBPImageDecoder::findFirstRequiredFrameToDecode): 17 (WebCore::WEBPImageDecoder::decode): 18 (WebCore::WEBPImageDecoder::decodeFrame): 19 (WebCore::WEBPImageDecoder::initFrameBuffer): 20 (WebCore::WEBPImageDecoder::clearFrameBufferCache): 21 1 22 2017-10-20 Basuke Suzuki <Basuke.Suzuki@sony.com> 2 23 -
trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp
r223728 r223754 34 34 namespace WebCore { 35 35 36 // Convenience function to improve code readability, as WebPDemuxGetFrame is +1 based. 37 bool webpFrameAtIndex(WebPDemuxer* demuxer, size_t index, WebPIterator* webpFrame) 38 { 39 return WebPDemuxGetFrame(demuxer, index + 1, webpFrame); 40 } 41 36 42 WEBPImageDecoder::WEBPImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption) 37 43 : ScalableImageDecoder(alphaOption, gammaAndColorProfileOption) … … 86 92 return 0; 87 93 88 // Check the most probable scenario first: the previous frame is complete, so we can decode the requested one. 89 if (m_frameBufferCache[frameIndex - 1].isComplete()) 90 return frameIndex; 91 92 // Check if the requested frame can be rendered without dependencies. This happens if the frame 93 // fills the whole area and doesn't have alpha. 94 WebPIterator webpFrame; 95 if (WebPDemuxGetFrame(demuxer, frameIndex + 1, &webpFrame)) { 94 // Go backwards and find the first complete frame. 95 size_t firstIncompleteFrame = frameIndex; 96 for (; firstIncompleteFrame; --firstIncompleteFrame) { 97 if (m_frameBufferCache[firstIncompleteFrame - 1].isComplete()) 98 break; 99 } 100 101 // Check if there are any independent frames between firstIncompleteFrame and frameIndex. 102 for (size_t firstIndependentFrame = frameIndex; firstIndependentFrame > firstIncompleteFrame ; --firstIndependentFrame) { 103 WebPIterator webpFrame; 104 if (!webpFrameAtIndex(demuxer, firstIndependentFrame, &webpFrame)) 105 continue; 106 96 107 IntRect frameRect(webpFrame.x_offset, webpFrame.y_offset, webpFrame.width, webpFrame.height); 97 if (frameRect.contains(IntRect(IntPoint(), size())) && !webpFrame.has_alpha) 98 return frameIndex; 99 } 100 101 // Go backwards in the list of frames, until we find the first complete frame or a frame that 102 // doesn't depend on previous frames. 103 for (size_t i = frameIndex - 1; i > 0; i--) { 104 // This frame is complete, so we can start the decoding from the next one. 105 if (m_frameBufferCache[i].isComplete()) 106 return i + 1; 107 108 if (WebPDemuxGetFrame(demuxer, i + 1, &webpFrame)) { 109 IntRect frameRect(webpFrame.x_offset, webpFrame.y_offset, webpFrame.width, webpFrame.height); 110 // This frame is not complete, but it fills the whole size and its disposal method is 111 // RestoreToBackground. This means that we will draw the next frame on an initially transparent 112 // buffer, so there's no dependency. We can start decoding from the next frame. 113 if (frameRect.contains(IntRect(IntPoint(), size())) && (m_frameBufferCache[i].disposalMethod() == ImageFrame::DisposalMethod::RestoreToBackground)) 114 return i + 1; 115 116 // This frame is not complete, but it fills the whole size and doesn't have alpha, 117 // so it doesn't depend on former frames. We can start decoding from here. 118 if (frameRect.contains(IntRect(IntPoint(), size())) && !webpFrame.has_alpha) 119 return i; 120 } 121 } 122 return 0; 108 if (!frameRect.contains({ { }, size() })) 109 continue; 110 111 // This frame covers the whole area and doesn't have alpha, so it can be rendered without 112 // dependencies. 113 if (!webpFrame.has_alpha) 114 return firstIndependentFrame; 115 116 // This frame covers the whole area and its disposalMethod is RestoreToBackground, which means 117 // that the next frame will be rendered on top of a transparent background, and can be decoded 118 // without dependencies. This can only be checked for frames prior to frameIndex. 119 if (firstIndependentFrame < frameIndex && m_frameBufferCache[firstIndependentFrame].disposalMethod() == ImageFrame::DisposalMethod::RestoreToBackground) 120 return firstIndependentFrame + 1; 121 } 122 123 return firstIncompleteFrame; 123 124 } 124 125 … … 144 145 // It is a fatal error if all data is received and we have decoded all frames available but the file is truncated. 145 146 if (frameIndex >= m_frameBufferCache.size() - 1 && allDataReceived && demuxer && demuxerState != WEBP_DEMUX_DONE) { 146 setFailed();147 return;148 }149 150 size_t startFrame = findFirstRequiredFrameToDecode(frameIndex, demuxer); 151 for (size_t i = startFrame; i <= frameIndex; i++)147 WebPDemuxDelete(demuxer); 148 setFailed(); 149 return; 150 } 151 152 for (size_t i = findFirstRequiredFrameToDecode(frameIndex, demuxer); i <= frameIndex; i++) 152 153 decodeFrame(i, demuxer); 153 154 … … 161 162 162 163 WebPIterator webpFrame; 163 if (! WebPDemuxGetFrame(demuxer, frameIndex + 1, &webpFrame))164 if (!webpFrameAtIndex(demuxer, frameIndex, &webpFrame)) 164 165 return; 165 166 … … 185 186 decoderBuffer.u.RGBA.size = decoderBuffer.u.RGBA.stride * webpFrame.height; 186 187 decoderBuffer.is_external_memory = 1; 187 decoderBuffer.u.RGBA.rgba = reinterpret_cast<uint8_t*>(fastMalloc(decoderBuffer.u.RGBA.size)); 188 std::unique_ptr<unsigned char[]> p(new uint8_t[decoderBuffer.u.RGBA.size]()); 189 decoderBuffer.u.RGBA.rgba = p.get(); 188 190 if (!decoderBuffer.u.RGBA.rgba) { 189 191 setFailed(); … … 193 195 WebPIDecoder* decoder = WebPINewDecoder(&decoderBuffer); 194 196 if (!decoder) { 195 fastFree(decoderBuffer.u.RGBA.rgba);196 197 setFailed(); 197 198 return; … … 206 207 if (!isAllDataReceived()) { 207 208 applyPostProcessing(frameIndex, decoder, decoderBuffer, blend); 209 buffer.setDecodingStatus(DecodingStatus::Partial); 208 210 break; 209 211 } … … 214 216 215 217 WebPIDelete(decoder); 216 fastFree(decoderBuffer.u.RGBA.rgba);217 218 } 218 219 … … 228 229 229 230 // Make sure the frameRect doesn't extend outside the buffer. 230 if (frameRect.maxX() > size().width()) 231 frameRect.setWidth(size().width() - webpFrame->x_offset); 232 if (frameRect.maxY() > size().height()) 233 frameRect.setHeight(size().height() - webpFrame->y_offset); 231 frameRect.intersect({ { }, size() }); 234 232 235 233 if (!frameIndex || !m_frameBufferCache[frameIndex - 1].backingStore()) { … … 255 253 buffer.setHasAlpha(webpFrame->has_alpha); 256 254 buffer.backingStore()->setFrameRect(frameRect); 257 buffer.setDecodingStatus(DecodingStatus::Partial);258 255 259 256 return true; … … 353 350 // 354 351 // In WEBP every frame depends on the previous one or none. That means that frames after clearBeforeFrame 355 // won't need any frame before them to render, so we can clear them all. If we find a buffer that is partial, 356 // don't delete it as it's being decoded. 352 // won't need any frame before them to render, so we can clear them all. 357 353 for (int i = clearBeforeFrame - 1; i >= 0; i--) { 358 354 ImageFrame& buffer = m_frameBufferCache[i]; 359 if ( buffer.isComplete() ||buffer.isInvalid())355 if (!buffer.isInvalid()) 360 356 buffer.clear(); 361 357 }
Note: See TracChangeset
for help on using the changeset viewer.