首先你明白 Android 中的相关控件的定义和区别吗?

SurfaceView: 因此它本质上是一个View。但与普通View不同的是,它有自己的Surface

GLSurfaceView:作为SurfaceView的补充。它可以看作是SurfaceView的一种典型使用模式。

SurfaceTexture: 和SurfaceView不同的是,它对图像流的处理并不直接显示,而是转为GL外部纹理,因此可用于图像流数据的二次处理(如Camera滤镜,桌面特效等). Android中,Camera设备、视频解码器等都可以产生图像流,SurfaceTexture从图像流中捕获视频帧并转换成GLES纹理。SurfaceTexture在创建的时候需要一个texture对象,捕获到的视频帧会更新到纹理,然后就可以利用GPU的能力进行高效的图像处理。SurfaceTexture将Surface和Texture结合在了一起:SurfaceTexture的构造需要texture对象;利用SurfaceTexture对象可以创建Surface;对Surface进行渲染同样可以把内容更新到对应的texture上。
 

TextureView:它可以将内容流直接投影到View中,可以用于实现Live preview等功能。和SurfaceView不同,它不会在WMS中单独创建窗口,而是作为View hierachy中的一个普通View,因此可以和其它普通View一样进行移动,旋转,缩放,动画等变化。

Android的图形系统底层使用BufferQueue作为基础组件。Surface通常与一个BufferQueue关联,当渲染到Surface上时,结果最终将出现在传送给消费者的缓冲区中。可以把Surface理解成图像生产者一侧的接口,图像生产者通过渲染的动作把图像传递给与Buffer的消费者。

EGL 的一些API

android画布restore android texture_Android

Opengl ES中我们使用最多的有两种类型的纹理:

TEXTURE_2D: 标准的RGB格式图像数据

TEXTURE_EXTERNAL_OES,Android特有的OES纹理,预览相机或者视频使用此纹理,通过SurfaceTexture来转换得到,而摄像头采集获得的数据一般是YUV格式的,事实上,通过查看Opengl的源码我们知道,Android底层对TEXTURE_EXTERNAL_OES这种类型的纹理是经过特殊转换的

Texture 使用的大概流程

// 1. create texure
    final int texture[] = new int[i];
    glGenTextures(1, texture, 0);
    final int texId = texture[0];
    glBindTexture(GL_TEXTURE_EXTERNAL_OES, texId);
    
    // 2. create SurfaceTexture
    SurfaceTexture st = new SurfaceTexture(texId);
    
    // 3. set listener
    st.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
        @Override
        public void onFrameAvailable(SurfaceTexture surfaceTexture) {
            // notify new Frame arrival
            a.  surfaceTexture.updateTexImage(); 
            b.  OES | 2D  ->  ProvideCameraTexture
        }
    }, handler);  // specify a thread for onFrameAvailable execution
    
    // 4. use SurfaceTexture to capture camera preview frame
    mCamera.setPreviewTexture(st);

编码

Surface inputSurface = mediaCodec.createInputSurface();
eglBase.createSurface(inputSurface);

 

1. Create TextureID ->  SurfaceTexture(texture ID) -> camera.setPreviewTexture (surfaceTexutre)  (surfaceTexture 不会显示图像)

2. Get share EGLContext  -> mediaCodec.createInputSurface() -> eglBase.createSurface & new GlRectDrawer

3. EglBase.makeCurrent -> GlRectDrawer.drawRgb/Oes by TextureID ,  则 Texture Data 会进入 mediaCodec

4. DequeueOutputBuffer ( releaseOutputBuffer.false) -> network send

 

Video Downlink:

1. OpenGl ES create Texture ID, SurfaceTexture(id) 绑定这个ID

2. Surface init with surfaceTexture

3. MediaCodec.create with Surface

4. Set listener with {  onTextureFrameAvailable ...   oes -> copy and save  |   2d -> textureCopy  RGB data bigger than yuv } 

5. releaseOutputBuffer -> render:false

6.  eglBase.makeCurrent();  &&  eglBase.makeCurrent();

7.  GlRectDrawer.drawRgb or drawOes  -> eglBase.swapBuffers();