在WebGL中如何将视频帧转换为GL纹理?

6

我希望能够将来自glfx.js的滤镜应用于实时视频。我已经成功地导入并处理了所需的帧,但这种方法效率低下。在我的页面设置中,我执行以下操作:

var fbCanvas = document.getElementById('framebuffer');
var fb = fbCanvas.getContext('2d');
var video = document.getElementById('video');
var output = fx.canvas();

然后,在25hz(视频的播放速率)下,我这样做:

fb.drawImage(video, 0, 0);
var frame = output.texture(fbCanvas);
output.draw(frame).hueSaturation(-0.5, 0).update();

但我希望能够做到这一点:

var frame = output.texture(video);
output.draw(frame).hueSaturation(-0.5, 0).update();

调用 output.texture 只是对 gl.texImage2D 的包装,它似乎只能接受图像或画布——而不是视频元素。

我的问题是,通过执行额外的 drawImage 到隐藏画布,会带来多少性能损失?获取视频帧并将其快速转换为 GL 纹理的最快方法是什么,以便可以在实时运行 GL 着色器?

谢谢。


1
我不了解glfx.js,但根据http://www.khronos.org/registry/webgl/specs/latest/的说明,`gl.texImage2D`将接受一个`HTMLVideoElement`。 - brainjam
是的,glfx.js的作者已经更新了库以支持它。谢谢,evanw! - mikepurvis
1个回答

0

使用桌面OpenGL进行实时视频处理(视频输入/输出,而不仅仅是记录或播放)通常需要多线程支持,但这需要支持上下文共享列表(以便在单独的线程中分离的上下文可以引用相同的资源句柄空间)。OpenGL ES支持上下文共享列表,但WebGL尚未支持,尽管我认为它在WebCL中得到了支持。因此,虽然有WebWorkers的支持,但WebGL的使用似乎仅限于单个线程。

但是,当(而不是如果)WebGL支持上下文共享列表时,我认为最快的方法是将纹理的准备隔离在具有共享上下文的辅助线程中,然后在主合成线程中运行GL着色器。

在桌面OpenGL中,一种实现方式是声明具有自己上下文的离屏1x1窗口(画布元素),与执行准备工作的唯一线程相关联。这些上下文与执行最终合成的主线程共享。

当(我认为不是如果)WebGL支持共享列表时,请查找getContext()上的替代签名,以允许与另一个上下文共享列表。

如果您尝试单线程进行此类视频处理,那么您将面临一个“双时钟”问题。(输入视频合同,输出视频合同。)您必须通过FIFO/缓存和多线程隔离处理延迟,以避免输出出现故障或错过输入帧。FIFO/缓存的必要性引入了视频处理延迟,如果您绕过音频,则需要延迟音频以匹配。您可以使用具有记录和播放之间偏移量的循环环形缓冲区轻松完成这项工作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接