SurfaceTexture详解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SurfaceTexture详解相关的知识,希望对你有一定的参考价值。
参考技术A 之前讲到了 flutter的TextureSurfaceTexture 是 Surface 和 OpenGL ES (GLES) 纹理的组合。SurfaceTexture 用于提供输出到 GLES 纹理的 Surface
SurfaceTexture 包含一个 BufferQueue。当生产方将新的缓冲区排入队列时,onFrameAvailable() 回调会通知应用。然后,应用调用 updateTexImage(),这会释放先前占有的缓冲区,从队列中获取新缓冲区并执行 EGL 调用,从而使 GLES 可将此缓冲区作为外部纹理使用。
关键方法:
SurfaceTexture(int texName, boolean singleBufferMode)构造方法
setOnFrameAvailableListener 设置回调,当生产者准备好新的帧后会调用Listener
updateTexImage 更新texture到指定的GLESContext
detachFromGLContext
attachToGLContext
解绑/绑定 当前GLContext
getTransformMatrix 设置重采样纹理矩阵,当渲染的时候会用到这个数据
release() 完全释放 SufaceTexture的 buffers并且吧Surface状态置为abandoned
android-8.0.0_r1 源码解析:
GLConsumer参数解释:
bq是BufferQueue创建BufferConsumer
tex 表示要将图像流传输到的OpenGL ES纹理名称。
texTarget指定了哪个纹理将被绑定
useFenceSync表示是否需要同步访问缓冲区
可以从一个OpenGL ES上下文中分离GLConsumer,然后分别使用detachFromContext和attachToContext方法将GLConsumer附加到另一个上下文。
如果设置tex参数则会通过attachToContext将GLConsumer附加到OpenGL ES context中。
第一次调用updateTexImage才会绑定,之后所有对updateTexImage的调用必须使用相同的当前OpenGL ES context进行
acquireBufferLocked创建EglImage并设置到EglSlots中
updateAndReleaseLocked 更新 EglImage
createIfNeeded 如果EGLDisplay改变或者crop改变则会创建EglImage
bindToTextureTarget 将调用glEGLImageTargetTexture2DOES去绑定image到指定的目标纹理
这里创建EGLImageKHR,EGLImageKHR用于共享EGL资源
EGL的ShareContext是常见的共享上下文的方式(ios平台的EAGL叫ShareGroup)。
当share_context参数传入另一个EGL的context时,这两个EGLContext就可以共享纹理以及VBO等。
需要注意的是container objects不能被共享,比如:
Framebuffer objects
Vertex array objects
Transform feedback objects
Program pipeline objects
参考: https://wiki.jikexueyuan.com/project/deep-android-v1/classes.html
EGLImageKHR: https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_image_base.txt
Android TextureView+SurfaceTexture实现相机预览
AndroidManifest.xml
<uses-permission android:name="android.permission.RECORD_AUDIO"/><!--音频录制权限-->
<uses-permission android:name="android.permission.CAMERA"/><!--摄像头权限-->
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/><!--存储权限-->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
MainActivity .java
import android.Manifest;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.Gravity;
import android.view.TextureView;
import android.view.View;
import android.widget.FrameLayout;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import java.io.IOException;
public class MainActivity extends AppCompatActivity implements TextureView.SurfaceTextureListener
private Camera mCamera;
private TextureView mTextureView;
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
/**
* 在 Android 6.0 以上需要动态添加权限
*/
ActivityCompat.requestPermissions(this,
new String[]Manifest.permission.CAMERA,Manifest.permission.RECORD_AUDIO,
100);
mTextureView = new TextureView(this);
mTextureView.setSurfaceTextureListener(this);
mTextureView.setScaleX(-1f);
setContentView(mTextureView);
@Override
public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height)
mCamera = Camera.open(1);
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详解的主要内容,如果未能解决你的问题,请参考以下文章
如何以类似于相机为 SurfaceTexture 生成帧的方式生成 YUVI420 帧到 SurfaceTexture?
SurfaceTexture.getTransformMatrix的返回值是啥意思,谁能解释一下?
从 NDK 中获取 SurfaceTexture 的 GL 上下文
Android - 在 SurfaceTexture 上绘制 YouTube 视频