Chromium Code Reviews| 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 0d29bce0f18e6463f7fcbfd94cabe702c6455231..165100c9eccca3c44aebdf7121997800cc870ac9 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,6 +102,7 @@ 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())) |
|
aleksandar.stojiljkovic
2015/12/04 15:36:59
haraken@
|
| , m_isMultiFrame(isMultiFrame) |
| , m_decodeFailedAndEmpty(false) |
| , m_decodeCount(0) |
| @@ -116,15 +118,56 @@ ImageFrameGenerator::~ImageFrameGenerator() |
| 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) |
| { |
| + 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 |
| + // Deref m_data now. |
| + dataTransport->deref(); |
| +} |
| + |
| +SkData* ImageFrameGenerator::refEncodedData() const |
| +{ |
| + // Every SkData instance and SharedBuffer need to hold reference to buffer->data(). |
| + // Both SkData and m_data->m_readBuffer are having separate reference counting |
| + // implementations. |
| + // |
| + // SkData's SkData::NewWithProc is designed with similar use case in mind, |
| + // unmapping wrapped shmem data once all SkData instances are disposed. |
| + // |
| + // In this case, sharedSkDataReleaseCallback would get called when SkData is disposed. |
| + // In sharedSkDataReleaseCallback, we deref ThreadSafeDataTransport (and ImageFrameGenerator |
| + // might still hold a reference to ThreadSafeDataTransport). |
| + // |
| + // Multithreading concerns: |
| + // ThreadSafeDataTransport disposal needs to be thread safe - SkData could get disposed |
| + // in any thread, and SkData would still need to hold the reference to SharedBuffer when |
| + // ImageFrameGenerator is deleted. This is why m_data (ThreadSafeRefCounted) is passed to |
| + // client - to hold the reference to SharedBuffer (accompanying returned SkData). |
| + // |
| + // A note about allDataReceived: |
| + // SkData is returned only when full image (encoded) data is downloaded. 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; |
| + |
| + // While SkData is holding reference to underlying data, prevent disposing m_data and its content. |
| + m_data->ref(); |
| + return SkData::NewWithProc(buffer->data(), buffer->size(), sharedSkDataReleaseCallback, m_data.get()); |
| } |
| bool ImageFrameGenerator::decodeAndScale(const SkImageInfo& info, size_t index, void* pixels, size_t rowBytes) |
| @@ -184,7 +227,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 +333,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 +401,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) |