作者:刘洪涛,华清远见嵌入式培训中心讲师。
1. Android-Camera架构分析
Android的camera系统架构自上而下分别为应用层-框架层-硬件抽象层-linux驱动层。层与层之间通过Binder、回调函数或者系统调用联系。
我们主要关心的是CameraService与CameraHAL之间的联系以及CameraHAL本身的实现。
2. CameraService
系统初始化时会开启一个CameraService的守护进程,为上层应用提供camera对应的功能接口。并与与硬件抽象层之间通过回调函数传递数据。
CameraService的实现位于:
frameworks/base/camera/libcameraservice/CameraService.cpp
CameraService的主要功能有取景Preview,拍照takePicture和摄影Recording
CameraService在整个Android-Camera架构处于如下位置:
3. Camera-HAL
HAL层的实现和具体硬件平台相关。Android定义好了它的接口,是一个C++的类和几个回调函数,定义位于头文件:
frameworks/base/include/ui/CameraHardwareInterface.h
FS_S5PC100平台的Camera-HAL的实现位于:
vendor/farsight/fs_proprietary/libcamera/
其中,SecCameraHWInterface.cpp是真正的HAL实现,SecCamera.cpp则是对摄像头具体操作的封装,SecCameraHWInterface中会包含一个SecCamera类的对象。
需要注意的是虽然Camera-HAL已经实现好了,我们还是需要稍作改动才能让它工作。
首先,需要修改摄像头对应的设备文件名:
vendor/farsight/fs_proprietary/libcamera/SecCamera.h
#define CAMERA_DEV_NAME "/dev/video0"
默认设备文件是/dev/video0,但是在这个定制过的éclair里面,video0已经被libfimc打开,这里再次打开的话就会失败。我们也不能用video1,因为它会被libcopybit打开,因此只能使用video2:
#define CAMERA_DEV_NAME "/dev/video2"
其次,需要对预览和拍照的格式进行设置:
vendor/farsight/fs_proprietary/libcamera/SecCameraHWInterface.cpp
p.setPreviewFormat("yuv420sp");
p.setPictureFormat("yuv422i");
4. CameraService与Camera-HAL的联系
在CameraHardwareInterface.h中,定义了一个由C语言方式导出符号的函数:
/** factory function to instantiate a camera hardware object */
extern "C" sp<CameraHardwareInterface> openCameraHardware();
这样,CameraService就可以调用openCameraHardware得到一个CameraHardwareInterface,从而实现Camera的底层操作。
另外,在CameraHardwareInterface.h中,还定义了三个回调函数原型:
typedef void (*notify_callback)(int32_t msgType,
int32_t ext1,
int32_t ext2,
void* user);
typedef void (*data_callback)(int32_t msgType,
const sp<IMemory>& dataPtr,
void* user);
typedef void (*data_callback_timestamp)(nsecs_t timestamp,
int32_t msgType,
const sp<IMemory>& dataPtr,
void* user);
这三个回调函数均由CameraService::client来实现,继而在Cmaera-HAL中回调这些函数来向CameraService传递消息或者视频数据流。
其中,notify_callback主要用于传递一些消息,如按下快门或者开始/停止预览等等;
data_callback用于返回Camera-HAL得到的raw data;
data_callback_timestamp用于返回Camera-HAL得到的raw data并携带时间戳(用于同步);
CameraHardwareInterface还需实现消息使能的方法:
virtual void enableMsgType(int32_t msgType) = 0;
用于指定msg对应的callback是否可用。比如:
enableMsgType(CAMERA_MSG_PREVIEW_FRAME),则data_callback可用。
二者的调用关系如下图: