android - 从 NDK 中获取 SurfaceTexture 的 GL 上下文

标签 android opengl-es android-camera opengl-es-2.0

目的: 我正在使用 SurfaceTexture 来显示相机预览,并且需要通过从 NDK 获取 GL 上下文在表面上绘制。我选择了 SurfaceTexture 方法,因为我可以避免相机帧缓冲区从 java 手动传递到 NDK,以节省一些性能。

public class MainActivity extends Activity implements SurfaceTextureListener {

private Camera mCamera;
private TextureView mTextureView;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mTextureView = new TextureView(this);
    mTextureView.setSurfaceTextureListener(this);

    setContentView(mTextureView);
}

@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
    mCamera = Camera.open();
    Camera.Size previewSize = mCamera.getParameters().getPreviewSize();
    mTextureView.setLayoutParams(new FrameLayout.LayoutParams(previewSize.width, previewSize.height, Gravity.CENTER));

    try {
        mCamera.setPreviewTexture(surface);
    } catch (IOException t) {
    }

    mCamera.startPreview();
}

@Override
public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
    // Ignored, the Camera does all the work for us
}

@Override
public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
    mCamera.stopPreview();
    mCamera.release();
    return true;
}

@Override
public void onSurfaceTextureUpdated(SurfaceTexture surface) {
    // Update your view here
}

我尝试过的: 我想 SurfaceTexture 在内部使用 GL 功能来绘制上下文。从 NDK 获取默认显示失败并出现 BAD_DISPLAY 错误。

EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);

当然,我能够初始化一个新的 GL 上下文并进行绘图,但我仍然希望在后台保留 java 代码显示的纹理。

问题: 在使用 SurfaceTexture 时是否可以从 NDK 中获取 GL 上下文? 可能我必须在 GLSurfaceView 上使用,从 Java 代码手动初始化 GL 上下文并从 NDK 获取它?

最佳答案

你的问题对我来说并不完全有意义,所以让我列出一些事情。

  • SurfaceTexture 不绘制任何东西。当 Camera 作为生产者连接时,SurfaceTexture 接收 YUV 帧,并使用 EGL 函数将其设置为“外部”纹理。然后您可以使用 GLES 渲染该纹理。

  • EGL 上下文可以一次在一个线程中是“当前的”。指向当前上下文的指针保存在 native 线程本地存储中。 Java 语言 GLES 绑定(bind)是 native 代码的薄包装器,因此在使用 GLES 时,Java 和 C++ 之间几乎没有概念上的区别。

  • SurfaceTexture 的纹理将与对象创建时的当前上下文相关联,但您可以使用附加/分离调用将其切换到不同的上下文。您无法“获取”SurfaceTexture 的 EGL 上下文,但可以告诉它您希望它使用哪一个。

  • SurfaceTexture(和一般的 Surface)只能有一个生产者。您不能将相机帧发送到您正在使用 GLES 渲染的表面。您可以在它们之间来回切换,但通常最好使用两个不同的 Surface 对象。

  • TextureView 是具有嵌入式 SurfaceTexture 的 View 。当要求重绘时,它会使用 GLES 从纹理进行渲染(这就是为什么如果禁用硬件渲染,您根本看不到任何东西)。

如果我没有正确理解你的问题,我认为你想要做的是:

  • 将相机输出发送到在渲染器线程上创建的新 SurfaceTexture。
  • 为 TextureView 的 SurfaceTexture 创建一个 EGLSurface。
  • 使用 GLES 渲染到 TextureView,使用来自相机的纹理作为示例源。添加您想要的任何其他 GLES 渲染。

可以在 Grafika 中找到各种示例,例如“来自相机的纹理” Activity 。

关于android - 从 NDK 中获取 SurfaceTexture 的 GL 上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33613192/

相关文章:

java - 何时在 android 中使用静态变量和共享首选项

Android - 使用 NDK 的 OpenGL ES 2.0 教程?

opengl-es - 有没有办法将矢量图形整合到LibGDX开发中?

android - SurfaceView 或 TextureView 哪个更适合 Preview

android - 单击按钮将其捕获到图库中后,启动相机捕获图片并存储图像

android - 暂停时从服务更新 Activity 数据

java - 在 Android >= Api 26 中不调用 BroadcastReceiver

java - 在android中读取数据sqlite失败

opengl - openGL ES和OpenGL函数的区别

android Camera2 Jpeg回调的命中超时