У меня есть два видео, показывающих рендеринг декодированной видеопоследовательности MJPEG, в которой воспроизводится только одно видео:
Описание видео: слева (источник), Средний (холст-копия потока), правый (декодированный из сети).
На этом этапе видео плавное как из источника в сеть, так и обратно (веб-сокет). И, по крайней мере, до 5 видео декодируется и воспроизводится достаточно плавно. Однако, если я рендуюсь как 20 видео, все начинает отставать:
Мой вопрос заключается в том, какой алгоритм лучше всего позволяет рендерить (или в многопоточном контексте) быстрее. Вот мой код:
socket.onmessage = function (m) {
let blob = m.data;
videoDecoder.postMessage(blob);
videoDecoder2.postMessage(blob);
videoDecoder3.postMessage(blob);
// and so on... to 20
}
В целях тестирования я просто публикую все BLOB-объекты на различных веб-рабочих видеодекодера. Теперь для части рендеринга:
videoDecoder.onmessage = async function (e) {
await renderImage(dCtx2, e.data);
};
Итак, в моем коде у меня есть 20 таких обработчиков onmessage
(опять же, для простоты, просто скопируйте и вставьте код.)
async function renderImage(ctx, blob) {
const isChrome = !!window.chrome && (!!window.chrome.webstore || !!window.chrome.runtime);
if(isChrome) {
const blobURL = URL.createObjectURL(blob);
const img = new Image();
img.onload = function() {
ctx.drawImage(img, 0, 0);
URL.revokeObjectURL(blobURL);
};
img.src = blobURL;
} else {
const bmp = await createImageBitmap(blob);
ctx.drawImage(bmp, 0, 0);
bmp.close();
}
}
Так как видеодекодеры - это, по сути, веб-работники, работающие в каждом отдельном потоке, поэтому это не является причиной падения FPS в «проигрывателях» холста в пользовательском интерфейсе. Метод renderImage
здесь является основной причиной, и именно он задерживает основной поток (поток пользовательского интерфейса). Что можно сделать, чтобы каждый контекст холста отображался на веб-рабочих, возможно, независимо от того, сколько у меня здесь игроков, он не будет влиять друг на друга?
ОБНОВЛЕНИЕ:
Я переехал рендеринг веб-работникам, то есть передача контекста по веб-работнику:
videoDecoders[i] = new Worker("videoDecoder.js");
const canvas = document.querySelector("#canvas" + (i+1)); // get the canvas
const offscreen = canvas.transferControlToOffscreen();
videoDecoders[i].postMessage({ action: 'init', canvas: offscreen }, [offscreen] );
Тогда в основном это просто изображение рендеринга на холсте, но внутри потока веб-работника.
И это не помогло сделать воспроизведение плавным.