java - OpenGL ES 2.0 - 如何有效地将纹理复制到帧缓冲区中

标签 java android opengl-es-2.0 libvlc

简而言之 - 我有一个 OpenGL 纹理,需要在 OpenGL ES 2.0 下以最有效的方式将其复制到 FBO 或另一个纹理中。

目前我只是将第一个纹理绘制到 FBO 中。

有没有更有效的方法?例如。某种像素复制,不涉及将像素数据拉回 RAM,然后缓冲到另一个纹理 - 在 ES 2.0 配置文件中。

为您提供背景信息 - 这是与视频渲染相关的:

我有一个 OpenGL 纹理,它使用来自 LibVLC 的视频帧数据进行缓冲,但由于我的应用程序重绘率和解码器刷新率之间的计时问题,OpenGL 纹理可能没有新的帧要更新,如果我将纹理绘制到屏幕上而没有要更新的帧,则非常奇怪 - 它不是包含前一帧的数据,而是绘制自己的一些奇怪的图像(它看起来像太空入侵者??) - 因此为什么我需要“缓存”前一帧的内容。

具体来说,这是一个 OpenGL 纹理,用于创建 Android SurfaceTexture,我必须手动调用 updateTexImage 和 releaseTexImage 来更新纹理的内容,然后在绘制 SurfaceTexture 的内容后标记它已完成。如果我不发布它,那么就无法更新它的新框架。如果我释放它,我就无法多次重绘同一帧。这导致我在纹理更新后对其进行缓存,以便解码器可以自由地写入它,并且如果当我再次绘制且尚未更新时,我仍然拥有前一帧。

谢谢。

最佳答案

该解决方案基于如何正确地与 Android SurfaceTexture 交互以避免必须完全缓存其内容。

如果有人想分享有关 OpenGL ES 2.0 中高效纹理副本的答案,请随意 - 这将适合我原来的问题。

对于任何感兴趣的人,这就是我所做的:

用于在 Android 上渲染视频的 GLPaint 类包含 SurfaceTexture 实例,它是从 JOGL OpenGL 纹理创建的(使用它的 ID) - 这使我能够将纹理绘制为 GLPaint.paint 函数的一部分。

该GLPaint实现了SurfaceTexture.OnFrameAvailableListener接口(interface)的onFrameAvailable方法。我有一个私有(private) boolean 值来标记第一帧何时被“写入” - 这是避免过早释放 SurfaceTexture 所必需的。

类 GUIThreadLock 是我对 ReentrantLock 的扩展 - 我扩展它以获得额外的调试信息并创建静态单例。这个锁定在我的 UI 中线程的“一进一出” Controller 中,确保一次只有一个线程在我的 UI 中处于 Activity 状态(通常只是主渲染器循环程序),而且每当一个线程分别获取和放弃锁时,也会处理将 OpenGL 上下文绑定(bind)或取消绑定(bind)到锁所有者线程。

@Override
    public void onFrameAvailable( SurfaceTexture pSurfaceTexture )
    {
        try
        {
            GUIThreadLock.acquire();
            if( written )
            {
                pSurfaceTexture.releaseTexImage();
            }
            pSurfaceTexture.updateTexImage();
            written = true;
        }
        finally
        {
            GUIThreadLock.relinquish();
        }
    }

这意味着当新帧准备好时,SurfaceTexture 会释放旧帧并更新为新帧 - 然后它会与当前帧一起缓冲,用于我希望绘制视频的任何点,直到下一帧准备好。 GUIThreadLock 可以保护 SurfaceTexture 在我绘制内容时不更新内容,但也获取我的 GL 上下文,以便回调线程可以在此处实际执行更新。

我的重绘线程在绘制我的应用程序之前还需要 GUIThreadLock - 因此 GL 上下文受到保护,并且框架更新和框架绘制之间的关系得到巩固。

关于java - OpenGL ES 2.0 - 如何有效地将纹理复制到帧缓冲区中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36132302/

相关文章:

java - 需要将 jar 内的 tar.gz 文件读取为文件

java - 如何在android中查找Edittext的字长?

android opengl es 2.0 将屏幕坐标转换为世界坐标

ios - 使用 GL_POINTS 时,gl_Position 是否设置矩形的中心?

ios - 如何从 AVCaptureVideoPreviewLayer 获取 UIImage?

ios - OpenGL 2.0 使用同一着色器渲染多个对象

java - 为什么类变量的运行时多态性行为会发生变化

java - JComboBox 像 HTML select 一样提交值

Java 转换、覆盖和多态性

java - 以编程方式在android中缩放webview