| Index: third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
|
| diff --git a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
|
| index 0230e474f4411dec576b02d6f865cad892eb5c7c..39a11f9ea619244d84ebd18df4dbbdba22cfbd6d 100644
|
| --- a/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
|
| +++ b/third_party/WebKit/Source/platform/graphics/ImageFrameGenerator.cpp
|
| @@ -27,6 +27,7 @@
|
|
|
| #include "platform/graphics/ImageFrameGenerator.h"
|
|
|
| +#include "SkData.h"
|
| #include "platform/SharedBuffer.h"
|
| #include "platform/TraceEvent.h"
|
| #include "platform/graphics/ImageDecodingStore.h"
|
| @@ -101,30 +102,77 @@ static bool updateYUVComponentSizes(ImageDecoder* decoder, SkISize componentSize
|
|
|
| ImageFrameGenerator::ImageFrameGenerator(const SkISize& fullSize, PassRefPtr<SharedBuffer> data, bool allDataReceived, bool isMultiFrame)
|
| : m_fullSize(fullSize)
|
| + , m_data(adoptRef(new ThreadSafeDataTransport()))
|
| , m_isMultiFrame(isMultiFrame)
|
| , m_decodeFailedAndEmpty(false)
|
| , m_decodeCount(0)
|
| , m_frameCount(0)
|
| + , m_encodedData(nullptr)
|
| {
|
| setData(data.get(), allDataReceived);
|
| }
|
|
|
| ImageFrameGenerator::~ImageFrameGenerator()
|
| {
|
| + if (m_encodedData)
|
| + m_encodedData->unref();
|
| ImageDecodingStore::instance().removeCacheIndexedByGenerator(this);
|
| }
|
|
|
| void ImageFrameGenerator::setData(PassRefPtr<SharedBuffer> data, bool allDataReceived)
|
| {
|
| - m_data.setData(data.get(), allDataReceived);
|
| + m_data->setData(data.get(), allDataReceived);
|
| }
|
|
|
| -void ImageFrameGenerator::copyData(RefPtr<SharedBuffer>* data, bool* allDataReceived)
|
| +static void sharedSkDataReleaseCallback(const void* address, void* context)
|
| {
|
| + // This gets called when m_encodedData reference count becomes 0 - and it could happen in
|
| + // ImageFrameGenerator destructor or later when m_encodedData gets dereferenced.
|
| + // In this method, we deref ThreadSafeDataTransport, as ThreadSafeDataTransport is the owner
|
| + // of data returned via refEncodedData.
|
| +
|
| + ThreadSafeDataTransport* dataTransport = static_cast<ThreadSafeDataTransport*>(context);
|
| +#if ENABLE(ASSERT)
|
| + ASSERT(dataTransport);
|
| SharedBuffer* buffer = 0;
|
| - m_data.data(&buffer, allDataReceived);
|
| - if (buffer)
|
| - *data = buffer->copy();
|
| + bool allDataReceived = false;
|
| + dataTransport->data(&buffer, &allDataReceived);
|
| + ASSERT(allDataReceived && buffer && buffer->data() == address);
|
| +#endif
|
| + // Dereference m_data now.
|
| + dataTransport->deref();
|
| +}
|
| +
|
| +SkData* ImageFrameGenerator::refEncodedData()
|
| +{
|
| + // SkData is returned only when full image (encoded) data is received. This is important
|
| + // since DeferredImageDecoder::setData is called only once with allDataReceived set to true,
|
| + // and after that m_data->m_readBuffer.data() is not changed. See also RELEASE_ASSERT used in
|
| + // ThreadSafeDataTransport::data().
|
| + SharedBuffer* buffer = 0;
|
| + bool allDataReceived = false;
|
| + m_data->data(&buffer, &allDataReceived);
|
| + if (!allDataReceived)
|
| + return nullptr;
|
| +
|
| + {
|
| + // Prevents concurrent access to m_encodedData creation.
|
| + MutexLocker lock(m_decodeMutex);
|
| + if (m_encodedData) {
|
| + m_encodedData->ref();
|
| + return m_encodedData;
|
| + }
|
| + // m_encodedData is created with initial reference count == 1. ImageFrameGenerator always holds one
|
| + // reference to m_encodedData, as it prevents write access in SkData::writable_data.
|
| + m_encodedData = SkData::NewWithProc(buffer->data(), buffer->size(), sharedSkDataReleaseCallback, m_data.get());
|
| + // While m_encodedData is referenced, prevent disposing m_data and its content.
|
| + // it is dereferenced in sharedSkDataReleaseCallback, called when m_encodedData gets dereferenced.
|
| + m_data->ref();
|
| + }
|
| + // Increase the reference, caller must decrease it. One reference is always kept by ImageFrameGenerator and released
|
| + // in destructor.
|
| + m_encodedData->ref();
|
| + return m_encodedData;
|
| }
|
|
|
| bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes)
|
| @@ -184,7 +232,7 @@ bool ImageFrameGenerator::decodeToYUV(SkISize componentSizes[3], void* planes[3]
|
|
|
| SharedBuffer* data = 0;
|
| bool allDataReceived = false;
|
| - m_data.data(&data, &allDataReceived);
|
| + m_data->data(&data, &allDataReceived);
|
|
|
| // FIXME: YUV decoding does not currently support progressive decoding.
|
| ASSERT(allDataReceived);
|
| @@ -290,7 +338,7 @@ bool ImageFrameGenerator::decode(size_t index, ImageDecoder** decoder, SkBitmap*
|
| SharedBuffer* data = 0;
|
| bool allDataReceived = false;
|
| bool newDecoder = false;
|
| - m_data.data(&data, &allDataReceived);
|
| + m_data->data(&data, &allDataReceived);
|
|
|
| // Try to create an ImageDecoder if we are not given one.
|
| if (!*decoder) {
|
| @@ -358,7 +406,7 @@ bool ImageFrameGenerator::getYUVComponentSizes(SkISize componentSizes[3])
|
|
|
| SharedBuffer* data = 0;
|
| bool allDataReceived = false;
|
| - m_data.data(&data, &allDataReceived);
|
| + m_data->data(&data, &allDataReceived);
|
|
|
| // FIXME: YUV decoding does not currently support progressive decoding.
|
| if (!allDataReceived)
|
|
|