2 * Copyright (C) 2012 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
28 #include "platform/graphics/ImageFrameGenerator.h"
30 #include "platform/SharedBuffer.h"
31 #include "platform/TraceEvent.h"
32 #include "platform/graphics/ImageDecodingStore.h"
33 #include "platform/image-decoders/ImageDecoder.h"
37 static bool compatibleInfo(const SkImageInfo
& src
, const SkImageInfo
& dst
)
42 // It is legal to write kOpaque_SkAlphaType pixels into a kPremul_SkAlphaType buffer.
43 // This can happen when DeferredImageDecoder allocates an kOpaque_SkAlphaType image
44 // generator based on cached frame info, while the ImageFrame-allocated dest bitmap
45 // stays kPremul_SkAlphaType.
46 if (src
.alphaType() == kOpaque_SkAlphaType
&& dst
.alphaType() == kPremul_SkAlphaType
) {
47 const SkImageInfo
& tmp
= src
.makeAlphaType(kPremul_SkAlphaType
);
54 // Creates a SkPixelRef such that the memory for pixels is given by an external body.
55 // This is used to write directly to the memory given by Skia during decoding.
56 class ImageFrameGenerator::ExternalMemoryAllocator
: public SkBitmap::Allocator
{
58 ExternalMemoryAllocator(const SkImageInfo
& info
, void* pixels
, size_t rowBytes
)
61 , m_rowBytes(rowBytes
)
65 bool allocPixelRef(SkBitmap
* dst
, SkColorTable
* ctable
) override
67 const SkImageInfo
& info
= dst
->info();
68 if (kUnknown_SkColorType
== info
.colorType())
71 if (!compatibleInfo(m_info
, info
) || m_rowBytes
!= dst
->rowBytes())
74 if (!dst
->installPixels(info
, m_pixels
, m_rowBytes
))
86 static bool updateYUVComponentSizes(ImageDecoder
* decoder
, SkISize componentSizes
[3], ImageDecoder::SizeType sizeType
)
88 if (!decoder
->canDecodeToYUV())
91 IntSize size
= decoder
->decodedYUVSize(0, sizeType
);
92 componentSizes
[0].set(size
.width(), size
.height());
93 size
= decoder
->decodedYUVSize(1, sizeType
);
94 componentSizes
[1].set(size
.width(), size
.height());
95 size
= decoder
->decodedYUVSize(2, sizeType
);
96 componentSizes
[2].set(size
.width(), size
.height());
100 ImageFrameGenerator::ImageFrameGenerator(const SkISize
& fullSize
, PassRefPtr
<SharedBuffer
> data
, bool allDataReceived
, bool isMultiFrame
)
101 : m_fullSize(fullSize
)
102 , m_isMultiFrame(isMultiFrame
)
103 , m_decodeFailedAndEmpty(false)
107 setData(data
.get(), allDataReceived
);
110 ImageFrameGenerator::~ImageFrameGenerator()
112 ImageDecodingStore::instance().removeCacheIndexedByGenerator(this);
115 void ImageFrameGenerator::setData(PassRefPtr
<SharedBuffer
> data
, bool allDataReceived
)
117 m_data
.setData(data
.get(), allDataReceived
);
120 void ImageFrameGenerator::copyData(RefPtr
<SharedBuffer
>* data
, bool* allDataReceived
)
122 SharedBuffer
* buffer
= 0;
123 m_data
.data(&buffer
, allDataReceived
);
125 *data
= buffer
->copy();
128 bool ImageFrameGenerator::decodeAndScale(const SkImageInfo
& info
, size_t index
, void* pixels
, size_t rowBytes
)
130 // This method is called to populate a discardable memory owned by Skia.
132 // Prevents concurrent decode or scale operations on the same image data.
133 MutexLocker
lock(m_decodeMutex
);
135 // This implementation does not support scaling so check the requested size.
136 SkISize scaledSize
= SkISize::Make(info
.width(), info
.height());
137 ASSERT(m_fullSize
== scaledSize
);
139 if (m_decodeFailedAndEmpty
)
142 TRACE_EVENT2("blink", "ImageFrameGenerator::decodeAndScale", "generator", this, "decodeCount", m_decodeCount
);
144 m_externalAllocator
= adoptPtr(new ExternalMemoryAllocator(info
, pixels
, rowBytes
));
146 SkBitmap bitmap
= tryToResumeDecode(scaledSize
, index
);
150 // Don't keep the allocator because it contains a pointer to memory
151 // that we do not own.
152 m_externalAllocator
.clear();
154 ASSERT(bitmap
.width() == scaledSize
.width());
155 ASSERT(bitmap
.height() == scaledSize
.height());
158 SkAutoLockPixels
bitmapLock(bitmap
);
159 // Check to see if decoder has written directly to the memory provided
160 // by Skia. If not make a copy.
161 if (bitmap
.getPixels() != pixels
)
162 result
= bitmap
.copyPixelsTo(pixels
, rowBytes
* info
.height(), rowBytes
);
166 bool ImageFrameGenerator::decodeToYUV(SkISize componentSizes
[3], void* planes
[3], size_t rowBytes
[3])
168 // This method is called to populate a discardable memory owned by Skia.
170 // Prevents concurrent decode or scale operations on the same image data.
171 MutexLocker
lock(m_decodeMutex
);
173 if (m_decodeFailedAndEmpty
)
176 TRACE_EVENT2("blink", "ImageFrameGenerator::decodeToYUV", "generator", this, "decodeCount", static_cast<int>(m_decodeCount
));
178 if (!planes
|| !planes
[0] || !planes
[1] || !planes
[2]
179 || !rowBytes
|| !rowBytes
[0] || !rowBytes
[1] || !rowBytes
[2]) {
183 SharedBuffer
* data
= 0;
184 bool allDataReceived
= false;
185 m_data
.data(&data
, &allDataReceived
);
187 // FIXME: YUV decoding does not currently support progressive decoding.
188 ASSERT(allDataReceived
);
190 OwnPtr
<ImageDecoder
> decoder
= ImageDecoder::create(*data
, ImageDecoder::AlphaPremultiplied
, ImageDecoder::GammaAndColorProfileApplied
);
194 decoder
->setData(data
, allDataReceived
);
196 OwnPtr
<ImagePlanes
> imagePlanes
= adoptPtr(new ImagePlanes(planes
, rowBytes
));
197 decoder
->setImagePlanes(imagePlanes
.release());
199 bool sizeUpdated
= updateYUVComponentSizes(decoder
.get(), componentSizes
, ImageDecoder::ActualSize
);
200 RELEASE_ASSERT(sizeUpdated
);
202 bool yuvDecoded
= decoder
->decodeToYUV();
204 setHasAlpha(0, false); // YUV is always opaque
208 SkBitmap
ImageFrameGenerator::tryToResumeDecode(const SkISize
& scaledSize
, size_t index
)
210 TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "index", static_cast<int>(index
));
212 ImageDecoder
* decoder
= 0;
213 const bool resumeDecoding
= ImageDecodingStore::instance().lockDecoder(this, m_fullSize
, &decoder
);
214 ASSERT(!resumeDecoding
|| decoder
);
216 SkBitmap fullSizeImage
;
217 bool complete
= decode(index
, &decoder
, &fullSizeImage
);
221 if (index
>= m_frameComplete
.size())
222 m_frameComplete
.resize(index
+ 1);
223 m_frameComplete
[index
] = complete
;
225 // If we are not resuming decoding that means the decoder is freshly
226 // created and we have ownership. If we are resuming decoding then
227 // the decoder is owned by ImageDecodingStore.
228 OwnPtr
<ImageDecoder
> decoderContainer
;
230 decoderContainer
= adoptPtr(decoder
);
232 if (fullSizeImage
.isNull()) {
233 // If decode has failed and resulted an empty image we can save work
234 // in the future by returning early.
235 m_decodeFailedAndEmpty
= !m_isMultiFrame
&& decoder
->failed();
238 ImageDecodingStore::instance().unlockDecoder(this, decoder
);
242 // If the image generated is complete then there is no need to keep
243 // the decoder. For multi-frame images, if all frames in the image are
244 // decoded, we remove the decoder.
247 if (m_isMultiFrame
) {
248 size_t decodedFrameCount
= 0;
249 for (Vector
<bool>::iterator it
= m_frameComplete
.begin(); it
!= m_frameComplete
.end(); ++it
) {
253 removeDecoder
= m_frameCount
&& (decodedFrameCount
== m_frameCount
);
255 removeDecoder
= complete
;
258 if (resumeDecoding
) {
260 ImageDecodingStore::instance().removeDecoder(this, decoder
);
261 m_frameComplete
.clear();
263 ImageDecodingStore::instance().unlockDecoder(this, decoder
);
265 } else if (!removeDecoder
) {
266 ImageDecodingStore::instance().insertDecoder(this, decoderContainer
.release());
268 return fullSizeImage
;
271 void ImageFrameGenerator::setHasAlpha(size_t index
, bool hasAlpha
)
273 MutexLocker
lock(m_alphaMutex
);
274 if (index
>= m_hasAlpha
.size()) {
275 const size_t oldSize
= m_hasAlpha
.size();
276 m_hasAlpha
.resize(index
+ 1);
277 for (size_t i
= oldSize
; i
< m_hasAlpha
.size(); ++i
)
278 m_hasAlpha
[i
] = true;
280 m_hasAlpha
[index
] = hasAlpha
;
283 bool ImageFrameGenerator::decode(size_t index
, ImageDecoder
** decoder
, SkBitmap
* bitmap
)
285 TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize
.width(), "height", m_fullSize
.height());
288 SharedBuffer
* data
= 0;
289 bool allDataReceived
= false;
290 bool newDecoder
= false;
291 m_data
.data(&data
, &allDataReceived
);
293 // Try to create an ImageDecoder if we are not given one.
296 if (m_imageDecoderFactory
)
297 *decoder
= m_imageDecoderFactory
->create().leakPtr();
300 *decoder
= ImageDecoder::create(*data
, ImageDecoder::AlphaPremultiplied
, ImageDecoder::GammaAndColorProfileApplied
).leakPtr();
306 if (!m_isMultiFrame
&& newDecoder
&& allDataReceived
) {
307 // If we're using an external memory allocator that means we're decoding
308 // directly into the output memory and we can save one memcpy.
309 ASSERT(m_externalAllocator
.get());
310 (*decoder
)->setMemoryAllocator(m_externalAllocator
.get());
312 (*decoder
)->setData(data
, allDataReceived
);
314 ImageFrame
* frame
= (*decoder
)->frameBufferAtIndex(index
);
315 // For multi-frame image decoders, we need to know how many frames are
316 // in that image in order to release the decoder when all frames are
317 // decoded. frameCount() is reliable only if all data is received and set in
318 // decoder, particularly with GIF.
320 m_frameCount
= (*decoder
)->frameCount();
322 (*decoder
)->setData(0, false); // Unref SharedBuffer from ImageDecoder.
323 (*decoder
)->clearCacheExceptFrame(index
);
324 (*decoder
)->setMemoryAllocator(0);
326 if (!frame
|| frame
->status() == ImageFrame::FrameEmpty
)
329 // A cache object is considered complete if we can decode a complete frame.
330 // Or we have received all data. The image might not be fully decoded in
332 const bool isDecodeComplete
= frame
->status() == ImageFrame::FrameComplete
|| allDataReceived
;
333 SkBitmap fullSizeBitmap
= frame
->getSkBitmap();
334 if (!fullSizeBitmap
.isNull())
336 ASSERT(fullSizeBitmap
.width() == m_fullSize
.width() && fullSizeBitmap
.height() == m_fullSize
.height());
337 setHasAlpha(index
, !fullSizeBitmap
.isOpaque());
339 *bitmap
= fullSizeBitmap
;
340 return isDecodeComplete
;
343 bool ImageFrameGenerator::hasAlpha(size_t index
)
345 MutexLocker
lock(m_alphaMutex
);
346 if (index
< m_hasAlpha
.size())
347 return m_hasAlpha
[index
];
351 bool ImageFrameGenerator::getYUVComponentSizes(SkISize componentSizes
[3])
353 ASSERT(componentSizes
);
355 TRACE_EVENT2("webkit", "ImageFrameGenerator::getYUVComponentSizes", "width", m_fullSize
.width(), "height", m_fullSize
.height());
357 SharedBuffer
* data
= 0;
358 bool allDataReceived
= false;
359 m_data
.data(&data
, &allDataReceived
);
361 // FIXME: YUV decoding does not currently support progressive decoding.
362 if (!allDataReceived
)
365 OwnPtr
<ImageDecoder
> decoder
= ImageDecoder::create(*data
, ImageDecoder::AlphaPremultiplied
, ImageDecoder::GammaAndColorProfileApplied
);
369 // JPEG images support YUV decoding: other decoders do not. So don't pump data into decoders
370 // that always return false to updateYUVComponentSizes() requests.
371 if (decoder
->filenameExtension() != "jpg")
374 // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding.
375 decoder
->setData(data
, allDataReceived
);
376 OwnPtr
<ImagePlanes
> dummyImagePlanes
= adoptPtr(new ImagePlanes
);
377 decoder
->setImagePlanes(dummyImagePlanes
.release());
379 return updateYUVComponentSizes(decoder
.get(), componentSizes
, ImageDecoder::SizeForMemoryAllocation
);