背景
正常的合成视频是个什么样流程? 主要有三大类方法:MediaMux硬解码,mp4parser,FFmepg三种方式详情传送门, 但是并不能把高帧率、分辨率屏幕视频实时保存下来 那么Android screenrecord命令是怎么做的呢?
一般的android图像流程
图像流生产方
图像流生产方可以是生成图形缓冲区以供消耗的任何内容。例如 OpenGL ES、Canvas 2D 和 mediaserver 视频解码器。
图像流消耗方
图像流的最常见消耗方是 SurfaceFlinger,该系统服务会消耗当前可见的 Surface,并使用窗口管理器中提供的信息将它们合成到屏幕。SurfaceFlinger 是可以修改所显示部分内容的唯一服务。SurfaceFlinger 使用 OpenGL 和 Hardware Composer 来合成一组 Surface。
其他 OpenGL ES 应用也可以消耗图像流,例如相机应用会消耗相机预览图像流。非 GL 应用也可以是使用方,例如 ImageReader 类。
BufferQueue
BufferQueues 是 Android 图形组件之间的粘合剂。它们是一对队列,可以调解缓冲区从生产方到消耗方的固定周期。一旦生产方移交其缓冲区,SurfaceFlinger 便会负责将所有内容合成到显示部分。
screenrecord做了什么
现在我们了解了一般的android图像流程, 那么screenrecord做了什么: screenrecord 命令可让用户将屏幕上显示的所有内容作为一个 .mp4
文件记录在磁盘上。为此,系统从 SurfaceFlinger 接收合成的帧,将它们写入视频编码器,然后将已编码的视频数据写入一个文件。视频编解码器由单独的进程 (mediaserver
) 进行管理,因此我们必须在系统中移动大量图形缓冲区。
从触发screenrecord屏幕录制命令Surfaceflinger创建一个镜像主屏幕的虚拟屏幕(即它与主屏幕具有完全相同的层)并指示它将输出发送到来自 mediaserver 进程的 Surface。在这种情况下,SurfaceFlinger 是缓冲区的生产方,而不是使用方。
配置完成后,screenrecord 会在编码数据显示时触发。在应用绘制时,其缓冲区会前往 SurfaceFlinger,SurfaceFlinger 将它们合成为单个缓冲区,然后直接发送到 mediaserver 进程中的视频编码器。screenrecord 进程从未出现完整的帧。在内部,mediaserver 进程具有自己的移动缓冲区的方式,这种方式还通过句柄传递数据,从而最大限度地降低开销。
参考资料
1.screenrecord 命令源码
2.Android 图形框架
3.Android中音视频合成的几种方案详析