Эффективное копирование данных из видео-тега в функцию webAssembly - PullRequest
1 голос
/ 27 марта 2020

Я пытаюсь взять вход с веб-камеры (через getUserMedia) и обработать его в функции WebAssembly. Процесс выглядит следующим образом:

У меня есть два HTML элемента: video и canvas.

// get references to the elements
const vid = document.getElementById('vid');
const canv = document.getElementById('canv');

// load the video from a connected webcam
const stream = await navigator.mediaDevices.getUserMedia({video:true, audio:false});
vid.source.srcObject = stream;

// configure the canvas to have the same dimensions
const settings = stream.getVideoTracks()[0].getSettings();
canv.width = settings.width;
canv.height = settings.height;

. У меня также есть (заполнитель) функция WebAssembly, построенная из немного простого C кода:

int SumPixels( unsigned char *data, size_t size ) {
  int r=0;
  for (size_t i=0; i < size; i++) {
    r+=*data++;
  }
  return r;
}

Это было собрано с использованием emscriptem и было загружено в глобальный Module объект. При инициализации мне также нужно зарезервировать некоторую разделяемую память

//reserve memory to use as a frame buffer
const len = canv.width*canv.height*4;
const pMem = Module._malloc(len);
const mem = new UInt8Array(Module.HEAP8.buffer, pMem, len);

Наконец, периодически используя requestAnimationFrame, я делаю следующее

      const context = canv.getContext('2d');
      context.drawImage(vid, 0, 0);
      const imageData = context.getImageData(0, 0, canv.width, canv.height);
      const {data, width, height} = imageData;
      // copy data to reserved memory
      mem.set(data);
      // instead of an array, pass a pointer to the heap position of the data
      const pixSum = Module._SumPixels(pMem,len);

Это работает, но медленно. 5 кадров в секунду с Full HD входом. Профилирование в chrome медленный шаг - это getImageData, занимающий большую часть времени.

Теперь, если у меня был холст webgl, я мог бы сделать следующее:

  const gl = canv.getContext('webgl');

  //Do something to copy from the video element to the webgl canvas

  gl.readPixels(0,0,gl.drawingBufferWidth, gl.drawingBufferHeight, gl.RGBA, gl.UNSIGNED_BYTE, mem);
  const pixSum = Module._SumPixels(pMem,len);

При очистке вверх, всегда освобождайте используемую память модуля WASM

Module._free(pMem);
mem=null;

шаги webgl выполняются быстро, и он копируется непосредственно в память WASM, что очень приятно, однако нет никакого аналога, который я вижу, чтобы скопировать данные из элемент video в canvas (и невозможно получить доступ к холсту через webgl и 2d-контекст).

Итак, вопрос в том, есть ли способ эффективно копировать кадры из видео тега в холст webgl? Или есть другой способ сделать это, чтобы эффективно передавать кадры камеры из видео-тега в скомпилированную функцию веб-сборки?

...