目的:
我正在使用 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/