Commit 5643915e authored by Kuo Jen Wei's avatar Kuo Jen Wei Committed by Chromium LUCI CQ

CCA: Fix video broken thumbnail bug

Fixed by waiting for |requestVideoFrameCallback()| returned before draw
video onto canvas.

Bug: b/172214187
Test: tast run "camera.CCAUI*"
Change-Id: I7352a58f08d36cc2c2459af06883ae124ad7ad77
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2611148
Commit-Queue: Shik Chen <shik@chromium.org>
Reviewed-by: default avatarShik Chen <shik@chromium.org>
Auto-Submit: Inker Kuo <inker@chromium.org>
Cr-Commit-Position: refs/heads/master@{#841005}
parent c02603df
...@@ -215,14 +215,11 @@ export function getDefaultFacing() { ...@@ -215,14 +215,11 @@ export function getDefaultFacing() {
export async function scalePicture(blob, isVideo, width, height = undefined) { export async function scalePicture(blob, isVideo, width, height = undefined) {
const element = isVideo ? dom.create('video', HTMLVideoElement) : const element = isVideo ? dom.create('video', HTMLVideoElement) :
dom.create('img', HTMLImageElement); dom.create('img', HTMLImageElement);
if (isVideo) {
element.preload = 'auto';
}
try { try {
await new Promise((resolve, reject) => { let requestFrameTimeout = false;
element.addEventListener(isVideo ? 'canplay' : 'load', resolve); if (isVideo) {
element.addEventListener('error', () => { await new Promise((resolve, reject) => {
if (isVideo) { element.addEventListener('error', () => {
let msg = 'Failed to load video'; let msg = 'Failed to load video';
/** /**
* https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/error * https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/error
...@@ -233,12 +230,42 @@ export async function scalePicture(blob, isVideo, width, height = undefined) { ...@@ -233,12 +230,42 @@ export async function scalePicture(blob, isVideo, width, height = undefined) {
msg += `: ${err.message}`; msg += `: ${err.message}`;
} }
reject(new Error(msg)); reject(new Error(msg));
} else { });
reject(new Error('Failed to load image')); /**
} * For resolving https://goo.gl/LdLk22 asynchronous play-pause problem.
* @type {!Promise}
*/
let playing = Promise.resolve();
Promise
.race([
new Promise(
(resolve) =>
element.requestVideoFrameCallback(() => resolve(false))),
// The |requestVideoFrameCallback| may not be triggerred when
// playing malformatted video. Set 300ms timeout here to prevent
// UI be blocked forever.
new Promise((resolve) => setTimeout(() => resolve(true), 300)),
])
.then((isTimeout) => {
requestFrameTimeout = isTimeout;
return playing;
})
.then(() => {
element.pause();
resolve();
});
element.preload = 'auto';
element.src = URL.createObjectURL(blob);
playing = assertInstanceof(element.play(), Promise);
}); });
element.src = URL.createObjectURL(blob); } else {
}); await new Promise((resolve, reject) => {
element.addEventListener(
'error', () => reject(new Error('Failed to load image')));
element.addEventListener('load', resolve);
element.src = URL.createObjectURL(blob);
});
}
if (height === undefined) { if (height === undefined) {
const ratio = isVideo ? element.videoHeight / element.videoWidth : const ratio = isVideo ? element.videoHeight / element.videoWidth :
element.height / element.width; element.height / element.width;
...@@ -252,9 +279,16 @@ export async function scalePicture(blob, isVideo, width, height = undefined) { ...@@ -252,9 +279,16 @@ export async function scalePicture(blob, isVideo, width, height = undefined) {
*/ */
const data = ctx.getImageData(0, 0, width, height).data; const data = ctx.getImageData(0, 0, width, height).data;
if (data.every((byte) => byte === 0)) { if (data.every((byte) => byte === 0)) {
let msg =
`The ${isVideo ? 'video' : 'photo'} thumbnail content is broken.`;
if (requestFrameTimeout) {
msg += ' ; while requestVideoFrameCallback is timeout.';
}
reportError( reportError(
ErrorType.BROKEN_THUMBNAIL, ErrorLevel.ERROR, ErrorType.BROKEN_THUMBNAIL,
new Error('The thumbnail content is broken.')); ErrorLevel.ERROR,
new Error(msg),
);
// Do not throw an error here. A black thumbnail is still better than no // Do not throw an error here. A black thumbnail is still better than no
// thumbnail to let user open the corresponding picutre in gallery. // thumbnail to let user open the corresponding picutre in gallery.
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment