Android Camera調用流程

來源:互聯網
上載者:User

Android中Camera的調用流程可分為以下幾個層次:
Package->Framework->JNI->Camera(cpp)--(binder)-->CameraService->Camera HAL->Camera Driver

以拍照流程為例:
1. 各個參數設定完成,對焦完成後,位於Package的Camera.java會調用Framework中Camera.java的takePicture函數,如下:
public final void takePicture(ShutterCallback shutter, PictureCallback raw,
            PictureCallback postview, PictureCallback jpeg) {
        mShutterCallback = shutter;
        mRawImageCallback = raw;
        mPostviewCallback = postview;
        mJpegCallback = jpeg;
        native_takePicture();
}
此函數儲存Package層傳下的callback函數,同時調用JNI層的native_takePicture

2. JNI層的native_takePicture自己並沒有做太多事情,只是簡單地調用cpp的Camera中的takePicture函數。此前已經把JNI中的一個對象註冊成了Camera.cpp的listener

3. 位於frameworks/base/libs/camera是向CameraService請求服務的用戶端,但它本身也繼承了一個BnCameraClient類,用於CameraService回調自己。
class ICameraClient: public IInterface
{
public:
    DECLARE_META_INTERFACE(CameraClient);

    virtual void            notifyCallback(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
    virtual void            dataCallback(int32_t msgType, const sp<IMemory>& data) = 0;
    virtual void            dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) = 0;
};
從上面的介面定義可以看到,這個類就是用於回調。

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,如下:
void CameraService::Client::dataCallback(int32_t msgType,
        const sp<IMemory>& dataPtr, void* user) {
    LOG2("dataCallback(%d)", msgType);

    sp<Client> client = getClientFromCookie(user);
    if (client == 0) return;
    if (!client->lockIfMessageWanted(msgType)) return;

    if (dataPtr == 0) {
        LOGE("Null data returned in data callback");
        client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0);
        return;
    }

    switch (msgType) {
        case CAMERA_MSG_PREVIEW_FRAME:
            client->handlePreviewData(dataPtr);
            break;
        case CAMERA_MSG_POSTVIEW_FRAME:
            client->handlePostview(dataPtr);
            break;
        case CAMERA_MSG_RAW_IMAGE:
            client->handleRawPicture(dataPtr);
            break;
        case CAMERA_MSG_COMPRESSED_IMAGE:
            client->handleCompressedPicture(dataPtr);
            break;
        default:
            client->handleGenericData(msgType, dataPtr);
            break;
    }
}
// picture callback - compressed picture ready
void CameraService::Client::handleCompressedPicture(const sp<IMemory>& mem) {
    int restPictures =  mHardware->getPictureRestCount();
    if (!restPictures)
    {
        disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
    }

    sp<ICameraClient> c = mCameraClient;
    mLock.unlock();
    if (c != 0) {
        c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE, mem);
    }
}

6. Camera.cpp會繼續通知它的listener:
// callback from camera service when frame or image is ready
void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr)
{
    sp<CameraListener> listener;
    {
        Mutex::Autolock _l(mLock);
        listener = mListener;
    }
    if (listener != NULL) {
        listener->postData(msgType, dataPtr);
    }
}

7. 而這個listener就是我們的JNI層的JNICameraContext對象了:
void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr)
{
    // VM pointer will be NULL if object is released
    Mutex::Autolock _l(mLock);
    JNIEnv *env =
AndroidRuntime::getJNIEnv();
    if (mCameraJObjectWeak == NULL) {
        LOGW("callback on dead camera object");
        return;
    }

    // return data based on callback type
    switch(msgType) {
    case CAMERA_MSG_VIDEO_FRAME:
        // should never happen
        break;
    // don't return raw data to Java
    case CAMERA_MSG_RAW_IMAGE:
        LOGV("rawCallback");
        env->CallStaticVoidMethod(mCameraJClass, fields.post_event,
                mCameraJObjectWeak, msgType, 0, 0, NULL);
        break;
    default:
        // TODO: Change to LOGV
        LOGV("dataCallback(%d, %p)", msgType, dataPtr.get());
        copyAndPost(env, dataPtr, msgType);
        break;
    }
}

8. 可以看到JNI層最終都會調用來自java層的函數postEventFromNative,這個函數會發送對應的訊息給自己的eventhandler,收到訊息後就會根據訊息的類型回調Package層Camera.java最初傳下來的callback函數。至此,我們就在最上層拿到了映像資料。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.