Android Camera源码分析

回顾这半年做的项目基本都跟Camera有关,从手势识别控制空调,到人脸识别的门禁,都是围绕相机的数据处理和渲染。这里相机不限于本地的相机,还包括远程的RTSP相机,要将数据流拉到本地进行渲染。

这两天好好读了一下Camera的源码,大概理清了整体架构,总结了一下,其实没多少东西,Android的各个模块都差不多,都是有个系统服务,然后Java封一层,Native封一层,Java层和Native层的对象互相绑定,上面的请求从Java层往下到Native层,然后跨进程丢到系统服务中处理,这里Binder是不可避免的,传接口或文件句柄之类的。对于大块内存就不能指望Binder了,这时候共享内存就出场了,打开设备获得描述符,各自映射到进程的用户空间,这里描述符通过Binder传递,不过要注意的是跨进程传递后描述符可能会变,不过没关系,内核空间还是对应着同一个文件对象。接着说系统服务,这里面很可能继续往下调到HAL层,这个就是定义的一套设备的标准接口,不同厂家实现好了so,这里直接加载,然后调用对应的设备操作函数就好了。底层拿到了数据,或者状态变化需要通知上层,则又一层层地回调回去。

有了这么一个大框架,读起源码来就顺多了。总的来说,Android有两个核心,一个是跨进程通信,一个是内存管理,其它的各系统服务诸如AMS、WMS、PMS或者相机蓝牙什么的都可以看做是架在上面的业务层。

好了,接下来我们从Camera的Java层调用入手,过一遍源码。

Camera的调用大致如下:

Camera camera = Camera.open(1);
camera.setPreviewTexture(surfaceTexture);
camera.setPreviewCallbackWithBuffer(callback);
camera.addCallbackBuffer(buffer);
camera.startPreview();

本文将重点分析以上几个函数,看看底层是如何实现的。

首先说说Camera.open,这是个静态函数。Camera有个系统服务,在系统启动的时候注册到ServiceManager,每次调用Camera.open都会创建一个Camera Java对象,然后调到Native层初始化,连接到CameraService,拿到对应的Binder句柄,生成Camera Native层的对象和上下文数据结构,然后绑定到Java层的Camera类中。

Camera的open会调到native_setup,传入cameraId,

// android_hardware_Camera.cpp
static jint android_hardware_Camera_native_setup(JNIEnv *env, ...) {
    sp<Camera> camera = Camera::connect(cameraId, clientName, );

    sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);

    camera->setListener(context);
    env->SetLongField(thiz, fields.context, (jlong)context.get());
}
// Camera.cpp
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName, ) {
    return CameraBaseT::connect(cameraId, clientPackageName, clientUid);
}

要注意的是Camera类继承自模板类CameraBase,如下:

// Camera.h
class Camera : public CameraBase<Camera>, public BnCameraClient

上面调用了CameraBaseT的connect函数,这是个静态函数,CameraBaseT定义在CameraBase中,

typedef CameraBase<TCam>         CameraBaseT;

而对于Camera类来说就是CameraBase,再往下看connect的实现:

// CameraBase.cpp
template <typename TCam, typename TCamTraits>
sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId, ) {
    sp<TCam> c = new TCam(cameraId);
    sp<TCamCallbacks> cl = c;
    const sp<::android::hardware::ICameraService> cs = getCameraService();

    binder::Status ret;
    if (cs != nullptr) {
        TCamConnectService fnConnectService = TCamTraits::fnConnectService;
        ret = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid, clientPid, &c->mCamera);
    }
    if (ret.isOk() && c->mCamera != nullptr) {
        IInterface::asBinder(c->mCamera)->linkToDeath(c);
        c->mStatus = NO_ERROR;
    }
    return c;
}

这里先获取CameraService

  • 5
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值