android Camera API1+HAL1 takePicture流程 & Android M

本文详细介绍了Android Camera API1+HAL1中拍照的控制流和数据流回调流程,从java层的takePicture接口开始,分析了数据如何通过JNI层传递到HAL层,再到数据回调到应用程序的过程,涉及匿名共享内存的分配和传递。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

上一篇文章讲述了camera开启预览的流程,有了预览后,一般常见的操作是拍照。本文将讲述拍照的控制流的下发和数据流的回调整个流程,因为囊括了数据回调,中间会涉及到一点CameraHAL层的代码讲解。

首先依然从java层的接口开始分析,一般在apk代码里会实例化ShutterCallback和PictureCallback类,并实现各自的回调函数,然后把实例传递到camera java接口层,供后续数据回调。

1. takePicture

  • Camera.java
    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;
    }

其中的参数是四个回调实例,这些参数是在apk层实例化,并传递下来的

  • ShutterCallback shutter:通知回调,控制播放拍照快门声
  • PictureCallback raw: 回调camera原始数据,如yuv或者bayer raw格式的数据,很少使用
  • PictureCallback postview:这个很少使用,不清楚具体用途
  • PictureCallback jpeg:编码后的JPEG数据,就是拍的照片,主要使用这个
    msgType |= CAMERA_MSG_COMPRESSED_IMAGE一定会执行的,这个msgType 会一直传递到HAL层去。

接下来调用到JNI层的native_takePicture函数

  • android_hardware_Camera.cpp
{
    "native_takePicture",
  "(I)V",
  (void *)android_hardware_Camera_takePicture },

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;
	......
    if (camera->takePicture(msgType) != NO_ERROR) {
   
        jniThrowRuntimeException(env, "takePicture failed");
        return;
    }
}
  • Camera.cpp
// take a picture
status_t Camera::takePicture(int msgType)
{
   
    ALOGV("takePicture: 0x%x", msgType);
    sp <ICamera> c = mCamera;
    if (c == 0) return NO_INIT;
    return c->takePicture(msgType);
}
  • ICamera.cpp
class BpCamera: public BpInterface<ICamera>
{
   
public:
    // 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);
        remote()->transact(TAKE_PICTURE, data, &reply);
        status_t ret = reply.readInt32();
        return ret;
    }

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;
  • 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);  // 这个type是有的

    enableMsgType(picMsgType);   // 使能这个类型,一直调用到hal层

    return mHardware->takePicture();
}
  • CameraHardwareInterface.cpp
    /**
     * 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;
    }

前面这些流程都比较简单,都是直接一步步往下调用,至此framework层的takePicture控制流的下发就完了,接下来会传递到CameraHal中,前面说过我目前主要先分析framework层的流程和代码,所以takePicture下发到hal层的流程暂时就不分析了。


下面将讲述拍照编码后的JPEG数据的回调流程,因为这部分涉及到一些匿名共享内存的分配和传递,会稍微夹带分析一点hal层的代码和流程,这也是为了更方便的理解和阅读framework层的代码。

hal层要想回调数据,必须先获取到framework层的回调接口,将framework层的callback函数指针设置到hal层的函数

2. dataCallback

  • CameraClient.cpp
status_t CameraClient::initialize(CameraModule *module) {
   
	......
    mHardware->setCallbacks(notifyCallback,
            dataCallback,
            dataCallbackTimestamp,
            (void *)(uintptr_t)mCameraId);
     ......
}

这个initialize函数在前面的o

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值