从NDK

时间:2015-11-09 16:03:02

标签: 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中获取它?

1 个答案:

答案 0 :(得分:3)

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

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

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

  • SurfaceTexture的纹理将与创建对象时当前的上下文相关联,但您可以使用attach / detach调用将其切换到不同的上下文。你不能“抓住”SurfaceTexture的EGL上下文,但你可以告诉它你想要它使用哪一个。

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

  • TextureView是一个嵌入了SurfaceTexture的视图。当要求重绘时,它使用GLES从纹理渲染(这就是为什么如果禁用硬件渲染你根本看不到任何东西)。

如果我正确理解你的问题,我想你想做的是:

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

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