短视频Android干货集

抖音录制视频预习资料

2018-10-31  本文已影响746人  十年开发程序员

Frame Buffer Object

​ 帧缓冲对象:FBO。默认情况下,我们在GLSurfaceView中绘制的结果是显示到屏幕上,然而实际中有很多情况并不需要渲染到屏幕上,这个时候使用FBO就可以很方便的实现这类需求。FBO可以让我们的渲染不渲染到屏幕上,而是渲染到离屏Buffer中。

​ 在上节课中我们创建了一个ScreenFilter类用来封装将摄像头数据显示当屏幕上,然而我们需要在显示之前增加各种"效果",如果我们只存在一个ScreenFilter,那么所有的"效果"都会积压在这个类中,同时也需要大量的if else来判断是否开启效果。

结构1.png

​ 我们可以将每种效果写到单独的一个Filter中去,并且在ScreenFilter之前的所有Filter都不需要显示到屏幕中,所以在ScreenFilter之前都将其使用FBO进行缓存。

需要注意的是: 摄像头画面经过FBO的缓存时候,我们再从FBO绘制到屏幕,这时候就不需要再使用samplerExternalOES与变换矩阵了。这意味着ScreenFilter,使用的采样器就是正常的sampler2D,也不需要#extension GL_OES_EGL_image_external : require

然而在最原始的状态下是没有开启任何效果的,所以ScreenFilter就比较尴尬。

1、开启效果: 使用sampler2D

2、未开启效果: 使用samplerExternalOES

那么就需要在ScreenFilter中使用if else来进行判断,但这个判断稍显麻烦,所以这里选择使用:

结构2.png

从摄像头使用的纹理首先绘制到CameraFilterFBO中,这样无论是否开启效果ScreenFilter都是以sampler2D来进行采样。

MediaCodec

​ MediaCodec是Android 4.1.2(API 16)提供的一套编解码API。它的使用非常简单,它存在一个输入缓冲区与一个输出缓冲区,在编码时我们将数据塞入输入缓冲区,然后从输出缓冲区取出编码完成后的数据就可以了。

mediacodec.png

除了直接操作输入缓冲区之外,还有另一种方式来告知MediaCodec需要编码的数据,那就是:

public native final Surface createInputSurface();

使用此接口创建一个Surface,然后我们在这个Surface中"作画",MediaCodec就能够自动的编码Surface中的“画作”,我们只需要从输出缓冲区取出编码完成之后的数据即可。

​ 此前,我们使用OpenGL进行绘画显示在屏幕上,然而想要复制屏幕图像到cpu内存中却不是一件非常轻松的事情。所以我们可以直接将OpenGL显示到屏幕中的图像,同时绘制到MediaCodec#createInputSurface当中去。

PBO(Pixel Buffer Object,像素缓冲对象)通过直接的内存访问(Direct Memory Access,DMA)高速的复制屏幕图像像素数据到CPU内存,但这里我们直接使用createInputSurface更简单......

录制我们在另外一个线程中进行(录制现场),所以录制的EGL环境和显示的EGL环境(GLSurfaceView,显示线程)是两个独立的工作环境,他们又能够共享上下文资源:显示线程中使用的texture等,需要能够在录制线程中操作(通过录制线程中使用OpenGL绘制到MediaCodec的Surface)。

在这个线程中我们需要自己来:

1、配置录制使用的EGL环境(参照GLSurfaceView是怎么配置的)

2、完成将显示的图像绘制到MediaCodec的Surface中

3、编码(H.264)与复用(封装mp4)的工作

上一篇下一篇

猜你喜欢

热点阅读