记录自己的学习过程。。。。。。。
注:1. surfaceflinger暂时不完全懂,后续研究
2. 平台mx53
android 中文件调用流程: hardware/camera.java -----> libs/camera.camera.cpp ------> cameraservice.cpp ------> CameraHal.cpp
hardware/camera.java -----> libs/camera.camera.cpp ------> ICamera.cpp ------> cameraservice.cpp ------> CameraHal.cpp
android 中打开摄像头驱动的基本流程:
public static Camera open() {
int numberOfCameras = getNumberOfCameras(); //获取camera数量
CameraInfo cameraInfo = new CameraInfo();
for (int i = 0; i < numberOfCameras; i++) {
getCameraInfo(i, cameraInfo);
if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) { //看注释,好像是判断是前置摄像头,还是后置摄像头
return new Camera(i);
}
}
return null;
}
Camera(int cameraId) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
mPreviewCallback = null;
mPostviewCallback = null;
mZoomListener = null;
Looper looper;
if ((looper = Looper.myLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else if ((looper = Looper.getMainLooper()) != null) {
mEventHandler = new EventHandler(this, looper);
} else {
mEventHandler = null;
}
native_setup(new WeakReference(this), cameraId); //connect to camera service
}
b) native_setup会调用到android_hardware_camera.cpp文件中的android_hardware_camera_native_setup()函数
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId)
{
sp camera = Camera::connect(cameraId); //framework/base/libs/camera/camera.cpp中的connect函数,如下
if (camera == NULL) {
jniThrowException(env, "java/lang/RuntimeException",
"Fail to connect to camera service");
return;
}
// make sure camera hardware is alive
if (camera->getStatus() != NO_ERROR) { //判断可用
jniThrowException(env, "java/lang/RuntimeException", "Camera initialization failed");
return;
}
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "Can't find android/hardware/Camera");
return;
}
// We use a weak reference so the Camera object can be garbage collected.
// The reference is only used as a proxy for callbacks.
sp context = new JNICameraContext(env, weak_this, clazz, camera);
context->incStrong(thiz);
camera->setListener(context);
// save context in opaque field
env->SetIntField(thiz, fields.context, (int)context.get());
}
c)调用framework/base/libs/camera/camera.cpp中的connect函数
sp Camera::connect(int cameraId)
{
LOGV("connect");
sp c = new Camera(); //申请camera
const sp& cs = getCameraService(); //获取camera service,在systemserver中调用并运行
if (cs != 0) {
c->mCamera = cs->connect(c, cameraId); //绑定申请的camera到camera service,详细代码如下
}
if (c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
c.clear();
}
return c;
}
d)调用cameraservice.cpp中的master端的connect函数
sp CameraService::connect(
const sp& cameraClient, int cameraId) {
int callingPid = getCallingPid();
LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
/*下面一段,属于容错处理,特殊情况特殊对待*/
sp client;
if (cameraId < 0 || cameraId >= mNumberOfCameras) { //camera的ID越界,超过可以使用的camera的数量
LOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
callingPid, cameraId);
return NULL;
}
Mutex::Autolock lock(mServiceLock);
if (mClient[cameraId] != 0) { //申请试用的camera ID是不是重复申请了,或者上次没有释放
client = mClient[cameraId].promote();
if (client != 0) {
if (cameraClient->asBinder() == client->getCameraClient()->asBinder()) {
LOG1("CameraService::connect X (pid %d) (the same client)",
callingPid);
return client;
} else {
LOGW("CameraService::connect X (pid %d) rejected (existing client).",
callingPid);
return NULL;
}
}
mClient[cameraId].clear();
}
if (mBusy[cameraId]) { //正在试用
LOGW("CameraService::connect X (pid %d) rejected"
" (camera %d is still busy).", callingPid, cameraId);
return NULL;
}
sp hardware = HAL_openCameraHardware(cameraId); //打开camera设备,并初始化相关信息,下一步贴代码,并注释
if (hardware == NULL) {
LOGE("Fail to open camera hardware (id=%d)", cameraId);
return NULL;
}
CameraInfo info;
HAL_getCameraInfo(cameraId, &info); //获取camera info,包括facing, rotate
client = new Client(this, cameraClient, hardware, cameraId, info.facing, //初始化获取到的cameraID的camera,设置相应的service,callback,busy flag
callingPid);
mClient[cameraId] = client;
LOG1("CameraService::connect X");
return client;
}
e)Hal_openCameraHardware会调用到 hardware/mx5x/libcamera/cameraHal.cpp中的函数
sp HAL_openCameraHardware(int cameraId)
{
char *SelectedCameraName;
int back_camera_num = 0, front_camera_num = 0;
sp pCaptureDevice = NULL;
sp pPPDevice = NULL;
sppJpegEncoder = NULL;
if (HAL_getNumberOfCameras() ==0 ){
CAMERA_HAL_ERR("There is no configure for Cameras");
return NULL;
}
SelectedCameraName = Camera_name[sCameraInfo[cameraId].facing]; //获取对应cameraID的设备名称
pCaptureDevice = createCaptureDevice(SelectedCameraName); //创建cameraID对应的设备,还么有正式打开
pPPDevice = createPPDevice(); //postprocessing device
pJpegEncoder = createJpegEncoder(SOFTWARE_JPEG_ENC); //jpeg encode,应该是拍照用的
CameraHal *pCameraHal = new CameraHal(); //new CameraHal对象,并设置其中相应的device(capture, pp. jpegencode)
if (pCameraHal->setCaptureDevice(pCaptureDevice) < 0 ||
pCameraHal->setPostProcessDevice(pPPDevice) < 0 ||
pCameraHal->setJpegEncoder(pJpegEncoder) < 0)
return NULL;
if (pCameraHal->Init() < 0) //init函数,下一步贴代码,加注释
return NULL;
//now the board has only one csi camera sensor, so just do mirror for it
if(strstr(SelectedCameraName, "ov") != NULL){
pCameraHal->setPreviewRotate(CAMERA_PREVIEW_BACK_REF);
}
sp hardware(pCameraHal);
CAMERA_HAL_LOG_INFO("created the fsl Camera hal");
return hardware;
}
};
f) init 函数,cameraHal.cpp文件中
CAMERA_HAL_ERR_RET CameraHal::Init()
{
CAMERA_HAL_LOG_FUNC;
CAMERA_HAL_ERR_RET ret = CAMERA_HAL_ERR_NONE;
mCameraReady == true;
if ((ret = AolLocForInterBuf())<0) //如函数名,申请buf
return ret;
if ((ret = InitCameraHalParam()) < 0) //init函数,会打开/dev/vedio设备,不会关闭,获取支持的Format,size,Fps,等数据,(以及是否可用。。。)
return ret;
if (mPPDeviceNeed == true && mPPDevice == NULL)
return CAMERA_HAL_ERR_PP_NULL;
if ((ret = CameraMiscInit()) < 0) //一些相关的mutex, overlay, pp
return ret;
return ret;
}
至此,open流程结束,主要目的是,获取一个可以使用的camera接口cameraID,并创建相对应的camera 的client,绑定到camera的service上,打开cameraID对应的device,通常情况下是/dev/vedio0等,获取相关的parameters,ctrl状况,设置busy flag, 申请buffer, 初始化overlay 的mutex等。
3. setparameters
这两个函数调用过程极其相似,详细调用过程如下:
a) getparameters
到这里,就直接返回当前设置并存放的parameters,
对于现在使用的平台,会继续调用DevGetInputValid---->V4l2GetInputValid---------->VIDIOC_G_CTRL获取当前camera control的状态。
b) setparameters类似
现在的平台会相继调用:DevSetSource ----------->V4l2SetSource ------------->VIDIOC_S_CTRL 设置当前的camera control的状态。
4. start preview
和getparameters调用流程类似,最后调用到cameraHal.cpp函数中CameraHALStartPreview函数:
status_t CameraHal::CameraHALStartPreview()
{
CAMERA_HAL_LOG_FUNC;
status_t ret = NO_ERROR;
int max_fps, min_fps;
mParameters.getPreviewSize((int *)&(mCaptureDeviceCfg.width),(int *)&(mCaptureDeviceCfg.height));
mCaptureDeviceCfg.fmt = mPreviewCapturedFormat;
mCaptureDeviceCfg.rotate = (SENSOR_PREVIEW_ROTATE)mPreviewRotate;
mCaptureDeviceCfg.tv.numerator = 1;
mCaptureDevice->GetDevName(mCameraSensorName);
if (strstr(mCameraSensorName, "uvc") == NULL){
//according to google's doc getPreviewFrameRate & getPreviewFpsRange should support both.
// so here just a walkaround, if the app set the frameRate, will follow this frame rate.
if (mParameters.getPreviewFrameRate() >= 15)
mCaptureDeviceCfg.tv.denominator = mParameters.getPreviewFrameRate();
else{
mParameters.getPreviewFpsRange(&min_fps, &max_fps);
CAMERA_HAL_LOG_INFO("###start the capture the fps is %d###", max_fps);
mCaptureDeviceCfg.tv.denominator = max_fps/1000;
}
}else{
mCaptureDeviceCfg.tv.denominator = 15;
}
mCaptureBufNum = PREVIEW_CAPTURE_BUFFER_NUM;
mPPbufNum = POST_PROCESS_BUFFER_NUM;
mTakePicFlag = false;
if ((ret = PrepareCaptureDevices()) < 0){ //打开设备,设置(VIDEOC_S_CTRL),mmap prepare(VIDEOC_QBUF)
CAMERA_HAL_ERR("PrepareCaptureDevices error ");
return ret;
}
if (mPPDeviceNeed){
if ((ret = PreparePostProssDevice()) < 0){
CAMERA_HAL_ERR("PreparePostProssDevice error");
return ret;
}
}
if ((ret = PreparePreviwBuf()) < 0){
CAMERA_HAL_ERR("PreparePreviwBuf error");
return ret;
}
if ((ret = PreparePreviwMisc()) < 0){
CAMERA_HAL_ERR("PreparePreviwMisc error");
return ret;
}
if ((ret = CameraHALPreviewStart()) < 0){ //关键函数,开启相关处理线程
CAMERA_HAL_ERR("CameraHALPreviewStart error");
return ret;
}
return ret;
}
cameraHalPreviewStart函数,是用来来气处理线程,如下
status_t CameraHal ::CameraHALPreviewStart()
{
CAMERA_HAL_LOG_FUNC;
status_t ret = NO_ERROR;
if (mCaptureDevice->DevStart()<0)
return INVALID_OPERATION;
mCaptureFrameThread = new CaptureFrameThread(this); //这几个线程的具体实现过程以及功能,暂时不了啊.....不懂的好多啊。。。。
mPreviewShowFrameThread = new PreviewShowFrameThread(this);
mEncodeFrameThread = new EncodeFrameThread(this);
if(mPPDeviceNeed){
mPostProcessThread = new PostProcessThread(this);
if (mPostProcessThread == NULL)
return UNKNOWN_ERROR;
}
if (mCaptureFrameThread == NULL ||
mPreviewShowFrameThread == NULL ||
mEncodeFrameThread == NULL){
return UNKNOWN_ERROR;
}
mPreviewRunning = true;
return ret;
}