imx6平台Android源码笔记——Camera系统架构

Camera的架构与Android系统的整体架构保持一致,如下图所示,本文主要从以下四个方面对其进行说明。

  1. Framework:Camera.java
  2. Android Runtime:android_hardware_Camera.cpp
  3. Library:Camera Client和Camera Service
  4. HAL:CameraHardwareInterface
14527792381330663_thumb9

一、Framework:Camera.java

Camera是应用层软件直接使用的类,涵盖了启动、预览、拍摄及关闭等操作摄像头的全部接口。Camera.java在Android源码中的路径为:framework/base/core/java/android/hardware。为了说明整个Camera系统的架构,这里暂不横向分析Camera.java的功能,下面从open()方法着手:

   /**
     * Creates a new Camera object to access the first back-facing camera on the
     * device. If the device does not have a back-facing camera, this returns
     * null.
     * @see #open(int)
     */
    public static Camera open() {
        int numberOfCameras = getNumberOfCameras();
        CameraInfo cameraInfo = new CameraInfo();
        for (int i = 0; i < numberOfCameras; i++) {
            getCameraInfo(i, cameraInfo);
            if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) {
                return new Camera(i);
            }
        }
        return null;
    }

open()方法需要注意以下几点:

  • getNumberOfCameras为native方法,实现在android_hardware_Camera.cpp中;
  • CameraInfo是Camera定义的静态内部类,包含facing、orientation、canDisableShutterSound;
  • getCameraInfo内部调用native方法_getCameraInfo获取摄像头信息;
  • open()默认启动的是后置摄像头(CAMERA_FACING_BACK)。
Camera(int cameraId) {
        mShutterCallback = null;
        mRawImageCallback = null;
        mJpegCallback = null;
        mPreviewCallback = null;
        mPostviewCallback = null;
        mZoomListener = null;

        Looper looper;
        if ((looper = Looper.myLooper()) != null) {
            mEventHandler = new EventHandler(this, looper);
        } else if ((looper = Looper.getMainLooper()) != null) {
            mEventHandler = new EventHandler(this, looper);
        } else {
            mEventHandler = null;
        }

        String packageName = ActivityThread.currentPackageName();

        native_setup(new WeakReference<Camera>(this), cameraId, packageName);
    }

调用本地方法native_setup(),由此进入到android_hardware_Camera.cppframeworks\base\core\jni

private native final void native_setup(Object camera_this, int cameraId,
                                           String packageName);



二、Android Runtime:android_hardware_Camera.cpp

native_setup()被动态注册到JNI,通过JNI调用android_hardware_Camera_native_setup()方法。

// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
    jobject weak_this, jint cameraId, jstring clientPackageName)
{
    // Convert jstring to String16
    const char16_t *rawClientName = env->GetStringChars(clientPackageName, NULL);
    jsize rawClientNameLen = env->GetStringLength(clientPackageName);
    String16 clientName(rawClientName, rawClientNameLen);
    env->ReleaseStringChars(clientPackageName, rawClientName);

    sp<Camera> camera = Camera::connect(cameraId, clientName,
            Camera::USE_CALLING_UID);

    if (camera == NULL) {
        jniThrowRuntimeException(env, "Fail to connect to camera service");
        return;
    }

    // make sure camera hardware is alive
    if (camera->getStatus() != NO_ERROR) {
        jniThrowRuntimeException(env, "Camera initialization failed");
        return;
    }

    jclass clazz = env->GetObjectClass(thiz);
    if (clazz == NULL) {
        jniThrowRuntimeException(env, "Can't find android/hardware/Camera");
        return;
    }

    // We use a weak reference so the Camera object can be garbage collected.
    // The reference is only used as a proxy for callbacks.
    sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
    context->incStrong((void*)android_hardware_Camera_native_setup);
    camera->setListener(context);

    // save context in opaque field
    env->SetIntField(thiz, fields.context, (int)context.get());
}

android_hardware_Camera_native_setup()方法通过调用Camera::connect()方法请求连接CameraService服务。入参中:

  • clientName是通过将clientPackageName从jstring转换为String16格式得到;
  • Camera::USE_CALLING_UID是定义在Camera.h中的枚举类型,其值为ICameraService::USE_CALLING_UID(同样为枚举类型,值为-1)。

Camera::connect()位于Camera.cpp(frameworks\av\camera)中,由此进入到Library层。


三、Library:Camera Client和Camera Service

如上述架构图中所示,ICameraService.h、ICameraClient.h和ICamera.h(frameworks\av\include\camera)三个类定义了Camera的接口和架构,ICameraService.cpp和Camera.cpp两个文件用于Camera架构的实现,Camera的具体功能在下层调用硬件相关的接口来实现。Camera.h是Camera系统对上层的接口。

具体的,Camera类继承模板类CameraBase,Camera::connect()调用了CameraBase.cpp中的connect()方法。

sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
        int clientUid)
{
    return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
}

CameraBase实际上又继承了IBinder的DeathRecipient内部类,DeathRecipient虚拟继承自RefBase。RefBase是Android中的引用计数基础类,其中定义了incStrong、decStrong、incWeak和decWeak等涉及sp/wp的指针操作函数,当然这扯远了。

template <typename TCam>
struct CameraTraits {
};

template <typename TCam, typename TCamTraits = CameraTraits<TCam> >
class CameraBase : public IBinder::DeathRecipient
{
public:
    
    static sp<TCam>      connect(int cameraId,
                                 const String16& clientPackageName,
                                 int clientUid);
    ……
}
class DeathRecipient : public virtual RefBase
{
public:
    virtual void binderDied(const wp<IBinder>& who) = 0;
};



回到Camera::connect()的实现上,其中,new TCam(cameraId)生成BnCameraClient对象,BnCameraClient定义在ICameraClient.h文件中,继承自模板类BnInterface。getCameraService()方法返回CameraService的服务代理BpCameraService,BpCameraService同样继承自模板类BnInterface。然后通过Binder通信发送CONNECT命令,当BnCameraService收到CONNECT命令后调用CameraService的connect()成员函数来做相应的处理。

frameworks\av\camera\CameraBase.cpp

template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId,
                                         const String16& clientPackageName,
                                               int clientUid)
{
    ALOGV("%s: connect", __FUNCTION__);
    sp<TCam> c = new TCam(cameraId);
    sp<TCamCallbacks> cl = c;
    const sp<ICameraService>& cs = getCameraService();
    if (cs != 0) {
        c->mCamera = cs->connect(cl, cameraId, clientPackageName, clientUid);
    }
    if (c->mCamera != 0) {
        c->mCamera->asBinder()->linkToDeath(c);
        c->mStatus = NO_ERROR;
    } else {
        c.clear();
    }
    return c;
}
class BnCameraService: public BnInterface<ICameraService>
{
public:
    virtual status_t    onTransact( uint32_t code,
                                    const Parcel& data,
                                    Parcel* reply,
                                    uint32_t flags = 0);
};


注:connect()函数在BpCameraService和BnCameraService的父类ICameraService中声明为纯虚函数,在BpCameraService和CameraService中分别给出了实现,BpCameraService作为代理类,提供接口给客户端,真正实现在BnCameraService的子类CameraService中。

在BpCameraService中,connect()函数实现如下:

frameworks\av\camera\ICameraService.cpp

    // connect to camera service
    virtual sp<ICamera> connect(const sp<ICameraClient>& cameraClient, int cameraId,
                                const String16 &clientPackageName, int clientUid)
    {
        Parcel data, reply;
        data.writeInterfaceToken(ICameraService::getInterfaceDescriptor());
        data.writeStrongBinder(cameraClient->asBinder());
        data.writeInt32(cameraId);
        data.writeString16(clientPackageName);
        data.writeInt32(clientUid);
        remote()->transact(BnCameraService::CONNECT, data, &reply);
        return interface_cast<ICamera>(reply.readStrongBinder());
    }


首先将传递过来的Camera对象cameraClient转换成IBinder类型,将调用的参数写到Parcel(可理解为Binder通信的管道)中,通过BpBinder的transact()函数发送消息,然后由BnCameraService去响应该连接,最后就是等待服务端返回,如果成功则生成一个BpCamera实例。

真正的服务端响应实现在BnCameraService的onTransact()函数中,其负责解包收到的Parcel并执行client端的请求的方法。

status_t BnCameraService::onTransact(
    uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
    switch(code) {
        case GET_NUMBER_OF_CAMERAS: {
            CHECK_INTERFACE(ICameraService, data, reply);
            reply->writeInt32(getNumberOfCameras());
            return NO_ERROR;
        } break;
        case GET_CAMERA_INFO: {
            CHECK_INTERFACE(ICameraService, data, reply);
            CameraInfo cameraInfo;
            memset(&cameraInfo, 0, sizeof(cameraInfo));
            status_t result = getCameraInfo(data.readInt32(), &cameraInfo);
            reply->writeInt32(cameraInfo.facing);
            reply->writeInt32(cameraInfo.orientation);
            reply->writeInt32(result);
            return NO_ERROR;
        } break;
        case CONNECT: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraClient> cameraClient =
                    interface_cast<ICameraClient>(data.readStrongBinder());
            int32_t cameraId = data.readInt32();
            const String16 clientName = data.readString16();
            int32_t clientUid = data.readInt32();
            sp<ICamera> camera = connect(cameraClient, cameraId,
                    clientName, clientUid);
            reply->writeStrongBinder(camera->asBinder());
            return NO_ERROR;
        } break;
        case CONNECT_PRO: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<IProCameraCallbacks> cameraClient = interface_cast<IProCameraCallbacks>(data.readStrongBinder());
            int32_t cameraId = data.readInt32();
            const String16 clientName = data.readString16();
            int32_t clientUid = data.readInt32();
            sp<IProCameraUser> camera = connect(cameraClient, cameraId,
                                                clientName, clientUid);
            reply->writeStrongBinder(camera->asBinder());
            return NO_ERROR;
        } break;
        case ADD_LISTENER: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraServiceListener> listener =
                interface_cast<ICameraServiceListener>(data.readStrongBinder());
            reply->writeInt32(addListener(listener));
            return NO_ERROR;
        } break;
        case REMOVE_LISTENER: {
            CHECK_INTERFACE(ICameraService, data, reply);
            sp<ICameraServiceListener> listener =
                interface_cast<ICameraServiceListener>(data.readStrongBinder());
            reply->writeInt32(removeListener(listener));
            return NO_ERROR;
        } break;
        default:
            return BBinder::onTransact(code, data, reply, flags);
    }
}

主要的处理包括:

  1. 通过data中Camera的Binder对象生成Camera客户代理BpCameraClient实例;
  2. 将生成的BpCameraClient对象作为参数传递到CameraService(/frameworks/av/services/camera /libcameraservice/CameraService.cpp)的connect()函数中,该函数会返回一个BpCamera实例;
  3. 将在上述实例对象以IBinder的形式打包到Parcel中返回。
status_t CameraClient::initialize(camera_module_t *module) {
    int callingPid = getCallingPid();
    status_t res;

    LOG1("CameraClient::initialize E (pid %d, id %d)", callingPid, mCameraId);

    // Verify ops permissions
    res = startCameraOps();
    if (res != OK) {
        return res;
    }

    char camera_device_name[10];
    snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);

    mHardware = new CameraHardwareInterface(camera_device_name);
    res = mHardware->initialize(&module->common);
    if (res != OK) {
        ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
                __FUNCTION__, mCameraId, strerror(-res), res);
        mHardware.clear();
        return NO_INIT;
    }

    mHardware->setCallbacks(notifyCallback,
            dataCallback,
            dataCallbackTimestamp,
            (void *)mCameraId);

    // Enable zoom, error, focus, and metadata messages by default
    enableMsgType(CAMERA_MSG_ERROR | CAMERA_MSG_ZOOM | CAMERA_MSG_FOCUS |
                  CAMERA_MSG_PREVIEW_METADATA | CAMERA_MSG_FOCUS_MOVE);

    LOG1("CameraClient::initialize X (pid %d, id %d)", callingPid, mCameraId);
    return OK;
}

上述函数中,主要注意以下流程:

  1. 加粗的代码CameraHardwareInterface新建了了一个Camera硬件接口,当然,camera_device_name为摄像头设备名;
  2. mHardware->initialize(&module->common)调用底层硬件的初始化方法;
  3. mHardware->setCallbacks将CamerService处的回调函数注册到HAL处。

CameraHardwareInterface定义了Camera的硬件抽象特征,由此进入到HAL。

四、HAL:CameraHardwareInterface

CameraHardwareInterface的作用在于链接Camera Server和V4L2,通过实现CameraHardwareInterface可以屏蔽不同的driver对Camera Server的影响。CameraHardwareInterface同样虚拟继承自RefBase。

class CameraHardwareInterface : public virtual RefBase {
public:
    CameraHardwareInterface(const char *name)
    {
        mDevice = 0;
        mName = name;
    }
    ……
}
CameraHardwareInterface中包含了控制通道和数据通道,控制通道用于处理预览和视频获取的开始/停止、拍摄照片、自动对焦等功能,数据通道通过回调函数来获得预览、视频录制、自动对焦等数据。当需要支持新的硬件时就需要继承于CameraHardwareInterface ,来实现对应的功能。CameraHardwareInterface提供的public方法如下:

1258.tmp

在前一节中,initialize()函数调用了mHardware->initialize和mHardware->setCallbacks,下面来看下CameraHardwareInterface.h对其的实现。

status_t initialize(hw_module_t *module)
    {
        ALOGI("Opening camera %s", mName.string());
        int rc = module->methods->open(module, mName.string(),
                                       (hw_device_t **)&mDevice);
        if (rc != OK) {
            ALOGE("Could not open camera %s: %d", mName.string(), rc);
            return rc;
        }
        initHalPreviewWindow();
        return rc;
    }

在initialize()方法中,通过module->methods->open打开摄像头模组,initHalPreviewWindow()用于初始化Preview的相关流opspreview_stream_ops,初始化hal的预览窗口。


硬件抽象层:
module->methods->open直接调用到 hardware\imx\mx6\libcamera\CameraModule.cpp
static struct hw_module_methods_t camera_module_methods = {
open: camera_device_open
};

camera_module_t HAL_MODULE_INFO_SYM = {
    common:       {
        tag: HARDWARE_MODULE_TAG,
        version_major: 1,
        version_minor: 0,
        id: CAMERA_HARDWARE_MODULE_ID,
        name: "Freescale CameraHal Module",
        author: "Freescale",
        methods: &camera_module_methods,
        dso: NULL,       /* remove compilation warnings */
        reserved: { 0 }, /* remove compilation warnings */
    },
    get_number_of_cameras: camera_get_number_of_cameras,
    get_camera_info: camera_get_camera_info,
};

/* open device handle to one of the cameras
 *
 * assume camera service will keep singleton of each camera
 * so this function will always only be called once per camera instance
 */
int camera_device_open(const hw_module_t *module,
                       const char        *name,
                       hw_device_t      **device)
{
    int rv          = 0;
    int num_cameras = 0;
    int cameraid;
    fsl_camera_device_t *camera_device = NULL;
    camera_device_ops_t *camera_ops    = NULL;
    CameraHal *camera                  = NULL;
    char *SelectedCameraName;

    android::Mutex::Autolock lock(gCameraHalDeviceLock);

    ALOGI("camera_device open: %s", name);

    if (name != NULL) {
        cameraid    = atoi(name);
        num_cameras = camera_get_number_of_cameras();

        if (cameraid > num_cameras)
        {
            ALOGE("camera service provided cameraid out of bounds, "
                  "cameraid = %d, num supported = %d",
                  cameraid, num_cameras);
            rv = -EINVAL;
            goto fail;
        }

        camera_device = (fsl_camera_device_t *)malloc(sizeof(*camera_device));
        if (!camera_device)
        {
            ALOGE("camera_device allocation fail");
            rv = -ENOMEM;
            goto fail;
        }

        camera_ops = (camera_device_ops_t *)malloc(sizeof(*camera_ops));
        if (!camera_ops)
        {
            ALOGE("camera_ops allocation fail");
            rv = -ENOMEM;
            goto fail;
        }

        memset(camera_device, 0, sizeof(*camera_device));
        memset(camera_ops, 0, sizeof(*camera_ops));

        camera_device->base.common.tag     = HARDWARE_DEVICE_TAG;
        camera_device->base.common.version = 0;
        camera_device->base.common.module  = (hw_module_t *)(module);
        camera_device->base.common.close   = camera_device_close;
        camera_device->base.ops            = camera_ops;

        camera_ops->set_preview_window         = camera_set_preview_window;
        camera_ops->set_callbacks              = camera_set_callbacks;
        camera_ops->enable_msg_type            = camera_enable_msg_type;
        camera_ops->disable_msg_type           = camera_disable_msg_type;
        camera_ops->msg_type_enabled           = camera_msg_type_enabled;
        camera_ops->start_preview              = camera_start_preview;
        camera_ops->stop_preview               = camera_stop_preview;
        camera_ops->preview_enabled            = camera_preview_enabled;
        camera_ops->store_meta_data_in_buffers =
            camera_store_meta_data_in_buffers;
        camera_ops->start_recording         = camera_start_recording;
        camera_ops->stop_recording          = camera_stop_recording;
        camera_ops->recording_enabled       = camera_recording_enabled;
        camera_ops->release_recording_frame = camera_release_recording_frame;
        camera_ops->auto_focus              = camera_auto_focus;
        camera_ops->cancel_auto_focus       = camera_cancel_auto_focus;
        camera_ops->take_picture            = camera_take_picture;
        camera_ops->cancel_picture          = camera_cancel_picture;
        camera_ops->set_parameters          = camera_set_parameters;
        camera_ops->get_parameters          = camera_get_parameters;
        camera_ops->put_parameters          = camera_put_parameters;
        camera_ops->send_command            = camera_send_command;
        camera_ops->release                 = camera_release;
        camera_ops->dump                    = camera_dump;

        *device = &camera_device->base.common;

        camera_device->cameraid = cameraid;

        camera = new CameraHal(cameraid);

        if (!camera)
        {
            ALOGE("Couldn't create instance of CameraHal class");
            rv = -ENOMEM;
            goto fail;
        }

        if (camera->initialize(sCameraInfo[cameraid]) < 0) {
            rv = -EINVAL;
            goto fail;
        }

        gCameraHals[cameraid] = camera;
        gCamerasOpen++;
    }

    return rv;

fail:
    if (camera_device) {
        free(camera_device);
        camera_device = NULL;
    }
    if (camera_ops) {
        free(camera_ops);
        camera_ops = NULL;
    }
    if (camera) {
        delete camera;
        camera = NULL;
    }
    *device = NULL;
    return rv;
}

hardware\imx\mx6\libcamera\CameraHal.cpp
status_t CameraHal::initialize(const CameraInfo& info)
{
    status_t ret = NO_ERROR;

    FLOG_RUNTIME("initialize name:%s, path:%s", info.name, info.devPath);
    mDeviceAdapter = DeviceAdapter::Create(info);
    if (mDeviceAdapter == NULL) {
        FLOGE("CameraHal: DeviceAdapter create failed");
        return BAD_VALUE;
    }

    ret = mDeviceAdapter->initialize(info);
    if (ret) {
        FLOGE("CameraHal: DeviceAdapter initialize failed");
        return ret;
    }

    mCameraBridge = new CameraBridge();
    if (mCameraBridge == NULL) {
        FLOGE("CameraHal: new CameraBridge failed");
        return BAD_VALUE;
    }

    ret = mCameraBridge->initialize();
    if (ret) {
        FLOGE("CameraHal: CameraBridge initialize failed");
        return ret;
    }

    mCameraBridge->getSupportedRecordingFormat(mSupportedRecordingFormat,
                                               MAX_VPU_SUPPORT_FORMAT);
    mCameraBridge->getSupportedPictureFormat(mSupportedPictureFormat,
                                             MAX_PICTURE_SUPPORT_FORMAT);
    ret = mDeviceAdapter->initParameters(mParameters,
                                         mSupportedRecordingFormat,
                                         MAX_VPU_SUPPORT_FORMAT,
                                         mSupportedPictureFormat,
                                         MAX_PICTURE_SUPPORT_FORMAT);
    if (ret) {
        FLOGE("CameraHal: DeviceAdapter initParameters failed");
        return ret;
    }

    ret = mCameraBridge->initParameters(mParameters);
    if (ret) {
        FLOGE("CameraHal: CameraBridge initParameters failed");
        return ret;
    }

    mDeviceAdapter->setErrorListener(mCameraBridge.get());
    mCameraBridge->setCameraFrameProvider(mDeviceAdapter.get());
    mCameraBridge->setCameraEventProvider(CameraEvent::EVENT_INVALID,
                                          mDeviceAdapter.get());
    mBufferProvider = NULL;

    return ret;
}
这里主要是硬件抽象层对接驱动层代码,DeviceAdapter::initialize类打开设备节点。

参考文档:http://www.cnblogs.com/younghao/p/5337058.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值