Рендеринг контекста Canvas в рабочем потоке для плавного воспроизведения - PullRequest
1 голос
/ 21 апреля 2020

У меня есть два видео, показывающих рендеринг декодированной видеопоследовательности MJPEG, в которой воспроизводится только одно видео:

image description

Описание видео: слева (источник), Средний (холст-копия потока), правый (декодированный из сети).

На этом этапе видео плавное как из источника в сеть, так и обратно (веб-сокет). И, по крайней мере, до 5 видео декодируется и воспроизводится достаточно плавно. Однако, если я рендуюсь как 20 видео, все начинает отставать:

image description

Мой вопрос заключается в том, какой алгоритм лучше всего позволяет рендерить (или в многопоточном контексте) быстрее. Вот мой код:

        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] );

Тогда в основном это просто изображение рендеринга на холсте, но внутри потока веб-работника.

И это не помогло сделать воспроизведение плавным.

...