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

Issue 1331443009: Implement Asynchronous image encoding for Canvas.toBlob (Closed)

Created:
5 years, 3 months ago by xlai (Olivia)
Modified:
4 years, 9 months ago
Reviewers:
Justin Novosad
Base URL:
https://chromium.googlesource.com/chromium/blink.git@master
Target Ref:
refs/heads/master
Project:
blink
Visibility:
Public.

Description

Implement Asynchronous image encoding for Canvas.toBlob Main thread creates a new thread to carry out the computation-intensive asynchronous image encoding operation. Afterwards the encoded image is passed back to the main thread to create blob and invoke user callback. Empty blob is passed to user callback in the senarios when the canvas has zero pixels or when the image encoding fails. This code review issue is migrated to https://codereview.chromium.org/1355333005/. BUG=523414 BUG=67587

Patch Set 1 #

Total comments: 5

Patch Set 2 : Edited based on first feedback; fixed small bugs #

Patch Set 3 : Change const double* to const double& for quality argument; Pass double by value in multi-threaded … #

Total comments: 5

Patch Set 4 : add constant and remove useless comments #

Patch Set 5 : rebase with latest code #

Total comments: 2

Patch Set 6 : Complex Layout Tests filing many toBlob calls at once and a toDataURL call #

Patch Set 7 : More complicated layout tests (number of toBlob calls and toDataURL calls are configurable) #

Patch Set 8 : static variable s_thread added #

Total comments: 12
Unified diffs Side-by-side diffs Delta from patch set Stats (+363 lines, -28 lines) Patch
A LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-jpeg.html View 1 2 3 4 5 6 1 chunk +79 lines, -0 lines 5 comments Download
A LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-jpeg-expected.txt View 1 2 3 4 5 6 1 chunk +21 lines, -0 lines 0 comments Download
A LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-png.html View 1 2 3 4 5 6 1 chunk +79 lines, -0 lines 1 comment Download
A LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-png-expected.txt View 1 2 3 4 5 6 1 chunk +21 lines, -0 lines 0 comments Download
A LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-webp.html View 1 2 3 4 5 6 1 chunk +79 lines, -0 lines 0 comments Download
A LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-webp-expected.txt View 1 2 3 4 5 6 1 chunk +21 lines, -0 lines 0 comments Download
M Source/core/fileapi/File.h View 1 chunk +1 line, -1 line 0 comments Download
M Source/core/fileapi/File.cpp View 1 chunk +1 line, -1 line 0 comments Download
M Source/core/html/HTMLCanvasElement.h View 1 2 3 4 5 6 7 4 chunks +7 lines, -2 lines 0 comments Download
M Source/core/html/HTMLCanvasElement.cpp View 1 2 3 4 5 6 7 8 chunks +46 lines, -16 lines 6 comments Download
M Source/platform/graphics/ImageBuffer.h View 1 2 3 4 1 chunk +2 lines, -2 lines 0 comments Download
M Source/platform/graphics/ImageBuffer.cpp View 1 2 2 chunks +6 lines, -6 lines 0 comments Download

Messages

Total messages: 12 (2 generated)
xlai (Olivia)
Hi Justin, Perhaps you want to take a look at the code first. I did ...
5 years, 3 months ago (2015-09-10 14:13:26 UTC) #2
Justin Novosad
As discussed by e-mail, the idea behind the idle task approach was to spread the ...
5 years, 3 months ago (2015-09-10 14:53:20 UTC) #3
Justin Novosad
https://codereview.chromium.org/1331443009/diff/1/Source/core/html/HTMLCanvasElement.cpp File Source/core/html/HTMLCanvasElement.cpp (right): https://codereview.chromium.org/1331443009/diff/1/Source/core/html/HTMLCanvasElement.cpp#newcode596 Source/core/html/HTMLCanvasElement.cpp:596: // Add a ref to keep image data alive ...
5 years, 3 months ago (2015-09-10 15:04:17 UTC) #4
xlai (Olivia)
Changed based on first code review (replies are inline). I pass the quality argument by ...
5 years, 3 months ago (2015-09-17 21:12:11 UTC) #5
Justin Novosad
https://codereview.chromium.org/1331443009/diff/40001/Source/core/html/HTMLCanvasElement.cpp File Source/core/html/HTMLCanvasElement.cpp (right): https://codereview.chromium.org/1331443009/diff/40001/Source/core/html/HTMLCanvasElement.cpp#newcode533 Source/core/html/HTMLCanvasElement.cpp:533: double quality = -1.0; Use a named constant instead ...
5 years, 3 months ago (2015-09-21 14:12:38 UTC) #6
xlai (Olivia)
Changed code accordingly.
5 years, 3 months ago (2015-09-21 16:01:12 UTC) #7
Justin Novosad
https://codereview.chromium.org/1331443009/diff/80001/Source/core/html/HTMLCanvasElement.cpp File Source/core/html/HTMLCanvasElement.cpp (right): https://codereview.chromium.org/1331443009/diff/80001/Source/core/html/HTMLCanvasElement.cpp#newcode551 Source/core/html/HTMLCanvasElement.cpp:551: if (!ImageDataBuffer(imageSize, imageData->data()).encodeImage(mimeType, quality, encodedImage.get())) { Do we know ...
5 years, 3 months ago (2015-09-21 16:51:56 UTC) #8
xlai (Olivia)
Added 3 layout tests to test the thread-safety of PNG, JPEG, WEBP image encoder respectively. ...
5 years, 3 months ago (2015-09-22 22:03:08 UTC) #9
Justin Novosad
https://codereview.chromium.org/1331443009/diff/160001/LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-jpeg.html File LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-jpeg.html (right): https://codereview.chromium.org/1331443009/diff/160001/LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-jpeg.html#newcode9 LayoutTests/fast/canvas/canvas-toBlob-toDataURL-race-imageEncoder-jpeg.html:9: var numToBlobCalls = 9; // number of toBlob calls ...
5 years, 3 months ago (2015-09-23 19:38:57 UTC) #11
Justin Novosad
5 years, 3 months ago (2015-09-23 20:32:32 UTC) #12
https://codereview.chromium.org/1331443009/diff/160001/Source/core/html/HTMLC...
File Source/core/html/HTMLCanvasElement.cpp (right):

https://codereview.chromium.org/1331443009/diff/160001/Source/core/html/HTMLC...
Source/core/html/HTMLCanvasElement.cpp:84: const int InvalidQualityValue = -1.0;
I would call this Undefined instead of Invalid. "Invalid" suggest this is an
error, "Undefined" suggest a default should be used.

https://codereview.chromium.org/1331443009/diff/160001/Source/core/html/HTMLC...
Source/core/html/HTMLCanvasElement.cpp:107: static WebThread* s_thread = 0;
You should make these statics members of HTMLCanvasElement.  Also, the name is
not very descriptive. s_blobEncoderThread would be better.

https://codereview.chromium.org/1331443009/diff/160001/Source/core/html/HTMLC...
Source/core/html/HTMLCanvasElement.cpp:108: static int numCanvasInstances = 0;
missing s_

https://codereview.chromium.org/1331443009/diff/160001/Source/core/html/HTMLC...
Source/core/html/HTMLCanvasElement.cpp:134: s_thread = 0;
This is a memory leak. You should make s_thread an OwnPtr<WebThread>, and call
clear() on it.

https://codereview.chromium.org/1331443009/diff/160001/Source/core/html/HTMLC...
Source/core/html/HTMLCanvasElement.cpp:598: // ImageData object will be disposed
on leaving stack scope; only imageData->data and imageData->size are passed to
s_thread
This comment describes poorly what is happening. The scoped disposal forces the
imageData to unref it's data, which we keep alive for the thread by taking a
refptr. This way, the life time of the data is tied to the completion of the
async encode, rather than to the garbage collection of imageData.

https://codereview.chromium.org/1331443009/diff/160001/Source/core/html/HTMLC...
Source/core/html/HTMLCanvasElement.cpp:607:
s_thread->taskRunner()->postTask(FROM_HERE, new
Task(threadSafeBind(&HTMLCanvasElement::encodeImageAsync,
AllowCrossThreadAccess(this),
AllowCrossThreadAccess(imageDataRef.release().leakRef()), imageData->size(),
AllowCrossThreadAccess(callback), encodingMimeType, quality)));
This is unsafe. We cannot guarantee that 'this' will stay alive long enough. 
You should add a layout test that does this:
1) create an offscreen canvas with: var canvas =
document.createElement('canvas');
2) draw to the canvas and call toBlob
3) dereference the canvas (set the variable to null)
4) force an immediate garbage collection (there is a test API for this either on
internals or testRunner)
5) wait for the callback to be invoked and verify the blob for correctness.

Powered by Google App Engine
This is Rietveld 408576698