Chinaunix首页 | 论坛 | 博客
  • 博客访问: 353466
  • 博文数量: 197
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 303
  • 用 户 组: 普通用户
  • 注册时间: 2013-09-02 14:21
文章分类

全部博文(197)

文章存档

2014年(89)

2013年(108)

我的朋友

分类: LINUX

2014-03-20 17:12:37

原文地址:Android Camera调用流程 作者:守候心田

Android中Camera的调用流程可分为以下几个层次:
Package->Framework->JNI->Camera(cpp)--(binder)-->CameraService->Camera HAL->Camera Driver

以拍照流程为例:
1. 各个参数设置完成,对焦完成后,位于Package的Camera.java会调用Framework中Camera.java的takePicture函数,如下:
1public final void takePicture(ShutterCallback shutter, PictureCallback raw,
2            PictureCallback postview, PictureCallback jpeg) {
3        mShutterCallback = shutter;
4        mRawImageCallback = raw;
5        mPostviewCallback = postview;
6        mJpegCallback = jpeg;
7        native_takePicture();
8}

此函数保存Package层传下的callback函数,同时调用JNI层的native_takePicture

2. JNI层的native_takePicture自己并没有做太多事情,只是简单地调用cpp的Camera中的takePicture函数。此前已经把JNI中的一个对象注册成了Camera.cpp的listener

3. 位于frameworks/base/libs/camera是向CameraService请求服务的客户端,但它本身也继承了一个BnCameraClient类,用于CameraService回调自己。
1class ICameraClient: public IInterface
2{
3public:
4    DECLARE_META_INTERFACE(CameraClient);
5 
6    virtual void            notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
7    virtual void            dataCallback(int32_t msgType, const sp& data) = 0;
8    virtual void            dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp& data) = 0;
9};

从上面的接口定义可以看到,这个类就是用于回调。

Camera.cpp的takePicture函数是利用open Camera时得到的ICamera对象来继续调用takePicture

4. 接下来通过binder转到另一个进程CameraService中的处理。CameraService中之前已经实例化了一个HAL层的 CameraHardware,并把自己的data callback传递给了CameraHardware,这些工作都是由CameraService的内部类Client来完成的,这个Client类继 承自BnCamera,是真正提供Camera操作API的类

5. 然后自然是调用HAL层CameraHardware的takePicture函数。从HAL层向下就不是Android的标准代码了,各个厂商有自己不 同的实现。但思路应该都是相同的:Camera遵循V4L2架构,利用ioctl发送VIDIOC_DQBUF命令得到有效的图像数据,接着回调HAL层 的data callback接口以通知CameraService,CameraService会通过binder通知Camera.cpp,如下:
01void CameraService::Client::dataCallback(int32_t msgType,
02        const sp& dataPtr, void* user) {
03    LOG2("dataCallback(%d)", msgType);
04 
05    sp client = getClientFromCookie(user);
06    if (client == 0) return;
07    if (!client->lockIfMessageWanted(msgType)) return;
08 
09    if (dataPtr == 0) {
10        LOGE("Null data returned in data callback");
11        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
12        return;
13    }
14 
15    switch (msgType) {
16        case CAMERA_MSG_PREVIEW_FRAME:
17            client->handlePreviewData(dataPtr);
18            break;
19        case CAMERA_MSG_POSTVIEW_FRAME:
20            client->handlePostview(dataPtr);
21            break;
22        case CAMERA_MSG_RAW_IMAGE:
23            client->handleRawPicture(dataPtr);
24            break;
25        case CAMERA_MSG_COMPRESSED_IMAGE:
26            client->handleCompressedPicture(dataPtr);
27            break;
28        default:
29            client->handleGenericData(msgType, dataPtr);
30            break;
31    }
32}
33// picture callback - compressed picture ready
34void CameraService::Client::handleCompressedPicture(const sp& mem) {
35    int restPictures =  mHardware->getPictureRestCount();
36    if (!restPictures)
37    {
38        disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
39    }
40 
41    sp c = mCameraClient;
42    mLock.unlock();
43    if (c != 0) {
44        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
45    }
46}


6. Camera.cpp会继续通知它的listener:
01// callback from camera service when frame or image is ready
02void Camera::dataCallback(int32_t msgType, const sp& dataPtr)
03{
04    sp listener;
05    {
06        Mutex::Autolock _l(mLock);
07        listener = mListener;
08    }
09    if (listener != NULL) {
10        listener->postData(msgType, dataPtr);
11    }
12}


7. 而这个listener就是我们的JNI层的JNICameraContext对象了:
01void JNICameraContext::postData(int32_t msgType, const sp& dataPtr)
02{
03    // VM pointer will be NULL if object is released
04    Mutex::Autolock _l(mLock);
05    JNIEnv *env = AndroidRuntime::getJNIEnv();
06    if (mCameraJObjectWeak == NULL) {
07        LOGW("callback on dead camera object");
08        return;
09    }
10 
11    // return data based on callback type
12    switch(msgType) {
13    case CAMERA_MSG_VIDEO_FRAME:
14        // should never happen
15        break;
16    // don't return raw data to Java
17    case CAMERA_MSG_RAW_IMAGE:
18        LOGV("rawCallback");
19        env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
20                mCameraJObjectWeak, msgType, 0, 0, NULL);
21        break;
22    default:
23        // TODO: Change to LOGV
24        LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
25        copyAndPost(env, dataPtr, msgType);
26        break;
27    }
28}


8. 可以看到JNI层最终都会调用来自java层的函数postEventFromNative,这个函数会发送对应的消息给自己的 eventhandler,收到消息后就会根据消息的类型回调Package层Camera.java最初传下来的callback函数。至此,我们就在 最上层拿到了图像数据。
阅读(689) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~