Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(243)

Side by Side Diff: third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp

Issue 1527433002: Deferred GIF image decodes should report decode failures (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 componentSizes[1].set(size.width(), size.height()); 97 componentSizes[1].set(size.width(), size.height());
98 size = decoder->decodedYUVSize(2, sizeType); 98 size = decoder->decodedYUVSize(2, sizeType);
99 componentSizes[2].set(size.width(), size.height()); 99 componentSizes[2].set(size.width(), size.height());
100 return true; 100 return true;
101 } 101 }
102 102
103 ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<Sha redBuffer> data, bool allDataReceived, bool isMultiFrame) 103 ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<Sha redBuffer> data, bool allDataReceived, bool isMultiFrame)
104 : m_fullSize(fullSize) 104 : m_fullSize(fullSize)
105 , m_data(adoptRef(new ThreadSafeDataTransport())) 105 , m_data(adoptRef(new ThreadSafeDataTransport()))
106 , m_isMultiFrame(isMultiFrame) 106 , m_isMultiFrame(isMultiFrame)
107 , m_decodeFailedAndEmpty(false) 107 , m_decodeFailed(false)
108 , m_decodeCount(0)
109 , m_frameCount(0) 108 , m_frameCount(0)
110 , m_encodedData(nullptr) 109 , m_encodedData(nullptr)
111 { 110 {
112 setData(data.get(), allDataReceived); 111 setData(data.get(), allDataReceived);
113 } 112 }
114 113
115 ImageFrameGenerator::~ImageFrameGenerator() 114 ImageFrameGenerator::~ImageFrameGenerator()
116 { 115 {
117 if (m_encodedData) 116 if (m_encodedData)
118 m_encodedData->unref(); 117 m_encodedData->unref();
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 // While m_encodedData is referenced, prevent disposing m_data and its c ontent. 167 // While m_encodedData is referenced, prevent disposing m_data and its c ontent.
169 // it is dereferenced in sharedSkDataReleaseCallback, called when m_enco dedData gets dereferenced. 168 // it is dereferenced in sharedSkDataReleaseCallback, called when m_enco dedData gets dereferenced.
170 m_data->ref(); 169 m_data->ref();
171 } 170 }
172 // Increase the reference, caller must decrease it. One reference is always kept by ImageFrameGenerator and released 171 // Increase the reference, caller must decrease it. One reference is always kept by ImageFrameGenerator and released
173 // in destructor. 172 // in destructor.
174 m_encodedData->ref(); 173 m_encodedData->ref();
175 return m_encodedData; 174 return m_encodedData;
176 } 175 }
177 176
178 bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes) 177 bool ImageFrameGenerator::decodeAndScale(size_t index, const SkImageInfo& info, void* pixels, size_t rowBytes)
179 { 178 {
180 // This method is called to populate a discardable memory owned by Skia. 179 // Prevent concurrent decode or scale operations on the same image data.
180 MutexLocker lock(m_decodeMutex);
181 181
182 // Prevents concurrent decode or scale operations on the same image data. 182 if (m_decodeFailed)
183 MutexLocker lock(m_decodeMutex); 183 return false;
184
185 TRACE_EVENT1("blink", "ImageFrameGenerator::decodeAndScale", "frame index", static_cast<int>(index));
186
187 m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, row Bytes));
184 188
185 // This implementation does not support scaling so check the requested size. 189 // This implementation does not support scaling so check the requested size.
186 SkISize scaledSize = SkISize::Make(info.width(), info.height()); 190 SkISize scaledSize = SkISize::Make(info.width(), info.height());
187 ASSERT(m_fullSize == scaledSize); 191 ASSERT(m_fullSize == scaledSize);
188 192
189 if (m_decodeFailedAndEmpty) 193 SkBitmap bitmap = tryToResumeDecode(index, scaledSize);
190 return false;
191
192 TRACE_EVENT2("blink", "ImageFrameGenerator::decodeAndScale", "generator", th is, "decodeCount", m_decodeCount);
193
194 m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, row Bytes));
195
196 SkBitmap bitmap = tryToResumeDecode(scaledSize, index);
197 if (bitmap.isNull()) 194 if (bitmap.isNull())
198 return false; 195 return false;
199 196
200 // Don't keep the allocator because it contains a pointer to memory 197 // Don't keep the allocator because it contains a pointer to memory
201 // that we do not own. 198 // that we do not own.
202 m_externalAllocator.clear(); 199 m_externalAllocator.clear();
203 200
201 // Check to see if the decoder has written directly to the memory provided
202 // by Skia. If not, make a copy.
scroggo_chromium 2015/12/18 18:12:06 I support removing the comment above ("This method
Noel Gordon 2015/12/21 03:23:22 Thanks Leon, done. Removed the "by Skia" bit.
204 ASSERT(bitmap.width() == scaledSize.width()); 203 ASSERT(bitmap.width() == scaledSize.width());
205 ASSERT(bitmap.height() == scaledSize.height()); 204 ASSERT(bitmap.height() == scaledSize.height());
206
207 bool result = true;
208 SkAutoLockPixels bitmapLock(bitmap); 205 SkAutoLockPixels bitmapLock(bitmap);
209 // Check to see if decoder has written directly to the memory provided
210 // by Skia. If not make a copy.
211 if (bitmap.getPixels() != pixels) 206 if (bitmap.getPixels() != pixels)
212 result = bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes) ; 207 return bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes);
213 return result; 208 return true;
214 } 209 }
215 210
216 bool ImageFrameGenerator::decodeToYUV(SkISize componentSizes[3], void* planes[3] , size_t rowBytes[3]) 211 bool ImageFrameGenerator::decodeToYUV(size_t index, SkISize componentSizes[3], v oid* planes[3], size_t rowBytes[3])
217 { 212 {
218 // This method is called to populate a discardable memory owned by Skia. 213 // Prevent concurrent decode or scale operations on the same image data.
219
220 // Prevents concurrent decode or scale operations on the same image data.
221 MutexLocker lock(m_decodeMutex); 214 MutexLocker lock(m_decodeMutex);
222 215
223 if (m_decodeFailedAndEmpty) 216 if (m_decodeFailed)
224 return false; 217 return false;
225 218
226 TRACE_EVENT2("blink", "ImageFrameGenerator::decodeToYUV", "generator", this, "decodeCount", static_cast<int>(m_decodeCount)); 219 TRACE_EVENT1("blink", "ImageFrameGenerator::decodeToYUV", "frame index", sta tic_cast<int>(index));
227 220
228 if (!planes || !planes[0] || !planes[1] || !planes[2] 221 if (!planes || !planes[0] || !planes[1] || !planes[2]
229 || !rowBytes || !rowBytes[0] || !rowBytes[1] || !rowBytes[2]) { 222 || !rowBytes || !rowBytes[0] || !rowBytes[1] || !rowBytes[2]) {
230 return false; 223 return false;
231 } 224 }
232 225
233 SharedBuffer* data = 0; 226 SharedBuffer* data = 0;
234 bool allDataReceived = false; 227 bool allDataReceived = false;
235 m_data->data(&data, &allDataReceived); 228 m_data->data(&data, &allDataReceived);
236 229
237 // FIXME: YUV decoding does not currently support progressive decoding. 230 // FIXME: YUV decoding does not currently support progressive decoding.
238 ASSERT(allDataReceived); 231 ASSERT(allDataReceived);
239 232
240 OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, ImageDecoder::Alp haPremultiplied, ImageDecoder::GammaAndColorProfileApplied); 233 OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, ImageDecoder::Alp haPremultiplied, ImageDecoder::GammaAndColorProfileApplied);
241 if (!decoder) 234 if (!decoder)
242 return false; 235 return false;
243 236
244 decoder->setData(data, allDataReceived); 237 decoder->setData(data, allDataReceived);
245 238
246 OwnPtr<ImagePlanes> imagePlanes = adoptPtr(new ImagePlanes(planes, rowBytes) ); 239 OwnPtr<ImagePlanes> imagePlanes = adoptPtr(new ImagePlanes(planes, rowBytes) );
247 decoder->setImagePlanes(imagePlanes.release()); 240 decoder->setImagePlanes(imagePlanes.release());
248 241
249 bool sizeUpdated = updateYUVComponentSizes(decoder.get(), componentSizes, Im ageDecoder::ActualSize); 242 bool sizeUpdated = updateYUVComponentSizes(decoder.get(), componentSizes, Im ageDecoder::ActualSize);
250 RELEASE_ASSERT(sizeUpdated); 243 RELEASE_ASSERT(sizeUpdated);
251 244
252 bool yuvDecoded = decoder->decodeToYUV(); 245 if (decoder->decodeToYUV()) {
253 if (yuvDecoded)
254 setHasAlpha(0, false); // YUV is always opaque 246 setHasAlpha(0, false); // YUV is always opaque
255 return yuvDecoded; 247 return true;
248 }
249
250 ASSERT(decoder->failed());
251 m_decodeFailed = true;
252 return false;
256 } 253 }
257 254
258 SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_ t index) 255 SkBitmap ImageFrameGenerator::tryToResumeDecode(size_t index, const SkISize& sca ledSize)
259 { 256 {
260 TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "ind ex", static_cast<int>(index)); 257 TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecode", "frame index ", static_cast<int>(index));
261 258
262 ImageDecoder* decoder = 0; 259 ImageDecoder* decoder = 0;
263 const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder); 260 const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder);
264 ASSERT(!resumeDecoding || decoder); 261 ASSERT(!resumeDecoding || decoder);
265 262
266 SkBitmap fullSizeImage; 263 SkBitmap fullSizeImage;
267 bool complete = decode(index, &decoder, &fullSizeImage); 264 bool complete = decode(index, &decoder, &fullSizeImage);
268 265
269 if (!decoder) 266 if (!decoder)
270 return SkBitmap(); 267 return SkBitmap();
271 if (index >= m_frameComplete.size()) 268 if (index >= m_frameComplete.size())
272 m_frameComplete.resize(index + 1); 269 m_frameComplete.resize(index + 1);
273 m_frameComplete[index] = complete; 270 m_frameComplete[index] = complete;
274 271
275 // If we are not resuming decoding that means the decoder is freshly 272 // If we are not resuming decoding that means the decoder is freshly
276 // created and we have ownership. If we are resuming decoding then 273 // created and we have ownership. If we are resuming decoding then
277 // the decoder is owned by ImageDecodingStore. 274 // the decoder is owned by ImageDecodingStore.
278 OwnPtr<ImageDecoder> decoderContainer; 275 OwnPtr<ImageDecoder> decoderContainer;
279 if (!resumeDecoding) 276 if (!resumeDecoding)
280 decoderContainer = adoptPtr(decoder); 277 decoderContainer = adoptPtr(decoder);
281 278
282 if (fullSizeImage.isNull()) { 279 if (fullSizeImage.isNull()) {
283 // If decode has failed and resulted an empty image we can save work 280 // If decoding has failed, we can save work in the future by
284 // in the future by returning early. 281 // ignoring further requests to decode the image.
285 m_decodeFailedAndEmpty = !m_isMultiFrame && decoder->failed(); 282 m_decodeFailed = decoder->failed();
286
287 if (resumeDecoding) 283 if (resumeDecoding)
288 ImageDecodingStore::instance().unlockDecoder(this, decoder); 284 ImageDecodingStore::instance().unlockDecoder(this, decoder);
289 return SkBitmap(); 285 return SkBitmap();
290 } 286 }
291 287
292 // If the image generated is complete then there is no need to keep 288 // If the image generated is complete then there is no need to keep
293 // the decoder. For multi-frame images, if all frames in the image are 289 // the decoder. For multi-frame images, if all frames in the image are
294 // decoded, we remove the decoder. 290 // decoded, we remove the decoder.
295 bool removeDecoder; 291 bool removeDecoder;
296 292
(...skipping 30 matching lines...) Expand all
327 for (size_t i = oldSize; i < m_hasAlpha.size(); ++i) 323 for (size_t i = oldSize; i < m_hasAlpha.size(); ++i)
328 m_hasAlpha[i] = true; 324 m_hasAlpha[i] = true;
329 } 325 }
330 m_hasAlpha[index] = hasAlpha; 326 m_hasAlpha[index] = hasAlpha;
331 } 327 }
332 328
333 bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap) 329 bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap)
334 { 330 {
335 TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize.wid th(), "height", m_fullSize.height()); 331 TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize.wid th(), "height", m_fullSize.height());
336 332
337 ASSERT(decoder);
338 SharedBuffer* data = 0; 333 SharedBuffer* data = 0;
339 bool allDataReceived = false; 334 bool allDataReceived = false;
340 bool newDecoder = false;
341 m_data->data(&data, &allDataReceived); 335 m_data->data(&data, &allDataReceived);
342 336
343 // Try to create an ImageDecoder if we are not given one. 337 // Try to create an ImageDecoder if we are not given one.
338 ASSERT(decoder);
339 bool newDecoder = false;
344 if (!*decoder) { 340 if (!*decoder) {
345 newDecoder = true; 341 newDecoder = true;
346 if (m_imageDecoderFactory) 342 if (m_imageDecoderFactory)
347 *decoder = m_imageDecoderFactory->create().leakPtr(); 343 *decoder = m_imageDecoderFactory->create().leakPtr();
348 344
349 if (!*decoder) 345 if (!*decoder)
350 *decoder = ImageDecoder::create(*data, ImageDecoder::AlphaPremultipl ied, ImageDecoder::GammaAndColorProfileApplied).leakPtr(); 346 *decoder = ImageDecoder::create(*data, ImageDecoder::AlphaPremultipl ied, ImageDecoder::GammaAndColorProfileApplied).leakPtr();
351 347
352 if (!*decoder) 348 if (!*decoder)
353 return false; 349 return false;
354 } 350 }
355 351
356 if (!m_isMultiFrame && newDecoder && allDataReceived) { 352 if (!m_isMultiFrame && newDecoder && allDataReceived) {
357 // If we're using an external memory allocator that means we're decoding 353 // If we're using an external memory allocator that means we're decoding
358 // directly into the output memory and we can save one memcpy. 354 // directly into the output memory and we can save one memcpy.
359 ASSERT(m_externalAllocator.get()); 355 ASSERT(m_externalAllocator.get());
360 (*decoder)->setMemoryAllocator(m_externalAllocator.get()); 356 (*decoder)->setMemoryAllocator(m_externalAllocator.get());
361 } 357 }
358
362 (*decoder)->setData(data, allDataReceived); 359 (*decoder)->setData(data, allDataReceived);
360 ImageFrame* frame = (*decoder)->frameBufferAtIndex(index);
363 361
364 ImageFrame* frame = (*decoder)->frameBufferAtIndex(index);
365 // For multi-frame image decoders, we need to know how many frames are 362 // For multi-frame image decoders, we need to know how many frames are
366 // in that image in order to release the decoder when all frames are 363 // in that image in order to release the decoder when all frames are
367 // decoded. frameCount() is reliable only if all data is received and set in 364 // decoded. frameCount() is reliable only if all data is received and set in
368 // decoder, particularly with GIF. 365 // decoder, particularly with GIF.
369 if (allDataReceived) 366 if (allDataReceived)
370 m_frameCount = (*decoder)->frameCount(); 367 m_frameCount = (*decoder)->frameCount();
371 368
372 (*decoder)->setData(0, false); // Unref SharedBuffer from ImageDecoder. 369 (*decoder)->setData(0, false); // Unref SharedBuffer from ImageDecoder.
373 (*decoder)->clearCacheExceptFrame(index); 370 (*decoder)->clearCacheExceptFrame(index);
374 (*decoder)->setMemoryAllocator(0); 371 (*decoder)->setMemoryAllocator(0);
375 372
376 if (!frame || frame->status() == ImageFrame::FrameEmpty) 373 if (!frame || frame->status() == ImageFrame::FrameEmpty)
377 return false; 374 return false;
378 375
379 // A cache object is considered complete if we can decode a complete frame. 376 // A cache object is considered complete if we can decode a complete frame.
380 // Or we have received all data. The image might not be fully decoded in 377 // Or we have received all data. The image might not be fully decoded in
381 // the latter case. 378 // the latter case.
382 const bool isDecodeComplete = frame->status() == ImageFrame::FrameComplete | | allDataReceived; 379 const bool isDecodeComplete = frame->status() == ImageFrame::FrameComplete | | allDataReceived;
380
383 SkBitmap fullSizeBitmap = frame->getSkBitmap(); 381 SkBitmap fullSizeBitmap = frame->getSkBitmap();
384 if (!fullSizeBitmap.isNull()) 382 if (!fullSizeBitmap.isNull()) {
385 {
386 ASSERT(fullSizeBitmap.width() == m_fullSize.width() && fullSizeBitmap.he ight() == m_fullSize.height()); 383 ASSERT(fullSizeBitmap.width() == m_fullSize.width() && fullSizeBitmap.he ight() == m_fullSize.height());
387 setHasAlpha(index, !fullSizeBitmap.isOpaque()); 384 setHasAlpha(index, !fullSizeBitmap.isOpaque());
388 } 385 }
386
389 *bitmap = fullSizeBitmap; 387 *bitmap = fullSizeBitmap;
390 return isDecodeComplete; 388 return isDecodeComplete;
391 } 389 }
392 390
393 bool ImageFrameGenerator::hasAlpha(size_t index) 391 bool ImageFrameGenerator::hasAlpha(size_t index)
394 { 392 {
395 MutexLocker lock(m_alphaMutex); 393 MutexLocker lock(m_alphaMutex);
396 if (index < m_hasAlpha.size()) 394 if (index < m_hasAlpha.size())
397 return m_hasAlpha[index]; 395 return m_hasAlpha[index];
398 return true; 396 return true;
399 } 397 }
400 398
401 bool ImageFrameGenerator::getYUVComponentSizes(SkISize componentSizes[3]) 399 bool ImageFrameGenerator::getYUVComponentSizes(SkISize componentSizes[3])
402 { 400 {
403 ASSERT(componentSizes);
404
405 TRACE_EVENT2("blink", "ImageFrameGenerator::getYUVComponentSizes", "width", m_fullSize.width(), "height", m_fullSize.height()); 401 TRACE_EVENT2("blink", "ImageFrameGenerator::getYUVComponentSizes", "width", m_fullSize.width(), "height", m_fullSize.height());
406 402
407 SharedBuffer* data = 0; 403 SharedBuffer* data = 0;
408 bool allDataReceived = false; 404 bool allDataReceived = false;
409 m_data->data(&data, &allDataReceived); 405 m_data->data(&data, &allDataReceived);
410 406
411 // FIXME: YUV decoding does not currently support progressive decoding. 407 // FIXME: YUV decoding does not currently support progressive decoding.
412 if (!allDataReceived) 408 if (!allDataReceived)
413 return false; 409 return false;
414 410
415 OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, ImageDecoder::Alp haPremultiplied, ImageDecoder::GammaAndColorProfileApplied); 411 OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, ImageDecoder::Alp haPremultiplied, ImageDecoder::GammaAndColorProfileApplied);
416 if (!decoder) 412 if (!decoder)
417 return false; 413 return false;
418 414
419 // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding. 415 // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding.
420 decoder->setData(data, allDataReceived); 416 decoder->setData(data, allDataReceived);
421 OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes); 417 OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes);
422 decoder->setImagePlanes(dummyImagePlanes.release()); 418 decoder->setImagePlanes(dummyImagePlanes.release());
423 419
420 ASSERT(componentSizes);
424 return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder:: SizeForMemoryAllocation); 421 return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder:: SizeForMemoryAllocation);
425 } 422 }
426 423
427 } // namespace blink 424 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698