如何将纹理渲染到 Android GLSurfaceView

How to render a texture to an Android GLSurfaceView

我有一个标准的 GLSurfaceView class:

public class TestSurfaceView extends GLSurfaceView {
    public MainRenderer mRenderer;

    public GStreamerSurfaceView(Context context) {
        super(context);

        setEGLContextClientVersion(2);
        mRenderer = new MainRenderer(context);
        setRenderer(mRenderer);
        setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
    }
}

我有一个实现 GLSurfaceView.Renderer:

的渲染器 class
public class MainRenderer implements GLSurfaceView.Renderer {
    private int[] hTex;
    private SurfaceTexture mSTexture;
    private Context context;

    MainRenderer(Context c) {
        context = c;
    }

    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
    }

    public void onDrawFrame(GL10 unused) {
    }

    public void onSurfaceChanged(GL10 unused, int width, int height) {
    }

    public void onSurfaceCreated(GL10 arg0, javax.microedition.khronos.egl.EGLConfig arg1) {
    }
}

在单独的 JNI 线程中,我将一些视频数据(YUV 格式)上传到 OpenGLES 纹理。我在 Java 收到新纹理可用的通知,并且我有相应的纹理 ID。

如何在渲染器中显示此纹理的内容class,同时对性能的影响最小?

对于帧来自 Camera 或 MediaCodec 的情况,有一些非常有效的解决方案。不过,这听起来像是您正在用软件生成或解码视频,这让事情变得温和(尽管您的代码中确实声明了 SurfaceTexture,这很奇怪)。诀窍是 "OpenGL ES texture" 部分,因为纹理与 EGL 上下文相关联,而 EGL 上下文一次只能在一个线程中处于活动状态。

因为您使用的是 GLSurfaceView,而不是普通的 SurfaceView,所以您无法控制 GLSurfaceView 渲染器线程中的 EGL 上下文。解决此问题的最简单方法是跳过一些步骤以创建与第一个共享的第二个 EGL 上下文。完成后,在单独的 JNI 线程中创建的纹理将可用于 GLSurfaceView 渲染器线程。

您可以在 Grafika's "show + capture camera" activity 中找到这方面的示例。如果您查看 CameraCaptureActivity.java 中的 onDrawFrame() 方法,您可以看到它调用 updateSharedContext(),它将消息传递给线程 运行ning TextureMovieEncoder 以使其成为 运行 handleUpdateSharedContext(),它(重新)创建用于馈送视频编码器的表面。

如果您改用普通的 SurfaceView,并进行自己的 EGL 和线程管理,代码将不会那么曲折。您可以同时创建两个上下文,然后将其中一个传递给生成图像的线程。您还可以创建单个上下文并使用 eglMakeCurrent() 在线程之间转移它,但这在某些平台上可能很昂贵。

更新: Grafika "show + capture camera" 实现存在竞争条件;有关问题和解决方案的详细信息,请参阅 this bug report。在一个线程中创建纹理并在另一个线程中使用它时,您必须执行一些额外的步骤。通常最好在一个线程的一个上下文中执行所有操作。 Grafika 中的其他活动使用普通的 SurfaceView 并进行自己的 EGL 上下文和线程管理。