【问题标题】:How to render a texture to an Android GLSurfaceView如何将纹理渲染到 Android GLSurfaceView
【发布时间】:2015-06-02 01:04:13
【问题描述】:

我有一个标准的 GLSurfaceView 类:

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 的 Renderer 类:

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。

如何在 Renderer 类中以最小的性能影响显示此纹理的内容?

【问题讨论】:

    标签: android opengl-es-2.0 glsurfaceview textureview


    【解决方案1】:

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

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

    您可以在Grafika's“显示 + 捕获相机”活动中找到一个示例。如果您查看 CameraCaptureActivity.java 中的 onDrawFrame() 方法,您可以看到它调用了 updateSharedContext(),该方法将消息传递给运行 TextureMovieEncoder 的线程以使其运行 handleUpdateSharedContext(),从而(重新)创建用于输入视频编码器。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-04-09
      • 2018-06-11
      • 1970-01-01
      • 2019-05-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多