1/*
2 * Copyright (C) 2012 Google Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27
28#include "platform/graphics/ImageFrameGenerator.h"
29
30#include "platform/SharedBuffer.h"
31#include "platform/TraceEvent.h"
32#include "platform/graphics/ImageDecodingStore.h"
33#include "platform/image-decoders/ImageDecoder.h"
34
35#include "skia/ext/image_operations.h"
36#include "third_party/skia/include/core/SkMallocPixelRef.h"
37
38namespace blink {
39
40// Creates a SkPixelRef such that the memory for pixels is given by an external body.
41// This is used to write directly to the memory given by Skia during decoding.
42class ImageFrameGenerator::ExternalMemoryAllocator : public SkBitmap::Allocator {
43public:
44    ExternalMemoryAllocator(const SkImageInfo& info, void* pixels, size_t rowBytes)
45        : m_info(info)
46        , m_pixels(pixels)
47        , m_rowBytes(rowBytes)
48    {
49    }
50
51    virtual bool allocPixelRef(SkBitmap* dst, SkColorTable* ctable) OVERRIDE
52    {
53        const SkImageInfo& info = dst->info();
54        if (kUnknown_SkColorType == info.colorType())
55            return false;
56
57        if (info != m_info || m_rowBytes != dst->rowBytes())
58            return false;
59
60        if (!dst->installPixels(m_info, m_pixels, m_rowBytes))
61            return false;
62        dst->lockPixels();
63        return true;
64    }
65
66private:
67    SkImageInfo m_info;
68    void* m_pixels;
69    size_t m_rowBytes;
70};
71
72static bool updateYUVComponentSizes(ImageDecoder* decoder, SkISize componentSizes[3], ImageDecoder::SizeType sizeType)
73{
74    // canDecodeToYUV() has to be called AFTER isSizeAvailable(),
75    // otherwise the output color space may not be set in the decoder.
76    if (!decoder->isSizeAvailable() || !decoder->canDecodeToYUV())
77        return false;
78
79    IntSize size = decoder->decodedYUVSize(0, sizeType);
80    componentSizes[0].set(size.width(), size.height());
81    size = decoder->decodedYUVSize(1, sizeType);
82    componentSizes[1].set(size.width(), size.height());
83    size = decoder->decodedYUVSize(2, sizeType);
84    componentSizes[2].set(size.width(), size.height());
85    return true;
86}
87
88ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<SharedBuffer> data, bool allDataReceived, bool isMultiFrame)
89    : m_fullSize(fullSize)
90    , m_isMultiFrame(isMultiFrame)
91    , m_decodeFailedAndEmpty(false)
92    , m_decodeCount(0)
93{
94    setData(data.get(), allDataReceived);
95}
96
97ImageFrameGenerator::~ImageFrameGenerator()
98{
99    ImageDecodingStore::instance()->removeCacheIndexedByGenerator(this);
100}
101
102void ImageFrameGenerator::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
103{
104    m_data.setData(data.get(), allDataReceived);
105}
106
107void ImageFrameGenerator::copyData(RefPtr<SharedBuffer>* data, bool* allDataReceived)
108{
109    SharedBuffer* buffer = 0;
110    m_data.data(&buffer, allDataReceived);
111    if (buffer)
112        *data = buffer->copy();
113}
114
115bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes)
116{
117    // This method is called to populate a discardable memory owned by Skia.
118
119    // Prevents concurrent decode or scale operations on the same image data.
120    MutexLocker lock(m_decodeMutex);
121
122    // This implementation does not support scaling so check the requested size.
123    SkISize scaledSize = SkISize::Make(info.fWidth, info.fHeight);
124    ASSERT(m_fullSize == scaledSize);
125
126    if (m_decodeFailedAndEmpty)
127        return false;
128
129    TRACE_EVENT2("blink", "ImageFrameGenerator::decodeAndScale", "generator", this, "decodeCount", m_decodeCount);
130
131    m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, rowBytes));
132
133    SkBitmap bitmap = tryToResumeDecode(scaledSize, index);
134    if (bitmap.isNull())
135        return false;
136
137    // Don't keep the allocator because it contains a pointer to memory
138    // that we do not own.
139    m_externalAllocator.clear();
140
141    ASSERT(bitmap.width() == scaledSize.width());
142    ASSERT(bitmap.height() == scaledSize.height());
143
144    bool result = true;
145    // Check to see if decoder has written directly to the memory provided
146    // by Skia. If not make a copy.
147    if (bitmap.getPixels() != pixels)
148        result = bitmap.copyPixelsTo(pixels, rowBytes * info.fHeight, rowBytes);
149    return result;
150}
151
152bool ImageFrameGenerator::decodeToYUV(SkISize componentSizes[3], void* planes[3], size_t rowBytes[3])
153{
154    // This method is called to populate a discardable memory owned by Skia.
155
156    // Prevents concurrent decode or scale operations on the same image data.
157    MutexLocker lock(m_decodeMutex);
158
159    if (m_decodeFailedAndEmpty)
160        return false;
161
162    TRACE_EVENT2("blink", "ImageFrameGenerator::decodeToYUV", "generator", this, "decodeCount", static_cast<int>(m_decodeCount));
163
164    if (!planes || !planes[0] || !planes[1] || !planes[2]
165        || !rowBytes || !rowBytes[0] || !rowBytes[1] || !rowBytes[2]) {
166        return false;
167    }
168
169    SharedBuffer* data = 0;
170    bool allDataReceived = false;
171    m_data.data(&data, &allDataReceived);
172
173    // FIXME: YUV decoding does not currently support progressive decoding.
174    ASSERT(allDataReceived);
175
176    OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileApplied);
177    if (!decoder)
178        return false;
179
180    decoder->setData(data, allDataReceived);
181
182    OwnPtr<ImagePlanes> imagePlanes = adoptPtr(new ImagePlanes(planes, rowBytes));
183    decoder->setImagePlanes(imagePlanes.release());
184
185    bool sizeUpdated = updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder::ActualSize);
186    RELEASE_ASSERT(sizeUpdated);
187
188    bool yuvDecoded = decoder->decodeToYUV();
189    if (yuvDecoded)
190        setHasAlpha(0, false); // YUV is always opaque
191    return yuvDecoded;
192}
193
194SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_t index)
195{
196    TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "index", static_cast<int>(index));
197
198    ImageDecoder* decoder = 0;
199    const bool resumeDecoding = ImageDecodingStore::instance()->lockDecoder(this, m_fullSize, &decoder);
200    ASSERT(!resumeDecoding || decoder);
201
202    SkBitmap fullSizeImage;
203    bool complete = decode(index, &decoder, &fullSizeImage);
204
205    if (!decoder)
206        return SkBitmap();
207
208    // If we are not resuming decoding that means the decoder is freshly
209    // created and we have ownership. If we are resuming decoding then
210    // the decoder is owned by ImageDecodingStore.
211    OwnPtr<ImageDecoder> decoderContainer;
212    if (!resumeDecoding)
213        decoderContainer = adoptPtr(decoder);
214
215    if (fullSizeImage.isNull()) {
216        // If decode has failed and resulted an empty image we can save work
217        // in the future by returning early.
218        m_decodeFailedAndEmpty = !m_isMultiFrame && decoder->failed();
219
220        if (resumeDecoding)
221            ImageDecodingStore::instance()->unlockDecoder(this, decoder);
222        return SkBitmap();
223    }
224
225    // If the image generated is complete then there is no need to keep
226    // the decoder. The exception is multi-frame decoder which can generate
227    // multiple complete frames.
228    const bool removeDecoder = complete && !m_isMultiFrame;
229
230    if (resumeDecoding) {
231        if (removeDecoder)
232            ImageDecodingStore::instance()->removeDecoder(this, decoder);
233        else
234            ImageDecodingStore::instance()->unlockDecoder(this, decoder);
235    } else if (!removeDecoder) {
236        ImageDecodingStore::instance()->insertDecoder(this, decoderContainer.release());
237    }
238    return fullSizeImage;
239}
240
241void ImageFrameGenerator::setHasAlpha(size_t index, bool hasAlpha)
242{
243    MutexLocker lock(m_alphaMutex);
244    if (index >= m_hasAlpha.size()) {
245        const size_t oldSize = m_hasAlpha.size();
246        m_hasAlpha.resize(index + 1);
247        for (size_t i = oldSize; i < m_hasAlpha.size(); ++i)
248            m_hasAlpha[i] = true;
249    }
250    m_hasAlpha[index] = hasAlpha;
251}
252
253bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap)
254{
255    TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize.width(), "height", m_fullSize.height());
256
257    ASSERT(decoder);
258    SharedBuffer* data = 0;
259    bool allDataReceived = false;
260    bool newDecoder = false;
261    m_data.data(&data, &allDataReceived);
262
263    // Try to create an ImageDecoder if we are not given one.
264    if (!*decoder) {
265        newDecoder = true;
266        if (m_imageDecoderFactory)
267            *decoder = m_imageDecoderFactory->create().leakPtr();
268
269        if (!*decoder)
270            *decoder = ImageDecoder::create(*data, ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileApplied).leakPtr();
271
272        if (!*decoder)
273            return false;
274    }
275
276    if (!m_isMultiFrame && newDecoder && allDataReceived) {
277        // If we're using an external memory allocator that means we're decoding
278        // directly into the output memory and we can save one memcpy.
279        ASSERT(m_externalAllocator.get());
280        (*decoder)->setMemoryAllocator(m_externalAllocator.get());
281    }
282    (*decoder)->setData(data, allDataReceived);
283
284    ImageFrame* frame = (*decoder)->frameBufferAtIndex(index);
285    (*decoder)->setData(0, false); // Unref SharedBuffer from ImageDecoder.
286    (*decoder)->clearCacheExceptFrame(index);
287    (*decoder)->setMemoryAllocator(0);
288
289    if (!frame || frame->status() == ImageFrame::FrameEmpty)
290        return false;
291
292    // A cache object is considered complete if we can decode a complete frame.
293    // Or we have received all data. The image might not be fully decoded in
294    // the latter case.
295    const bool isDecodeComplete = frame->status() == ImageFrame::FrameComplete || allDataReceived;
296    SkBitmap fullSizeBitmap = frame->getSkBitmap();
297    if (!fullSizeBitmap.isNull())
298    {
299        ASSERT(fullSizeBitmap.width() == m_fullSize.width() && fullSizeBitmap.height() == m_fullSize.height());
300        setHasAlpha(index, !fullSizeBitmap.isOpaque());
301    }
302    *bitmap = fullSizeBitmap;
303    return isDecodeComplete;
304}
305
306bool ImageFrameGenerator::hasAlpha(size_t index)
307{
308    MutexLocker lock(m_alphaMutex);
309    if (index < m_hasAlpha.size())
310        return m_hasAlpha[index];
311    return true;
312}
313
314bool ImageFrameGenerator::getYUVComponentSizes(SkISize componentSizes[3])
315{
316    ASSERT(componentSizes);
317
318    TRACE_EVENT2("webkit", "ImageFrameGenerator::getYUVComponentSizes", "width", m_fullSize.width(), "height", m_fullSize.height());
319
320    SharedBuffer* data = 0;
321    bool allDataReceived = false;
322    m_data.data(&data, &allDataReceived);
323
324    // FIXME: YUV decoding does not currently support progressive decoding.
325    if (!allDataReceived)
326        return false;
327
328    OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, ImageSource::AlphaPremultiplied, ImageSource::GammaAndColorProfileApplied);
329    if (!decoder)
330        return false;
331
332    // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding.
333    decoder->setData(data, allDataReceived);
334    OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes);
335    decoder->setImagePlanes(dummyImagePlanes.release());
336
337    return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder::SizeForMemoryAllocation);
338}
339
340} // namespace blink
341