Android Camera 流程学习记录(五,完结)—— Camera.takePicture() 流程解析




简介

  • 在前面的几篇笔记中,我已经把 Camera 控制流的部分梳理得比较清楚了。在 Camera 流程中,还有一个重要的部分,即数据流。
  • Camera API 1 中,数据流主要是通过函数回调的方式,依照从下往上的方向,逐层 return 到 Applications 中。
  • 由于数据流的部分相对来说比较简单,所以我就将其与 Camera 的控制流结合起来,从 takePicture() 方法切入,追踪一个比较完整的 Camera 流程,这个系列的笔记到这篇也就可以结束了。



takePicture() flow



1. Open 流程

  • Camera Open 的流程,在之前的一篇笔记中已经比较详细地描述了。
  • 在这里,再关注一下这个流程中,HAL 层的部分。

1.1 CameraHardwareInterface.h

  • 位置:frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
  • setCallback()
    • 设置 notify 回调,这用来通知数据已经更新。
    • 设置 data 回调以及 dataTimestamp 回调,对应的是函数指针 mDataCbmDataCvTimestamp
    • 注意到,设置 mDevice->ops 对应回调函数时,传入的不是之前设置的函数指针,而是 __data_cb 这样的函数。在该文件中,实现了 __data_cb ,将回调函数做了一层封装。
/** 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()
    • 对原 callback 函数简单封装,附加了一个防止数组越界判断。
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<CameraHardwareInterface *>(user);
    sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(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);
}


2. 控制流


2.1 Framework

2.1.1 Camera.java
  • 位置:frameworks/base/core/java/android/hardware/Camera.java
  • takePicture()
    • 设置快门回调。
    • 设置各种类型的图片数据回调。
    • 调用 JNI takePicture 方法。
    • 注意,传入的参数 msgType 是根据相应 CallBack 是否存在而确定的,每种 Callback 应该对应一个二进制中的数位(如 1,10,100 中 1 的位置),于是这里采用 |= 操作给它赋值。
public final void takePicture(ShutterCallback shutter, PictureCallback raw,
        PictureCallback postview, PictureCallback jpeg) {
    mShutterCallback = shutter;
    mRawImageCallback = raw;
    mPostviewCallback = postview;
    mJpegCallback = jpeg;

    // If callback is not set, do not send me callbacks.
    int msgType = 0;
    if (mShutterCallback != null) {
        msgType |= CAMERA_MSG_SHUTTER;
    }
    if (mRawImageCallback != null) {
        msgType |= CAMERA_MSG_RAW_IMAGE;
    }
    if (mPostviewCallback != null) {
        msgType |= CAMERA_MSG_POSTVIEW_FRAME;
    }
    if (mJpegCallback != null) {
        msgType |= CAMERA_MSG_COMPRESSED_IMAGE;
    }

    native_takePicture(msgType);
    mFaceDetectionRunning = false;
}

2.2 Android Runtime

2.2.1 android_hardware_Camera.cpp
  • 位置:frameworks/base/core/jni/android_hardware_Camera.cpp
    • takePicture()
    • 获取已经打开的 camera 实例,调用其 takePicture() 接口。
    • 注意,在这个函数中,对于 RAW_IMAGE 有一些附加操作:
      • 如果设置了 RAWcallback ,则要检查上下文中,是否能找到对应 Buffer
      • 若无法找到 Buffer ,则将 CAMERA_MSG_RAW_IMAGE 的信息去掉,换成 CAMERA_MSG_RAW_IMAGE_NOTIFY
      • 替换后,就只会获得 notification 的消息,而没有对应的图像数据。
static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz, jint msgType)
{
    ALOGV("takePicture");
    JNICameraContext* context;
    sp<Camera> 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 th
  • 6
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值