将数据从视频标签高效复制到 webAssembly 函数

Eua*_*ith 5 javascript video canvas webgl webassembly

我正在尝试从网络摄像头获取输入(通过 getUserMedia)并在 WebAssembly 函数中对其进行处理。过程是这样的:

我有两个 HTML 元素, avideo和 a 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;
Run Code Online (Sandbox Code Playgroud)

我还有一个由一些简单的 C 代码构建的(占位符)WebAssembly 函数:

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

这是使用 emscriptem 构建的,并已加载到全局Module对象中。初始化时我还需要保留一些共享内存

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

最后,定期使用requestAnimationFrame我执行以下操作

//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);
Run Code Online (Sandbox Code Playgroud)

这可行,但速度很慢。全高清输入时每秒 5 帧。在 chrome 中进行性能分析这个缓慢的步骤getImageData花费了大部分时间。

现在,如果我有一个 webgl 画布,我可以执行以下操作:

      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);
Run Code Online (Sandbox Code Playgroud)

清理时,始终释放使用的 WASM 模块内存

  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);
Run Code Online (Sandbox Code Playgroud)

webgl 步骤很快,并且它直接复制到 WASM 内存中,这非常好,但是我可以看到没有等效的方法将数据从元素复制videocanvas(并且不可能通过 webgl 访问画布)和二维上下文)。

那么,问题是,有没有一种方法可以有效地将视频标签中的帧复制到 webgl 画布中?或者是否有另一种方法可以有效地将相机帧从视频标签获取到 Web 程序集编译函数?