| 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 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |