安卓SurfaceTexture中updateTexImage使用及源码分析

本文首发地址 https://h89.cn/archives/140.html
最新更新地址 https://gitee.com/chenjim/chenjimblog

引言

在Android系统中,SurfaceTexture 是一个特殊的类,它将来自硬件纹理缓冲区(如相机预览流或视频解码输出)的图像数据转换为 OpenGL ES 可以直接使用的纹理。updateTexImage() 方法是 SurfaceTexture 类的核心方法之一,此方法的主要作用是从 SurfaceTexture 内部持有的图像缓冲区中取出最新一帧,并将其内容复制到与 SurfaceTexture 关联的 OpenGL 纹理上。这对于实时图形渲染、视频播放以及从相机捕获并实时处理图像等场景至关重要。

updateTexImage 简单使用

下面是一个简化的使用 SurfaceTexture 与 GLSurfaceView 实现渲染的基本流程:

// 初始化 SurfaceTexture
SurfaceTexture surfaceTexture = new SurfaceTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
   
   
    @Override
    public void onFrameAvailable(SurfaceTexture st) {
   
   
        // 新帧到达时,通知主线程进行渲染
        // 在这里可以调用 requestRender() 或者通过 Handler 发送消息
    }
});

// 在GL线程中初始化纹理并绑定
fun initTexture(){
   
   
    int[] textureId = new int[1];
    GLES20.glGenTextures(1, textureId, 0);
    GLES20 glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, textureId[0]);

    // 设置纹理参数
    GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
            GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_LINEAR);
    GLES20.glTexParameterf(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
            GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

    // 将SurfaceTexture关联到OpenGL纹理
    surfaceTexture.attachToGLContext(textureId[0]);
}

// 在onDrawFrame(GL10 gl)方法中更新和渲染纹理
@Override
public void onDrawFrame(GL10 unused) {
   
   
    // 检查是否有新帧可用
    if (surfaceTexture.isFrameAvailable()) {
   
   
        // 更新纹理数据
        surfaceTexture.updateTexImage();

        // 获取变换矩阵
        float[] transformMatrix = new float[16];
        surfaceTexture.getTransformMatrix(transformMatrix);

        // 使用该矩阵进行纹理坐标变换后渲染
        // ...
    }
}
// 注意:实际应用中需要确保在正确的线程上调用 updateTexImage() 和其他OpenGL函数

SurfaceTexture 初始化相关源码分析

android.graphics.SurfaceTexture 初始化

    // frameworks.base\graphics\java\android\graphics\SurfaceTexture.java
    public SurfaceTexture(int texName, boolean singleBufferMode) {
   
   
        mCreatorLooper = Looper.myLooper();
        mIsSingleBuffered 
### SurfaceTexture 使用指南与示例代码 `SurfaceTexture` 是 Android 提供的一个类,用于将图像流(如相机预览或视频解码)转换为 OpenGL 纹理。它广泛应用于需要对图像流进行处理的场景,例如相机预览、视频播放和实时图像处理。 #### 基本原理 `SurfaceTexture` 通过将图像数据作为纹理提供给 OpenGL,允许开发者直接操作图像流。当图像流更新时,`SurfaceTexture` 会通过回调通知开发者,开发者可以在回调中更新纹理并进行渲染。这种方式使得图像处理更加灵活,并支持复杂的图形操作。 #### 创建与初始化 要使用 `SurfaceTexture`,首先需要创建一个实例,并将其与 `TextureView` 或其他支持纹理的视图结合使用。以下是一个简单的初始化示例: ```java // 获取 TextureView 的 SurfaceTexture SurfaceTexture surfaceTexture = textureView.getSurfaceTexture(); // 创建一个新的 SurfaceTexture 实例 SurfaceTexture newSurfaceTexture = new SurfaceTexture(surfaceTexture); // 将新的 SurfaceTexture 设置回 TextureView textureView.setSurfaceTexture(newSurfaceTexture); ``` #### 绑定到相机预览 在相机应用中,`SurfaceTexture` 常用于接收相机预览数据。以下是如何将 `SurfaceTexture` 与相机预览结合使用的示例: ```java // 创建一个 SurfaceTexture SurfaceTexture surfaceTexture = new SurfaceTexture(textureView.getSurfaceTexture()); textureView.setSurfaceTexture(surfaceTexture); // 创建一个 Surface 对象 Surface surface = new Surface(surfaceTexture); // 配置相机预览会话 Preview preview = new Preview.Builder().build(); preview.setSurfaceProvider(previewView.createSurfaceProvider()); ``` #### 处理图像流更新 当图像流更新时,`SurfaceTexture` 会触发 `onFrameAvailable` 回调。开发者可以在该回调中更新纹理并进行渲染: ```java surfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() { @Override public void onFrameAvailable(SurfaceTexture surfaceTexture) { // 更新纹理 surfaceTexture.updateTexImage(); // 获取纹理矩阵 float[] textureMatrix = new float[16]; surfaceTexture.getTransformMatrix(textureMatrix); // 在此处进行渲染操作 renderFrame(); } }, null); ``` #### 示例代码 以下是一个完整的示例,展示如何在 `TextureView` 中使用 `SurfaceTexture` 来显示相机预览: ```java public class CameraPreviewActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener { private TextureView textureView; private Camera camera; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); textureView = new TextureView(this); textureView.setSurfaceTextureListener(this); setContentView(textureView); } @Override public void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture, int width, int height) { try { // 打开相机 camera = Camera.open(); // 创建 Surface Surface surface = new Surface(surfaceTexture); // 设置预览显示 camera.setPreviewDisplay(surface); // 开始预览 camera.startPreview(); } catch (IOException e) { e.printStackTrace(); } } @Override public void onSurfaceTextureSizeChanged(SurfaceTexture surfaceTexture, int width, int height) { // 处理大小变化 } @Override public boolean onSurfaceTextureDestroyed(SurfaceTexture surfaceTexture) { // 释放相机资源 if (camera != null) { camera.stopPreview(); camera.release(); camera = null; } return true; } @Override public void onSurfaceTextureUpdated(SurfaceTexture surfaceTexture) { // 每次纹理更新时调用 } } ``` #### 注意事项 - **生命周期管理**:确保在适当的生命周期阶段释放 `SurfaceTexture` 和相关资源,避免内存泄漏。 - **性能优化**:由于 `SurfaceTexture` 可能引入一定的延迟和性能开销,建议在不需要时及时释放资源。 - **线程安全**:`SurfaceTexture` 的某些操作可能需要在特定线程中执行,确保线程安全。 ###
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清霜辰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值