Overlay是Android经常看到的名字,我们可以理解为视频叠加,Overlay也可以理解为视频输出
视频输出和视频叠加是密切相关的,一般来说,输出的视频背景是系统UI层,而视频输出是叠加到UI层上的。
视频输出和系统UI一般使用独立的显存区,系统UI通过framebuffer显示;而视频输出在驱动层可以有两种实现方式:1. framebuffer方式,2. V4L2的output设备实现方式,具体使用哪种,是和平台密切相关的,甚至有的平台两种方式都实现了,比如freescale imx51,应用层既可以通过/dev/fb2实现视频输出,又可以通过output设别/dev/video16实现视频输出,具体使用哪个就是overlayHAL的工作了。
三星s5PV210平台使用output设备来输出视频,设备节点/dev/video1(对应fimc1控制器),其实不一定非要使用fimc1控制器的,fimc0 fimc2也可以实现视频输出,具体是用哪个FIMC作为视频输出,是overlayHAL的实现决定的。
参看文件device/samsung/proprietary/liboverlay/v4l2_utilc.c
- 76 int v4l2_overlay_open(int id)
- 77 {
- 78 LOG_FUNCTION_NAME
- 79 return open("/dev/video1", O_RDWR);
- 80 }
这里直接hardcode overlay设备节点为/dev/video1
主显示区和overlay显示区的叠加是通过硬件来实现的,至于主FB和overlay的层次关系,blending方式一般是由驱动层来实现的;当然应用层可以控制层次关系,叠加层的位置,大小旋转和透明等。
Android视频输出系统结构
Android视频输出系统包括:驱动层(output 驱动,framebuffer驱动), OverlayHAL,Overlay服务器SurfaceFlinger,本地框架
Overlay视频输出系统结构图如下:
1. Overlay驱动层:Framebuffer驱动程序,V4L2 output 驱动程序
2. OverlayHAL:hardware/libhardware/include/hardware/overlay.h,三星s5pv210 overlayHAL实现在device/samsung/proprietary/liboverlay/目录下
4. Overlay的本地框架代码:
头文件路径:frameworks/base/inlcude/ui
源文件路径:frameworks/base/libs/ui
Overlay系统框架是库libui.so的一部分,提供的方法供camera 取景器以及视频输出的render环节使用,三星平台取景器调用参见device/samsung/proprietary/libcamera/SecCameraHWInterface.cpp,视频输出render参见samsung/proprietary/libstagefrighthw/SecHardwareRenderer.cpp。在这两个文件中要实现对overlay系统的调用。
Overlay 驱动层
S5PV210 Overlay在驱动层涉及到output 驱动和framebuffer驱动
output驱动实际上是FIMC控制器驱动的一种特殊形式,FIMC是S5PV210平台的图像处理单元,FIMC控制器的输入可以是camera sensor或者mem,输出则是mem。
如果输入是camera sensor,那么FIMC就是fimc_capture;如果输入是mem,那么FIMC就是fimc_ouput。
当FIMC用做Overlay时,工作流程如下:
1. FIMC的输入设置为camera preview或者视频解码输出的数据地址
2. FIMC的输出地址设置为framebuffer的mem_base
3. 启动FIMC控制器,进行旋转,缩放以及颜色空间转换处理,FIMC控制器把处理结果存放到输出地址
4. FIMC做完转换后,调用fb_set_par,通过这个函数间接的调用到s3c_set_par和s3c_pan_display,这一步非常重要,前面step2 step3是把要显示的内容转换到framebuffer指向的内存,但是并没有刷新到display,fb_set_par的目的就是刷新framebuffer的内容到LCD上。
Note:步骤4,framebuffer中保存的是显示在屏上的内容,改写framebuffer内容后,并不会自动更新到LCD上,必须设置CPU的display 控制器显示内容地址寄存器,使之指向framebuffer的物理内存地址后,内容才会刷到屏上。
display 控制器的地址寄存器只支持物理地址,这也解释了为什么framebuffer需要一大块连续的物理内存。