當前位置:首頁 » 安卓系統 » androidcamerahal

androidcamerahal

發布時間: 2023-03-03 14:06:18

Ⅰ Android Camera 驅動開發入門必備知識有哪些

1:硬體相關:簡單的數字電路要懂,看的懂電路圖(這個很簡單),能根據電路找到相應Camera硬體連接的GPIO,並根據晶元手冊配置GPIO為相應的模式;比如GPIO模式,輸入IO或輸出IO;或配置成PWM模式;不同的模式這個GPIO的工作方式是不同的;

2:Camera驅動:比如ov5640;要找本linux驅動相關的書看看,比如《linux設備驅動程序》知道簡單的linux設備驅動寫法;當然工作中Camera驅動不需要你寫的,有參考的可以使用,但是參考驅動一般支持實現錄像、拍照功能,別的白平衡、對焦等都需要你去自己調試;

3:要學習V4L2協議,因為驅動導出/dev/video0介面是通過V4L2協議的;上層C的應用也是通過V4L2協議訪問/dev/video0的;實際V4L2協議就是通過一些標志linux ioctl()函數和底層驅動通信的;V4L2協議是為了屏蔽各種Camera驅動的不同(比如usb攝像頭,mipi介面攝像頭)而提供的統一和攝像頭驅動通信的規范;

4:要知道C++的class的相關知識,最好能看到C++的代碼,既然有C的知識,哪把C++的面相對象看懂,知道C++的class就可以了;為什麼要懂C++呢?因為Android Camera HAL訪問/dev/video0都是用C++寫的,二十幾個個xxxx.cpp不同的類相互繼承實現的;而且要懂Android HAL層的寫法,至少查查資料知道用哪裡看;一般都是CameraMole.cpp或CameraHal.cpp;

5:JNI的寫法最好以知道一些,至少可以抄就可以,因為這些寫法都是固定的,因為調試的過程中有時候你一個人要從java層跟蹤代碼到HAL層再到驅動;

6:要會用Linux,因為所有的Android源碼都是在Linux下編譯的;要知道ARM架構,交叉編譯器;比如arm-linux-gcc;知道怎麼編譯Android和kernel源碼;怎麼刷機;怎麼調試;最好買塊帶Camera的Android開發板;

Ⅱ android中camera的hal模塊怎麼被調用

CameraService.cpp (frameworks\base\services\camera\libcameraservice)

中調用hw_get_mole

[cpp] view plain print?
void CameraService::onFirstRef()
{
BnCameraService::onFirstRef();

<span style="color: rgb(255, 0, 0);">if (hw_get_mole(CAMERA_HARDWARE_MODULE_ID,
(const hw_mole_t **)&mMole) < 0)</span> {
LOGE("Could not load camera HAL mole");
mNumberOfCameras = 0;
}
else {
mNumberOfCameras = mMole->get_number_of_cameras();
if (mNumberOfCameras > MAX_CAMERAS) {
LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
mNumberOfCameras, MAX_CAMERAS);
mNumberOfCameras = MAX_CAMERAS;
}
for (int i = 0; i < mNumberOfCameras; i++) {
setCameraFree(i);
}
}
}
void CameraService::onFirstRef()
{
BnCameraService::onFirstRef();

if (hw_get_mole(CAMERA_HARDWARE_MODULE_ID,
(const hw_mole_t **)&mMole) < 0) {
LOGE("Could not load camera HAL mole");
mNumberOfCameras = 0;
}
else {
mNumberOfCameras = mMole->get_number_of_cameras();
if (mNumberOfCameras > MAX_CAMERAS) {
LOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",
mNumberOfCameras, MAX_CAMERAS);
mNumberOfCameras = MAX_CAMERAS;
}
for (int i = 0; i < mNumberOfCameras; i++) {
setCameraFree(i);
}
}
}

看一下hw_get_mole是怎麼回事

[cpp] view plain print?
int hw_get_mole(const char *id, const struct hw_mole_t **mole)
{
return <span style="color: rgb(255, 0, 0);">hw_get_mole_by_class(id, NULL, mole);
</span>}
int hw_get_mole(const char *id, const struct hw_mole_t **mole)
{
return hw_get_mole_by_class(id, NULL, mole);
}

他只是一個封裝實際調用了[email protected] (hardware\libhardware)
好在不長,看看吧

[cpp] view plain print?
int hw_get_mole_by_class(const char *class_id, const char *inst,
const struct hw_mole_t **mole)
{
int status;
int i;
const struct hw_mole_t *hmi = NULL;
<span style="color: rgb(255, 0, 0);"> char prop[PATH_MAX];//幾個關鍵的數組
char path[PATH_MAX];//在下面起了重要
char name[PATH_MAX];//作用
</span>
if (inst)
snprintf(name, PATH_MAX, "%s.%s", class_id, inst);
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 of the library).
* We also assume that dlopen() is thread-safe.
*/

/* Loop through the configuration variants looking for a mole */
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)
<span style="color: rgb(255, 0, 0);">//在這里將prop的路徑得到,分別從
"ro.hardware[qcom]"
"ro.proct.board"[7x27],
"ro.board.platform"[msm7627a],
"ro.arch",
"ro.hw_platform"[QRD_SKU3-1100]
這幾個屬性文件中獲得硬體的信息
有些硬體信息的字元串會出現在編譯後生成的.so名字中</span>
{
continue;
}
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, prop);
if (access(path, R_OK) == 0) break;

snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, prop);<span style="color: rgb(255, 0, 0);">//走這里,在這里得到/system/lib/hw/camera.msm7627a.so
這樣一個路徑,這個庫里有QualcommCamera.cpp,這是
camera模塊HAL代碼開始的地方</span>
if (access(path, R_OK) == 0) break;
} else {
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH1, name);
if (access(path, R_OK) == 0) break;
}
}

status = -ENOENT;
if (i < HAL_VARIANT_KEYS_COUNT+1) {
/* load the mole, if this fails, we're doomed, and we should not try
* to load a different variant. */
status = load(class_id, path, mole);<span style="color: rgb(255, 0, 0);">//這里關鍵,函數的三個參數可以串聯成一句話:
到path(/system/lib/hw/camera.msm7627a.so)這個路徑下找到一個id(camera)匹配的mole</span>
}

return status;
}
int hw_get_mole_by_class(const char *class_id, const char *inst,
const struct hw_mole_t **mole)
{
int status;
int i;
const struct hw_mole_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);
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 of the library).
* We also assume that dlopen() is thread-safe.
*/

/* Loop through the configuration variants looking for a mole */
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)
//在這里將prop的路徑得到,分別從
"ro.hardware[qcom]"
"ro.proct.board"[7x27],
"ro.board.platform"[msm7627a],
"ro.arch",
"ro.hw_platform"[QRD_SKU3-1100]
這幾個屬性文件中獲得硬體的信息
有些硬體信息的字元串會出現在編譯後生成的.so名字中
{
continue;
}
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH2, name, prop);
if (access(path, R_OK) == 0) break;

snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, prop);//走這里,在這里得到/system/lib/hw/camera.msm7627a.so
這樣一個路徑,這個庫里有QualcommCamera.cpp,這是
camera模塊HAL代碼開始的地方
if (access(path, R_OK) == 0) break;
} else {
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH1, name);
if (access(path, R_OK) == 0) break;
}
}

status = -ENOENT;
if (i < HAL_VARIANT_KEYS_COUNT+1) {
/* load the mole, if this fails, we're doomed, and we should not try
* to load a different variant. */
status = load(class_id, path, mole);//這里關鍵,函數的三個參數可以串聯成一句話:
到path(/system/lib/hw/camera.msm7627a.so)這個路徑下找到一個id(camera)匹配的mole
}

return status;
}

再來看看load這個函數@hardware.c (hardware\libhardware)

[cpp] view plain print?
static int load(const char *id,
const char *path,
const struct hw_mole_t **pHmi)
{
int status;
void *handle;
struct hw_mole_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();
LOGE("load: mole=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}

<span style="color: rgb(255, 0, 0);"> /* Get the address of the struct hal_mole_info. */
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_mole_t *)dlsym(handle, sym);
</span> if (hmi == NULL) {
LOGE("load: couldn't find symbol %s", sym);
status = -EINVAL;
goto done;
}

/* Check that the id matches */
if (strcmp(id, hmi->id) != 0) {
LOGE("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 {
LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, *pHmi, handle);
}

*pHmi = hmi;

return status;
}
static int load(const char *id,
const char *path,
const struct hw_mole_t **pHmi)
{
int status;
void *handle;
struct hw_mole_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();
LOGE("load: mole=%s\n%s", path, err_str?err_str:"unknown");
status = -EINVAL;
goto done;
}

/* Get the address of the struct hal_mole_info. */
const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
hmi = (struct hw_mole_t *)dlsym(handle, sym);
if (hmi == NULL) {
LOGE("load: couldn't find symbol %s", sym);
status = -EINVAL;
goto done;
}

/* Check that the id matches */
if (strcmp(id, hmi->id) != 0) {
LOGE("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 {
LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
id, path, *pHmi, handle);
}

*pHmi = hmi;

return status;
}

在打開的.so(camera.msm7627a.so)中查找HMI符號的地址,並保存在hmi中。至此,.so中的hw_mole_t已經被成功獲取,從而可以根
據它獲取別的相關介面。
1)HAL通過hw_get_mole函數獲取hw_mole_t
2)HAL通過hw_mole_t->methods->open獲取hw_device_t指針,並在此open函數中初始化hw_device_t的包裝結構中的
函數及hw_device_t中的close函數,如gralloc_device_open。
3)三個重要的數據結構:
a) struct hw_device_t: 表示硬體設備,存儲了各種硬體設備的公共屬性和方法
b)struct hw_mole_t: 可用hw_get_mole進行載入的mole
c)struct hw_mole_methods_t: 用於定義操作設備的方法,其中只定義了一個打開設備的方法open.

Ⅲ Android Camera API 1.0,2.0,3.0 知多少

看到源碼裡面有諸如Camera.h , Camera2.h, Camera3.h的文件,覺得奇怪,後面在Camera3.h

中找到了對前後3個版本的概要性描述。

BTW, 我們看代碼的過程中,如何避免不需要的文件被添加到工程?

我是指: 我只想看Camera3.0的代碼,怎麼去除掉其他版本的呢?

不知道各位是否知道這些牽涉到哪些文件? 謝謝!!

* S1. Version history:
* 1.0: Initial Android camera HAL (Android 4.0) [camera.h]:
*
* - Converted from C3;3; CameraHardwareInterface abstraction layer.
*
* - Supports android.hardware.Camera API.
*
* 2.0: Initial release of expanded-capability HAL (Android 4.2) [camera2.h]:
*
* - Sufficient for implementing existing android.hardware.Camera API.
*
* - Allows for ZSL queue in camera service layer
*
* - Not tested for any new features such manual capture control, Bayer RAW
* capture, reprocessing of RAW data.
* 3.0: First revision of expanded-capability HAL:
*
* - Major version change since the ABI is completely different. No change to
* the required hardware capabilities or operational model from 2.0.
*
* - Reworked input request and stream queue interfaces: Framework calls into
* HAL with next request and stream buffers already dequeued. Sync framework
* support is included, necessary for efficient implementations.
*
* - Moved triggers into requests, most notifications into results.
*
* - Consolidated all callbacks into framework into one structure, and all
* setup methods into a single initialize() call.
* - Made stream configuration into a single call to simplify stream
* management. Bidirectional streams replace STREAM_FROM_STREAM construct.

熱點內容
廣東人社賬號密碼多少 發布:2025-05-10 03:43:11 瀏覽:616
python對象參數 發布:2025-05-10 03:43:11 瀏覽:575
自己伺服器搭建梯子 發布:2025-05-10 03:31:39 瀏覽:573
華為升級包怎麼解壓 發布:2025-05-10 03:18:24 瀏覽:603
c語言以什麼結束 發布:2025-05-10 03:18:22 瀏覽:257
160android 發布:2025-05-10 03:03:30 瀏覽:178
pythonstorage 發布:2025-05-10 02:58:38 瀏覽:499
如何查看電腦配置顯卡參數 發布:2025-05-10 02:37:00 瀏覽:106
證券交易密碼在哪裡修改 發布:2025-05-10 02:31:56 瀏覽:839
javafor是什麼意思 發布:2025-05-10 02:23:09 瀏覽:842