真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

android7相機(jī)拍照流程是怎樣的

今天小編給大家分享一下android7相機(jī)拍照流程是怎樣的的相關(guān)知識(shí)點(diǎn),內(nèi)容詳細(xì),邏輯清晰,相信大部分人都還太了解這方面的知識(shí),所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來(lái)了解一下吧。

成都創(chuàng)新互聯(lián)公司云計(jì)算的互聯(lián)網(wǎng)服務(wù)提供商,擁有超過(guò)13年的服務(wù)器租用、樂(lè)山服務(wù)器托管、云服務(wù)器、雅安服務(wù)器托管、網(wǎng)站系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn),已先后獲得國(guó)家工業(yè)和信息化部頒發(fā)的互聯(lián)網(wǎng)數(shù)據(jù)中心業(yè)務(wù)許可證。專(zhuān)業(yè)提供云主機(jī)、雅安服務(wù)器托管、主機(jī)域名、VPS主機(jī)、云服務(wù)器、香港云服務(wù)器、免備案服務(wù)器等。

在 Camera 流程中,還有一個(gè)重要的部分,即數(shù)據(jù)流。
Camera API 1 中,數(shù)據(jù)流主要是通過(guò)函數(shù)回調(diào)的方式,依照從下往上的方向,逐層 return 到 Applications 中。
由于數(shù)據(jù)流的部分相對(duì)來(lái)說(shuō)比較簡(jiǎn)單,所以我就將其與 Camera 的控制流結(jié)合起來(lái),從 takePicture() 方法切入,追蹤一個(gè)比較完整的 Camera 流程。

位置:frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
setCallback():
設(shè)置 notify 回調(diào),這用來(lái)通知數(shù)據(jù)已經(jīng)更新。
設(shè)置 data 回調(diào)以及 dataTimestamp 回調(diào),對(duì)應(yīng)的是函數(shù)指針 mDataCb 與 mDataCvTimestamp 。
注意到,設(shè)置 mDevice->ops 對(duì)應(yīng)回調(diào)函數(shù)時(shí),傳入的不是之前設(shè)置的函數(shù)指針,而是 __data_cb 這樣的函數(shù)。在該文件中,實(shí)現(xiàn)了 __data_cb ,將回調(diào)函數(shù)做了一層封裝。
/** Set the notification and data callbacks */
void setCallbacks(notify_callback notify_cb,
                  data_callback data_cb,
                  data_callback_timestamp data_cb_timestamp,
                  void* user)
{
    mNotifyCb = notify_cb;
    mDataCb = data_cb;
    mDataCbTimestamp = data_cb_timestamp;
    mCbUser = user;

    ALOGV("%s(%s)", __FUNCTION__, mName.string());

    if (mDevice->ops->set_callbacks) {
        mDevice->ops->set_callbacks(mDevice,
                               __notify_cb,
                               __data_cb,
                               __data_cb_timestamp,
                               __get_memory,
                               this);
    }
}

__data_cb():
對(duì)原 callback 函數(shù)簡(jiǎn)單封裝,附加了一個(gè)防止數(shù)組越界判斷。
static void __data_cb(int32_t msg_type,
                      const camera_memory_t *data, unsigned int index,
                      camera_frame_metadata_t *metadata,
                      void *user)
{
    ALOGV("%s", __FUNCTION__);
    CameraHardwareInterface *__this =
            static_cast(user);
    sp mem(static_cast(data->handle));
    if (index >= mem->mNumBufs) {
        ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__,
             index, mem->mNumBufs);
        return;
    }
    __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser);
}
位置:frameworks/base/core/jni/android_hardware_Camera.cpp
takePicture():
獲取已經(jīng)打開(kāi)的 camera 實(shí)例,調(diào)用其 takePicture() 接口。
注意,在這個(gè)函數(shù)中,對(duì)于 RAW_IMAGE 有一些附加操作:
如果設(shè)置了 RAW 的 callback ,則要檢查上下文中,是否能找到對(duì)應(yīng) Buffer。
若無(wú)法找到 Buffer ,則將 CAMERA_MSG_RAW_IMAGE 的信息去掉,換成 CAMERA_MSG_RAW_IMAGE_NOTIFY。
替換后,就只會(huì)獲得 notification 的消息,而沒(méi)有對(duì)應(yīng)的圖像數(shù)據(jù)。

static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz, jint msgType)
{
    ALOGV("takePicture");
    JNICameraContext* context;

  //先前有分析,https://my.oschina.net/u/920274/blog/5034592
    sp camera = get_native_camera(env, thiz, &context);
    if (camera == 0) return;

    /*
     * When CAMERA_MSG_RAW_IMAGE is requested, if the raw image callback
     * buffer is available, CAMERA_MSG_RAW_IMAGE is enabled to get the
     * notification _and_ the data; otherwise, CAMERA_MSG_RAW_IMAGE_NOTIFY
     * is enabled to receive the callback notification but no data.
     *
     * Note that CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed to the
     * Java application.
     */
    if (msgType & CAMERA_MSG_RAW_IMAGE) {
        ALOGV("Enable raw image callback buffer");
        if (!context->isRawImageCallbackBufferAvailable()) {
            ALOGV("Enable raw image notification, since no callback buffer exists");
            msgType &= ~CAMERA_MSG_RAW_IMAGE;
            msgType |= CAMERA_MSG_RAW_IMAGE_NOTIFY;
        }
    }

    if (camera->takePicture(msgType) != NO_ERROR) {
        jniThrowRuntimeException(env, "takePicture failed");
        return;
    }
}

調(diào)用camera->takePicture(msgType)后,來(lái)到下面的地方。

位置:frameworks/av/camera/Camera.cpp
takePicture():
獲取一個(gè) ICamera,調(diào)用其 takePicture 接口。
這里直接用 return 的方式調(diào)用,比較簡(jiǎn)單。

// take a picture
status_t Camera::takePicture(int msgType)
{
    ALOGV("takePicture: 0x%x", msgType);

   //https://my.oschina.net/u/920274/blog/5034592 有分析
    sp c = mCamera;
    if (c == 0) return NO_INIT;
    return c->takePicture(msgType);
}

然后跳轉(zhuǎn)到

位置:frameworks/av/camera/ICamera.cpp
takePicture():
利用 Binder 機(jī)制發(fā)送相應(yīng)指令到服務(wù)端。
實(shí)際調(diào)用到的是 CameraClient::takePicture() 函數(shù)。

 // take a picture - returns an IMemory (ref-counted mmap)
    status_t takePicture(int msgType)
    {
        ALOGV("takePicture: 0x%x", msgType);
        Parcel data, reply;
        data.writeInterfaceToken(ICamera::getInterfaceDescriptor());
        data.writeInt32(msgType);

       //后面會(huì)分析這個(gè)地方的調(diào)用
        remote()->transact(TAKE_PICTURE, data, &reply);
        status_t ret = reply.readInt32();
        return ret;
    }

remote()->transact(TAKE_PICTURE, data, &reply);

binder調(diào)用到文件的CameraService.cpp的CameraService::onTransact方法

status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
        uint32_t flags) {

    const int pid = getCallingPid();
    const int selfPid = getpid();

    // Permission checks
    switch (code) {
        case BnCameraService::CONNECT:
        case BnCameraService::CONNECT_DEVICE:
        case BnCameraService::CONNECT_LEGACY: {
            if (pid != selfPid) {
                // we're called from a different process, do the real check
                if (!checkCallingPermission(
                        String16("android.permission.CAMERA"))) {
                    const int uid = getCallingUid();
                    ALOGE("Permission Denial: "
                         "can't use the camera pid=%d, uid=%d", pid, uid);
                    return PERMISSION_DENIED;
                }
            }
            break;
        }
        case BnCameraService::NOTIFY_SYSTEM_EVENT: {
            if (pid != selfPid) {
                // Ensure we're being called by system_server, or similar process with
                // permissions to notify the camera service about system events
                if (!checkCallingPermission(
                        String16("android.permission.CAMERA_SEND_SYSTEM_EVENTS"))) {
                    const int uid = getCallingUid();
                    ALOGE("Permission Denial: cannot send updates to camera service about system"
                            " events from pid=%d, uid=%d", pid, uid);
                    return PERMISSION_DENIED;
                }
            }
            break;
        }
    }

    return BnCameraService::onTransact(code, data, reply, flags);//然后會(huì)調(diào)用到這來(lái)
}

繼續(xù)往下到文件ICameraService.cpp


status_t BnCameraService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
     。。。
     。。。
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

繼續(xù)會(huì)調(diào)用到文件ICamera.cpp


status_t BnCamera::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
     
        case TAKE_PICTURE: {
            ALOGV("TAKE_PICTURE");
            CHECK_INTERFACE(ICamera, data, reply);
            int msgType = data.readInt32();
            reply->writeInt32(takePicture(msgType));
            return NO_ERROR;
        } break;
     
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

會(huì)調(diào)用到文件CameraClient.cpp下的takePicture(),是因?yàn)镃ameraClient繼承 BnCamera

繼續(xù)往下看文件 CameraClient.cpp

// take a picture - image is returned in callback
status_t CameraClient::takePicture(int msgType) {
    LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType);

    Mutex::Autolock lock(mLock);
    status_t result = checkPidAndHardware();
    if (result != NO_ERROR) return result;

    if ((msgType & CAMERA_MSG_RAW_IMAGE) &&
        (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) {
        ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY"
                " cannot be both enabled");
        return BAD_VALUE;
    }

    // We only accept picture related message types
    // and ignore other types of messages for takePicture().
    int picMsgType = msgType
                        & (CAMERA_MSG_SHUTTER |
                           CAMERA_MSG_POSTVIEW_FRAME |
                           CAMERA_MSG_RAW_IMAGE |
                           CAMERA_MSG_RAW_IMAGE_NOTIFY |
                           CAMERA_MSG_COMPRESSED_IMAGE);

    enableMsgType(picMsgType);

    return mHardware->takePicture();
}

位置:frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
takePicture():
通過(guò) mDevice 中設(shè)置的函數(shù)指針,調(diào)用 HAL 層中具體平臺(tái)對(duì)應(yīng)的 takePicture 操作的實(shí)現(xiàn)邏輯。
接下來(lái)就是與具體的平臺(tái)相關(guān)的流程了,這部分內(nèi)容對(duì)我并非主要,而且在上一篇筆記中已經(jīng)有比較深入的探索,所以在這里就不繼續(xù)向下挖掘了。
控制流程到了 HAL 層后,再向 Linux Drivers 發(fā)送控制指令,從而使具體的 Camera 設(shè)備執(zhí)行指令,并獲取數(shù)據(jù)。
   /**
     * Take a picture.
     */
    status_t takePicture()
    {
        ALOGV("%s(%s)", __FUNCTION__, mName.string());
        if (mDevice->ops->take_picture)
            return mDevice->ops->take_picture(mDevice);
        return INVALID_OPERATION;
    }

后面就是 數(shù)據(jù)流
由于數(shù)據(jù)流是通過(guò) callback 函數(shù)實(shí)現(xiàn)的,所以探究其流程的時(shí)候我是從底層向上層進(jìn)行分析的。

以上就是“android7相機(jī)拍照流程是怎樣的”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會(huì)為大家更新不同的知識(shí),如果還想學(xué)習(xí)更多的知識(shí),請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。


網(wǎng)站題目:android7相機(jī)拍照流程是怎樣的
文章分享:http://weahome.cn/article/pjscse.html

其他資訊

在線(xiàn)咨詢(xún)

微信咨詢(xún)

電話(huà)咨詢(xún)

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部