您的位置:首页 > 其它

三、Camera显示之Hal层的适配(一)

2015-11-27 10:58 411 查看
转载来自:http://blog.csdn.net/wsb1321/article/details/21975951
http://blog.csdn.net/wsb1321/article/details/21975951
本篇接着上一篇:


Camera显示之Framework层设置显示窗口

话说上一篇说道

else if ( window == 0 ) {

result = mHardware->setPreviewWindow(window);//将window设置到hal层, Android代码架构真正的实现就止于此,hal层的东西就看具体厂家根据自身情况进行实现了。 }

那究竟mHardware是如何和hal联系起来的的呢?

1.在CameraClient.cpp中:

[cpp] view
plaincopy





status_t CameraClient::initialize(camera_module_t *module) {

int callingPid = getCallingPid();

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

char camera_device_name[10];

status_t res;

snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);

mHardware = new CameraHardwareInterface(camera_device_name);//<span style="color:#FF0000;">注意到此处。</span>

res = mHardware->initialize(&module->common);//<span style="color:#FF0000;">注意此处</span>

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);

//!++

#ifdef MTK_CAMERA_BSP_SUPPORT

// Enable MTK-extended messages by default

enableMsgType(MTK_CAMERA_MSG_EXT_NOTIFY | MTK_CAMERA_MSG_EXT_DATA);

#endif

//!--

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

return OK;

}

从代码片段:

[cpp] view
plaincopy





mHardware = new CameraHardwareInterface(camera_device_name);//注意到此处。

mHardware 定义是 CameraHardwareInterface, 他也是Android的通用接口。 各个厂家提供的功能都要通过CameraHardwareInterface适配向CameraService提供硬件操作接口。

这篇的主题就是主要分享CameraHardwareInterface如何进行适配的。

2. 接着1中的代码片段:

[cpp] view
plaincopy





res = mHardware->initialize(&module->common);//涉及到module,module即为CameraClient::initialize(camera_module_t *module)传进来的参数, 为一个结构体变量的指针。

[cpp] view
plaincopy





CameraClient::initialize(camera_module_t *module)调用的地方为CameraService中connect camera的时候调用:

[cpp] view
plaincopy





sp<ICamera> CameraService::connect(

const sp<ICameraClient>& cameraClient, int cameraId) {

#ifdef MTK_CAMERAPROFILE_SUPPORT

initCameraProfile();

AutoCPTLog cptlog(Event_CS_connect);

#endif

int callingPid = getCallingPid();

LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);

if (!mModule) {

ALOGE("Camera HAL module not loaded");

...........................

............................

#endif

if (client->initialize(mModule) != OK) {//在这里调用CameraClient的initialize, 而传入的参数为mModule。

#ifdef MTK_CAMERAPROFILE_SUPPORT

CPTLogStr(Event_CS_newCamHwIF, CPTFlagEnd, "new CameraHardwareInterface failed");

#endif

#ifdef MTK_CAMERA_BSP_SUPPORT

所以这里我们就关注下mModule这成员, mModule的定义:

[cpp] view
plaincopy





Mutex mSoundLock;

sp<MediaPlayer> mSoundPlayer[NUM_SOUNDS];

int mSoundRef; // reference count (release all MediaPlayer when 0)

camera_module_t *mModule;//

为一个camera_module_t结构体变量的指针。

Camera最先被使用到的地方是在onFirstRef()函数中, 在这里主要是初始化了mModule的一些变量。 至于onFirstRef何时调用, 后续进行相关的分享, 这里大家只要记住,这个是和sp相关的, 并且在构建sp的时候就会调用。 可以参考这位的博客:http://blog.csdn.net/gzzaigcnforever/article/details/20649781

[cpp] view
plaincopy





void CameraService::onFirstRef()

{

BnCameraService::onFirstRef();

if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,//这个定义为"came"

(const hw_module_t **)&mModule) < 0) {//<span style="color:#FF0000;">注意这个函数调用</span>

ALOGE("Could not load camera HAL module");

mNumberOfCameras = 0;

}

else {

mNumberOfCameras = mModule->get_number_of_cameras();

if (mNumberOfCameras > MAX_CAMERAS) {

ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",

mNumberOfCameras, MAX_CAMERAS);

mNumberOfCameras = MAX_CAMERAS;

}

for (int i = 0; i < mNumberOfCameras; i++) {

setCameraFree(i);

}

}

}

/** Base path of the hal modules */

#define HAL_LIBRARY_PATH1 "/system/lib/hw"

#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"

#define HAL_LIBRARY_PATH3 "/system/lib"

int hw_get_module(const char *id, const struct hw_module_t **module)

{

return hw_get_module_by_class(id, NULL, module);

}

int hw_get_module_by_class(const char *class_id, const char *inst,

const struct hw_module_t **module)

{

int status;

int i;

const struct hw_module_t *hmi = NULL;

char prop[PATH_MAX];

char path[PATH_MAX];

char name[PATH_MAX];

if (inst)

snprintf(name, PATH_MAX, "%s.%s", class_id, inst);//class_id为camera, inst为null, 所以现在name=“camera”

else

strlcpy(name, class_id, PATH_MAX);

/*

* Here we rely on the fact that calling dlopen multiple times on

* the same .so will simply increment a refcount (and not load

* a new copy of the library).

* We also assume that dlopen() is thread-safe.

*/

/* Loop through the configuration variants looking for a module */

for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {

if (i < HAL_VARIANT_KEYS_COUNT) {

if (property_get(variant_keys[i], prop, NULL) == 0) {

continue;

}

snprintf(path, sizeof(path), "%s/%s.%s.so",

HAL_LIBRARY_PATH2, name, prop);//path=/vendor/lib/hw/camera.**.so, 根据属性的配置值生成文件名。

if (access(path, R_OK) == 0) break;//判断是否有读文件权限。

snprintf(path, sizeof(path), "%s/%s.%s.so",//path=/system/lib/hw/camera.**.so

HAL_LIBRARY_PATH1, name, prop);

if (access(path, R_OK) == 0) break;

snprintf(path, sizeof(path), "%s/%s.%s.so",

HAL_LIBRARY_PATH3, name, prop);//path=/system/lib/camera.**.so

if (access(path, R_OK) == 0) break;

} else {

snprintf(path, sizeof(path), "%s/%s.default.so",

HAL_LIBRARY_PATH1, name);//path=/vendor/lib/hw/camera.default.so

if (access(path, R_OK) == 0) break;

snprintf(path, sizeof(path), "%s/%s.default.so",//path=/system/lib/camera.default.so

HAL_LIBRARY_PATH3, name);

if (access(path, R_OK) == 0) break;

}

}

status = -ENOENT;

if (i < HAL_VARIANT_KEYS_COUNT+1) {

/* load the module, if this fails, we're doomed, and we should not try

* to load a different variant. */

status = load(class_id, path, module);//动态加载动态库。

}

return status;

}

上面的思路就是:

遍历

[cpp] view
plaincopy





#define HAL_LIBRARY_PATH1 "/system/lib/hw"

#define HAL_LIBRARY_PATH2 "/vendor/lib/hw"

#define HAL_LIBRARY_PATH3 "/system/lib"

这几个目录下的so库,so库的名字为: a.camera.属性名.so和b.camera.default.so。 其中会优先找到a, 在没找到a后再去找到b。 在mtk平台上, 编译生成的so库就为 camera.default.so, 所以最终加载的会是camera.default.so这个库。

继续看看:load(class_id, path, module);:

[cpp] view
plaincopy





static int load(const char *id,

const char *path,

const struct hw_module_t **pHmi)

{

int status;

void *handle;

struct hw_module_t *hmi;

/*

* load the symbols resolving undefined symbols before

* dlopen returns. Since RTLD_GLOBAL is not or'd in with

* RTLD_NOW the external symbols will not be global

*/

handle = dlopen(path, RTLD_NOW);

if (handle == NULL) {

char const *err_str = dlerror();

ALOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");

status = -EINVAL;

goto done;

}

/* Get the address of the struct hal_module_info. */

const char *sym = HAL_MODULE_INFO_SYM_AS_STR;

hmi = (struct hw_module_t *)dlsym(handle, sym);//关注这两句

if (hmi == NULL) {

ALOGE("load: couldn't find symbol %s", sym);

status = -EINVAL;

goto done;

}

/* Check that the id matches */

if (strcmp(id, hmi->id) != 0) {

ALOGE("load: id=%s != hmi->id=%s", id, hmi->id);

status = -EINVAL;

goto done;

}

hmi->dso = handle;

/* success */

status = 0;

done:

if (status != 0) {

hmi = NULL;

if (handle != NULL) {

dlclose(handle);

handle = NULL;

}

} else {

ALOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",

id, path, *pHmi, handle);

}

*pHmi = hmi;

return status;

}

关注这两句:

[cpp] view
plaincopy





const char *sym = HAL_MODULE_INFO_SYM_AS_STR;

hmi = (struct hw_module_t *)dlsym(handle, sym);//关注这两句

[cpp] view
plaincopy





HAL_MODULE_INFO_SYM_AS_STR:

[cpp] view
plaincopy





/**

* Name of the hal_module_info

*/

#define HAL_MODULE_INFO_SYM HMI

/**

* Name of the hal_module_info as a string

*/

#define HAL_MODULE_INFO_SYM_AS_STR "HMI"

从上面可以看出就是要获取名为“HMI”函数的指针, 而HMI又是HAL_MODULE_INFO_SYM 的宏定义, 所以最终就是要找HAL_MODULE_INFO_SYM实现的地方:

[cpp] view
plaincopy





static

camera_module

instantiate_camera_module()

{

CAM_LOGD("[%s]", __FUNCTION__);

//

// (1) Prepare One-shot init.

MtkCamUtils::Property::clear();

// (2)

camera_module module = {

common: {

tag: HARDWARE_MODULE_TAG,

module_api_version: 1,

hal_api_version: 0,

id: CAMERA_HARDWARE_MODULE_ID,

name: "MTK Camera Module",

author: "MTK",

methods: CamDeviceManager::get_module_methods(),

dso: NULL,

reserved: {0},

},

get_number_of_cameras: CamDeviceManager::get_number_of_cameras,

get_camera_info: CamDeviceManager::get_camera_info,

};

return module;

}

/*******************************************************************************

* Implementation of camera_module

*******************************************************************************/

camera_module HAL_MODULE_INFO_SYM = instantiate_camera_module();

上面这个代码片段就是mtk实现的, 结合上边, 可以得到*pHmi指向了module这个结构体。 也即是说最后将*pHmi指向这里的module。 进一步回到上面, 就是CameraService中的mModule指向了这里的module。所以说后面的引用大概是CameraService中通过mModule->common->methods这种方式去或则mModule->get_number_of_cameras实现到MTK的hal层的调用。
这样就将Android原生CameraService通过CameraHardwareInterface连接到MTK实现的Hal层, 通过CamDeviceManager来承上启下的作用。

3.继续2关注到CamDeviceManager::get_module_methods()这个函数:

[cpp] view
plaincopy





hw_module_methods_t*

CamDeviceManager::

get_module_methods()

{

static

hw_module_methods_t

_methods =

{

open: CamDeviceManager::open_device

};

return &_methods;

}

呵呵, 可以看到通过mModule->common->methods-->open可以引用到CamDeviceManager::open_device。

通过名字可以猜测到这个方法应该是在Camera启动的时候会去调用。

所以我们看看何时调用CamDeviceManager::open_device这个方法:

回到CameraService:CameraClient:

[cpp] view
plaincopy





status_t CameraClient::initialize(camera_module_t *module) {

int callingPid = getCallingPid();

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

char camera_device_name[10];

status_t res;

snprintf(camera_device_name, sizeof(camera_device_name), "%d", mCameraId);

mHardware = new CameraHardwareInterface(camera_device_name);

res = mHardware->initialize(&module->common);//这里初始化了, 并且传入的module->common

回到CameraHardwareInterface:

[cpp] view
plaincopy





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);//这里进行了打开camera的操作, 这里调用到的已经是MTK hal层的方法了, 注意最后一个参数。

if (rc != OK) {

ALOGE("Could not open camera %s: %d", mName.string(), rc);

return rc;

}

initHalPreviewWindow();

return rc;

}

关注到CamDeviceManager::open_device

[cpp] view
plaincopy





int

CamDeviceManager::

open_device(const hw_module_t* module, const char* name, hw_device_t** device)

{

return CamDeviceManager::getInstance().openDevice(module, name, device);

}

int

CamDeviceManager::

openDevice(const hw_module_t* module, const char* name, hw_device_t** device)

{

int err = OK;

//

ICamDevice* pdev = NULL;

int32_t i4OpenId = 0;

//

Mutex::Autolock lock(mMtxOpenLock);

//

MY_LOGI("+ mi4OpenNum(%d), mi4DeviceNum(%d)", mi4OpenNum, mi4DeviceNum);

if (name != NULL)

{

i4OpenId = ::atoi(name);

//

if ( DevMetaInfo::queryNumberOfDevice() < i4OpenId )

{

err = -EINVAL;

goto lbExit;

}

//

if ( MAX_SIMUL_CAMERAS_SUPPORTED <= mi4OpenNum )

{

MY_LOGW("open number(%d) >= maximum number(%d)", mi4OpenNum, MAX_SIMUL_CAMERAS_SUPPORTED);

MY_LOGE("does not support multi-open");

err = -ENOMEM;

goto lbExit;

}

//

pdev = createIDevice(

i4OpenId,

*get_hw_device(),

module

);//注意此处, 进行camDevice的创建

//

if ( ! pdev )

{

MY_LOGE("camera device allocation fail: pdev(0)");

err = -ENOMEM;

goto lbExit;

}

*device = pdev->get_hw_device();//此处将CamDevice的指针付给传进来形参, 最终是CameraHardwareInterface中的mDevice指向了CamDevice。

//

mi4OpenNum++;

}

lbExit:

if ( OK != err )

{

if ( pdev )

{

destroyDevice(pdev);

pdev = NULL;

}

//

*device = NULL;

}

MY_LOGI("- mi4OpenNum(%d)", mi4OpenNum);

return err;

}

4.继续往下关注到

[cpp] view
plaincopy





pdev = createIDevice(

i4OpenId,

*get_hw_device(),

module

);

的实现:

[cpp] view
plaincopy





static

ICamDevice*

createIDevice(

int32_t const i4DevOpenId,

hw_device_t const& hwdevice,

hw_module_t const*const hwmodule

)

{

g_s8ClientAppMode = queryClientAppMode();

//

MY_LOGI("+ tid:%d OpenID:%d ClientAppMode:%s", ::gettid(), i4DevOpenId, g_s8ClientAppMode.string());

//

ICamDevice* pdev = NSCamDevice::createDevice(g_s8ClientAppMode, i4DevOpenId);//pDeve 指向的就是ICamDevice的一个对象

//

if ( pdev != 0 )

{

pdev->incStrong(pdev);

//

hw_device_t* hwdev = pdev->get_hw_device();//

*hwdev = hwdevice;

hwdev->module = const_cast<hw_module_t*>(hwmodule);

//

if ( ! pdev->init() )//在这里初始化了ICamDvice

{

MY_LOGE("fail to initialize a newly-created instance");

pdev->uninit();

pdev = NULL;

}

}

//

MY_LOGI("- created instance=%p", &(*pdev));

return pdev;//返回创建的ICamDevice。

}

现在可以得出pdev即是指向ICamDevice对象

注意到ICamDevice对象的构造函数:

[cpp] view
plaincopy





ICamDevice::

ICamDevice()

: camera_device_t()

, RefBase()

, mDevOps()

//

, mMtxLock()

//

{

MY_LOGD("ctor");

::memset(static_cast<camera_device_t*>(this), 0, sizeof(camera_device_t));

this->priv = this;

this->ops = &mDevOps;//ops指向了mDevOps

mDevOps = gCameraDevOps;//mDevOps为gCameraDevOps指向的结构体

}

[cpp] view
plaincopy





gCameraDevOps:

[cpp] view
plaincopy





static camera_device_ops_t const gCameraDevOps = {

set_preview_window: camera_set_preview_window,

set_callbacks: camera_set_callbacks,

enable_msg_type: camera_enable_msg_type,

disable_msg_type: camera_disable_msg_type,

msg_type_enabled: camera_msg_type_enabled,

start_preview: camera_start_preview,

stop_preview: camera_stop_preview,

preview_enabled: camera_preview_enabled,

store_meta_data_in_buffers: camera_store_meta_data_in_buffers,

start_recording: camera_start_recording,

stop_recording: camera_stop_recording,

recording_enabled: camera_recording_enabled,

release_recording_frame: camera_release_recording_frame,

auto_focus: camera_auto_focus,

cancel_auto_focus: camera_cancel_auto_focus,

take_picture: camera_take_picture,

cancel_picture: camera_cancel_picture,

set_parameters: camera_set_parameters,

get_parameters: camera_get_parameters,

put_parameters: camera_put_parameters,

send_command: camera_send_command,

release: camera_release,

dump: camera_dump,

};

所以在CameraHardwareInterface中通过:

mDevice->ops->set_preview_window(mDevice, 0)类似的方法就可以调用到ICamDevice中对应的方法了。

5. 我们回到Camera显示相关的东西,

在CameraClient中//!++

else if ( window == 0 ) {

result = mHardware->setPreviewWindow(window);

}

进而在CameraHardwareInterface中:

[cpp] view
plaincopy





/** Set the ANativeWindow to which preview frames are sent */

status_t setPreviewWindow(const sp<ANativeWindow>& buf)

{

ALOGV("%s(%s) buf %p", __FUNCTION__, mName.string(), buf.get());

if (mDevice->ops->set_preview_window) {

//!++

if ( buf == 0 ) {

ALOGD("set_preview_window(0) before mPreviewWindow = 0");

mDevice->ops->set_preview_window(mDevice, 0);//直接调用了ICamDevice的相关的方法。

mPreviewWindow = 0;

return OK;

}

//!--

mPreviewWindow = buf;

mHalPreviewWindow.user = this;

ALOGV("%s &mHalPreviewWindow %p mHalPreviewWindow.user %p", __FUNCTION__,

&mHalPreviewWindow, mHalPreviewWindow.user);

return mDevice->ops->set_preview_window(mDevice,

buf.get() ? &mHalPreviewWindow.nw : 0);

}

return INVALID_OPERATION;

}

5.说到这里, CameraService::CameraClient--->CameraHardwareInterface-->CamDeviceManager-->ICamDevice这一条完整的路线非常清楚。

具体思路就是:

a.CameraHardwareInterface是Android原生定义的和硬件hal层连接的适配接口。各个厂家根据需要去具体实现这些接口,并具体实现底层的相关功能。

b.为了代码通用性和模块的分离性, 对hal层模块的实现封装成动态库(so), CameraService根据需要动态加载hal层的库。

c.CamDeviceManager是Hal层的一个入口类, 从CameraService打开关闭camera的时候都是通过它进行总的安排。

d.hal层下具体的实现都是不断的适配CameraHardwareInterface向上提供的接口的一个过程。

附上以一个打开Camera的流程图供参考:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: