spin_lock_irqsave;msm_eventq=filep->private_data;spin_unlock_irqrestore;
/*unlockcam_lock,weneedreleaseglobalintf_lockincamera_open,*inordernotblockoperationofotherCameraindualcamerausecase.*/pthread_mutex_unlock;returnrc;}
if{LOGE ",dev_name,strerror);rc=-1;gotoon_error;}#else/*DAEMON_PRESENT*/cam_status_tcam_status;cam_status=mm_camera_module_open_session;if{LOGE;if{rc=-EUSERS;}else{rc=-1;}gotoon_error;}#endif/*DAEMON_PRESENT*/
/*registermsm_v4l2_pm_qos_request*/msm_pm_qos_add_request;returnrc;}---------------------------------------------------------------------------------分析一下APP上层调用framework接口opencamera是怎么调用的!<一>骁龙相机用反射的方法打开摄像机:packages/apps/SnapdragonCamera/src/com/android/camera/AndroidCameraManagerImpl.java@OverridepublicvoidhandleMessage{try{switch{caseOPEN_CAMERA:try{Log.e;MethodopenMethod=Class.forName.getMethod;mCamera=openMethod.invoke;//HAL1versioncode:privatestaticfinalintCAMERA_HAL_API_VERSION_1_0=0x100;}catch{/*RetrywithopenifopenLegacydoesn"texist/fails*/Log.v+",usingopeninstead");mCamera=android.hardware.Camera.open;}...用反射的方法找到类Class.forName,也就是frameworks/base/core/java/android/hardware/Camera.java这个Camera.java类的getMethod的openLegacy方法,frameworks/base/core/java/android/hardware/Camera.javapublicstaticCameraopenLegacy{//能够多传递一个halVersion参数Log.e;if{thrownewIllegalArgumentException;}if||){Log.e;returnnull;}
if{LOGE;rc=-1;}else{if{close;my_obj->ctrl_fd=-1;}#ifdefDAEMON_PRESENTif{mm_camera_socket_close;my_obj->ds_fd=-1;}#endif}
/*unlockcam_lock,weneedreleaseglobalintf_lockincamera_open,*inordernotblockoperationofotherCameraindualcamerausecase.*/pthread_mutex_unlock;LOGD ",rc);returnrc;
if{LOGE ",dev_name,strerror);ifrc=-EUSERS;elserc=-1;gotoon_error;}else{mm_camera_get_session_id;LOGH;}
LOGD;snprintf;mm_camera_cmd_thread_launchmy_obj);
if)returnrc;
#ifdefDAEMON_PRESENT/*opendomainsocket*/n_try=MM_CAMERA_DEV_OPEN_TRIES;do{n_try--;my_obj->ds_fd=mm_camera_socket_create;l_errno=errno;LOGD;if||){LOGD;break;}LOGD;usleep;}while;
上面的系统调用open函数是应用层的,它最终对应内核层的open函数为msm_open,如下:
staticintmsm_open//msm.c{intrc=-1;unsignedlongflags;structmsm_video_device*pvdev=video_drvdata;
if{LOGE;rc=-1;}
gQCamera2Factory->openLegacy<----------QCamera2Factory.cpp//qcom和mtk厂商定制的接口||QCamera2HardwareInterface*hw=newQCamera2HardwareInterfacecameraId);rc=hw->openCamera;<-----------------------QCamera2Factory.cpp||intQCamera2HardwareInterface::openCamera<-----------------------QCamera2HWI.cpp||camera_openmCameraId,&mCameraHandle);<---------------mm_camera_interface.c//不管API1还是API2最后都是要跑到这里的||rc=mm_camera_open;<---mm_camera.c//不管API1还是API2最后都是要跑到这里的||my_obj->ctrl_fd=open;
*/do{n_try--;errno=0;my_obj->ctrl_fd=open;//调用系统调用open的方法,打开设备节点dev/video0,dev/video1,这个顺序是和video的注册顺序相关的。l_errno=errno;LOGD;if||||){break;}LOGE,sleep_msec);usleep;}while;
/*!!!onlyONEopenisallowed!!!*/if)return-EBUSY;
/*launcheventpollthread*wewilladdevtfdintoeventpollthreaduponuserfirstregisterforevt*/LOGD;snprintf;mm_camera_poll_thread_launch;mm_camera_evt_sub;
spin_lock_irqsave;msm_pid=get_pid);spin_unlock_irqrestore;
pthread_mutex_init;pthread_mutex_init;pthread_mutex_init;pthread_cond_init;pthread_condattr_destroy;
console:/#catsys/class/video4linux/video0/namemsm-configconsole:/#catsys/class/video4linux/video1/namemsm-sensorconsole:/#catsys/class/video4linux/video2/namemsm-sensor
privateCamera{Log.e;interr=cameraInitVersion;//然后调用cameraInitVersion方法if){if{thrownewRuntimeException;}elseif{thrownewRuntimeException;}elseif{thrownewRuntimeException;}elseif{thrownewRuntimeException;}elseif{thrownewRuntimeException;}elseif{thrownewRuntimeException;}elseif{thrownewRuntimeException;}//Shouldneverhitthis.thrownewRuntimeException;}}
在V4L2框架中,Camera被看做一个视频设备,使用open函数打开这个设备,接下来就会调用到Kernel层的代码||staticstructv4l2_file_operationsmsm_fops={<------------msm.c.owner=THIS_MODULE,.open=msm_open,.poll=msm_poll,.release=msm_close,.unlocked_ioctl=video_ioctl2,#ifdefCONFIG_COMPAT.compat_ioctl32=video_ioctl2,#endif};||staticintmsm_open<------------msm.c||rc=v4l2_fh_open;<--------------v4l2-fh.c||rc=msm_camera_power_up;<---msm_camera_dt_util.c||rc=msm_sensor_match_id;<-------msm_sensor.c||msm_camera_power_down;<--msm_camera_dt_util.c分析下代码:hardware/qcom/camera/QCamera2/stack/mm-camera-interface/src/mm_camera.c/*===========================================================================*FUNCTION:mm_camera_open**DESCRIPTION:openacamera**PARAMETERS:*@my_obj:ptrtoacameraobject**RETURN:int32_ttypeofstatus*0--success*-1--failure*==========================================================================*/int32_tmm_camera_open{chardev_name[MM_CAMERA_DEV_NAME_LEN];int32_trc=0;int8_tn_try=MM_CAMERA_DEV_OPEN_TRIES;uint8_tsleep_msec=MM_CAMERA_DEV_OPEN_RETRY_SLEEP;intcam_idx=0;constchar*dev_name_value=NULL;intl_errno=0;pthread_condattr_tcond_attr;
LOGD;
if{gotoon_error;}
returnrc;}
dev_name_value=mm_camera_util_get_dev_name_by_num;if{gotoon_error;}snprintf,"/dev/%s",dev_name_value);sscanf;LOGI;//后摄:[wanghl]devname=/dev/video1,cam_idx=1后辅摄:[wanghl]devname=/dev/video2,cam_idx=2/*开后双摄的时候:11-0111:33:44495621509IQCamera:
kernel/msm-9/drivers/media/platform/msm/camera_v2/msm.cstaticstructv4l2_file_operationsmsm_fops={.owner=THIS_MODULE,.open=msm_open,//真正的open.poll=msm_poll,.release=msm_close,.unlocked_ioctl=video_ioctl2,#ifdefCONFIG_COMPAT.compat_ioctl32=video_ioctl2,#endif};
pthread_condattr_init;pthread_condattr_setclock;
文章为作者独立观点,不代表股票配资公司观点