1591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch/*
2591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * Copyright (C) 2013 Google Inc. All rights reserved.
3591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch *
4591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * Redistribution and use in source and binary forms, with or without
5591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * modification, are permitted provided that the following conditions are
6591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * met:
7591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch *
8591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch *     * Redistributions of source code must retain the above copyright
9591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * notice, this list of conditions and the following disclaimer.
10591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch *     * Redistributions in binary form must reproduce the above
11591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * copyright notice, this list of conditions and the following disclaimer
12591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * in the documentation and/or other materials provided with the
13591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * distribution.
14591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch *     * Neither the name of Google Inc. nor the names of its
15591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * contributors may be used to endorse or promote products derived from
16591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * this software without specific prior written permission.
17591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch *
18591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch */
30591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
31591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "config.h"
32591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
33591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/platform/image-decoders/webp/WEBPImageDecoder.h"
34591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
35591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "RuntimeEnabledFeatures.h"
36591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "core/platform/SharedBuffer.h"
37591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "public/platform/Platform.h"
38591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "public/platform/WebData.h"
39591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "public/platform/WebSize.h"
40591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "public/platform/WebUnitTestSupport.h"
41591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/OwnPtr.h"
42591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/PassOwnPtr.h"
43591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/StringHasher.h"
44591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/Vector.h"
45591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include "wtf/dtoa/utils.h"
46591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#include <gtest/gtest.h>
47591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
48591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochusing namespace WebCore;
49591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochusing namespace WebKit;
50591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
51591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#if !OS(ANDROID)
52591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
53591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochnamespace {
54591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
55591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochPassRefPtr<SharedBuffer> readFile(const char* fileName)
56591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
57591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    String filePath = Platform::current()->unitTestSupport()->webKitRootDir();
58591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    filePath.append(fileName);
59591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
600474e3614ae9be9fbf4fd50d825fd6e7c3d30b63Ben Murdoch    return Platform::current()->unitTestSupport()->readFromFile(filePath);
61591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
62591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
63591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochPassOwnPtr<WEBPImageDecoder> createDecoder()
64591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
65591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return adoptPtr(new WEBPImageDecoder(ImageSource::AlphaNotPremultiplied, ImageSource::GammaAndColorProfileApplied));
66591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
67591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
68591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochunsigned hashSkBitmap(const SkBitmap& bitmap)
69591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
70591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    return StringHasher::hashMemory(bitmap.getPixels(), bitmap.getSize());
71591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
72591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
73591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid createDecodingBaseline(SharedBuffer* data, Vector<unsigned>* baselineHashes)
74591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
75591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    OwnPtr<WEBPImageDecoder> decoder = createDecoder();
76591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->setData(data, true);
77591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    size_t frameCount = decoder->frameCount();
78591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t i = 0; i < frameCount; ++i) {
79591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        ImageFrame* frame = decoder->frameBufferAtIndex(i);
80591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        baselineHashes->append(hashSkBitmap(frame->getSkBitmap()));
81591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
82591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
83591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
84591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid testRandomFrameDecode(const char* webpFile)
85591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
86591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    SCOPED_TRACE(webpFile);
87591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
88591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<SharedBuffer> fullData = readFile(webpFile);
89591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_TRUE(fullData.get());
90591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    Vector<unsigned> baselineHashes;
91591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    createDecodingBaseline(fullData.get(), &baselineHashes);
92591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    size_t frameCount = baselineHashes.size();
93591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
94591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // Random decoding should get the same results as sequential decoding.
95591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    OwnPtr<WEBPImageDecoder> decoder = createDecoder();
96591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->setData(fullData.get(), true);
97591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const size_t skippingStep = 5;
98591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t i = 0; i < skippingStep; ++i) {
99591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for (size_t j = i; j < frameCount; j += skippingStep) {
100591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
101591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            ImageFrame* frame = decoder->frameBufferAtIndex(j);
102591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap()));
103591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
104591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
105591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
106591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // Decoding in reverse order.
107591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder = createDecoder();
108591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->setData(fullData.get(), true);
109591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t i = frameCount; i; --i) {
110591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        SCOPED_TRACE(testing::Message() << "Reverse i:" << i);
111591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        ImageFrame* frame = decoder->frameBufferAtIndex(i - 1);
112591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(baselineHashes[i - 1], hashSkBitmap(frame->getSkBitmap()));
113591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
114591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
115591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
116591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochvoid testRandomDecodeAfterClearFrameBufferCache(const char* webpFile)
117591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
118591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    SCOPED_TRACE(webpFile);
119591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
120591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<SharedBuffer> data = readFile(webpFile);
121591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_TRUE(data.get());
122591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    Vector<unsigned> baselineHashes;
123591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    createDecodingBaseline(data.get(), &baselineHashes);
124591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    size_t frameCount = baselineHashes.size();
125591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
126591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    OwnPtr<WEBPImageDecoder> decoder = createDecoder();
127591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->setData(data.get(), true);
128591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t clearExceptFrame = 0; clearExceptFrame < frameCount; ++clearExceptFrame) {
129591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        decoder->clearCacheExceptFrame(clearExceptFrame);
130591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const size_t skippingStep = 5;
131591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for (size_t i = 0; i < skippingStep; ++i) {
132591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            for (size_t j = 0; j < frameCount; j += skippingStep) {
133591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                SCOPED_TRACE(testing::Message() << "Random i:" << i << " j:" << j);
134591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                ImageFrame* frame = decoder->frameBufferAtIndex(j);
135591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                EXPECT_EQ(baselineHashes[j], hashSkBitmap(frame->getSkBitmap()));
136591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            }
137591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
138591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
139591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
140591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
141591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch} // namespace
142591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
143591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochclass AnimatedWebPTests : public ::testing::Test {
144591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdochprotected:
145591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    virtual void SetUp()
146591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    {
147591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        // Enable animated WebP for all the tests.
148591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        WebCore::RuntimeEnabledFeatures::setAnimatedWebPEnabled(true);
149591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
150591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch};
151591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
152591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochTEST_F(AnimatedWebPTests, verifyAnimationParametersTransparentImage)
153591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
154591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    OwnPtr<WEBPImageDecoder> decoder = createDecoder();
155591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
156591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
157591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/webp-animated.webp");
158591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_TRUE(data.get());
159591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->setData(data.get(), true);
160591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
161591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const int canvasWidth = 11;
162591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const int canvasHeight = 29;
163591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const struct AnimParam {
164591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        int xOffset, yOffset, width, height;
165591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        ImageFrame::FrameDisposalMethod dispose;
166591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        unsigned duration;
167591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        bool hasAlpha;
168591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } frameParameters[] = {
169591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        { 0, 0, 11, 29, ImageFrame::DisposeKeep, 1000u, true },
170591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        { 2, 10, 7, 17, ImageFrame::DisposeKeep, 500u, true },
171591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        { 2, 2, 7, 16, ImageFrame::DisposeKeep, 1000u, true },
172591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    };
173591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
174591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t i = 0; i < ARRAY_SIZE(frameParameters); ++i) {
175591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
176591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
177591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(canvasWidth, frame->getSkBitmap().width());
178591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(canvasHeight, frame->getSkBitmap().height());
179591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].xOffset, frame->originalFrameRect().x());
180591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].yOffset, frame->originalFrameRect().y());
181591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].width, frame->originalFrameRect().width());
182591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].height, frame->originalFrameRect().height());
183591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].dispose, frame->disposalMethod());
184591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].duration, frame->duration());
185591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].hasAlpha, frame->hasAlpha());
186591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
187591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
188591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(ARRAY_SIZE(frameParameters), decoder->frameCount());
189591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
190591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
191591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
192591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochTEST_F(AnimatedWebPTests, verifyAnimationParametersOpaqueFramesTransparentBackground)
193591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
194591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    OwnPtr<WEBPImageDecoder> decoder = createDecoder();
195591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
196591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
197591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/webp-animated-opaque.webp");
198591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_TRUE(data.get());
199591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->setData(data.get(), true);
200591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
201591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const int canvasWidth = 94;
202591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const int canvasHeight = 87;
203591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const struct AnimParam {
204591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        int xOffset, yOffset, width, height;
205591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        ImageFrame::FrameDisposalMethod dispose;
206591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        unsigned duration;
207591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        bool hasAlpha;
208591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } frameParameters[] = {
209591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        { 4, 10, 33, 32, ImageFrame::DisposeOverwriteBgcolor, 1000u, true },
210591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        { 34, 30, 33, 32, ImageFrame::DisposeOverwriteBgcolor, 1000u, true },
211591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        { 62, 50, 32, 32, ImageFrame::DisposeOverwriteBgcolor, 1000u, true },
212591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        { 10, 54, 32, 33, ImageFrame::DisposeOverwriteBgcolor, 1000u, true },
213591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    };
214591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
215591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t i = 0; i < ARRAY_SIZE(frameParameters); ++i) {
216591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const ImageFrame* const frame = decoder->frameBufferAtIndex(i);
217591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(ImageFrame::FrameComplete, frame->status());
218591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(canvasWidth, frame->getSkBitmap().width());
219591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(canvasHeight, frame->getSkBitmap().height());
220591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].xOffset, frame->originalFrameRect().x());
221591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].yOffset, frame->originalFrameRect().y());
222591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].width, frame->originalFrameRect().width());
223591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].height, frame->originalFrameRect().height());
224591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].dispose, frame->disposalMethod());
225591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].duration, frame->duration());
226591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(frameParameters[i].hasAlpha, frame->hasAlpha());
227591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
228591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
229591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(ARRAY_SIZE(frameParameters), decoder->frameCount());
230591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(cAnimationLoopInfinite, decoder->repetitionCount());
231591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
232591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
233591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochTEST_F(AnimatedWebPTests, parseAndDecodeByteByByte)
234591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
235591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const struct TestImage {
236591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        const char* filename;
237591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        unsigned frameCount;
238591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        int repetitionCount;
239591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } testImages[] = {
240591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        { "/LayoutTests/fast/images/resources/webp-animated.webp", 3u, cAnimationLoopInfinite },
241591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        { "/LayoutTests/fast/images/resources/webp-animated-icc-xmp.webp", 13u, 32000 },
242591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    };
243591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
244591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t i = 0; i < ARRAY_SIZE(testImages); ++i) {
245591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        OwnPtr<WEBPImageDecoder> decoder = createDecoder();
246591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        RefPtr<SharedBuffer> data = readFile(testImages[i].filename);
247591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        ASSERT_TRUE(data.get());
248591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
249591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        size_t frameCount = 0;
250591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        size_t framesDecoded = 0;
251591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
252591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        // Pass data to decoder byte by byte.
253591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        for (size_t length = 1; length <= data->size(); ++length) {
254591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), length);
255591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            decoder->setData(tempData.get(), length == data->size());
256591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
257591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            EXPECT_LE(frameCount, decoder->frameCount());
258591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            frameCount = decoder->frameCount();
259591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
260591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            ImageFrame* frame = decoder->frameBufferAtIndex(frameCount - 1);
261591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            if (frame && frame->status() == ImageFrame::FrameComplete && framesDecoded < frameCount)
262591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                ++framesDecoded;
263591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
264591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
265591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(testImages[i].frameCount, decoder->frameCount());
266591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(testImages[i].frameCount, framesDecoded);
267591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(testImages[i].repetitionCount, decoder->repetitionCount());
268591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
269591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
270591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
271591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochTEST_F(AnimatedWebPTests, invalidImage)
272591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
273591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    OwnPtr<WEBPImageDecoder> decoder = createDecoder();
274591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
275591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/invalid-animated-webp.webp");
276591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_TRUE(data.get());
277591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->setData(data.get(), true);
278591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
279591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(0u, decoder->frameCount());
280591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ImageFrame* frame = decoder->frameBufferAtIndex(0);
281591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_FALSE(frame);
282591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(cAnimationLoopOnce, decoder->repetitionCount());
283591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
284591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
285591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochTEST_F(AnimatedWebPTests, progressiveDecode)
286591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
287591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources/webp-animated.webp");
288591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_TRUE(fullData.get());
289591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const size_t fullLength = fullData->size();
290591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
291591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    OwnPtr<WEBPImageDecoder>  decoder;
292591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ImageFrame* frame;
293591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
294591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    Vector<unsigned> truncatedHashes;
295591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    Vector<unsigned> progressiveHashes;
296591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
297591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // Compute hashes when the file is truncated.
298591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    const size_t increment = 1;
299591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t i = 1; i <= fullLength; i += increment) {
300591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        decoder = createDecoder();
301591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i);
302591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        decoder->setData(data.get(), i == fullLength);
303591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        frame = decoder->frameBufferAtIndex(0);
304591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!frame) {
305591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            truncatedHashes.append(0);
306591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            continue;
307591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
308591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        truncatedHashes.append(hashSkBitmap(frame->getSkBitmap()));
309591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
310591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
311591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // Compute hashes when the file is progressively decoded.
312591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder = createDecoder();
313591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t i = 1; i <= fullLength; i += increment) {
314591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), i);
315591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        decoder->setData(data.get(), i == fullLength);
316591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        frame = decoder->frameBufferAtIndex(0);
317591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (!frame) {
318591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            progressiveHashes.append(0);
319591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            continue;
320591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
321591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        progressiveHashes.append(hashSkBitmap(frame->getSkBitmap()));
322591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
323591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
324591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    bool match = true;
325591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t i = 0; i < truncatedHashes.size(); ++i) {
326591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        if (truncatedHashes[i] != progressiveHashes[i]) {
327591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            match = false;
328591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            break;
329591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        }
330591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    }
331591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_TRUE(match);
332591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
333591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
334591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochTEST_F(AnimatedWebPTests, frameIsCompleteAndDuration)
335591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
336591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    OwnPtr<WEBPImageDecoder> decoder = createDecoder();
337591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
338591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<SharedBuffer> data = readFile("/LayoutTests/fast/images/resources/webp-animated.webp");
339591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_TRUE(data.get());
340591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
341591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_GE(data->size(), 10u);
342591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<SharedBuffer> tempData = SharedBuffer::create(data->data(), data->size() - 10);
343591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->setData(tempData.get(), false);
344591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
345591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(2u, decoder->frameCount());
346591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_FALSE(decoder->failed());
347591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0));
348591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(1000, decoder->frameDurationAtIndex(0));
349591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1));
350591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(500, decoder->frameDurationAtIndex(1));
351591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
352591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->setData(data.get(), true);
353591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(3u, decoder->frameCount());
354591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_TRUE(decoder->frameIsCompleteAtIndex(0));
355591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(1000, decoder->frameDurationAtIndex(0));
356591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_TRUE(decoder->frameIsCompleteAtIndex(1));
357591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(500, decoder->frameDurationAtIndex(1));
358591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_TRUE(decoder->frameIsCompleteAtIndex(2));
359591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(1000.0, decoder->frameDurationAtIndex(2));
360591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
361591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
362591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochTEST_F(AnimatedWebPTests, updateRequiredPreviousFrameAfterFirstDecode)
363591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
364591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    OwnPtr<WEBPImageDecoder> decoder = createDecoder();
365591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
366591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources/webp-animated.webp");
367591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_TRUE(fullData.get());
368591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
369591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // Give it data that is enough to parse but not decode in order to check the status
370591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // of requiredPreviousFrameIndex before decoding.
371591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    size_t partialSize = 1;
372591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    do {
373591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), partialSize);
374591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        decoder->setData(data.get(), false);
375591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        ++partialSize;
376591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty);
377591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
378591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(notFound, decoder->frameBufferAtIndex(0)->requiredPreviousFrameIndex());
379591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    unsigned frameCount = decoder->frameCount();
380591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t i = 1; i < frameCount; ++i)
381591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(i - 1, decoder->frameBufferAtIndex(i)->requiredPreviousFrameIndex());
382591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
383591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->setData(fullData.get(), true);
384591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    for (size_t i = 0; i < frameCount; ++i)
385591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        EXPECT_EQ(notFound, decoder->frameBufferAtIndex(i)->requiredPreviousFrameIndex());
386591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
387591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
388591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochTEST_F(AnimatedWebPTests, randomFrameDecode)
389591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
390591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated.webp");
391591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated-opaque.webp");
392591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated-large.webp");
393591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    testRandomFrameDecode("/LayoutTests/fast/images/resources/webp-animated-icc-xmp.webp");
394591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
395591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
396591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochTEST_F(AnimatedWebPTests, randomDecodeAfterClearFrameBufferCache)
397591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
398591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resources/webp-animated.webp");
399591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resources/webp-animated-opaque.webp");
400591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resources/webp-animated-large.webp");
401591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    testRandomDecodeAfterClearFrameBufferCache("/LayoutTests/fast/images/resources/webp-animated-icc-xmp.webp");
402591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
403591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
404591b958dee2cf159d33a0b931e6231072eaf38d5Ben MurdochTEST_F(AnimatedWebPTests, resumePartialDecodeAfterClearFrameBufferCache)
405591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch{
406591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    RefPtr<SharedBuffer> fullData = readFile("/LayoutTests/fast/images/resources/webp-animated-large.webp");
407591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ASSERT_TRUE(fullData.get());
408591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    Vector<unsigned> baselineHashes;
409591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    createDecodingBaseline(fullData.get(), &baselineHashes);
410591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    size_t frameCount = baselineHashes.size();
411591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
412591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    OwnPtr<WEBPImageDecoder> decoder = createDecoder();
413591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
414591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // Let frame 0 be partially decoded.
415591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    size_t partialSize = 1;
416591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    do {
417591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        RefPtr<SharedBuffer> data = SharedBuffer::create(fullData->data(), partialSize);
418591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        decoder->setData(data.get(), false);
419591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        ++partialSize;
420591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    } while (!decoder->frameCount() || decoder->frameBufferAtIndex(0)->status() == ImageFrame::FrameEmpty);
421591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
422591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // Skip to the last frame and clear.
423591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->setData(fullData.get(), true);
424591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(frameCount, decoder->frameCount());
425591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ImageFrame* lastFrame = decoder->frameBufferAtIndex(frameCount - 1);
426591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(baselineHashes[frameCount - 1], hashSkBitmap(lastFrame->getSkBitmap()));
427591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    decoder->clearCacheExceptFrame(notFound);
428591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
429591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    // Resume decoding of the first frame.
430591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    ImageFrame* firstFrame = decoder->frameBufferAtIndex(0);
431591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(ImageFrame::FrameComplete, firstFrame->status());
432591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch    EXPECT_EQ(baselineHashes[0], hashSkBitmap(firstFrame->getSkBitmap()));
433591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch}
434591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch
435591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch#endif
436