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

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

Issue 1403393004: JPEGImageDecoder RGB565 and downsample support and related Skia imagegenerator changes Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Continued decoding fix and downscale combined Created 5 years, 1 month 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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
125 *data = buffer->copy(); 125 *data = buffer->copy();
126 } 126 }
127 127
128 bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes) 128 bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes)
129 { 129 {
130 // This method is called to populate a discardable memory owned by Skia. 130 // This method is called to populate a discardable memory owned by Skia.
131 131
132 // Prevents concurrent decode or scale operations on the same image data. 132 // Prevents concurrent decode or scale operations on the same image data.
133 MutexLocker lock(m_decodeMutex); 133 MutexLocker lock(m_decodeMutex);
134 134
135 // This implementation does not support scaling so check the requested size. 135 SkISize outputSize = SkISize::Make(info.width(), info.height());
136 SkISize scaledSize = SkISize::Make(info.width(), info.height());
137 ASSERT(m_fullSize == scaledSize);
138 136
139 if (m_decodeFailedAndEmpty) 137 if (m_decodeFailedAndEmpty)
140 return false; 138 return false;
141 139
142 TRACE_EVENT2("blink", "ImageFrameGenerator::decodeAndScale", "generator", th is, "decodeCount", m_decodeCount); 140 TRACE_EVENT2("blink", "ImageFrameGenerator::decodeAndScale", "generator", th is, "decodeCount", m_decodeCount);
143 141
144 m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, row Bytes)); 142 m_externalAllocator = adoptPtr(new ExternalMemoryAllocator(info, pixels, row Bytes));
145 143
146 SkBitmap bitmap = tryToResumeDecode(scaledSize, index); 144 SkBitmap bitmap = tryToResumeDecode(outputSize, index, info.colorType(), row Bytes);
147 if (bitmap.isNull())
148 return false;
149 145
150 // Don't keep the allocator because it contains a pointer to memory 146 // Don't keep the allocator because it contains a pointer to memory
151 // that we do not own. 147 // that we do not own.
152 m_externalAllocator.clear(); 148 m_externalAllocator.clear();
153 149
154 ASSERT(bitmap.width() == scaledSize.width()); 150 if (bitmap.isNull())
155 ASSERT(bitmap.height() == scaledSize.height()); 151 return false;
152
153 ASSERT(bitmap.width() == outputSize.width());
154 ASSERT(bitmap.height() == outputSize.height());
156 155
157 bool result = true; 156 bool result = true;
158 SkAutoLockPixels bitmapLock(bitmap); 157 SkAutoLockPixels bitmapLock(bitmap);
159 // Check to see if decoder has written directly to the memory provided 158 // Check to see if decoder has written directly to the memory provided
160 // by Skia. If not make a copy. 159 // by Skia. If not make a copy.
161 if (bitmap.getPixels() != pixels) 160 if (bitmap.getPixels() != pixels)
162 result = bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes) ; 161 result = bitmap.copyPixelsTo(pixels, rowBytes * info.height(), rowBytes) ;
163 return result; 162 return result;
164 } 163 }
165 164
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
198 197
199 bool sizeUpdated = updateYUVComponentSizes(decoder.get(), componentSizes, Im ageDecoder::ActualSize); 198 bool sizeUpdated = updateYUVComponentSizes(decoder.get(), componentSizes, Im ageDecoder::ActualSize);
200 RELEASE_ASSERT(sizeUpdated); 199 RELEASE_ASSERT(sizeUpdated);
201 200
202 bool yuvDecoded = decoder->decodeToYUV(); 201 bool yuvDecoded = decoder->decodeToYUV();
203 if (yuvDecoded) 202 if (yuvDecoded)
204 setHasAlpha(0, false); // YUV is always opaque 203 setHasAlpha(0, false); // YUV is always opaque
205 return yuvDecoded; 204 return yuvDecoded;
206 } 205 }
207 206
208 SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& scaledSize, size_ t index) 207 SkBitmap ImageFrameGenerator::tryToResumeDecode(const SkISize& outputSize, size_ t index, SkColorType outputType, size_t rowBytes)
209 { 208 {
210 TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "ind ex", static_cast<int>(index)); 209 TRACE_EVENT1("blink", "ImageFrameGenerator::tryToResumeDecodeAndScale", "ind ex", static_cast<int>(index));
211 210
212 ImageDecoder* decoder = 0; 211 ImageDecoder* decoder = 0;
213 const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder); 212 const bool resumeDecoding = ImageDecodingStore::instance().lockDecoder(this, m_fullSize, &decoder);
214 ASSERT(!resumeDecoding || decoder); 213 ASSERT(!resumeDecoding || decoder);
215 214
216 SkBitmap fullSizeImage; 215 SkBitmap image;
217 bool complete = decode(index, &decoder, &fullSizeImage); 216 bool complete = decode(index, &decoder, &image, outputType, outputSize, rowB ytes);
218 217
219 if (!decoder) 218 if (!decoder)
220 return SkBitmap(); 219 return SkBitmap();
221 if (index >= m_frameComplete.size()) 220 if (index >= m_frameComplete.size())
222 m_frameComplete.resize(index + 1); 221 m_frameComplete.resize(index + 1);
223 m_frameComplete[index] = complete; 222 m_frameComplete[index] = complete;
224 223
225 // If we are not resuming decoding that means the decoder is freshly 224 // If we are not resuming decoding that means the decoder is freshly
226 // created and we have ownership. If we are resuming decoding then 225 // created and we have ownership. If we are resuming decoding then
227 // the decoder is owned by ImageDecodingStore. 226 // the decoder is owned by ImageDecodingStore.
228 OwnPtr<ImageDecoder> decoderContainer; 227 OwnPtr<ImageDecoder> decoderContainer;
229 if (!resumeDecoding) 228 if (!resumeDecoding)
230 decoderContainer = adoptPtr(decoder); 229 decoderContainer = adoptPtr(decoder);
231 230
232 if (fullSizeImage.isNull()) { 231 if (image.isNull()) {
233 // If decode has failed and resulted an empty image we can save work 232 // If decode has failed and resulted an empty image we can save work
234 // in the future by returning early. 233 // in the future by returning early.
235 m_decodeFailedAndEmpty = !m_isMultiFrame && decoder->failed(); 234 m_decodeFailedAndEmpty = !m_isMultiFrame && decoder->failed();
236 235
237 if (resumeDecoding) 236 if (resumeDecoding)
238 ImageDecodingStore::instance().unlockDecoder(this, decoder); 237 ImageDecodingStore::instance().unlockDecoder(this, decoder);
239 return SkBitmap(); 238 return SkBitmap();
240 } 239 }
241 240
242 // If the image generated is complete then there is no need to keep 241 // If the image generated is complete then there is no need to keep
(...skipping 15 matching lines...) Expand all
258 if (resumeDecoding) { 257 if (resumeDecoding) {
259 if (removeDecoder) { 258 if (removeDecoder) {
260 ImageDecodingStore::instance().removeDecoder(this, decoder); 259 ImageDecodingStore::instance().removeDecoder(this, decoder);
261 m_frameComplete.clear(); 260 m_frameComplete.clear();
262 } else { 261 } else {
263 ImageDecodingStore::instance().unlockDecoder(this, decoder); 262 ImageDecodingStore::instance().unlockDecoder(this, decoder);
264 } 263 }
265 } else if (!removeDecoder) { 264 } else if (!removeDecoder) {
266 ImageDecodingStore::instance().insertDecoder(this, decoderContainer.rele ase()); 265 ImageDecodingStore::instance().insertDecoder(this, decoderContainer.rele ase());
267 } 266 }
268 return fullSizeImage; 267 return image;
269 } 268 }
270 269
271 void ImageFrameGenerator::setHasAlpha(size_t index, bool hasAlpha) 270 void ImageFrameGenerator::setHasAlpha(size_t index, bool hasAlpha)
272 { 271 {
273 MutexLocker lock(m_alphaMutex); 272 MutexLocker lock(m_alphaMutex);
274 if (index >= m_hasAlpha.size()) { 273 if (index >= m_hasAlpha.size()) {
275 const size_t oldSize = m_hasAlpha.size(); 274 const size_t oldSize = m_hasAlpha.size();
276 m_hasAlpha.resize(index + 1); 275 m_hasAlpha.resize(index + 1);
277 for (size_t i = oldSize; i < m_hasAlpha.size(); ++i) 276 for (size_t i = oldSize; i < m_hasAlpha.size(); ++i)
278 m_hasAlpha[i] = true; 277 m_hasAlpha[i] = true;
279 } 278 }
280 m_hasAlpha[index] = hasAlpha; 279 m_hasAlpha[index] = hasAlpha;
281 } 280 }
282 281
283 bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap) 282 bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap* bitmap, SkColorType outputType, const SkISize& outputSize, size_t rowBytes)
284 { 283 {
285 TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize.wid th(), "height", m_fullSize.height()); 284 TRACE_EVENT2("blink", "ImageFrameGenerator::decode", "width", m_fullSize.wid th(), "height", m_fullSize.height());
286 285
287 ASSERT(decoder); 286 ASSERT(decoder);
288 SharedBuffer* data = 0; 287 SharedBuffer* data = 0;
289 bool allDataReceived = false; 288 bool allDataReceived = false;
290 bool newDecoder = false;
291 m_data.data(&data, &allDataReceived); 289 m_data.data(&data, &allDataReceived);
292 290
291 if (outputSize.width() != m_fullSize.width() || outputSize.height() != m_ful lSize.height()) {
292 ASSERT(allDataReceived);
293 ASSERT(!m_isMultiFrame);
294 if (m_isMultiFrame || !allDataReceived)
295 return false;
296 }
297
293 // Try to create an ImageDecoder if we are not given one. 298 // Try to create an ImageDecoder if we are not given one.
294 if (!*decoder) { 299 if (!*decoder) {
295 newDecoder = true;
296 if (m_imageDecoderFactory) 300 if (m_imageDecoderFactory)
297 *decoder = m_imageDecoderFactory->create().leakPtr(); 301 *decoder = m_imageDecoderFactory->create().leakPtr();
298 302
299 if (!*decoder) 303 if (!*decoder)
300 *decoder = ImageDecoder::create(*data, ImageDecoder::AlphaPremultipl ied, ImageDecoder::GammaAndColorProfileApplied).leakPtr(); 304 *decoder = ImageDecoder::create(*data, ImageDecoder::AlphaPremultipl ied, ImageDecoder::GammaAndColorProfileApplied).leakPtr();
301 305
302 if (!*decoder) 306 if (!*decoder)
303 return false; 307 return false;
304 } 308 }
305 309
306 if (!m_isMultiFrame && newDecoder && allDataReceived) { 310 if (!m_isMultiFrame && allDataReceived) {
307 // If we're using an external memory allocator that means we're decoding 311 // 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. 312 // directly into the output memory and we can save one memcpy.
309 ASSERT(m_externalAllocator.get()); 313 ASSERT(m_externalAllocator.get());
310 (*decoder)->setMemoryAllocator(m_externalAllocator.get()); 314 (*decoder)->setMemoryAllocator(m_externalAllocator.get());
315 if (outputType != kN32_SkColorType || outputSize.width() != m_fullSize.w idth() || outputSize.height() != m_fullSize.height()) {
316 size_t maxDecodeBytes = outputSize.height() * rowBytes;
317 if (!(*decoder)->activateDecodeAndScale(static_cast<ImageFrame::Colo rType>(outputType), maxDecodeBytes)) {
318 ASSERT(false);
319 (*decoder)->setMemoryAllocator(0);
320 return false;
321 }
322 }
311 } 323 }
312 (*decoder)->setData(data, allDataReceived); 324 (*decoder)->setData(data, allDataReceived);
325 ImageFrame* frame = (*decoder)->frameBufferAtIndex(index);
326 // restore back to default
327 (*decoder)->disableDecodeAndScale();
313 328
314 ImageFrame* frame = (*decoder)->frameBufferAtIndex(index);
315 // For multi-frame image decoders, we need to know how many frames are 329 // 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 330 // 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 331 // decoded. frameCount() is reliable only if all data is received and set in
318 // decoder, particularly with GIF. 332 // decoder, particularly with GIF.
319 if (allDataReceived) 333 if (allDataReceived)
320 m_frameCount = (*decoder)->frameCount(); 334 m_frameCount = (*decoder)->frameCount();
321 335
322 (*decoder)->setData(0, false); // Unref SharedBuffer from ImageDecoder. 336 (*decoder)->setData(0, false); // Unref SharedBuffer from ImageDecoder.
323 (*decoder)->clearCacheExceptFrame(index); 337 (*decoder)->clearCacheExceptFrame(index);
324 (*decoder)->setMemoryAllocator(0); 338 (*decoder)->setMemoryAllocator(0);
325 339
326 if (!frame || frame->status() == ImageFrame::FrameEmpty) 340 if (!frame || frame->status() == ImageFrame::FrameEmpty)
327 return false; 341 return false;
328 342
329 // A cache object is considered complete if we can decode a complete frame. 343 // 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 344 // Or we have received all data. The image might not be fully decoded in
331 // the latter case. 345 // the latter case.
332 const bool isDecodeComplete = frame->status() == ImageFrame::FrameComplete | | allDataReceived; 346 const bool isDecodeComplete = frame->status() == ImageFrame::FrameComplete | | allDataReceived;
333 SkBitmap fullSizeBitmap = frame->getSkBitmap(); 347 SkBitmap decodedBitmap = frame->getSkBitmap();
334 if (!fullSizeBitmap.isNull()) 348 if (!decodedBitmap.isNull())
335 { 349 {
336 ASSERT(fullSizeBitmap.width() == m_fullSize.width() && fullSizeBitmap.he ight() == m_fullSize.height()); 350 ASSERT(decodedBitmap.width() == outputSize.width() && decodedBitmap.heig ht() == outputSize.height());
337 setHasAlpha(index, !fullSizeBitmap.isOpaque()); 351 setHasAlpha(index, !decodedBitmap.isOpaque());
338 } 352 }
339 *bitmap = fullSizeBitmap; 353 *bitmap = decodedBitmap;
340 return isDecodeComplete; 354 return isDecodeComplete;
341 } 355 }
342 356
343 bool ImageFrameGenerator::hasAlpha(size_t index) 357 bool ImageFrameGenerator::hasAlpha(size_t index)
344 { 358 {
345 MutexLocker lock(m_alphaMutex); 359 MutexLocker lock(m_alphaMutex);
346 if (index < m_hasAlpha.size()) 360 if (index < m_hasAlpha.size())
347 return m_hasAlpha[index]; 361 return m_hasAlpha[index];
348 return true; 362 return true;
349 } 363 }
(...skipping 22 matching lines...) Expand all
372 return false; 386 return false;
373 387
374 // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding. 388 // Setting a dummy ImagePlanes object signals to the decoder that we want to do YUV decoding.
375 decoder->setData(data, allDataReceived); 389 decoder->setData(data, allDataReceived);
376 OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes); 390 OwnPtr<ImagePlanes> dummyImagePlanes = adoptPtr(new ImagePlanes);
377 decoder->setImagePlanes(dummyImagePlanes.release()); 391 decoder->setImagePlanes(dummyImagePlanes.release());
378 392
379 return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder:: SizeForMemoryAllocation); 393 return updateYUVComponentSizes(decoder.get(), componentSizes, ImageDecoder:: SizeForMemoryAllocation);
380 } 394 }
381 395
396 void ImageFrameGenerator::getAvailableDecodeAndScale(SkColorType* outType, float * scale, float* lowerScale)
397 {
398 // as the same buffer could be used to store consecutive frames, avoid the c omplexity
399 // since some of consecutive frames could have alpha
400 if (m_isMultiFrame) {
401 // pass the same content as in default ImageDecoder
402 ImageDecoder::defaultDecodeAndScale(reinterpret_cast<ImageFrame::ColorTy pe*>(outType), scale, lowerScale);
403 }
404
405 // FIXME check how much this cost (decoder creation) and, also for getYUVCom ponentSizes,
406 // cache it in ImageDecodingStore for the real decode
407 SharedBuffer* data = 0;
408 bool allDataReceived = false;
409 m_data.data(&data, &allDataReceived);
410
411 // partially received data needs to have alpha and skip downsampling
412 if (allDataReceived) {
413 OwnPtr<ImageDecoder> decoder = ImageDecoder::create(*data, ImageDecoder: :AlphaPremultiplied, ImageDecoder::GammaAndColorProfileApplied);
414 if (decoder) {
415 decoder->getAvailableDecodeAndScale(reinterpret_cast<ImageFrame::Col orType*>(outType), scale, lowerScale);
416 return;
417 }
418 }
419 ImageDecoder::defaultDecodeAndScale(reinterpret_cast<ImageFrame::ColorType*> (outType), scale, lowerScale);
420 }
421
382 } // namespace blink 422 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698