Android Camera2 Hal3(一)初始化

前段时间在4412的开发板上面调通了camera 5.0 hardware,现在来梳理下camera框架。
我这里的camera device api版本使用的是3.0;camera module api版本使用的是2.3;CameraService会根据这个api版本初始化不同的client,例如这里将初始化Camera2Client。

mDevice.common.version = CAMERA_DEVICE_API_VERSION_3_0;
camera_module_t HAL_MODULE_INFO_SYM = {
    .common = {
        .tag                = HARDWARE_MODULE_TAG,
        .module_api_version = CAMERA_MODULE_API_VERSION_2_3,
        .hal_api_version    = HARDWARE_HAL_API_VERSION,
        .id                 = CAMERA_HARDWARE_MODULE_ID,
        .name               = "V4l2 Camera",
    },
    .get_number_of_cameras  = android::HalModule::getNumberOfCameras,
    .get_camera_info        = android::HalModule::getCameraInfo,
    .set_callbacks          = android::HalModule::setCallbacks,
};

类说明:
CameraDeviceFactory:工具类,根据hal中选择的device版本来选择初始化Camera2Device或者Camera3Device;我这里是
CAMERA_DEVICE_API_VERSION_3_0,所以会初始化Camera3Device
CameraDeviceBase:Camera3Device和Camera2Device的基类。Camera2Client通过它来访问hardware

CameraService初始化

void CameraService::onFirstRef()
{
    LOG1("CameraService::onFirstRef");
    	hw_get_module(CAMERA_HARDWARE_MODULE_ID, (const hw_module_t **)&mModule) < 0
        mNumberOfCameras = mModule->get_number_of_cameras();	   //调用的是hal层的android::HalModule::getNumberOfCameras
        if (mModule->common.module_api_version >=
                CAMERA_MODULE_API_VERSION_2_1) {
            mModule->set_callbacks(this);		//api版本大于等于2.1设置回调,我这里没有具体实现这个接口,直接在hal层中return OK
        }
        if (mModule->common.module_api_version >= CAMERA_MODULE_API_VERSION_2_2) {
            setUpVendorTags();		//这里会调用camera_module_t的get_vendor_tag_ops,这个可以不实现
        }
        CameraDeviceFactory::registerService(this);	//将CameraService注册到CameraDeviceFactory中,用于调用CameraService中的接口
    }
}

开机过程

开机时候statusbar会去打开camera,读取一些信息。我们以CameraManager.getCameraCharacteristics为入口分析代码。
Android Camera2 Hal3(一)初始化_第1张图片
statusbar调用CameraManager.getCameraCharacteristics后,经过层层调用(如下bouml时序图)将调用CameraService端的connectHelperLocked函数,在这个函数里面会根据hardware传递过来的参数来决定初始化哪一种client。Android Camera2 Hal3(一)初始化_第2张图片

CameraService::connectHelperLocked{
	int deviceVersion = getDeviceVersion(cameraId, &facing);	//调用mModule->get_camera_info获取struct camera_info结构体信息,然后得到camera模块版本号
	switch(deviceVersion){
		case CAMERA_DEVICE_API_VERSION_2_0:
		......:2.03.2版本
		case CAMERA_DEVICE_API_VERSION_3_2:
			client = new Camera2Client(......);		//由于api为CAMERA_DEVICE_API_VERSION_3_0,所以它的构造函数会去初始化Camera3Device
	}
	status_t status = connectFinishUnsafe(client, client->getRemote())
}
status_t CameraService::connectFinishUnsafe(const sp<BasicClient>& client , ...){
	status_t status = client->initialize(mModule);	//这个函数将会调用Camera2ClientBase->initialize 然后调用Camera3Device->initialize 进行初始化,
																			并为CameraMetadata的初始化做一个准备。
}

下面来分析 client->initialize是是如何调用到Camera3Device->initialize ,进而初始化CameraMetadata相关的。
这里先来分析Camera2ClientBase中的mDevice指向的是哪一个类。
Android Camera2 Hal3(一)初始化_第3张图片
Camera2Client的类图如上图所示。查看源码可以知道Camera2Client的构造函数构造Camera2ClientBase,Camera2ClientBase的构造函数构造client(client是CameraService的内部类),Client的构造函数里面构造BasicClient(BasicClient是CameraService的内部类)。
这里面一个比较重要的构造过程是Camera2ClientBase的构造。

template <typename TClientBase>				//TClientBase为CameraService::client
Camera2ClientBase<TClientBase>::Camera2ClientBase(
        const sp<CameraService>& cameraService,
		......
        int servicePid):
        TClientBase(cameraService, remoteCallback, clientPackageName,
                cameraId, cameraFacing, clientPid, clientUid, servicePid),
		......
{
    mDevice = CameraDeviceFactory::createDevice(cameraId);		
	......
}

前面说过CameraDeviceFactory是一个工具类,它主要根据hal传递过来的camera device version来选择构造Camera2Device或者Camera3Device。

sp<CameraDeviceBase> CameraDeviceFactory::createDevice(int cameraId) {
    ......
    switch (deviceVersion) {
        case CAMERA_DEVICE_API_VERSION_2_0:
        case CAMERA_DEVICE_API_VERSION_2_1:
            device = new Camera2Device(cameraId);
            break;
        case CAMERA_DEVICE_API_VERSION_3_0:	//我从hal传递的是这个值
        case CAMERA_DEVICE_API_VERSION_3_1:
        case CAMERA_DEVICE_API_VERSION_3_2:
            device = new Camera3Device(cameraId);		//所以初始化Camera3Device
            break;
        default:......
    }
}

所以,Camera2ClientBase中的mDevice指向的是Camera3Device。

从Camera2Client的类图可以看出:父类BasicClient的虚函数initialize只有client没有实现。因为Camera2Client有实现这个接口,所以client->initialize会先调用Camera2Client->initialize

Camera2Client::initialize(camera_module_t *module){
	res = Camera2ClientBase::initialize(module);		//先执行父类Camera2ClientBase的
}
template <typename TClientBase>
status_t Camera2ClientBase<TClientBase>::initialize(camera_module_t *module) {
    res = mDevice->initialize(module);	//从上面分析可以看出这里调用的是Camera3Device->initialize
}

接下来来分析前面说的Camera3Device->initialize是如何初始化CameraMetadata的。
先来介绍下CameraMetadata,它是一个工具类,从它的头文件可以看到一句英文介绍:A convenience wrapper around the C-based camera_metadata_t library. 针对基于C库的camera_metadata_t结构的便捷包装。从它的代码中可以看出它重载了=,里面是对于私有变量
camera_metadata_t *mBuffer的赋值操作;然后还实现了追加元数据的函数append。所以这个类本质上是为了维护camera_metadata_t而创造的。

/**
 * A convenience wrapper around the C-based camera_metadata_t library.
 */
class CameraMetadata {
	CameraMetadata &operator=(const camera_metadata_t *buffer);
  private:
    camera_metadata_t *mBuffer;
 }
 CameraMetadata &CameraMetadata::operator=(const camera_metadata_t *buffer) {
    if (CC_LIKELY(buffer != mBuffer)) {
        camera_metadata_t *newBuffer = clone_camera_metadata(buffer);
		......
    }
    return *this;
status_t CameraMetadata::append(const camera_metadata_t* other) {
	......
    return append_camera_metadata(mBuffer, other);
}
}

在Camera3Device::initialize中调用到了camera_info结构的static_camera_characteristics(如下图Camera3Device::initialize调用所示),这个值在前面的camera_module_t HAL_MODULE_INFO_SYM被赋值,所以调用的是hal中对应的函数,我这里对应的函数是我hal中的camera_metadata_t *Camera::staticCharacteristics()
Android Camera2 Hal3(一)初始化_第4张图片
在hal的Camera::staticCharacteristics中,会生成一个CameraMetadata,然后设置摄像头分辨率,支持的图像格式,摄像头的水平角度等等。然后会返回给上层,保存在Camera3Device的mDeviceInfo(mDeviceInfo就是CameraMetadata)中。

camera_metadata_t *Camera::staticCharacteristics() {
	CameraMetadata cm;
    const int32_t sensorInfoPixelArraySize[] = {
        (int32_t)sensorRes.width,
        (int32_t)sensorRes.height
    };
    cm.update(ANDROID_SENSOR_INFO_PIXEL_ARRAY_SIZE, sensorInfoPixelArraySize, NELEM(sensorInfoPixelArraySize));	//设置分辨率大小
    static const int32_t scalerAvailableFormats[] = {
        HAL_PIXEL_FORMAT_RGBA_8888,
        HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED,
        /* Non-preview one, must be last - see following code */
        HAL_PIXEL_FORMAT_BLOB
    };
    cm.update(ANDROID_SCALER_AVAILABLE_FORMATS, scalerAvailableFormats, NELEM(scalerAvailableFormats));	//设置支持的格式
    ......
}

到了这里,我们已经知道了Cama2Client的构造和初始化(initialize)中会去调用hal层的代码创建CameraMetadata,然后得到摄像头的参数。接下来分析摄像头数据是在哪里解析的。
从状态栏关于camera的bouml调用中,我们可以看到初始化完Cama2Client,得到CameraMetadata后,会调用l.mParameters.initialize,元数据的解析就是在这里。l.mParameters.initialize实际上就是调用Parameters::initialize,只不过给它加了一把Mutex而已。
在调用 res = l.mParameters.initialize(&(mDevice->info()), mDeviceVersion);的时候,mDevice->info()作为参数传递进去,它其实是获取前面保存的Camera3Device::mDeviceInfo,也就是从底层初始化而来的CameraMetadata。下面举个例子看看Parameters是如何处理CameraMetadata。

tatus_t Parameters::initialize(const CameraMetadata *info, int deviceVersion) {
	res = getFilteredSizes(MAX_PREVIEW_SIZE, &availablePreviewSizes);	//获取分辨率
    for (size_t i = 0 ; i < availablePreviewSizes.size(); i++) {
        int newWidth = availablePreviewSizes[i].width;
        int newHeight = availablePreviewSizes[i].height;
        ...			//将分辨率保存起来
    }
    params.setPreviewSize(previewWidth, previewHeight);	// CameraParameters2 params;
}
status_t Parameters::getFilteredSizes(Size limit, Vector<Size> *sizes) {
	camera_metadata_ro_entry_t availableProcessedSizes =
			staticInfo(ANDROID_SCALER_AVAILABLE_PROCESSED_SIZES, SIZE_COUNT);	//获取分辨率
}
//Parameters从CameraMetadata中获取到底层传递过来的数据,通过其find函数去获取对应的数据段
camera_metadata_ro_entry_t Parameters::staticInfo(uint32_t tag,size_t minCount, size_t maxCount, bool required){
	camera_metadata_ro_entry_t entry = info->find(tag);	//这里的info就是CameraMetadata,也就是Parameters::initialize传递进来的参数
}

可以看出,Parameters在初始化的时候去查找CameraMetadata里面的数据,获取如分辨率,数据格式等信息。然后将信息保存在自己的CameraParameters2成员中。
至此,我们已经明白了,在device api为CAMERA_DEVICE_API_VERSION_3_0,module api为CAMERA_MODULE_API_VERSION_2_3的时候,CameraService初始化了Camera2Client Camera3Device;然后Camera2Client通过Camera3Device去获取hal中关于摄像头的信息,并将信息保存在Camera3Device里面的CameraMetadata类型成员mDeviceInfo。随后Parameters::initialize会去解析CameraMetadata,然后保存在CameraParameters2类型成员params中。
下一章我们继续分析camera,分析预览过程

你可能感兴趣的:(Android,Camera)