• Home
  • History
  • Annotate
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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