Changeset 223754 in webkit


Ignore:
Timestamp:
Oct 20, 2017 4:08:12 AM (7 years ago)
Author:
magomez@igalia.com
Message:

[GTK][WPE] Fix review comments on WEBPImageDecoder
https://bugs.webkit.org/show_bug.cgi?id=178080

Reviewed by Said Abou-Hallawa.

Source/WebCore:

Properly free the demuxer in case of error, improve the code to detect the first
required frame to decode, fix the usage of the DecodingStatus and some styling
changes.

Covered by existent tests.

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

(WebCore::webpFrameAtIndex):
(WebCore::WEBPImageDecoder::findFirstRequiredFrameToDecode):
(WebCore::WEBPImageDecoder::decode):
(WebCore::WEBPImageDecoder::decodeFrame):
(WebCore::WEBPImageDecoder::initFrameBuffer):
(WebCore::WEBPImageDecoder::clearFrameBufferCache):

LayoutTests:

Adjusted test duration.

  • fast/images/animated-webp.html:
Location:
trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r223753 r223754  
     12017-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
    1122017-10-20  Zan Dobersek  <zdobersek@igalia.com>
    213
  • trunk/LayoutTests/fast/images/animated-webp.html

    r222841 r223754  
    1313            if (window.testRunner)
    1414                testRunner.notifyDone();
    15         }, 500);
     15        }, 300);
    1616    }
    1717</script>
  • trunk/Source/WebCore/ChangeLog

    r223752 r223754  
     12017-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
    1222017-10-20  Basuke Suzuki  <Basuke.Suzuki@sony.com>
    223
  • trunk/Source/WebCore/platform/image-decoders/webp/WEBPImageDecoder.cpp

    r223728 r223754  
    3434namespace WebCore {
    3535
     36// Convenience function to improve code readability, as WebPDemuxGetFrame is +1 based.
     37bool webpFrameAtIndex(WebPDemuxer* demuxer, size_t index, WebPIterator* webpFrame)
     38{
     39    return WebPDemuxGetFrame(demuxer, index + 1, webpFrame);
     40}
     41
    3642WEBPImageDecoder::WEBPImageDecoder(AlphaOption alphaOption, GammaAndColorProfileOption gammaAndColorProfileOption)
    3743    : ScalableImageDecoder(alphaOption, gammaAndColorProfileOption)
     
    8692        return 0;
    8793
    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
    96107        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;
    123124}
    124125
     
    144145    // It is a fatal error if all data is received and we have decoded all frames available but the file is truncated.
    145146    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++)
    152153        decodeFrame(i, demuxer);
    153154
     
    161162
    162163    WebPIterator webpFrame;
    163     if (!WebPDemuxGetFrame(demuxer, frameIndex + 1, &webpFrame))
     164    if (!webpFrameAtIndex(demuxer, frameIndex, &webpFrame))
    164165        return;
    165166
     
    185186    decoderBuffer.u.RGBA.size = decoderBuffer.u.RGBA.stride * webpFrame.height;
    186187    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();
    188190    if (!decoderBuffer.u.RGBA.rgba) {
    189191        setFailed();
     
    193195    WebPIDecoder* decoder = WebPINewDecoder(&decoderBuffer);
    194196    if (!decoder) {
    195         fastFree(decoderBuffer.u.RGBA.rgba);
    196197        setFailed();
    197198        return;
     
    206207        if (!isAllDataReceived()) {
    207208            applyPostProcessing(frameIndex, decoder, decoderBuffer, blend);
     209            buffer.setDecodingStatus(DecodingStatus::Partial);
    208210            break;
    209211        }
     
    214216
    215217    WebPIDelete(decoder);
    216     fastFree(decoderBuffer.u.RGBA.rgba);
    217218}
    218219
     
    228229
    229230    // 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() });
    234232
    235233    if (!frameIndex || !m_frameBufferCache[frameIndex - 1].backingStore()) {
     
    255253    buffer.setHasAlpha(webpFrame->has_alpha);
    256254    buffer.backingStore()->setFrameRect(frameRect);
    257     buffer.setDecodingStatus(DecodingStatus::Partial);
    258255
    259256    return true;
     
    353350    //
    354351    // 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.
    357353    for (int i = clearBeforeFrame - 1; i >= 0; i--) {
    358354        ImageFrame& buffer = m_frameBufferCache[i];
    359         if (buffer.isComplete() || buffer.isInvalid())
     355        if (!buffer.isInvalid())
    360356            buffer.clear();
    361357    }
Note: See TracChangeset for help on using the changeset viewer.