feat(webcodecs): change to a faster render method

This commit is contained in:
Simon Chan 2024-03-07 20:00:49 +08:00
parent 48557f6203
commit c7549ad6c8
No known key found for this signature in database
GPG key ID: A8B69F750B9BCEDD

View file

@ -68,7 +68,7 @@ export class WebCodecsDecoder implements ScrcpyVideoDecoder {
return this.#sizeChanged.event; return this.#sizeChanged.event;
} }
#context: CanvasRenderingContext2D; #context: ImageBitmapRenderingContext;
#decoder: VideoDecoder; #decoder: VideoDecoder;
#config: Uint8Array | undefined; #config: Uint8Array | undefined;
@ -80,27 +80,43 @@ export class WebCodecsDecoder implements ScrcpyVideoDecoder {
this.#renderer = document.createElement("canvas"); this.#renderer = document.createElement("canvas");
this.#context = this.#renderer.getContext("2d")!; this.#context = this.#renderer.getContext("bitmaprenderer", {
alpha: false,
})!;
this.#decoder = new VideoDecoder({ this.#decoder = new VideoDecoder({
output: (frame) => { output: (frame) => {
if (this.#currentFrameRendered) { createImageBitmap(frame)
this.#frameSkipped += 1; .then((bitmap) => {
} else { if (this.#currentFrameRendered) {
this.#currentFrameRendered = true; this.#frameRendered += 1;
this.#frameRendered += 1; } else {
} this.#frameSkipped += 1;
}
this.#currentFrameRendered = false;
// PERF: H.264 renderer may draw multiple frames in one vertical sync interval to minimize latency. // PERF: H.264 renderer may draw multiple frames in one vertical sync interval to minimize latency.
// When multiple frames are drawn in one vertical sync interval, // When multiple frames are drawn in one vertical sync interval,
// only the last one is visible to users. // only the last one is visible to users.
// But this ensures users can always see the most up-to-date screen. // But this ensures users can always see the most up-to-date screen.
// This is also the behavior of official Scrcpy client. // This is also the behavior of official Scrcpy client.
// https://github.com/Genymobile/scrcpy/issues/3679 // https://github.com/Genymobile/scrcpy/issues/3679
this.#context.drawImage(frame, 0, 0); this.#context.transferFromImageBitmap(bitmap);
frame.close(); frame.close();
})
.catch((e) => {
console.warn(
"[@yume-chan/scrcpy-decoder-webcodecs]",
"createImageBitmap error",
e,
);
});
}, },
error(e) { error(e) {
void e; console.warn(
"[@yume-chan/scrcpy-decoder-webcodecs]",
"VideoDecoder error",
e,
);
}, },
}); });
@ -121,7 +137,7 @@ export class WebCodecsDecoder implements ScrcpyVideoDecoder {
} }
#onFramePresented = () => { #onFramePresented = () => {
this.#currentFrameRendered = false; this.#currentFrameRendered = true;
this.#animationFrameId = requestAnimationFrame(this.#onFramePresented); this.#animationFrameId = requestAnimationFrame(this.#onFramePresented);
}; };
@ -168,6 +184,10 @@ export class WebCodecsDecoder implements ScrcpyVideoDecoder {
this.#renderer.width = croppedWidth; this.#renderer.width = croppedWidth;
this.#renderer.height = croppedHeight; this.#renderer.height = croppedHeight;
this.#sizeChanged.fire({
width: croppedWidth,
height: croppedHeight,
});
const codec = [ const codec = [
"hev1", "hev1",