android4.2.2 Camera HAL的结构
本文均属自己阅读源码的点滴总结,转账请注明出处谢谢。
欢迎和大家交流。qq:1037701636 email:[email protected]
Android源码版本Version:4.2.2; 硬件平台 全志A31
这里单独以preview的控制和数据流来进行相关的camera的调用处理,主要先引入Camera 的HAL层的处理结构。
调用还是先从camera的JNI和HAL两个方面来分析:
step1:启动预览startPreview()
// start preview mode status_t Camera::startPreview() { ALOGV("startPreview"); sp <ICamera> c = mCamera; if (c == 0) return NO_INIT; return c->startPreview(); }
这里的mCamera是之前connect请求CameraService建立,该类是匿名的BpCamera直接和CameraService处的CameraClient(该类继承了CameraService的内部类Client,Client继承了BnCamera)进行交互。
step2:调用CameraService侧的CameraClient里的startpreview()
status_t CameraClient::startPreviewMode() { LOG1("startPreviewMode"); status_t result = NO_ERROR; // if preview has been enabled, nothing needs to be done if (mHardware->previewEnabled()) {//使能预览 return NO_ERROR; } if (mPreviewWindow != 0) { native_window_set_scaling_mode(mPreviewWindow.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); native_window_set_buffers_transform(mPreviewWindow.get(), mOrientation); } mHardware->setPreviewWindow(mPreviewWindow);//mPreviewWindow为一个本地窗口ANativeWindow result = mHardware->startPreview(); return result; }
这里出现了一个mPreviewWIndow对象,其类为ANativeWindow,很熟悉的一个应用端的本地窗口。那么这个窗口的初始化过程呢,即这个变量是哪里来的?
step3:探秘本地预览窗口mPreviewWinodw对象
java处:
public final void setPreviewDisplay(SurfaceHolder holder) throws IOException { if (holder != null) { setPreviewDisplay(holder.getSurface()); } else { setPreviewDisplay((Surface)null); } }
这个getSurface()的获取调用如下
static sp<Surface> getSurface(JNIEnv* env, jobject surfaceObj) { sp<Surface> result(android_view_Surface_getSurface(env, surfaceObj)); if (result == NULL) { /* * if this method is called from the WindowManager‘s process, it means * the client is is not remote, and therefore is allowed to have * a Surface (data), so we create it here. * If we don‘t have a SurfaceControl, it means we‘re in a different * process. */ SurfaceControl* const control = reinterpret_cast<SurfaceControl*>( env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl)); if (control) { result = control->getSurface(); if (result != NULL) { result->incStrong(surfaceObj); env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface, reinterpret_cast<jint>(result.get())); } } } return result; }
看到这里可以回顾到从Android Bootanimation理解SurfaceFlinger的客户端建立这一文中,对客户端的一个Surface建立,这里的过程几乎一摸一样,最终返回一个客户端需要的Surface用来绘图使用。
而这个surface最终也将进一步传递到JNI,HAL供实时的预览等。
JNI处:
static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, jobject jSurface) { ALOGV("setPreviewDisplay"); sp<Camera> camera = get_native_camera(env, thiz, NULL); if (camera == 0) return; sp<Surface> surface = NULL; if (jSurface != NULL) { surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface)); } if (camera->setPreviewDisplay(surface) != NO_ERROR) { jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed"); } }
来到JNI层的实现,获取之前由CameraService创作的Camera对象,该类继承了BpCamera用于进一步和CameraService端的CameraClient进行交互。
step4:CameraService处的响应
status_t BnCamera::onTransact( uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { ..... case SET_PREVIEW_DISPLAY: { ALOGV("SET_PREVIEW_DISPLAY"); CHECK_INTERFACE(ICamera, data, reply); sp<Surface> surface = Surface::readFromParcel(data); reply->writeInt32(setPreviewDisplay(surface)); return NO_ERROR; } break; ...... case START_PREVIEW: { ALOGV("START_PREVIEW"); CHECK_INTERFACE(ICamera, data, reply); reply->writeInt32(startPreview());//调用服务端的cameraclient处的函数,为该类的派生类 return NO_ERROR; } break; }
由于之前connect写入的Binder本地实体类对象为CameraClient,则由该类对象的成员函数来实现。
status_t CameraClient::setPreviewDisplay(const sp<Surface>& surface) { LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid()); sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0); sp<ANativeWindow> window(surface); return setPreviewWindow(binder, window); } 再调用SetPreviewWindow(),传入的Binder分别为Surface对象和一个ANativeWindow对象window。
status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder, const sp<ANativeWindow>& window) { Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; // return if no change in surface. if (binder == mSurface) { return NO_ERROR; } if (window != 0) { result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA); if (result != NO_ERROR) { ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result), result); return result; } } // If preview has been already started, register preview buffers now. if (mHardware->previewEnabled()) { if (window != 0) { native_window_set_scaling_mode(window.get(), NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); native_window_set_buffers_transform(window.get(), mOrientation); result = mHardware->setPreviewWindow(window); } } if (result == NO_ERROR) { // Everything has succeeded. Disconnect the old window and remember the // new window. disconnectWindow(mPreviewWindow); mSurface = binder;// This is a binder of Surface or SurfaceTexture. mPreviewWindow = window;//获取了预览的数据窗口 } else { // Something went wrong after we connected to the new window, so // disconnect here. disconnectWindow(window); } return result; }
调用mHardware这个硬件接口将本地的一个Window窗口传递到HAL层。并将这个windw记录到mPreviewWindow中。
Camera的HAL相关的具体实现结构
到了这里已经非讲不可的是mHardware啦,因为这个接口类将不得不访问HAL层。如最之前的result = mHardware->startPreview();函数。
status_t startPreview() { ALOGV("%s(%s)", __FUNCTION__, mName.string()); if (mDevice->ops->start_preview) return mDevice->ops->start_preview(mDevice); return INVALID_OPERATION; }
这是一个典型的底层设备的调用。因此将和大家分享Camera的HAL层的相关操作。
1.参考当前平台的Camera源码,CameraService启动时会调用Camera的HAL模块,第一次open操作的最终调用如下:
int HALCameraFactory::device_open(const hw_module_t* module, const char* name, hw_device_t** device)//最先被framework层调用 { /* * Simply verify the parameters, and dispatch the call inside the * HALCameraFactory instance. */ ..... return gEmulatedCameraFactory.cameraDeviceOpen(atoi(name), device); }
该Camera模块中gEmulatedCameraFactory是一个静态的全局对象。来看该对象的构造过程:
HALCameraFactory::HALCameraFactory() : mHardwareCameras(NULL), mAttachedCamerasNum(0), mRemovableCamerasNum(0), mConstructedOK(false) { F_LOG; LOGD("camera hal version: %s", CAMERA_HAL_VERSION); /* Make sure that array is allocated. */ if (mHardwareCameras == NULL) { mHardwareCameras = new CameraHardware*[MAX_NUM_OF_CAMERAS]; if (mHardwareCameras == NULL) { LOGE("%s: Unable to allocate V4L2Camera array for %d entries", __FUNCTION__, MAX_NUM_OF_CAMERAS); return; } memset(mHardwareCameras, 0, MAX_NUM_OF_CAMERAS * sizeof(CameraHardware*)); } /* Create the cameras */ for (int id = 0; id < MAX_NUM_OF_CAMERAS; id++) { // camera config information mCameraConfig[id] = new CCameraConfig(id);//读取camera配置文件.cfg if(mCameraConfig[id] == 0) { LOGW("create CCameraConfig failed"); } else { mCameraConfig[id]->initParameters(); mCameraConfig[id]->dumpParameters(); } mHardwareCameras[id] = new CameraHardware(&HAL_MODULE_INFO_SYM.common, mCameraConfig[id]);//创建CameraHardware if (mHardwareCameras[id] == NULL) { mHardwareCameras--; LOGE("%s: Unable to instantiate fake camera class", __FUNCTION__); return; } } // check camera cfg if (mCameraConfig[0] != NULL) { mAttachedCamerasNum = mCameraConfig[0]->numberOfCamera(); if ((mAttachedCamerasNum == 2) && (mCameraConfig[1] == NULL)) { return; } } mConstructedOK = true; }
这个全局对象是新建并初始化CameraHardware对象,而这里的Camera支持数目为2个。CameraHardware表示的是一个完整的摄像头类型,该类继承了camera_device这个结构体类:
CameraHardware::CameraHardware(struct hw_module_t* module, CCameraConfig* pCameraCfg) : mPreviewWindow(), mCallbackNotifier(), mCameraConfig(pCameraCfg), mIsCameraIdle(true), mFirstSetParameters(true), mFullSizeWidth(0), mFullSizeHeight(0), mCaptureWidth(0), mCaptureHeight(0), mVideoCaptureWidth(0), mVideoCaptureHeight(0), mUseHwEncoder(false), mFaceDetection(NULL), mFocusStatus(FOCUS_STATUS_IDLE), mIsSingleFocus(false), mOriention(0), mAutoFocusThreadExit(true), mIsImageCaptureIntent(false) { /* * Initialize camera_device descriptor for this object. */ F_LOG; /* Common header */ common.tag = HARDWARE_DEVICE_TAG; common.version = 0; common.module = module; common.close = CameraHardware::close; /* camera_device fields. */ ops = &mDeviceOps; priv = this; // instance V4L2CameraDevice object mV4L2CameraDevice = new V4L2CameraDevice(this, &mPreviewWindow, &mCallbackNotifier);//初始化V4L2CameraDevice if (mV4L2CameraDevice == NULL) { LOGE("Failed to create V4L2Camera instance"); return ; } memset((void*)mCallingProcessName, 0, sizeof(mCallingProcessName)); memset(&mFrameRectCrop, 0, sizeof(mFrameRectCrop)); memset((void*)mFocusAreasStr, 0, sizeof(mFocusAreasStr)); memset((void*)&mLastFocusAreas, 0, sizeof(mLastFocusAreas)); // init command queue OSAL_QueueCreate(&mQueueCommand, CMD_QUEUE_MAX); memset((void*)mQueueElement, 0, sizeof(mQueueElement)); // init command thread pthread_mutex_init(&mCommandMutex, NULL); pthread_cond_init(&mCommandCond, NULL); mCommandThread = new DoCommandThread(this); mCommandThread->startThread(); // init auto focus thread pthread_mutex_init(&mAutoFocusMutex, NULL); pthread_cond_init(&mAutoFocusCond, NULL); mAutoFocusThread = new DoAutoFocusThread(this); }
这里对这个CameraHardware对象进行了成员变量的初始化,其中包括camera_device_t结构体的初始化,其中ops是对Camera模块操作的核心所在。
typedef struct camera_device { /** * camera_device.common.version must be in the range * HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF). CAMERA_DEVICE_API_VERSION_1_0 is * recommended. */ hw_device_t common; camera_device_ops_t *ops; void *priv; } camera_device_t;
这里有出息了一个V4L2CameraDevice对象,真正的和底层内核打交道的地方,基于V4L2的架构实现。
V4L2CameraDevice::V4L2CameraDevice(CameraHardware* camera_hal, PreviewWindow * preview_window, CallbackNotifier * cb) : mCameraHardware(camera_hal), ....... { LOGV("V4L2CameraDevice construct"); memset(&mHalCameraInfo, 0, sizeof(mHalCameraInfo)); memset(&mRectCrop, 0, sizeof(Rect)); // init preview buffer queue OSAL_QueueCreate(&mQueueBufferPreview, NB_BUFFER);//建立10个预览帧 OSAL_QueueCreate(&mQueueBufferPicture, 2);//建立2个图片帧buffer // init capture thread mCaptureThread = new DoCaptureThread(this); pthread_mutex_init(&mCaptureMutex, NULL); pthread_cond_init(&mCaptureCond, NULL); mCaptureThreadState = CAPTURE_STATE_PAUSED; mCaptureThread->startThread();//启动视频采集 // init preview thread mPreviewThread = new DoPreviewThread(this); pthread_mutex_init(&mPreviewMutex, NULL); pthread_cond_init(&mPreviewCond, NULL); mPreviewThread->startThread();//启动预览 // init picture thread mPictureThread = new DoPictureThread(this); pthread_mutex_init(&mPictureMutex, NULL); pthread_cond_init(&mPictureCond, NULL); mPictureThread->startThread();//启动拍照 pthread_mutex_init(&mConnectMutex, NULL); pthread_cond_init(&mConnectCond, NULL); // init continuous picture thread mContinuousPictureThread = new DoContinuousPictureThread(this); pthread_mutex_init(&mContinuousPictureMutex, NULL); pthread_cond_init(&mContinuousPictureCond, NULL); mContinuousPictureThread->startThread();//启动连续拍照 }
创建预览mQueueBufferPreview队列,初始化并启动了Camera需要的几个线程:视频采集,预览,拍照,以及连续的拍照等。
通过以上的几个对象构造后Camera的硬件信息维护到了全局类HALCameraFactory的mHardwareCameras[id]成员变量当中。
在客户端的connect,最终调用HAL的cameraDeviceOpen打开真正的设备:
int HALCameraFactory::cameraDeviceOpen(int camera_id, hw_device_t** device) { ..... if (!mHardwareCameras[0]->isCameraIdle() || !mHardwareCameras[1]->isCameraIdle()) { LOGW("camera device is busy, wait a moment"); usleep(500000); } mHardwareCameras[camera_id]->setCameraHardwareInfo(&mHalCameraInfo[camera_id]); if (mHardwareCameras[camera_id]->connectCamera(device) != NO_ERROR)//连接camera硬件设备 { LOGE("%s: Unable to connect camera", __FUNCTION__); return -EINVAL; } if (mHardwareCameras[camera_id]->Initialize() != NO_ERROR) //camera硬件设备参数等初始化 { LOGE("%s: Unable to Initialize camera", __FUNCTION__); return -EINVAL; } return NO_ERROR; }
初始化的流程依次调用HAL的HardwareCamera的connectCamera函数,其实这里最终的核心是返回一个camera device给上层调用camera的具体操作:最终将CameraHardware的基类camera_devcie_t返回给device。
status_t CameraHardware::connectCamera(hw_device_t** device) { F_LOG; status_t res = EINVAL; { Mutex::Autolock locker(&mCameraIdleLock); mIsCameraIdle = false; } if (mV4L2CameraDevice != NULL) { res = mV4L2CameraDevice->connectDevice(&mHalCameraInfo); if (res == NO_ERROR) { *device = &common; ...... }
mV4L2CameraDevice->connectDevice(),真正的开启V4l2的相关Camera启动,内部通过openCameraDev来实现
status_t V4L2CameraDevice::connectDevice(HALCameraInfo * halInfo) { F_LOG; ..... // open v4l2 camera device int ret = openCameraDev(halInfo);//调用v4l2的camera标准接口 if (ret != OK) { return ret; } memcpy((void*)&mHalCameraInfo, (void*)halInfo, sizeof(HALCameraInfo)); ....... }
openCameraDev()函数内部的实现就是V4L2的典型的API流程,通过ioctl来完成对内核Camera视频采集的驱动的控制。该流程可以参考DM6446的视频前端VPFE驱动之ioctl控制(视频缓存区,CCDC,decoder)解析
int V4L2CameraDevice::openCameraDev(HALCameraInfo * halInfo) { F_LOG; int ret = -1; struct v4l2_input inp; struct v4l2_capability cap; if (halInfo == NULL) { LOGE("error HAL camera info"); return -1; } // open V4L2 device mCameraFd = open(halInfo->device_name, O_RDWR | O_NONBLOCK, 0); if (mCameraFd == -1) { LOGE("ERROR opening %s: %s", halInfo->device_name, strerror(errno)); return -1; } // check v4l2 device capabilities ret = ioctl (mCameraFd, VIDIOC_QUERYCAP, &cap); if (ret < 0) { LOGE("Error opening device: unable to query device."); goto END_ERROR; } if ((cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0) { LOGE("Error opening device: video capture not supported."); goto END_ERROR; } if ((cap.capabilities & V4L2_CAP_STREAMING) == 0) { LOGE("Capture device does not support streaming i/o"); goto END_ERROR; } if (!strcmp((char *)cap.driver, "uvcvideo")) { mIsUsbCamera = true; } if (!mIsUsbCamera) { // uvc do not need to set input inp.index = halInfo->device_id; if (-1 == ioctl (mCameraFd, VIDIOC_S_INPUT, &inp)) { LOGE("VIDIOC_S_INPUT error!"); goto END_ERROR; } } // try to support this format: NV21, YUYV ..... }
到这里为止一共典型的Camera从应用侧到CameraService再到Camera HAL处的初始化流程基本完成。
总结下的是HAL层建立了一个基于V4L2的V4L2CameraDevice对象来完成和内核视频采集模块的互动,返回一个camera_device_t结构体对象mDevice来为后续对Camera设备的进一步控制。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。