Я пытаюсь взять вход с веб-камеры (через 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? Или есть другой способ сделать это, чтобы эффективно передавать кадры камеры из видео-тега в скомпилированную функцию веб-сборки?