淺析Android Camera架構
本博文是基於Android 4.4講解
1、application 層:
當我們Android工程師想開啟camera時通常直接呼叫Camera.java中的 Camer.open(cameraId)靜態函式
camera.java 位於 frameworks/base/core/java/android/hardware目錄下
//以下是部分程式碼
public static Camera open(int cameraId) { return new Camera(cameraId); }
</pre><pre code_snippet_id="1846209" snippet_file_name="blog_20160823_3_8904287" name="code" class="html"><pre name="code" class="html">Camera(int cameraId) { mShutterCallback = null; mRawImageCallback = null; mJpegCallback = null; mPreviewCallback = null; mPostviewCallback = null; mUsingPreviewAllocation = false; 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(); <span style="color:#ff0000;">native_setup(new WeakReference<Camera>(this), cameraId, packageName);</span> }
其中native_setup介面是native介面其函式宣告如下
private native final void native_setup(Object camera_this, int cameraId,
String packageName);
2、jni層
在camera.java中會呼叫到native_setup函式,此jni介面定義在 frameworks/base/core/jni下面的android_hardware_Camera.cpp中
// 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);
<span style="color:#ff0000;"> sp<Camera> camera = Camera::connect(cameraId, clientName,
Camera::USE_CALLING_UID);
</span>
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());
}
其中上面會調Camera::connect介面此類是frameworks/av/camera/Camera.cpp
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName,
int clientUid)
{
return <span style="color:#ff0000;">CameraBaseT::connect</span>(cameraId, clientPackageName, clientUid);//呼叫了父類的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;
status_t status = NO_ERROR;
<span style="color:#ff0000;">const sp<ICameraService>& cs = getCameraService(); //得到CameraService.cpp例項</span>
if (cs != 0) {
<span style="color:#ff0000;"> TCamConnectService fnConnectService = TCamTraits::fnConnectService;
status = (cs.get()->*fnConnectService)(cl, cameraId, clientPackageName, clientUid,
/*out*/ c->mCamera); //此行最終會呼叫到CameraService.cpp中的connect介面</span>
}
if (status == OK && c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
ALOGW("An error occurred while connecting to camera: %d", cameraId);
c.clear();
}
return c;
}
frameworks/av/services/camera/libcameraservicw/CameraService.cpp
status_t CameraService::connect(
const sp<ICameraClient>& cameraClient,
int cameraId,
const String16& clientPackageName,
int clientUid,
/*out*/
sp<ICamera>& device) {
String8 clientName8(clientPackageName);
int callingPid = getCallingPid();
LOG1("CameraService::connect E (pid %d \"%s\", id %d)", callingPid,
clientName8.string(), cameraId);
status_t status = validateConnect(cameraId, /*inout*/clientUid);
if (status != OK) {
return status;
}
sp<Client> client;
{
Mutex::Autolock lock(mServiceLock);
sp<BasicClient> clientTmp;
if (!canConnectUnsafe(cameraId, clientPackageName,
cameraClient->asBinder(),
/*out*/clientTmp)) {
return -EBUSY;
} else if (client.get() != NULL) {
device = static_cast<Client*>(clientTmp.get());
return OK;
}
int facing = -1;
int deviceVersion = getDeviceVersion(cameraId, &facing);
// If there are other non-exclusive users of the camera,
// this will tear them down before we can reuse the camera
if (isValidCameraId(cameraId)) {
// transition from PRESENT -> NOT_AVAILABLE
updateStatus(ICameraServiceListener::STATUS_NOT_AVAILABLE,
cameraId);
}
switch(deviceVersion) {
case CAMERA_DEVICE_API_VERSION_1_0:
<span style="color:#ff0000;">client = new CameraClient(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid()); //我用的是camer1</span>
break;
case CAMERA_DEVICE_API_VERSION_2_0:
case CAMERA_DEVICE_API_VERSION_2_1:
case CAMERA_DEVICE_API_VERSION_3_0:
client = new Camera2Client(this, cameraClient,
clientPackageName, cameraId,
facing, callingPid, clientUid, getpid(),
deviceVersion);
break;
case -1:
ALOGE("Invalid camera id %d", cameraId);
return BAD_VALUE;
default:
ALOGE("Unknown camera device HAL version: %d", deviceVersion);
return INVALID_OPERATION;
}
<span style="color:#ff0000;"> status_t status = connectFinishUnsafe(client, client->getRemote()); //見下面定義</span>
if (status != OK) {
// this is probably not recoverable.. maybe the client can try again
// OK: we can only get here if we were originally in PRESENT state
updateStatus(ICameraServiceListener::STATUS_PRESENT, cameraId);
return status;
}
mClient[cameraId] = client;
LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId,
getpid());
}
// important: release the mutex here so the client can call back
// into the service from its destructor (can be at the end of the call)
device = client;
return OK;
}
status_t CameraService::connectFinishUnsafe(const sp<BasicClient>& client,
const sp<IBinder>& remoteCallback) {
<span style="color:#ff0000;"> status_t status = client->initialize(mModule); //其中 camera_module_t *mModule為一個結構體指標,此指標會在onFirstRef()介面中初始化見下面程式碼</span>
if (status != OK) {
return status;
}
remoteCallback->linkToDeath(this);
return OK;
}
//此介面會在CameraService例項化後呼叫,其中用到了sp機制,目前尚未研究通。
void CameraService::onFirstRef()
{
LOG1("CameraService::onFirstRef");
BnCameraService::onFirstRef();
if (<span style="color:#ff0000;">hw_get_module</span>(CAMERA_HARDWARE_MODULE_ID,//此句程式碼是關鍵之處
(const hw_module_t **)&mModule) < 0) {
ALOGE("Could not load camera HAL module");
mNumberOfCameras = 0;
}
else {
ALOGI("Loaded \"%s\" camera module", mModule->common.name);
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);
}
if (mModule->common.module_api_version >=
CAMERA_MODULE_API_VERSION_2_1) {
mModule->set_callbacks(this);
}
CameraDeviceFactory::registerService(this);
}
}
hw_get_module位於Android原始碼目錄下 hardware/libhardware/Hardware.c
int hw_get_module(const char *id, const struct hw_module_t **module)
{
return hw_get_module_by_class(id, NULL, module);
}
//此函式會載入動態庫"/system/lib/hw"下面有名字為class_id的動態庫
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);
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); // PATH2: "/vendor/lib/hw"
if (access(path, R_OK) == 0) break;
snprintf(path, sizeof(path), "%s/%s.%s.so",
HAL_LIBRARY_PATH1, name, prop); //PATH1: "/system/lib/hw"
if (access(path, R_OK) == 0) break;
} else {
snprintf(path, sizeof(path), "%s/%s.default.so",
HAL_LIBRARY_PATH2, name);
if (access(path, R_OK) == 0) break;
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 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;
}
<span style="color:#ff0000;">//</span>
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; //HAL_MODULE_INFO_SYM_AS_STR 為 "HMI"
<span style="color:#ff0000;">//dlsym根據sym去例項化hmi,其中Camera_Moduel.cpp下有"HMI"名字的camera_module_t變數,見下面程式碼</span>
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;
}
CameraHal_Module.cpp //此類位於hardware/rk29/camera/camerahal目錄下,這是我的原始碼camera模組
camera_module_t HAL_MODULE_INFO_SYM = {
common: {
tag: HARDWARE_MODULE_TAG,
version_major: ((CONFIG_CAMERAHAL_VERSION&0xff00)>>8),
version_minor: CONFIG_CAMERAHAL_VERSION&0xff,
id: CAMERA_HARDWARE_MODULE_ID,
name: CAMERA_MODULE_NAME,
author: "RockChip",
<span style="color:#ff0000;">methods: &camera_module_methods,</span>
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,
set_callbacks:NULL,
get_vendor_tag_ops:NULL,
reserved: {0}
};
到此frameworks/av/services/camera/libcameraservicw/CameraService.cpp下的mModule例項化完成
我們在進入到CameraClient.cpp(frameworks/av/services/camera/libcameraservice/api1)中(上面的CameraService.cpp例項化了CameraClient並且呼叫了它內部的initialize(camera_module_t *module)介面)
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);
<span style="color:#ff0000;">mHardware = new CameraHardwareInterface(camera_device_name);</span>
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;
}
CameraHardwareInterface.h位於 frameworks/av/services/camera/libcameraservice/device1
status_t initialize(hw_module_t *module)
{
ALOGI("Opening camera %s", mName.string());
<span style="color:#ff0000;">int rc = module->methods->open(module, mName.string(),
(hw_device_t **)&mDevice); //呼叫了上面CameraHal_Module.cpp下的</span><span style="color: rgb(255, 0, 0); font-family: Arial, Helvetica, sans-serif;">camera_module_t HAL_MODULE_INFO_SYM的open函式</span><span style="color:#ff0000;">,此函式定義見下面程式碼</span>
if (rc != OK) {
ALOGE("Could not open camera %s: %d", mName.string(), rc);
return rc;
}
initHalPreviewWindow();
return rc;
}
static struct hw_module_methods_t camera_module_methods = {
open: camera_device_open
};
int camera_device_open(const hw_module_t* module, const char* name,
hw_device_t** device)
{
int rv = 0;
int cameraid;
rk_camera_device_t* camera_device = NULL;
camera_device_ops_t* camera_ops = NULL;
android::CameraHal* camera = NULL;
android::Mutex::Autolock lock(gCameraHalDeviceLock);
LOGI("camera_device open");
if (name != NULL) {
cameraid = atoi(name);
if(cameraid > gCamerasNumber) {
LOGE("camera service provided cameraid out of bounds, "
"cameraid = %d, num supported = %d",
cameraid, gCamerasNumber);
rv = -EINVAL;
goto fail;
}
if(gCamerasOpen >= CAMERAS_SUPPORTED_SIMUL_MAX) {
LOGE("maximum number(%d) of cameras already open",gCamerasOpen);
rv = -ENOMEM;
goto fail;
}
camera_device = (rk_camera_device_t*)malloc(sizeof(*camera_device));
if(!camera_device) {
LOGE("camera_device allocation fail");
rv = -ENOMEM;
goto fail;
}
camera_ops = (camera_device_ops_t*)malloc(sizeof(*camera_ops));
if(!camera_ops) {
LOGE("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;
// -------- RockChip specific stuff --------
camera_device->cameraid = cameraid;
<span style="color:#ff0000;">camera = new android::CameraHal(cameraid); //進入hal層</span>
if(!camera) {
LOGE("Couldn't create instance of CameraHal class");
rv = -ENOMEM;
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;
}
3、hal層
hardware/rk29/camera/camerahal/CameraHal.cpp
//以下會根據camera硬體分類uvc soc isp等,例項化成對應的adapter.cpp(資料介面卡,此類會呼叫iotrl系統介面和驅動層進行通訊)
CameraHal::CameraHal(int cameraId)
:commandThreadCommandQ("commandCmdQ")
{
LOG_FUNCTION_NAME
{
char trace_level[PROPERTY_VALUE_MAX];
int level;
property_get(CAMERAHAL_TRACE_LEVEL_PROPERTY_KEY, trace_level, "0");
sscanf(trace_level,"%d",&level);
setTracerLevel(level);
}
mCamId = cameraId;
mCamFd = -1;
mCommandRunning = -1;
mCameraStatus = 0;
#if (CONFIG_CAMERA_MEM == CAMERA_MEM_ION)
mCamMemManager = new IonMemManager();
LOG1("%s(%d): Camera Hal memory is alloced from ION device",__FUNCTION__,__LINE__);
#elif(CONFIG_CAMERA_MEM == CAMERA_MEM_IONDMA)
if((strcmp(gCamInfos[cameraId].driver,"uvcvideo") == 0) //uvc camera
|| (gCamInfos[cameraId].pcam_total_info->mHardInfo.mSensorInfo.mPhy.type == CamSys_Phy_end)// soc cif
) {
gCamInfos[cameraId].pcam_total_info->mIsIommuEnabled = (IOMMU_ENABLED == 1)? true:false;
}
mCamMemManager = new IonDmaMemManager(gCamInfos[cameraId].pcam_total_info->mIsIommuEnabled);
LOG1("%s(%d): Camera Hal memory is alloced from ION device",__FUNCTION__,__LINE__);
#elif(CONFIG_CAMERA_MEM == CAMERA_MEM_PMEM)
if(access(CAMERA_PMEM_NAME, O_RDWR) < 0) {
LOGE("%s(%d): %s isn't registered, CameraHal_Mem current configuration isn't support ION memory!!!",
__FUNCTION__,__LINE__,CAMERA_PMEM_NAME);
} else {
mCamMemManager = new PmemManager((char*)CAMERA_PMEM_NAME);
LOG1("%s(%d): Camera Hal memory is alloced from %s device",__FUNCTION__,__LINE__,CAMERA_PMEM_NAME);
}
#endif
mPreviewBuf = new PreviewBufferProvider(mCamMemManager);
mVideoBuf = new BufferProvider(mCamMemManager);
mRawBuf = new BufferProvider(mCamMemManager);
mJpegBuf = new BufferProvider(mCamMemManager);
char value[PROPERTY_VALUE_MAX];
property_get(/*CAMERAHAL_TYPE_PROPERTY_KEY*/"sys.cam_hal.type", value, "none");
if (!strcmp(value, "fakecamera")) {
LOGD("it is a fake camera!");
mCameraAdapter = new CameraFakeAdapter(cameraId);
} else {
if((strcmp(gCamInfos[cameraId].driver,"uvcvideo") == 0)) {
LOGD("it is a uvc camera!");
mCameraAdapter = new CameraUSBAdapter(cameraId);
}
else if(gCamInfos[cameraId].pcam_total_info->mHardInfo.mSensorInfo.mPhy.type == CamSys_Phy_Cif){
LOGD("it is a isp soc camera");
if(gCamInfos[cameraId].pcam_total_info->mHardInfo.mSensorInfo.mPhy.info.cif.fmt == CamSys_Fmt_Raw_10b)
mCameraAdapter = new CameraIspSOCAdapter(cameraId);
else
mCameraAdapter = new CameraIspAdapter(cameraId);
}
else if(gCamInfos[cameraId].pcam_total_info->mHardInfo.mSensorInfo.mPhy.type == CamSys_Phy_Mipi){
LOGD("it is a isp camera");
mCameraAdapter = new CameraIspAdapter(cameraId);
}
else{
LOGD("it is a soc camera!");
mCameraAdapter = new CameraSOCAdapter(cameraId);
}
}
//initialize
{
char *call_process = getCallingProcess();
if(strstr(call_process,"com.android.cts.verifier")) {
mCameraAdapter->setImageAllFov(true);
} else {
mCameraAdapter->setImageAllFov(false);
}
}
mDisplayAdapter = new DisplayAdapter();
mEventNotifier = new AppMsgNotifier(mCameraAdapter);
mCameraAdapter->setEventNotifierRef(*mEventNotifier);
mCameraAdapter->initialize();
updateParameters(mParameters);
mCameraAdapter->setPreviewBufProvider(mPreviewBuf);
mCameraAdapter->setDisplayAdapterRef(*mDisplayAdapter);
mDisplayAdapter->setFrameProvider(mCameraAdapter);
mEventNotifier->setPictureRawBufProvider(mRawBuf);
mEventNotifier->setPictureJpegBufProvider(mJpegBuf);
mEventNotifier->setVideoBufProvider(mVideoBuf);
mEventNotifier->setFrameProvider(mCameraAdapter);
//command thread
mCommandThread = new CommandThread(this);
mCommandThread->run("CameraCmdThread", ANDROID_PRIORITY_URGENT_DISPLAY);
bool dataCbFrontMirror;
bool dataCbFrontFlip;
#if CONFIG_CAMERA_FRONT_MIRROR_MDATACB
if (gCamInfos[cameraId].facing_info.facing == CAMERA_FACING_FRONT) {
#if CONFIG_CAMERA_FRONT_MIRROR_MDATACB_ALL
dataCbFrontMirror = true;
#else
const char* cameraCallProcess = getCallingProcess();
if (strstr(CONFIG_CAMERA_FRONT_MIRROR_MDATACB_APK,cameraCallProcess)) {
dataCbFrontMirror = true;
} else {
dataCbFrontMirror = false;
}
if (strstr(CONFIG_CAMERA_FRONT_FLIP_MDATACB_APK,cameraCallProcess)) {
dataCbFrontFlip = true;
} else {
dataCbFrontFlip = false;
}
#endif
} else {
dataCbFrontMirror = false;
dataCbFrontFlip = false;
}
#else
dataCbFrontMirror = false;
#endif
mEventNotifier->setDatacbFrontMirrorFlipState(dataCbFrontMirror,dataCbFrontFlip);
// register for sensor events
mSensorListener = new SensorListener();
if (mSensorListener.get()) {
if (mSensorListener->initialize() == NO_ERROR) {
mSensorListener->setCallbacks(gsensor_orientation_cb, this);
mSensorListener->enableSensor(SensorListener::SENSOR_ORIENTATION);
} else {
LOGE("Error initializing SensorListener. not fatal, continuing");
mSensorListener.clear();
mSensorListener = NULL;
}
}
LOG_FUNCTION_NAME_EXIT
}
相關推薦
淺析Android Camera架構
本博文是基於Android 4.4講解 1、application 層: 當我們Android工程師想開啟camera時通常直接呼叫Camera.java中的 Camer.open(cameraId)靜態函式
淺析Android Camera開發中的三個尺寸和三種變形 貢獻一個自適配Picturesize和Previewsiz
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!  
Android Camera架構分層及程式碼結構(MTK version)
Android的Camera包含取景器(viewfinder)和拍攝照片(takepicture)的功能。目前MTKAndroid Camera程式的架構分成客戶端和伺服器兩個部分,它們建立在Android的程序間通訊Binder的結構上。Camera模組同樣遵循Andro
Qualcomm Android camera 架構簡析及如何debug
Qualcomm Android camera 架構簡析及如何debug 一. Camera模組(CCM)介紹: CCM一般包含四大件: 鏡頭(lens)、感測器(sensor)、軟板(FPC)、影象處理晶片(DSP): C
Android Camera架構
Android 的相機硬體抽象層 (HAL) 可將 Camera 2 中較高級別的相機框架 API 連線到底層的相機驅動程式和硬體
Android Camera 系統架構原始碼分析(4)---->Camera的資料來源及Camera的管理
Camera的資料來源及Camera的管理 我們接著第3篇,再返回Cam1DeviceBase::startPreview()的(4) mpCamAdapter->startPreview()。在講(4)前我們先來看看(1)onStartPreview(
Android Camera API2.0下全新的Camera FW/HAL架構簡述
本文均屬自己閱讀原始碼的點滴總結,轉賬請註明出處謝謝。歡迎和大家交流。qq:1037701636 email:Software:系統原始碼Android5.1前沿: 前面博文大多少總結的是Camera HAL1到HAL3的系統架構,但這些架構對於Camera A
Android 7.0 Camera架構原始碼分析
Android 7.0之前CameraService是在mediaserver程序中註冊的,看下Android 6.0的程式碼: //path: frameworks\av\media\mediaserver\main_mediaserver.cpp int m
Android Camera Subsystem 架構(Binder機制)及顯示分析(3)
Camera Display 對於AP層使用者,通過Camera介面, 以最直觀的方式能夠從Camera顯示視窗中看到的Camera Display主要包括三部分。各部分的具體細節如下所示。 (1)Camera Preview Display 對於Camera Pre
Android Camera 系統架構原始碼分析(2)---->Camera的startPreview和setPreviewCallback
Camera startPreview流程 上接第一篇,這個過程的主要任務是,如何讀取資料的,讀取的資料是什麼格式,最好能知道是如何去預覽的 上層APP呼叫的是Camera.java的startPreview();,下面列出startPreview的呼叫流程 //Camera
Android Camera HAL淺析
1、Camera成像原理介紹 Camera工作流程圖 &
android app 架構設計01
clas -h tab size data 資源 top post 樣式 1:本文有摘抄, 1 2 3 4 5 - 開發過程中。需求、設計、編碼的一致性 - 整個程序具有統一的風格,比方對話框樣式,button風格,色調等UI元素 - 整個程序詳細統一的結
玩轉Android Camera開發(二):使用TextureView和SurfaceTexture預覽Camera 基礎拍照demo
處理 pict all sans 格式 facet ace ets nth Google自Android4.0出了TextureView。為什麽推出呢?就是為了彌補Surfaceview的不足。另外一方面也是為了平衡GlSurfaceView。當然這是本人揣度的。關於Te
Android Camera 通過V4L2與kernel driver的完整交互過程
initial length 詳細 eas handler use orien amp com http://blog.chinaunix.net/uid-26215986-id-3552456.html 原文地址:Android Camera 通過V4L2與kernel
溫故而知新---淺析三層架構(一個超簡單的系統登錄三層架構實例)
lda code windows comm 面向 box reader 業務 兩個 剛開始接觸三層架構是在快兩個月前,那時候找了好多例子感覺也都看不怎麽懂,今天閑著沒事,就把以前學的東西翻出來,算是溫習溫習。由於本人也接觸時間不長,所以以下言論有不正確之處,多多
Android 程序架構: MVC、MVP、MVVM、Unidirectional、Clean...
不同 概念 可能 十年 tin gettext 聲明 數據 content 摘選自:GUI 應用程序架構的十年變遷:MVC、MVP、MVVM、Unidirectional、Cleanhttps://zhuanlan.zhihu.com/p/26799645 MV
Android Camera
ubi 驅動 fim andro cmm roi target 工作原理 camera android camera(一):camera模組CMM介紹 android camera(二):攝像頭工作原理、s5PV310 攝像頭接口(CAMIF) android came
android camera之nv21旋轉
現象 rtx 不可 行數據 灰度 upa sfc max ide 這周做的一個android的camera開發,需要獲取到視頻幀數據,並且需要是nv21格式的byte數組,並且視頻幀的圖像需要是正方向的。和android相機打過交道的都清楚,android的camera獲取
【轉】Android Camera 相機開發詳解
exc troy start 當前 container rac google getconf 對比度 在Android 5.0(SDK 21)中,Google使用Camera2替代了Camera接口。Camera2在接口和架構上做了巨大的變動, 但是基於眾所周知的原因
Android Camera fw學習(四)-recording流程分析
應用開發 facet internal server 中一 sca med erase 流程分析 Android Camera fw學習(四)-recording流程分析 備註:備註:本文是Android5.1學習筆記。博文按照軟件啟動流程分析。 且行且惜,一步一個腳印