| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "CanvasAsyncBlobCreator.h" | 5 #include "CanvasAsyncBlobCreator.h" |
| 6 | 6 |
| 7 #include "core/fileapi/Blob.h" | 7 #include "core/fileapi/Blob.h" |
| 8 #include "platform/ThreadSafeFunctional.h" | 8 #include "platform/ThreadSafeFunctional.h" |
| 9 #include "platform/graphics/ImageBuffer.h" | 9 #include "platform/graphics/ImageBuffer.h" |
| 10 #include "platform/heap/Handle.h" | 10 #include "platform/heap/Handle.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 const int NumChannelsPng = 4; | 27 const int NumChannelsPng = 4; |
| 28 const int LongTaskImageSizeThreshold = 1000 * 1000; // The max image size we exp
ect to encode in 14ms on Linux in PNG format | 28 const int LongTaskImageSizeThreshold = 1000 * 1000; // The max image size we exp
ect to encode in 14ms on Linux in PNG format |
| 29 | 29 |
| 30 bool isDeadlineNearOrPassed(double deadlineSeconds) | 30 bool isDeadlineNearOrPassed(double deadlineSeconds) |
| 31 { | 31 { |
| 32 return (deadlineSeconds - SlackBeforeDeadline - monotonicallyIncreasingTime(
) <= 0); | 32 return (deadlineSeconds - SlackBeforeDeadline - monotonicallyIncreasingTime(
) <= 0); |
| 33 } | 33 } |
| 34 | 34 |
| 35 } // anonymous namespace | 35 } // anonymous namespace |
| 36 | 36 |
| 37 CanvasAsyncBlobCreator* CanvasAsyncBlobCreator::create(DOMUint8ClampedArray* unp
remultipliedRGBAImageData, const String& mimeType, const IntSize& size, BlobCall
back* callback) | 37 PassRefPtr<CanvasAsyncBlobCreator> CanvasAsyncBlobCreator::create(PassRefPtr<DOM
Uint8ClampedArray> unpremultipliedRGBAImageData, const String& mimeType, const I
ntSize& size, BlobCallback* callback) |
| 38 { | 38 { |
| 39 return new CanvasAsyncBlobCreator(unpremultipliedRGBAImageData, mimeType, si
ze, callback); | 39 RefPtr<CanvasAsyncBlobCreator> asyncBlobCreator = adoptRef(new CanvasAsyncBl
obCreator(unpremultipliedRGBAImageData, mimeType, size, callback)); |
| 40 return asyncBlobCreator.release(); |
| 40 } | 41 } |
| 41 | 42 |
| 42 CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(DOMUint8ClampedArray* data, const
String& mimeType, const IntSize& size, BlobCallback* callback) | 43 CanvasAsyncBlobCreator::CanvasAsyncBlobCreator(PassRefPtr<DOMUint8ClampedArray>
data, const String& mimeType, const IntSize& size, BlobCallback* callback) |
| 43 : m_data(data) | 44 : m_data(data) |
| 44 , m_size(size) | 45 , m_size(size) |
| 45 , m_mimeType(mimeType) | 46 , m_mimeType(mimeType) |
| 46 , m_callback(callback) | 47 , m_callback(callback) |
| 47 { | 48 { |
| 48 ASSERT(m_data->length() == (unsigned) (size.height() * size.width() * 4)); | 49 ASSERT(m_data->length() == (unsigned) (size.height() * size.width() * 4)); |
| 49 m_encodedImage = adoptPtr(new Vector<unsigned char>()); | 50 m_encodedImage = adoptPtr(new Vector<unsigned char>()); |
| 50 m_pixelRowStride = size.width() * NumChannelsPng; | 51 m_pixelRowStride = size.width() * NumChannelsPng; |
| 51 m_numRowsCompleted = 0; | 52 m_numRowsCompleted = 0; |
| 52 } | 53 } |
| 53 | 54 |
| 54 CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() | 55 CanvasAsyncBlobCreator::~CanvasAsyncBlobCreator() |
| 55 { | 56 { |
| 56 } | 57 } |
| 57 | 58 |
| 58 void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(bool canUseIdlePeriodSche
duling, double quality) | 59 void CanvasAsyncBlobCreator::scheduleAsyncBlobCreation(bool canUseIdlePeriodSche
duling, double quality) |
| 59 { | 60 { |
| 60 // TODO: async blob creation should be supported in worker_pool threads as w
ell. but right now blink does not have that | 61 // TODO: async blob creation should be supported in worker_pool threads as w
ell. but right now blink does not have that |
| 61 ASSERT(isMainThread()); | 62 ASSERT(isMainThread()); |
| 62 | 63 |
| 63 // Make self-reference to keep this object alive until the final task comple
tes | 64 // Make self-reference to keep this object alive until the final task comple
tes |
| 64 m_keepAlive = this; | 65 m_selfRef = this; |
| 65 | 66 |
| 66 // At the time being, progressive encoding is only applicable to png image f
ormat, | 67 // At the time being, progressive encoding is only applicable to png image f
ormat, |
| 67 // and thus idle tasks scheduling can only be applied to png image format. | 68 // and thus idle tasks scheduling can only be applied to png image format. |
| 68 // TODO(xlai): Progressive encoding on jpeg and webp image formats (crbug.co
m/571398, crbug.com/571399) | 69 // TODO(xlai): Progressive encoding on jpeg and webp image formats (crbug.co
m/571398, crbug.com/571399) |
| 69 if (canUseIdlePeriodScheduling) { | 70 if (canUseIdlePeriodScheduling) { |
| 70 ASSERT(m_mimeType == "image/png"); | 71 ASSERT(m_mimeType == "image/png"); |
| 71 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_
HERE, bind<double>(&CanvasAsyncBlobCreator::initiatePngEncoding, this)); | 72 Platform::current()->mainThread()->scheduler()->postIdleTask(BLINK_FROM_
HERE, bind<double>(&CanvasAsyncBlobCreator::initiatePngEncoding, this)); |
| 72 } else if (m_mimeType == "image/jpeg") { | 73 } else if (m_mimeType == "image/jpeg") { |
| 73 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR
OM_HERE, bind(&CanvasAsyncBlobCreator::initiateJpegEncoding, this, quality)); | 74 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR
OM_HERE, bind(&CanvasAsyncBlobCreator::initiateJpegEncoding, this, quality)); |
| 74 } else { | 75 } else { |
| 75 BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.widt
h() >= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTa
sk : BackgroundTaskRunner::TaskSizeShortRunningTask; | 76 BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.widt
h() >= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTa
sk : BackgroundTaskRunner::TaskSizeShortRunningTask; |
| 76 BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafe
Bind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, AllowCrossThreadAccess
(this), quality), taskSize); | 77 BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafe
Bind(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, AllowCrossThreadAccess
(this), quality), taskSize); |
| 77 } | 78 } |
| 78 } | 79 } |
| 79 | 80 |
| 80 void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality) | 81 void CanvasAsyncBlobCreator::initiateJpegEncoding(const double& quality) |
| 81 { | 82 { |
| 82 m_jpegEncoderState = JPEGImageEncoderState::create(m_size, quality, m_encode
dImage.get()); | 83 m_jpegEncoderState = JPEGImageEncoderState::create(m_size, quality, m_encode
dImage.get()); |
| 83 if (!m_jpegEncoderState) { | 84 if (!m_jpegEncoderState) { |
| 84 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR
OM_HERE, bind(&BlobCallback::handleEvent, m_callback, nullptr)); | 85 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR
OM_HERE, bind(&BlobCallback::handleEvent, m_callback, nullptr)); |
| 85 m_keepAlive.clear(); | 86 m_selfRef.clear(); |
| 86 return; | 87 return; |
| 87 } | 88 } |
| 88 BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.width()
>= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTask :
BackgroundTaskRunner::TaskSizeShortRunningTask; | 89 BackgroundTaskRunner::TaskSize taskSize = (m_size.height() * m_size.width()
>= LongTaskImageSizeThreshold) ? BackgroundTaskRunner::TaskSizeLongRunningTask :
BackgroundTaskRunner::TaskSizeShortRunningTask; |
| 89 BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafeBind
(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, AllowCrossThreadAccess(thi
s), quality), taskSize); | 90 BackgroundTaskRunner::postOnBackgroundThread(BLINK_FROM_HERE, threadSafeBind
(&CanvasAsyncBlobCreator::encodeImageOnEncoderThread, AllowCrossThreadAccess(thi
s), quality), taskSize); |
| 90 } | 91 } |
| 91 | 92 |
| 92 void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) | 93 void CanvasAsyncBlobCreator::initiatePngEncoding(double deadlineSeconds) |
| 93 { | 94 { |
| 94 ASSERT(isMainThread()); | 95 ASSERT(isMainThread()); |
| 95 m_pngEncoderState = PNGImageEncoderState::create(m_size, m_encodedImage.get(
)); | 96 m_pngEncoderState = PNGImageEncoderState::create(m_size, m_encodedImage.get(
)); |
| 96 if (!m_pngEncoderState) { | 97 if (!m_pngEncoderState) { |
| 97 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR
OM_HERE, bind(&BlobCallback::handleEvent, m_callback, nullptr)); | 98 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FR
OM_HERE, bind(&BlobCallback::handleEvent, m_callback, nullptr)); |
| 98 m_keepAlive.clear(); | 99 m_selfRef.clear(); |
| 99 return; | 100 return; |
| 100 } | 101 } |
| 101 | 102 |
| 102 CanvasAsyncBlobCreator::idleEncodeRowsPng(deadlineSeconds); | 103 CanvasAsyncBlobCreator::idleEncodeRowsPng(deadlineSeconds); |
| 103 } | 104 } |
| 104 | 105 |
| 105 void CanvasAsyncBlobCreator::scheduleIdleEncodeRowsPng() | 106 void CanvasAsyncBlobCreator::scheduleIdleEncodeRowsPng() |
| 106 { | 107 { |
| 107 ASSERT(isMainThread()); | 108 ASSERT(isMainThread()); |
| 108 Platform::current()->currentThread()->scheduler()->postIdleTask(BLINK_FROM_H
ERE, WTF::bind<double>(&CanvasAsyncBlobCreator::idleEncodeRowsPng, this)); | 109 Platform::current()->currentThread()->scheduler()->postIdleTask(BLINK_FROM_H
ERE, WTF::bind<double>(&CanvasAsyncBlobCreator::idleEncodeRowsPng, this)); |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 156 } | 157 } |
| 157 | 158 |
| 158 scheduleCreateBlobAndCallOnMainThread(); | 159 scheduleCreateBlobAndCallOnMainThread(); |
| 159 } | 160 } |
| 160 | 161 |
| 161 void CanvasAsyncBlobCreator::clearSelfReference() | 162 void CanvasAsyncBlobCreator::clearSelfReference() |
| 162 { | 163 { |
| 163 // Some persistent members in CanvasAsyncBlobCreator can only be destroyed | 164 // Some persistent members in CanvasAsyncBlobCreator can only be destroyed |
| 164 // on the thread that creates them. In this case, it's the main thread. | 165 // on the thread that creates them. In this case, it's the main thread. |
| 165 ASSERT(isMainThread()); | 166 ASSERT(isMainThread()); |
| 166 m_keepAlive.clear(); | 167 m_selfRef.clear(); |
| 167 } | 168 } |
| 168 | 169 |
| 169 void CanvasAsyncBlobCreator::scheduleCreateBlobAndCallOnMainThread() | 170 void CanvasAsyncBlobCreator::scheduleCreateBlobAndCallOnMainThread() |
| 170 { | 171 { |
| 171 ASSERT(!isMainThread()); | 172 ASSERT(!isMainThread()); |
| 172 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H
ERE, threadSafeBind(&CanvasAsyncBlobCreator::createBlobAndCall, AllowCrossThread
Access(this))); | 173 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H
ERE, threadSafeBind(&CanvasAsyncBlobCreator::createBlobAndCall, AllowCrossThread
Access(this))); |
| 173 } | 174 } |
| 174 | 175 |
| 175 void CanvasAsyncBlobCreator::scheduleCreateNullptrAndCallOnMainThread() | 176 void CanvasAsyncBlobCreator::scheduleCreateNullptrAndCallOnMainThread() |
| 176 { | 177 { |
| 177 ASSERT(!isMainThread()); | 178 ASSERT(!isMainThread()); |
| 178 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H
ERE, threadSafeBind(&BlobCallback::handleEvent, m_callback.get(), nullptr)); | 179 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H
ERE, threadSafeBind(&BlobCallback::handleEvent, m_callback.get(), nullptr)); |
| 179 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H
ERE, threadSafeBind(&CanvasAsyncBlobCreator::clearSelfReference, AllowCrossThrea
dAccess(this))); | 180 Platform::current()->mainThread()->getWebTaskRunner()->postTask(BLINK_FROM_H
ERE, threadSafeBind(&CanvasAsyncBlobCreator::clearSelfReference, AllowCrossThrea
dAccess(this))); |
| 180 } | 181 } |
| 181 | 182 |
| 182 } // namespace blink | 183 } // namespace blink |
| OLD | NEW |