OLD | NEW |
---|---|
1 /* | 1 /* |
2 * Copyright (C) 2012 Google Inc. All rights reserved. | 2 * Copyright (C) 2012 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions | 5 * modification, are permitted provided that the following conditions |
6 * are met: | 6 * are met: |
7 * 1. Redistributions of source code must retain the above copyright | 7 * 1. Redistributions of source code must retain the above copyright |
8 * notice, this list of conditions and the following disclaimer. | 8 * notice, this list of conditions and the following disclaimer. |
9 * 2. Redistributions in binary form must reproduce the above copyright | 9 * 2. Redistributions in binary form must reproduce the above copyright |
10 * notice, this list of conditions and the following disclaimer in the | 10 * notice, this list of conditions and the following disclaimer in the |
(...skipping 18 matching lines...) Expand all Loading... | |
29 #include "platform/graphics/ImageDecodingStore.h" | 29 #include "platform/graphics/ImageDecodingStore.h" |
30 #include "platform/image-decoders/ImageDecoder.h" | 30 #include "platform/image-decoders/ImageDecoder.h" |
31 #include "platform/instrumentation/tracing/TraceEvent.h" | 31 #include "platform/instrumentation/tracing/TraceEvent.h" |
32 #include "third_party/skia/include/core/SkYUVSizeInfo.h" | 32 #include "third_party/skia/include/core/SkYUVSizeInfo.h" |
33 #include "wtf/PtrUtil.h" | 33 #include "wtf/PtrUtil.h" |
34 #include <memory> | 34 #include <memory> |
35 | 35 |
36 namespace blink { | 36 namespace blink { |
37 | 37 |
38 static bool compatibleInfo(const SkImageInfo& src, const SkImageInfo& dst) { | 38 static bool compatibleInfo(const SkImageInfo& src, const SkImageInfo& dst) { |
39 if (src == dst) | 39 bool compatibleSize = src.dimensions() == dst.dimensions(); |
40 return true; | 40 bool compatibleColorType = src.colorType() == dst.colorType(); |
41 | 41 |
42 // It is legal to write kOpaque_SkAlphaType pixels into a kPremul_SkAlphaType | 42 // We should be lenient with alphaType. Any image can be decoded to kUnpremul |
43 // buffer. This can happen when DeferredImageDecoder allocates an | 43 // or kPremul. Opaque images may be marked as kOpaque, but not until they |
44 // kOpaque_SkAlphaType image generator based on cached frame info, while the | 44 // are fully decoded. This means that the buffer may be kPremul, but we are |
45 // ImageFrame-allocated dest bitmap stays kPremul_SkAlphaType. | 45 // writing kOpaque pixels. |
46 if (src.alphaType() == kOpaque_SkAlphaType && | |
47 dst.alphaType() == kPremul_SkAlphaType) { | |
48 const SkImageInfo& tmp = src.makeAlphaType(kPremul_SkAlphaType); | |
49 return tmp == dst; | |
50 } | |
51 | 46 |
52 return false; | 47 // The color spaces also do not need to match. We will perform color space |
48 // conversions when necessary. | |
49 | |
50 return compatibleSize && compatibleColorType; | |
53 } | 51 } |
54 | 52 |
55 // Creates a SkPixelRef such that the memory for pixels is given by an external | 53 // Creates a SkPixelRef such that the memory for pixels is given by an external |
56 // body. This is used to write directly to the memory given by Skia during | 54 // body. This is used to write directly to the memory given by Skia during |
57 // decoding. | 55 // decoding. |
58 class ExternalMemoryAllocator final : public SkBitmap::Allocator { | 56 class ExternalMemoryAllocator final : public SkBitmap::Allocator { |
59 USING_FAST_MALLOC(ExternalMemoryAllocator); | 57 USING_FAST_MALLOC(ExternalMemoryAllocator); |
60 WTF_MAKE_NONCOPYABLE(ExternalMemoryAllocator); | 58 WTF_MAKE_NONCOPYABLE(ExternalMemoryAllocator); |
61 | 59 |
62 public: | 60 public: |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
96 componentWidthBytes[0] = decoder->decodedYUVWidthBytes(0); | 94 componentWidthBytes[0] = decoder->decodedYUVWidthBytes(0); |
97 size = decoder->decodedYUVSize(1); | 95 size = decoder->decodedYUVSize(1); |
98 componentSizes[1].set(size.width(), size.height()); | 96 componentSizes[1].set(size.width(), size.height()); |
99 componentWidthBytes[1] = decoder->decodedYUVWidthBytes(1); | 97 componentWidthBytes[1] = decoder->decodedYUVWidthBytes(1); |
100 size = decoder->decodedYUVSize(2); | 98 size = decoder->decodedYUVSize(2); |
101 componentSizes[2].set(size.width(), size.height()); | 99 componentSizes[2].set(size.width(), size.height()); |
102 componentWidthBytes[2] = decoder->decodedYUVWidthBytes(2); | 100 componentWidthBytes[2] = decoder->decodedYUVWidthBytes(2); |
103 return true; | 101 return true; |
104 } | 102 } |
105 | 103 |
106 ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, | 104 ImageFrameGenerator::ImageFrameGenerator(const SkImageInfo& info, |
107 bool isMultiFrame, | 105 bool isMultiFrame, |
108 const ColorBehavior& colorBehavior) | 106 const ColorBehavior& colorBehavior) |
109 : m_fullSize(fullSize), | 107 : m_info(info), |
110 m_decoderColorBehavior(colorBehavior), | 108 m_decoderColorBehavior(colorBehavior), |
111 m_isMultiFrame(isMultiFrame), | 109 m_isMultiFrame(isMultiFrame), |
112 m_decodeFailed(false), | 110 m_decodeFailed(false), |
113 m_yuvDecodingFailed(false), | 111 m_yuvDecodingFailed(false), |
114 m_frameCount(0) {} | 112 m_frameCount(0) {} |
115 | 113 |
116 ImageFrameGenerator::~ImageFrameGenerator() { | 114 ImageFrameGenerator::~ImageFrameGenerator() { |
117 ImageDecodingStore::instance().removeCacheIndexedByGenerator(this); | 115 ImageDecodingStore::instance().removeCacheIndexedByGenerator(this); |
118 } | 116 } |
119 | 117 |
120 bool ImageFrameGenerator::decodeAndScale(SegmentReader* data, | 118 bool ImageFrameGenerator::decodeAndScale(SegmentReader* data, |
121 bool allDataReceived, | 119 bool allDataReceived, |
122 size_t index, | 120 size_t index, |
123 const SkImageInfo& info, | 121 const SkImageInfo& dstInfo, |
124 void* pixels, | 122 void* pixels, |
125 size_t rowBytes) { | 123 size_t rowBytes) { |
126 if (m_decodeFailed) | 124 if (m_decodeFailed) |
127 return false; | 125 return false; |
128 | 126 |
129 TRACE_EVENT1("blink", "ImageFrameGenerator::decodeAndScale", "frame index", | 127 TRACE_EVENT1("blink", "ImageFrameGenerator::decodeAndScale", "frame index", |
130 static_cast<int>(index)); | 128 static_cast<int>(index)); |
131 | 129 |
132 // This implementation does not support scaling so check the requested size. | 130 // This implementation does not support scaling so check the requested size. |
133 SkISize scaledSize = SkISize::Make(info.width(), info.height()); | 131 SkISize scaledSize = SkISize::Make(dstInfo.width(), dstInfo.height()); |
134 ASSERT(m_fullSize == scaledSize); | 132 DCHECK(m_info.dimensions() == scaledSize); |
scroggo_chromium
2017/04/07 18:06:06
scaledSize looks to be never used again (or it doe
| |
135 | 133 |
136 // It is okay to allocate ref-counted ExternalMemoryAllocator on the stack, | 134 // It is okay to allocate ref-counted ExternalMemoryAllocator on the stack, |
137 // because 1) it contains references to memory that will be invalid after | 135 // because 1) it contains references to memory that will be invalid after |
138 // returning (i.e. a pointer to |pixels|) and therefore 2) should not live | 136 // returning (i.e. a pointer to |pixels|) and therefore 2) should not live |
139 // longer than the call to the current method. | 137 // longer than the call to the current method. |
140 ExternalMemoryAllocator externalAllocator(info, pixels, rowBytes); | 138 ExternalMemoryAllocator externalAllocator(dstInfo, pixels, rowBytes); |
141 SkBitmap bitmap = tryToResumeDecode(data, allDataReceived, index, scaledSize, | 139 SkBitmap bitmap = tryToResumeDecode(data, allDataReceived, index, scaledSize, |
142 &externalAllocator); | 140 &externalAllocator, dstInfo); |
143 DCHECK(externalAllocator.unique()); // Verify we have the only ref-count. | 141 DCHECK(externalAllocator.unique()); // Verify we have the only ref-count. |
144 | 142 |
145 if (bitmap.isNull()) | 143 if (bitmap.isNull()) |
146 return false; | 144 return false; |
147 | 145 |
148 // Check to see if the decoder has written directly to the pixel memory | 146 // Check to see if the decoder has written directly to the pixel memory |
149 // provided. If not, make a copy. | 147 // provided. If not, make a copy. |
150 ASSERT(bitmap.width() == scaledSize.width()); | 148 ASSERT(bitmap.width() == scaledSize.width()); |
scroggo_chromium
2017/04/07 18:06:06
If you drop scaledSize, this could be:
DCHECK_E
| |
151 ASSERT(bitmap.height() == scaledSize.height()); | 149 ASSERT(bitmap.height() == scaledSize.height()); |
152 SkAutoLockPixels bitmapLock(bitmap); | 150 SkAutoLockPixels bitmapLock(bitmap); |
153 if (bitmap.getPixels() != pixels) | 151 if (bitmap.getPixels() != pixels) |
154 return bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes); | 152 return bitmap.readPixels(bitmap.info(), pixels, rowBytes, 0, 0); |
scroggo_chromium
2017/04/07 18:06:06
Might bitmap.info() be different from dstInfo? I'm
| |
155 return true; | 153 return true; |
156 } | 154 } |
157 | 155 |
158 bool ImageFrameGenerator::decodeToYUV(SegmentReader* data, | 156 bool ImageFrameGenerator::decodeToYUV(SegmentReader* data, |
159 size_t index, | 157 size_t index, |
160 const SkISize componentSizes[3], | 158 const SkISize componentSizes[3], |
161 void* planes[3], | 159 void* planes[3], |
162 const size_t rowBytes[3]) { | 160 const size_t rowBytes[3]) { |
163 // TODO (scroggo): The only interesting thing this uses from the | 161 // TODO (scroggo): The only interesting thing this uses from the |
164 // ImageFrameGenerator is m_decodeFailed. Move this into | 162 // ImageFrameGenerator is m_decodeFailed. Move this into |
(...skipping 24 matching lines...) Expand all Loading... | |
189 if (decoder->decodeToYUV()) { | 187 if (decoder->decodeToYUV()) { |
190 setHasAlpha(0, false); // YUV is always opaque | 188 setHasAlpha(0, false); // YUV is always opaque |
191 return true; | 189 return true; |
192 } | 190 } |
193 | 191 |
194 ASSERT(decoder->failed()); | 192 ASSERT(decoder->failed()); |
195 m_yuvDecodingFailed = true; | 193 m_yuvDecodingFailed = true; |
196 return false; | 194 return false; |
197 } | 195 } |
198 | 196 |
199 SkBitmap ImageFrameGenerator::tryToResumeDecode( | 197 static inline bool needsColorXform(const SkImageInfo& src, |
200 SegmentReader* data, | 198 const SkImageInfo& dst) { |
201 bool allDataReceived, | 199 return src.colorSpace() && dst.colorSpace() && |
202 size_t index, | 200 !SkColorSpace::Equals(src.colorSpace(), dst.colorSpace()); |
203 const SkISize& scaledSize, | 201 } |
204 SkBitmap::Allocator* allocator) { | 202 |
203 SkBitmap ImageFrameGenerator::tryToResumeDecode(SegmentReader* data, | |
204 bool allDataReceived, | |
205 size_t index, | |
206 const SkISize& scaledSize, | |
207 SkBitmap::Allocator* allocator, | |
208 const SkImageInfo& dstInfo) { | |
205 TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecode", "frame index", | 209 TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecode", "frame index", |
206 static_cast<int>(index)); | 210 static_cast<int>(index)); |
207 | 211 |
208 ImageDecoder* decoder = 0; | 212 ImageDecoder* decoder = 0; |
209 | 213 |
214 const bool needsXform = needsColorXform(m_info, dstInfo); | |
215 ImageDecoder::AlphaOption alphaOption = ImageDecoder::AlphaPremultiplied; | |
216 if (needsXform && !dstInfo.isOpaque()) { | |
scroggo_chromium
2017/04/07 18:06:06
It might be worth noting that you check dstInfo be
msarett1
2017/04/10 14:42:46
Acknowledged.
| |
217 alphaOption = ImageDecoder::AlphaNotPremultiplied; | |
218 } | |
219 | |
210 // Lock the mutex, so only one thread can use the decoder at once. | 220 // Lock the mutex, so only one thread can use the decoder at once. |
211 MutexLocker lock(m_decodeMutex); | 221 MutexLocker lock(m_decodeMutex); |
212 const bool resumeDecoding = | 222 const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder( |
213 ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder); | 223 this, m_info.dimensions(), alphaOption, &decoder); |
214 ASSERT(!resumeDecoding || decoder); | 224 ASSERT(!resumeDecoding || decoder); |
215 | 225 |
216 SkBitmap fullSizeImage; | 226 SkBitmap fullSizeImage; |
217 bool complete = | 227 bool complete = decode(data, allDataReceived, index, &decoder, &fullSizeImage, |
218 decode(data, allDataReceived, index, &decoder, &fullSizeImage, allocator); | 228 allocator, alphaOption, dstInfo); |
219 | 229 |
220 if (!decoder) | 230 if (!decoder) |
221 return SkBitmap(); | 231 return SkBitmap(); |
222 | 232 |
223 // If we are not resuming decoding that means the decoder is freshly | 233 // If we are not resuming decoding that means the decoder is freshly |
224 // created and we have ownership. If we are resuming decoding then | 234 // created and we have ownership. If we are resuming decoding then |
225 // the decoder is owned by ImageDecodingStore. | 235 // the decoder is owned by ImageDecodingStore. |
226 std::unique_ptr<ImageDecoder> decoderContainer; | 236 std::unique_ptr<ImageDecoder> decoderContainer; |
227 if (!resumeDecoding) | 237 if (!resumeDecoding) |
228 decoderContainer = WTF::wrapUnique(decoder); | 238 decoderContainer = WTF::wrapUnique(decoder); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
273 m_hasAlpha[i] = true; | 283 m_hasAlpha[i] = true; |
274 } | 284 } |
275 m_hasAlpha[index] = hasAlpha; | 285 m_hasAlpha[index] = hasAlpha; |
276 } | 286 } |
277 | 287 |
278 bool ImageFrameGenerator::decode(SegmentReader* data, | 288 bool ImageFrameGenerator::decode(SegmentReader* data, |
279 bool allDataReceived, | 289 bool allDataReceived, |
280 size_t index, | 290 size_t index, |
281 ImageDecoder** decoder, | 291 ImageDecoder** decoder, |
282 SkBitmap* bitmap, | 292 SkBitmap* bitmap, |
283 SkBitmap::Allocator* allocator) { | 293 SkBitmap::Allocator* allocator, |
294 ImageDecoder::AlphaOption alphaOption, | |
295 const SkImageInfo& dstInfo) { | |
284 ASSERT(m_decodeMutex.locked()); | 296 ASSERT(m_decodeMutex.locked()); |
285 TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", | 297 TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_info.width(), |
286 m_fullSize.width(), "height", m_fullSize.height()); | 298 "height", m_info.height()); |
287 | 299 |
288 // Try to create an ImageDecoder if we are not given one. | 300 // Try to create an ImageDecoder if we are not given one. |
289 ASSERT(decoder); | 301 ASSERT(decoder); |
290 bool newDecoder = false; | 302 bool newDecoder = false; |
291 bool shouldCallSetData = true; | 303 bool shouldCallSetData = true; |
292 if (!*decoder) { | 304 if (!*decoder) { |
293 newDecoder = true; | 305 newDecoder = true; |
294 if (m_imageDecoderFactory) | 306 if (m_imageDecoderFactory) |
295 *decoder = m_imageDecoderFactory->create().release(); | 307 *decoder = m_imageDecoderFactory->create().release(); |
296 | 308 |
297 if (!*decoder) { | 309 if (!*decoder) { |
298 *decoder = ImageDecoder::create(data, allDataReceived, | 310 *decoder = ImageDecoder::create(data, allDataReceived, alphaOption, |
299 ImageDecoder::AlphaPremultiplied, | |
300 m_decoderColorBehavior) | 311 m_decoderColorBehavior) |
301 .release(); | 312 .release(); |
302 // The newly created decoder just grabbed the data. No need to reset it. | 313 // The newly created decoder just grabbed the data. No need to reset it. |
303 shouldCallSetData = false; | 314 shouldCallSetData = false; |
304 } | 315 } |
305 | 316 |
306 if (!*decoder) | 317 if (!*decoder) |
307 return false; | 318 return false; |
308 } | 319 } |
309 | 320 |
310 | |
311 if (shouldCallSetData) | 321 if (shouldCallSetData) |
312 (*decoder)->setData(data, allDataReceived); | 322 (*decoder)->setData(data, allDataReceived); |
313 | 323 |
314 bool usingExternalAllocator = false; | 324 bool usingExternalAllocator = false; |
315 | 325 |
316 // For multi-frame image decoders, we need to know how many frames are | 326 // For multi-frame image decoders, we need to know how many frames are |
317 // in that image in order to release the decoder when all frames are | 327 // in that image in order to release the decoder when all frames are |
318 // decoded. frameCount() is reliable only if all data is received and set in | 328 // decoded. frameCount() is reliable only if all data is received and set in |
319 // decoder, particularly with GIF. | 329 // decoder, particularly with GIF. |
320 if (allDataReceived) { | 330 if (allDataReceived) { |
(...skipping 22 matching lines...) Expand all Loading... | |
343 return false; | 353 return false; |
344 | 354 |
345 // A cache object is considered complete if we can decode a complete frame. | 355 // A cache object is considered complete if we can decode a complete frame. |
346 // Or we have received all data. The image might not be fully decoded in | 356 // Or we have received all data. The image might not be fully decoded in |
347 // the latter case. | 357 // the latter case. |
348 const bool isDecodeComplete = | 358 const bool isDecodeComplete = |
349 frame->getStatus() == ImageFrame::FrameComplete || allDataReceived; | 359 frame->getStatus() == ImageFrame::FrameComplete || allDataReceived; |
350 | 360 |
351 SkBitmap fullSizeBitmap = frame->bitmap(); | 361 SkBitmap fullSizeBitmap = frame->bitmap(); |
352 if (!fullSizeBitmap.isNull()) { | 362 if (!fullSizeBitmap.isNull()) { |
353 ASSERT(fullSizeBitmap.width() == m_fullSize.width() && | 363 DCHECK(fullSizeBitmap.width() == m_info.width() && |
scroggo_chromium
2017/04/07 18:06:06
So long as you're changing this, it could be:
D
msarett1
2017/04/10 14:42:46
Acknowledged.
| |
354 fullSizeBitmap.height() == m_fullSize.height()); | 364 fullSizeBitmap.height() == m_info.height()); |
355 setHasAlpha(index, !fullSizeBitmap.isOpaque()); | 365 setHasAlpha(index, !fullSizeBitmap.isOpaque()); |
356 } | 366 } |
357 | 367 |
368 if (needsColorXform(m_info, dstInfo)) { | |
scroggo_chromium
2017/04/07 18:06:06
I assume you do not need to do this if fullSizeBit
msarett1
2017/04/10 14:42:46
Acknowledged.
| |
369 DCHECK(dstInfo.isOpaque() || | |
370 ImageDecoder::AlphaNotPremultiplied == alphaOption); | |
371 std::unique_ptr<SkColorSpaceXform> xform = | |
372 SkColorSpaceXform::New(m_info.colorSpace(), dstInfo.colorSpace()); | |
373 | |
374 SkBitmap tmp(fullSizeBitmap); | |
scroggo_chromium
2017/04/07 18:06:06
IIRC, this will make tmp share fullSizeBitmap's Sk
msarett1
2017/04/10 14:42:46
Acknowledged.
| |
375 tmp.lockPixels(); | |
376 uint32_t* row = tmp.getAddr32(0, 0); | |
377 for (int y = 0; y < dstInfo.height(); y++) { | |
scroggo_chromium
2017/04/07 18:06:06
This method is called while m_decodeMutex is locke
msarett1
2017/04/10 14:42:45
Acknowledged.
| |
378 SkColorSpaceXform::ColorFormat format = | |
379 SkColorSpaceXform::kRGBA_8888_ColorFormat; | |
380 if (kN32_SkColorType == kBGRA_8888_SkColorType) { | |
381 format = SkColorSpaceXform::kBGRA_8888_ColorFormat; | |
382 } | |
383 SkAlphaType alphaType = | |
384 dstInfo.isOpaque() ? kOpaque_SkAlphaType : kUnpremul_SkAlphaType; | |
scroggo_chromium
2017/04/07 18:06:06
My first thought was that you could use dstInfo.al
msarett1
2017/04/10 14:42:46
Acknowledged.
| |
385 bool xformed = | |
386 xform->apply(format, row, format, row, dstInfo.width(), alphaType); | |
387 DCHECK(xformed); | |
388 | |
389 // To be compatible with dst space blending, premultiply in the dst space. | |
390 if (kPremul_SkAlphaType == dstInfo.alphaType()) { | |
391 for (int x = 0; x < dstInfo.width(); x++) { | |
392 row[x] = | |
393 SkPreMultiplyARGB(SkGetPackedA32(row[x]), SkGetPackedR32(row[x]), | |
394 SkGetPackedG32(row[x]), SkGetPackedB32(row[x])); | |
395 } | |
396 } | |
397 | |
398 row = (uint32_t*)(((uint8_t*)row) + fullSizeBitmap.rowBytes()); | |
scroggo_chromium
2017/04/07 18:06:06
I think tmp and fullSizeBitmap are essentially the
msarett1
2017/04/10 14:42:46
Acknowledged.
| |
399 } | |
400 } | |
401 | |
358 *bitmap = fullSizeBitmap; | 402 *bitmap = fullSizeBitmap; |
359 return isDecodeComplete; | 403 return isDecodeComplete; |
360 } | 404 } |
361 | 405 |
362 bool ImageFrameGenerator::hasAlpha(size_t index) { | 406 bool ImageFrameGenerator::hasAlpha(size_t index) { |
363 MutexLocker lock(m_alphaMutex); | 407 MutexLocker lock(m_alphaMutex); |
364 if (index < m_hasAlpha.size()) | 408 if (index < m_hasAlpha.size()) |
365 return m_hasAlpha[index]; | 409 return m_hasAlpha[index]; |
366 return true; | 410 return true; |
367 } | 411 } |
368 | 412 |
369 bool ImageFrameGenerator::getYUVComponentSizes(SegmentReader* data, | 413 bool ImageFrameGenerator::getYUVComponentSizes(SegmentReader* data, |
370 SkYUVSizeInfo* sizeInfo) { | 414 SkYUVSizeInfo* sizeInfo) { |
371 TRACE_EVENT2("blink", "ImageFrameGenerator::getYUVComponentSizes", "width", | 415 TRACE_EVENT2("blink", "ImageFrameGenerator::getYUVComponentSizes", "width", |
372 m_fullSize.width(), "height", m_fullSize.height()); | 416 m_info.width(), "height", m_info.height()); |
373 | 417 |
374 if (m_yuvDecodingFailed) | 418 if (m_yuvDecodingFailed) |
375 return false; | 419 return false; |
376 | 420 |
377 std::unique_ptr<ImageDecoder> decoder = ImageDecoder::create( | 421 std::unique_ptr<ImageDecoder> decoder = ImageDecoder::create( |
378 data, true, ImageDecoder::AlphaPremultiplied, m_decoderColorBehavior); | 422 data, true, ImageDecoder::AlphaPremultiplied, m_decoderColorBehavior); |
379 if (!decoder) | 423 if (!decoder) |
380 return false; | 424 return false; |
381 | 425 |
382 // Setting a dummy ImagePlanes object signals to the decoder that we want to | 426 // Setting a dummy ImagePlanes object signals to the decoder that we want to |
383 // do YUV decoding. | 427 // do YUV decoding. |
384 std::unique_ptr<ImagePlanes> dummyImagePlanes = | 428 std::unique_ptr<ImagePlanes> dummyImagePlanes = |
385 WTF::wrapUnique(new ImagePlanes); | 429 WTF::wrapUnique(new ImagePlanes); |
386 decoder->setImagePlanes(std::move(dummyImagePlanes)); | 430 decoder->setImagePlanes(std::move(dummyImagePlanes)); |
387 | 431 |
388 return updateYUVComponentSizes(decoder.get(), sizeInfo->fSizes, | 432 return updateYUVComponentSizes(decoder.get(), sizeInfo->fSizes, |
389 sizeInfo->fWidthBytes); | 433 sizeInfo->fWidthBytes); |
390 } | 434 } |
391 | 435 |
392 } // namespace blink | 436 } // namespace blink |
OLD | NEW |