Android SurfaceTexture解读

/ Android / 没有评论 / 8092浏览

1类结构

public class SurfaceTexture extends Object

java.lang.Object

android.graphics.SurfaceTexture

2解读

2.1作用

从Image Stream中捕获帧数据,用作OpenGLES的纹理,其中Image Stream来自相机预览或视频解码。

从SurfaceTexture对象中创建的Surface类对象可被用作下述类的输出目标: android.hardware.camera2MediaCodecMediaPlayer, 和 Allocation APIs

当为旧的Camera API指定输出目标时,也可使用SurfaceTexture来代替SurfaceHolder。如果这样做的话,ImageStream将把所有帧都送到SurfaceTexure对象,而不是设备的显示视图。

2.2 updateTexImage()

当updateTexImage()被调用时,SurfaceTexture对象所关联的OpenGLES中纹理对象的内容将被更新为Image Stream中最新的图片。 但是调用updateTexImage()方法可能会造成ImageStream中的某些帧被忽略。SurfaceTexture对象可以在任何线程中创建。 但是,updateTexImage()方法只能在包OpenGLES环境的线程里调用,即Renderer接口所独立创建的线程当中。一般在onDrawFrame中调用updateTexImage()将数据绑定给OpenGLES对应的纹理对象。

注意,必须显示的调用updateTexImage()将数据更新到GL_OES_EGL_image_external类型的OpenGL ES纹理对象中后,SurfaceTexture才有空间来获取下一帧的数据。否则下一帧数据永远不会交给SurfaceTexture。

2.3 getTransformMatrix()

当从OpenGL ES的纹理对象取样时,首先应该调用getTransformMatrix()来转换纹理坐标。每次updateTexImage()被调用时,纹理矩阵都可能发生变化。所以,每次texture image被更新时,getTransformMatrix ()也应该被调用。getTransformMatrix()得到的矩阵,将传统的形如(s,t,0,1的)OpenGL ES 二维纹理坐标列向量转换为纹理流中正确的采样位置。

例如,从图片的左下角取样,可使用获得的矩阵转换列向量(0,0,0,1)从而获取正确的位置;从图片的右上角取样,可使用获得的矩阵转换列向量(1,1,0,1)从而获取正确的位置。

2.4 GL_TEXTURE_EXTERNAL_OES纹理类型

updateTexImage()方法会将ImageStream的图片数据更新到GL_OES_EGL_image_external类型的纹理中。OpenGL ES中的纹理对象需要使用GL_TEXTURE_EXTERNAL_OES作为纹理类型,该类型在 GL_OES_EGL_image_external中定义,是OpenGL ES的扩展。 每当使用该类纹理对纹理对象进行绑定时,需使用GL_TEXTURE_EXTERNAL_OES而不是GL_TEXTURE_2D。 额外的,任何需要从该纹理类型采样的OpenGL ES 2.0版本的着色器,必须声明对该扩展的使用。例如,必须加入如下的指令:

"#extensionGL_OES_EGL_image_external : require"

着色器中对纹理采样器类型的声明应使用“samplerExternalOES”类型。 有如下例子:

private static final StringFRAGMENT_SHADER = " #extensionGL_OES_EGL_image_external : require \n "
 
        +" precision mediump float; \n uniform samplerExternalOESuTextureSampler; \n "
 
        +”................//其余的定义和声明................”

2.5      SurfaceTexture.OnFrameAvailableListener

新的数据帧有效时的回调接口。接口方法:

void onFrameAvailable (SurfaceTexture surfaceTexture)

可调用SurfaceTexture.setOnFrameAvailableListener()方法来设置该监听器。当数据帧有效时,即onFrameAvailable被调用时,可调用GLSurfaceView.requestRender(),来显示要求进行渲染,即触发Renderer的onDrawFrame()。