我有兴趣将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着色器?
感谢。
答案 0 :(得分:0)
使用桌面openGL进行实时视频处理(视频输入/输出,而不仅仅是记录或只是回放)通常是多线程的,但这需要支持上下文共享列表(这样单独的线程中的单独上下文可以引用相同的资源句柄在OpenGL ES中支持上下文共享列表,但WebGL尚未支持,但我认为它在WebCL中受支持。因此,虽然支持WebWorkers,但WebGL的使用似乎实际上仅限于单个线程。
但是,当(不是)WebGL支持上下文共享列表时,我认为最快的方法是将一个辅助线程中的纹理准备与一个共享上下文隔离,然后在一个主要的上运行GL着色器堆肥线程。
在桌面openGL中,这样做的一种方法是使用自己的上下文声明屏幕外1x1窗口(canvas元素),并与执行准备的唯一线程相关联。这些上下文与主线程共享列表,其中发生最终合成。
当(我认为,不是)WebGL支持共享列表时,在getContext()上寻找备用签名,允许与其他上下文共享列表。
如果你尝试做这种单线程的视频处理,你就是在克服“两个时钟”的问题。 (输入视频合同,输出视频合同。)您必须通过FIFO /缓存和多线程将处理延迟与那些硬时钟隔离开,否则您将在输出上出现毛刺,或者错过输入帧。 FIFO /高速缓存的必要性引入了视频处理延迟,如果您绕过音频,则需要延迟音频以匹配。您可以使用循环环形缓冲区轻松完成此操作,并在记录和回放之间进行偏移。