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
38 namespace 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.
42 class ImageFrameGenerator::ExternalMemoryAllocator : public SkBitmap::Allocator {
43 public:
ExternalMemoryAllocator(const SkImageInfo & info,void * pixels,size_t rowBytes)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
allocPixelRef(SkBitmap * dst,SkColorTable * ctable)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
66 private:
67 SkImageInfo m_info;
68 void* m_pixels;
69 size_t m_rowBytes;
70 };
71
updateYUVComponentSizes(ImageDecoder * decoder,SkISize componentSizes[3],ImageDecoder::SizeType sizeType)72 static 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
ImageFrameGenerator(const SkISize & fullSize,PassRefPtr<SharedBuffer> data,bool allDataReceived,bool isMultiFrame)88 ImageFrameGenerator::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
~ImageFrameGenerator()97 ImageFrameGenerator::~ImageFrameGenerator()
98 {
99 ImageDecodingStore::instance()->removeCacheIndexedByGenerator(this);
100 }
101
setData(PassRefPtr<SharedBuffer> data,bool allDataReceived)102 void ImageFrameGenerator::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
103 {
104 m_data.setData(data.get(), allDataReceived);
105 }
106
copyData(RefPtr<SharedBuffer> * data,bool * allDataReceived)107 void 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
decodeAndScale(const SkImageInfo & info,size_t index,void * pixels,size_t rowBytes)115 bool 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
decodeToYUV(SkISize componentSizes[3],void * planes[3],size_t rowBytes[3])152 bool 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
tryToResumeDecode(const SkISize & scaledSize,size_t index)194 SkBitmap 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
setHasAlpha(size_t index,bool hasAlpha)241 void 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
decode(size_t index,ImageDecoder ** decoder,SkBitmap * bitmap)253 bool 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
hasAlpha(size_t index)306 bool 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
getYUVComponentSizes(SkISize componentSizes[3])314 bool 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