从 NDK 中获取 SurfaceTexture 的 GL 上下文

Posted

技术标签:

【中文标题】从 NDK 中获取 SurfaceTexture 的 GL 上下文【英文标题】:Grabbing SurfaceTexture's GL context from NDK 【发布时间】:2016-02-10 08:08:07 【问题描述】:

目的: 我正在使用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获取它?

【问题讨论】:

您看过 Roman Guy 的 answer 关于使用 TextureView 和获取 EGL 上下文的内容吗? 【参考方案1】:

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

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

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

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

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

TextureView 是具有嵌入式 SurfaceTexture 的视图。当被要求重绘时,它使用 GLES 从纹理进行渲染(这就是为什么如果禁用硬件渲染你什么都看不到的原因)。

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

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

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

【讨论】:

感谢您对内部的澄清!

以上是关于从 NDK 中获取 SurfaceTexture 的 GL 上下文的主要内容,如果未能解决你的问题,请参考以下文章

获取每个android.hardware.camera2帧在surfacetexture上显示之前的数据

如何从eclipse环境中获取NDK路径?

通过 SurfaceTexture 在 GLSurfaceView 上显示相机流

如何在 NDK 中获取相机方向

一文了解surface,surfaceview,surfaceTexture,GLsurfaceView

音视频开发系列——详解Android SurfaceTexture