一、Camera 架构
NOTE:这是 Android Camera API 1 ,Camera 的架构与 Android 整体架构是保持一致的: Framework : Camera.java Android Runtime : android_hardware_Camera.cpp Library : Client (Camera.cpp, ICameraClient.cpp, etc...) Server (CameraService.cpp, ICameraService.cpp, etc...) HAL : CameraHardwareInterface.h
架构简图:
根据架构简图可以看到,实际上 Camera 的架构与 Android 架构是一一对应的,上层应用调用 Camera 相关的方法后,指令依次通过框架层、运行时环境、本地库、硬件抽象层,最终到达具体设备。设备执行动作后,获得的数据又会沿着反方向依次发送到最上层。
需要注意的是,在本地库这一层中,涉及到一个 C/S 结构:
- 即通过客户端与服务端的交互来传递指令与数据。
- 实际上,只有服务端与 HAL 层进行沟通。
- 由于客户端与服务端是不同的进程,它们之间需要依靠 IPC Binder 机制 来进行通讯。
相关源码位置(Android 7.1 源码):
Application:(这部分不是学习的重点) packages/apps/Camera2/src/com/android/camera/*** Framework: /frameworks/base/core/java/android/hardware/Camera.java Android Runtime: frameworks/base/core/jni/android_hardware_Camera.cpp C/C++ Libraries: Client: frameworks/av/camera/CameraBase.cpp frameworks/av/camera/Camera.cpp frameworks/av/camera/ICamera.cpp frameworks/av/camera/aidl/android/hardware/ICamera.aidl frameworks/av/camera/aidl/android/hardware/ICameraClient.aidl Server: frameworks/av/camera/cameraserver/main_cameraserver.cpp frameworks/av/services/camera/libcameraservice/CameraService.cpp frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp frameworks/av/camera/aidl/android/hardware/ICameraService.aidl HAL: HAL 1:(此篇文章分析) frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h HAL 3:(参考:https://www.cnblogs.com/blogs-of-lxl/p/10651611.html ) frameworks/av/services/camera/libcameraservice/device3/***
二、Camera Open 调用流程
1.Camera.java(Framework层):frameworks/base/core/java/android/hardware/Camera.java
/*** * Creates a new Camera object to access * the first back-facing camera on the * device. If the device does not have a back-facing camera, * this returns null. * @see #open(int) */ public static Camera open() { int numberOfCameras = getNumberOfCameras(); //获取 Camera 设备的个数。 CameraInfo cameraInfo = new CameraInfo(); for (int i = 0; i < numberOfCameras; i++) { getCameraInfo(i, cameraInfo); //依次获取设备信息, if (cameraInfo.facing == CameraInfo.CAMERA_FACING_BACK) { //如果是获取到后置摄像头(默认),则调用 new Camera(int) 构造对应的摄像头实例。 return new Camera(i); } } return null; }
Camera(int cameraId)
:
/** used by Camera#open, Camera#open(int) */ Camera(int cameraId) { int err = cameraInitNormal(cameraId); //通过调用 cameraInitNormal(Id) 方法对指定摄像头进行初始化。 if (checkInitErrors(err)) { if (err == -EACCES) { throw new RuntimeException("Fail to connect to camera service"); } else if (err == -ENODEV) { throw new RuntimeException("Camera initialization failed"); } // Should never hit this. throw new RuntimeException("Unknown camera error"); } }
cameraInitNormal(int cameraId)
:
private int cameraInitNormal(int cameraId) { return cameraInitVersion(cameraId, CAMERA_HAL_API_VERSION_NORMAL_CONNECT); //调用 cameraInitVersion(int cameraId, int halVersion),指定 halVersion 参数 }
cameraInitVersion(int cameraId, int halVersion)
:
private int cameraInitVersion(int cameraId, int halVersion) { //将各个回调函数置空 mShutterCallback = null; mRawImageCallback = null; mJpegCallback = null; mPreviewCallback = null; mPostviewCallback = null; mUsingPreviewAllocation = false; mZoomListener = null; Looper looper; //通过 Looper 对事件处理对象进行实例化后,就调用 native_setup 方法进入 JNI(Java Native Interface) 库中调用对应的函数。 if ((looper = Looper.myLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else if ((looper = Looper.getMainLooper()) != null) { mEventHandler = new EventHandler(this, looper); } else { mEventHandler = null; } return native_setup(new WeakReference<Camera>(this), cameraId, halVersion, ActivityThread.currentOpPackageName()); }
至此,open()
方法开始进入 Android Runtime
层。
简图总结:
2. android_hardware_Camera.cpp(Android Runtime):frameworks/base/core/jni/android_hardware_Camera.cpp
// connect to camera service static jint android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz, jobject weak_this, jint cameraId, jint halVersion, jstring clientPackageName) { // convert jstring to String16(clientPackageName -> clientName) //刚开始要先把clientPackageName
做一个类型转换,变成clientName
...... ...... sp<Camera> camera; //建立一个Camera
类型的StrongPointer(sp),然后通过
if (halVersion == CAMERA_HAL_API_VERSION_NORMAL_CONNECT) { /***** NOTE THIS *****/ // Default path: hal version is don't care, do normal camera connect. camera = Camera::connect(cameraId, clientName, //进入Camera::connect()
或Camera::connectLegacy()
,让客户端与服务端进行连接,并返回相应的Camera
实例C/C++ Libraries
的 C/S 结构中,而Camera
则属于Client
Camera::USE_CALLING_UID, Camera::USE_CALLING_PID); } else { jint status = Camera::connectLegacy(cameraId, halVersion, clientName, Camera::USE_CALLING_UID, camera); if (status != NO_ERROR) { return status; } } if (camera == NULL) { return -EACCES; } //最后对返回的实例进行一些基本的检查,并保存上下文 // make sure camera hardware is alive if (camera->getStatus() != NO_ERROR) { return NO_INIT; } // save context in opaque field ...... ...... }
简图总结:
3.Camera(C/C++ Libraries):
(1)frameworks/av/include/camera/Camera.h
template <> struct CameraTraits<Camera> { typedef CameraListener TCamListener; typedef ::android::hardware::ICamera TCamUser; typedef ::android::hardware::ICameraClient TCamCallbacks; typedef ::android::binder::Status(::android::hardware::ICameraService::*TCamConnectService) (const sp<::android::hardware::ICameraClient>&, int, const String16&, int, int, /*out*/ sp<::android::hardware::ICamera>*); static TCamConnectService fnConnectService; };
(2)framework/av/camera/Camera.cpp
CameraTraits<Camera>::TCamConnectService CameraTraits<Camera>::fnConnectService = //注:fnConnectService
是对应到ICameraService::connect
函数的 &::android::hardware::ICameraService::connect;
Camera::connect
:
sp<Camera> Camera::connect(int cameraId, const String16& clientPackageName, int clientUid, int clientPid) { return CameraBaseT::connect(cameraId, //直接调用了CameraBaseT::connect()
这是定义在CameraBase.cpp
中的函数。 clientPackageName, clientUid, clientPid); }
(3)frameworks/av/include/camera/CameraBase.h
template <typename TCam, typename TCamTraits = CameraTraits<TCam> > //TCam
对应Camera
;TCamTraits
对应CameraTraits<Camera>
注意类成员变量声明部分,即可知道 CameraBaseT
对应 CameraBase<Camera>
。
sp<TCamUser> mCamera; status_t mStatus; sp<TCamListener> mListener; const int mCameraId; /***** NOTE THIS *****/ typedef CameraBase<TCam> CameraBaseT;
(4)framework/av/camera/CameraBase.cpp
template <typename TCam, typename TCamTraits> sp<TCam> CameraBase<TCam, TCamTraits>::connect(int cameraId, const String16& clientPackageName, int clientUid, int clientPid) { ALOGV("%s: connect", __FUNCTION__); /***** NOTE THIS *****/ sp<TCam> c = new TCam(cameraId); //实例化一个Camera,
通过Camera
获取ICameraClient
指针。
sp<TCamCallbacks> cl = c; const sp<::android::hardware::ICameraService> cs = getCameraService(); binder::Status ret; if (cs != nullptr) { /***** NOTE THIS *****/ TCamConnectService fnConnectService = TCamTraits::fnConnectService; //通过
ret = (cs.get()->*fnConnectService)(cl, cameraId, //通过getCameraService()
函数获取ICameraService
。ICameraService::connect()
函数获得一个mCamera
, 即ICamera
实例。 clientPackageName, clientUid, clientPid, /*out*/ &c->mCamera); } if (ret.isOk() && c->mCamera != nullptr) { /***** NOTE THIS *****/ IInterface::asBinder(c->mCamera)->linkToDeath(c); //将ICamera
实例与Binder
建立联系。 c->mStatus = NO_ERROR; } else { ALOGW("An error occurred while connecting to camera %d: %s", cameraId, (cs != nullptr) ? "Service not available" : ret.toString8().string()); c.clear(); } return c; }
// establish binder interface to camera service template <typename TCam, typename TCamTraits> const sp<::android::hardware::ICameraService> CameraBase<TCam, TCamTraits>::getCameraService() { Mutex::Autolock _l(gLock); /***** NOTE THIS *****/ if (gCameraService.get() == 0) { //gCameraService
是一个ICameraService,调
用
char value[PROPERTY_VALUE_MAX]; property_get("config.disable_cameraservice", value, "0"); if (strncmp(value, "0", 2) != 0 && strncasecmp(value, "false", 6) != 0) { return gCameraService; //首先调用
get
函数,如果能获取到ICameraService
则返回。ICameraService
} /***** NOTE THIS *****/ //若没有返回,则通过IServiceManager
来获取一个ICameraService
,这个过程中主要是通过IBinder
来进行数据获取。 sp<IServiceManager> sm = defaultServiceManager(); sp<IBinder> binder; do { binder = sm->getService(String16(kCameraServiceName)); if (binder != 0) { break; } ALOGW("CameraService not published, waiting..."); usleep(kCameraServicePollDelay); } while(true); if (gDeathNotifier == NULL) { gDeathNotifier = new DeathNotifier(); } binder->linkToDeath(gDeathNotifier); /***** NOTE THIS *****/ gCameraService = interface_cast<::android::hardware::ICameraService>(binder); } ALOGE_IF(gCameraService == 0, "no CameraService!?"); return gCameraService; }
4.ICameraService:
- 这一节主要是了解一下关于 Binder 通讯中的一些内部逻辑。
- 实际上在
CameraBase
中,所调用的connect
对应的是CameraService::connect()
。
(1)frameworks/av/camera/aidl/android/hardware/ICameraService.aidl
/** * Open a camera device through the old camera API */ ICamera connect(ICameraClient client, int cameraId, String opPackageName, int clientUid, int clientPid);
(2)out/target/product/generic/obj/SHARED_LIBRARIES/libcamera_client_intermediates/aidl-generated/src/aidl/android/hardware/ICameraService.cpp
//这个ICameraService.cpp
以及其头文件ICameraService.h
都是根据其对应的aidl
文件自动生成的。 ::android::binder::Status BpCameraService::connect(const ::android::sp<::android::hardware::ICameraClient>& client, //这里是BpCameraservice
,它继承了ICameraService
,同时也继承了BpInterface
。 int32_t cameraId, const ::android::String16& opPackageName, int32_t clientUid, int32_t clientPid, ::android::sp<::android::hardware::ICamera>* _aidl_return) { ::android::Parcel _aidl_data; //Parcel
可以看成是Binder
通讯中的信息传递中介,后面将相应的数据写入Parcel ::android::Parcel _aidl_reply; //返回的reply
数据判断是否有error
::android::status_t _aidl_ret_status = ::android::OK; ::android::binder::Status _aidl_status; _aidl_ret_status = _aidl_data.writeInterfaceToken(getInterfaceDescriptor()); //首先把。 /***** NOTE THIS *****/ if (((_aidl_ret_status) != (::android::OK))) { goto _aidl_error; } _aidl_ret_status = _aidl_data.writeStrongBinder(::android::hardware::ICameraClient::asBinder(client)); if (((_aidl_ret_status) != (::android::OK))) { goto _aidl_error; } _aidl_ret_status = _aidl_data.writeInt32(cameraId); if (((_aidl_ret_status) != (::android::OK))) { goto _aidl_error; } _aidl_ret_status = _aidl_data.writeString16(opPackageName); if (((_aidl_ret_status) != (::android::OK))) { goto _aidl_error; } _aidl_ret_status = _aidl_data.writeInt32(clientUid); if (((_aidl_ret_status) != (::android::OK))) { goto _aidl_error; } _aidl_ret_status = _aidl_data.writeInt32(clientPid); if (((_aidl_ret_status) != (::android::OK))) { goto _aidl_error; } /***** NOTE THIS *****/ _aidl_ret_status = remote()->transact(ICameraService::CONNECT, _aidl_data, &_aidl_reply); //调用远程接口remote()
中的处理函数transact()
。 if (((_aidl_ret_status) != (::android::OK))) { goto _aidl_error; } _aidl_ret_status = _aidl_status.readFromParcel(_aidl_reply); if (((_aidl_ret_status) != (::android::OK))) { goto _aidl_error; } if (!_aidl_status.isOk()) { return _aidl_status; } _aidl_ret_status = _aidl_reply.readStrongBinder(_aidl_return); if (((_aidl_ret_status) != (::android::OK))) { goto _aidl_error; } _aidl_error: _aidl_status.setFromStatusT(_aidl_ret_status); return _aidl_status; }
BnCameraService::onTransact()
:消息处理函数
case Call::CONNECT: { ::android::sp<::android::hardware::ICameraClient> in_client; int32_t in_cameraId; ::android::String16 in_opPackageName; int32_t in_clientUid; int32_t in_clientPid; /***** NOTE THIS *****/ ::android::sp<::android::hardware::ICamera> _aidl_return; if (!(_aidl_data.checkInterface(this))) { _aidl_ret_status = ::android::BAD_TYPE; break; } //接收Bp
传来的数据 _aidl_ret_status = _aidl_data.readStrongBinder(&in_client); if (((_aidl_ret_status) != (::android::OK))) { break; } _aidl_ret_status = _aidl_data.readInt32(&in_cameraId); if (((_aidl_ret_status) != (::android::OK))) { break; } _aidl_ret_status = _aidl_data.readString16(&in_opPackageName); if (((_aidl_ret_status) != (::android::OK))) { break; } _aidl_ret_status = _aidl_data.readInt32(&in_clientUid); if (((_aidl_ret_status) != (::android::OK))) { break; } _aidl_ret_status = _aidl_data.readInt32(&in_clientPid); if (((_aidl_ret_status) != (::android::OK))) { break; } /***** NOTE THIS *****/ ::android::binder::Status _aidl_status(connect(in_client, in_cameraId, in_opPackageName, in_clientUid, in_clientPid, &_aidl_return)); //调用了具体的connect
函数获取ICamera
并且返 _aidl_ret_status = _aidl_status.writeToParcel(_aidl_reply); if (((_aidl_ret_status) != (::android::OK))) { break; } if (!_aidl_status.isOk()) { break; } /***** NOTE THIS *****/ _aidl_ret_status = _aidl_reply->writeStrongBinder(::android::hardware::ICamera::asBinder(_aidl_return)); if (((_aidl_ret_status) != (::android::OK))) { break; } } break;
5.ICamera:
(1)frameworks/av/camera/ICamera.cpp
virtual status_t connect(const sp<ICameraClient>& cameraClient) //BpCamera
类中的connect()
函数 { Parcel data, reply; data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); data.writeStrongBinder(IInterface::asBinder(cameraClient)); remote()->transact(CONNECT, data, &reply); return reply.readInt32(); }
BnCamera
类中,onTransact
函数则有相应的处理:
case CONNECT: { CHECK_INTERFACE(ICamera, data, reply); sp<ICameraClient> cameraClient = interface_cast<ICameraClient>(data.readStrongBinder()); reply->writeInt32(connect(cameraClient)); return NO_ERROR; } break;
(2)frameworks/av/services/camera/libcameraservice/CameraService.cpp
Status CameraService::connect( const sp<ICameraClient>& cameraClient, int cameraId, const String16& clientPackageName, int clientUid, int clientPid, /*out*/ sp<ICamera>* device) { ATRACE_CALL(); Status ret = Status::ok(); String8 id = String8::format("%d", cameraId); sp<Client> client = nullptr; //真正实现逻辑是在connectHelper()
函数中 ret = connectHelper<ICameraClient,Client>(cameraClient, id, CAMERA_HAL_API_VERSION_UNSPECIFIED, clientPackageName, clientUid, clientPid, API_1, /*legacyMode*/ false, /*shimUpdateOnly*/ false, /*out*/client); if(!ret.isOk()) { logRejected(id, getCallingPid(), String8(clientPackageName), ret.toString8()); return ret; } *device = client; //获得一个客户端实例并且通过*device
返回 return ret; }
(3)frameworks/av/services/camera/libcameraservice/CameraService.h
sp<BasicClient> clientTmp = nullptr; std::shared_ptr<resource_policy::ClientDescriptor<String8, sp<BasicClient>>> partial; if ((err = handleEvictionsLocked(cameraId, originalClientPid, effectiveApiLevel, IInterface::asBinder(cameraCb), clientName8, /*out*/&clientTmp, /*out*/&partial)) != NO_ERROR) { /***** do something *****/ } /***** NOTE THIS *****/ if (clientTmp.get() != nullptr) { //如果客户端实例已经存在于MediaRecorder
,则直接将其取出返回 // Handle special case for API1 MediaRecorder where the existing client is returned device = static_cast<CLIENT*>(clientTmp.get()); return ret; } // give flashlight a chance to close devices if necessary. mFlashlight->prepareDeviceOpen(cameraId); // TODO: Update getDeviceVersion + HAL interface to use strings for Camera IDs int id = cameraIdToInt(cameraId); if (id == -1) { ALOGE("%s: Invalid camera ID %s, cannot get device version from HAL.", __FUNCTION__, cameraId.string()); return STATUS_ERROR_FMT(ERROR_ILLEGAL_ARGUMENT, "Bad camera ID \"%s\" passed to camera open", cameraId.string()); } int facing = -1; /***** NOTE THIS *****/ int deviceVersion = getDeviceVersion(id, /*out*/&facing); //获取deviceVersion
,然后再调用makeClient()
函数创建一个客户端。 sp<BasicClient> tmp = nullptr; if(!(ret = makeClient(this, cameraCb, clientPackageName, id, facing, clientPid, clientUid, getpid(), legacyMode, halVersion, deviceVersion, effectiveApiLevel, /*out*/&tmp)).isOk()) { return ret; } client = static_cast<CLIENT*>(tmp.get()); LOG_ALWAYS_FATAL_IF(client.get() == nullptr, "%s: CameraService in invalid state", __FUNCTION__); /***** NOTE THIS *****/ if ((err = client->initialize(mModule)) != OK) { //调用其initialize()
函数进行初始化,注意其传入的参数是mModule
,这个参数是连接Libraries
与HAL
的关键参数。 /***** do somthing *****/ } // Update shim paremeters for legacy clients if (effectiveApiLevel == API_1) { // Assume we have always received a Client subclass for API1 sp<Client> shimClient = reinterpret_cast<Client*>(client.get()); String8 rawParams = shimClient->getParameters(); CameraParameters params(rawParams); auto cameraState = getCameraState(cameraId); if (cameraState != nullptr) { cameraState->setShimParams(params); } else { ALOGE("%s: Cannot update shim parameters for camera %s, no such device exists.", __FUNCTION__, cameraId.string()); } } if (shimUpdateOnly) { // If only updating legacy shim parameters, immediately disconnect client mServiceLock.unlock(); client->disconnect(); mServiceLock.lock(); } else { // Otherwise, add client to active clients list finishConnectLocked(client, partial); } } // lock is destroyed, allow further connect calls // 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;
(4)frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp
status_t CameraClient::initialize(CameraModule *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);
/***** NOTE THIS *****/
mHardware = new CameraHardwareInterface(camera_device_name); //获取 CameraHardwareInterface
实例。
res = mHardware->initialize(module);
if (res != OK) {
ALOGE("%s: Camera %d: unable to initialize device: %s (%d)",
__FUNCTION__, mCameraId, strerror(-res), res);
mHardware.clear();
return res;
}
//设置三个回调函数(这里与数据流密切相关)
mHardware->setCallbacks(notifyCallback,
dataCallback,
dataCallbackTimestamp,
(void *)(uintptr_t)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;
}
6.HAL:frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
status_t initialize(CameraModule *module) { ALOGI("Opening camera %s", mName.string()); camera_info info; status_t res = module->getCameraInfo(atoi(mName.string()), &info); //通过module
,从HAL
层的库中调用相关的函数获取Camera
设备信息 if (res != OK) { return res; } int rc = OK; //根据模块API
的版本,判断是用open
函数还是用openLegacy,
调用open
后,通过HAL
库与Linux Kernel交互
if (module->getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_3 && info.device_version > CAMERA_DEVICE_API_VERSION_1_0) { // Open higher version camera device as HAL1.0 device. rc = module->openLegacy(mName.string(), CAMERA_DEVICE_API_VERSION_1_0, (hw_device_t **)&mDevice); } else { rc = module->open(mName.string(), (hw_device_t **)&mDevice); } if (rc != OK) { ALOGE("Could not open camera %s: %d", mName.string(), rc); return rc; } initHalPreviewWindow(); return rc; }
至此, Camera1的Open
调用流程分析完毕。
三、Camera hw_get_module() 相关逻辑
本节由hw_get_module()
函数入手,去探究 Libraries
层是如何调用 HAL
层的库中的函数的,CameraService
是在开机时就会启动,会调用一个名为 onFirstRef()
的成员函数,下面就从这里开始分析。
1. CameraService:framework/av/services/camera/libcameraservice/CameraService.cpp
BnCameraService::onFirstRef(); //首先调用其基类的onFirstRef
函数 // Update battery life tracking if service is restarting BatteryNotifier& notifier(BatteryNotifier::getInstance()); //更新notifier
(从BatteryNotifier
看应该跟电池有关,估计是检测电池电量过低就不开启闪光灯或者相机)。 notifier.noteResetCamera(); notifier.noteResetFlashlight(); camera_module_t *rawModule; /*** NOTE THIS ***/ int err = hw_get_module(CAMERA_HARDWARE_MODULE_ID, //通过hw_get_module
函数获取rawModule
。 (const hw_module_t **)&rawModule); if (err < 0) { ALOGE("Could not load camera HAL module: %d (%s)", err, strerror(-err)); logServiceError("Could not load camera HAL module", err); return; } /*** NOTE THIS ***/ mModule = new CameraModule(rawModule); //利用rawModule
创建mModule
的实例,mModule
是CameraModule
类。 err = mModule->init();
2. hardware:
(1)hardware/libhardware/include/hardware/hardware.h
/** * 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"
/** * Get the module info associated with a module by id. * * @return: 0 == success, <0 == error and *module == NULL */ int hw_get_module(const char *id, const struct hw_module_t **module); //作用是通过传入的id
来获取模块相关的信息(成功则返回0
,出错则返回值小于0
且*module == NULL
) /** * Get the module info associated with a module instance by class 'class_id' * and instance 'inst'. * * Some modules types necessitate multiple instances. For example audio supports * multiple concurrent interfaces and thus 'audio' is the module class * and 'primary' or 'a2dp' are module interfaces. This implies that the files * providing these modules would be named audio.primary.<variant>.so and * audio.a2dp.<variant>.so * * @return: 0 == success, <0 == error and *module == NULL */ int hw_get_module_by_class(const char *class_id, const char *inst, //作用是通过class_id
获取与模块实例相关的信息。 const struct hw_module_t **module);
(2)hardware/libhardware/hardware.c
static const char *variant_keys[] = { "ro.hardware", /* This goes first so that it can pick up a different file on the emulator. */ "ro.product.board", "ro.board.platform", "ro.arch" };
int hw_get_module(const char *id, const struct hw_module_t **module) { return hw_get_module_by_class(id, NULL, module); //读取库文件,尝试的顺序是:ro.hardware、
} ... //通过ro.product.board、
ro.board.platform、
ro.arch、
default
load
函数加载模块。 /* First try a property specific to the class and possibly instance */ snprintf(prop_name, sizeof(prop_name), "ro.hardware.%s", name); if (property_get(prop_name, prop, NULL) > 0) { if (hw_module_exists(path, sizeof(path), name, prop) == 0) { goto found; } } /* Loop through the configuration variants looking for a module */ for (i=0 ; i<HAL_VARIANT_KEYS_COUNT; i++) { if (property_get(variant_keys[i], prop, NULL) == 0) { continue; } if (hw_module_exists(path, sizeof(path), name, prop) == 0) { goto found; } } /* Nothing found, try the default */ if (hw_module_exists(path, sizeof(path), name, "default") == 0) { goto found; } return -ENOENT; found: /* load the module, if this fails, we're doomed, and we should not try * to load a different variant. */ /*** NOTE THIS ***/ return load(class_id, path, module);
load()
:
NOTE:
为了获取动态链接库中的结构体,我们需要用到一个字符串 sym,sym 对应宏 HAL_MODULE_INFO_SYM_AS_STR,即 “HMI”。
动态链接库 .so 文件,是一个 ELF 文件。
ELF:Executable and Linkable Format,可执行链接格式,ELF 文件头保存了一个路线图,用于描述文件的组织结构。
通过 readelf -s 命令,我们可以查看对应的 .so 文件描述,可以看到其中有一个 Name 属性为 HMI ,其对应的位置就是我们所需要的结构体 hw_module_t。
于是通过 HMI 字段,就可以从动态链接库中读取出相应的结构体,从而得以在 Libraries 层中调用 HAL 层的库函数。
static int load(const char *id, const char *path, const struct hw_module_t **pHmi) { int status = -EINVAL; void *handle = NULL; struct hw_module_t *hmi = NULL; /* * 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 */ /*** NOTE THIS ***/ handle = dlopen(path, RTLD_NOW); //调用dlopen()
函数获取一个handle
。 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. */ /*** NOTE THIS ***/ const char *sym = HAL_MODULE_INFO_SYM_AS_STR; hmi = (struct hw_module_t *)dlsym(handle, sym); //调用dlsym()
函数从动态链接库中获取hw_module_t
类型的hmi
。 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; /*** NOTE THIS ***/ 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; }
至此,获得了最终的 rawModule
,然后回到 onFirstRef()
中继续分析。
3. CameraModule:
(1)frameworks/av/services/camera/libcameraservice/common/CameraModule.cpp
CameraModule::CameraModule(camera_module_t *module) { if (module == NULL) { ALOGE("%s: camera hardware module must not be null", __FUNCTION__); assert(0); } mModule = module; //mModule
是camera_module_t
类型。 }
init()
:
- 调用
mModule
的init()
函数。 - 如果没有指定的
init()
函数,则init
流程到这里就可以结束了。
int CameraModule::init() { ATRACE_CALL(); int res = OK; if (getModuleApiVersion() >= CAMERA_MODULE_API_VERSION_2_4 && mModule->init != NULL) { ATRACE_BEGIN("camera_module->init"); res = mModule->init(); ATRACE_END(); } mCameraInfoMap.setCapacity(getNumberOfCameras()); return res; }
(2)相关代码:
hardware/libhardware/include/hardware/camera_common.h hardware/qcom/camera/QCamera2/QCamera2Factory.h hardware/qcom/camera/QCamera2/QCamera2Factory.cpp hardware/qcom/camera/QCamera2/QCamera2Hal.cpp
简图总结:
上面从 CameraService::onFirstRef() 入手,逐渐理顺了以 hw_get_module() 为中心的一个调用逻辑。实际上,Android HAL 层有一个通用的入口,即宏 HAL_MODULE_INFO_SYM,通过它,可以获取 HAL 层中的模块实例,从而调用 HAL 层所提供的函数。理解了 HAL 层的入口,接下来就可以去对 Camera.startPreview() 的控制流程进行分析,从而再次加深对 Camera 控制流的理解。
四、Camera.startPreview()流程
1.Frameworks:frameworks/base/core/java/android/hardware/Camera.java
/** * Starts capturing and drawing preview frames to the screen. * Preview will not actually start until a surface is supplied * with {@link #setPreviewDisplay(SurfaceHolder)} or * {@link #setPreviewTexture(SurfaceTexture)}. * * <p>If {@link #setPreviewCallback(Camera.PreviewCallback)}, * {@link #setOneShotPreviewCallback(Camera.PreviewCallback)}, or * {@link #setPreviewCallbackWithBuffer(Camera.PreviewCallback)} were * called, {@link Camera.PreviewCallback#onPreviewFrame(byte[], Camera)} * will be called when preview data becomes available. */ public native final void startPreview(); //给上层 application 提供一个接口, 进入 Runtime 层。
2.Android Runtime:frameworks/base/core/jni/android_hardware_Camera.cpp
static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz) { ALOGV("startPreview"); sp<Camera> camera = get_native_camera(env, thiz, NULL); //调用get_native_camera()
函数获取一个Camera
实例。 if (camera == 0) return; if (camera->startPreview() != NO_ERROR) { jniThrowRuntimeException(env, "startPreview failed"); return; } }
sp<Camera> get_native_camera(JNIEnv *env, jobject thiz, JNICameraContext** pContext) { sp<Camera> camera; Mutex::Autolock _l(sLock); JNICameraContext* context = reinterpret_cast<JNICameraContext*>(env->GetLongField(thiz, fields.context)); //从DVM
中获取关于Camera
的上下文。 if (context != NULL) { camera = context->getCamera(); //从上下文信息中获取Camera
实例。 } ALOGV("get_native_camera: context=%p, camera=%p", context, camera.get()); if (camera == 0) { jniThrowRuntimeException(env, "Camera is being used after Camera.release() was called"); } if (pContext != NULL) *pContext = context; return camera; }
3. Libraries:
(1)frameworks/av/camera/Camera.cpp
// start preview mode status_t Camera::startPreview() { ALOGV("startPreview"); sp <::android::hardware::ICamera> c = mCamera; //mCamera
即是在connect
过程中返回的CameraClient
,它具体实现了startPreview()
接口。 if (c == 0) return NO_INIT; return c->startPreview(); }
(2)frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp
// start preview mode
status_t CameraClient::startPreview() {
LOG1("startPreview (pid %d)", getCallingPid());
return startCameraMode(CAMERA_PREVIEW_MODE); //通过 startCameraMode
函数进入具体的实现逻辑。
}
startCameraMode()
:
// start preview or recording status_t CameraClient::startCameraMode(camera_mode mode) { //根据传入的参数CAMERA_PREVIEW_MODE
确定进入的分支。 LOG1("startCameraMode(%d)", mode); Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; switch(mode) { case CAMERA_PREVIEW_MODE: if (mSurface == 0 && mPreviewWindow == 0) { LOG1("mSurface is not set yet."); // still able to start preview in this case. } return startPreviewMode();//调用startPreviewMode()
。 case CAMERA_RECORDING_MODE: if (mSurface == 0 && mPreviewWindow == 0) { ALOGE("mSurface or mPreviewWindow must be set before startRecordingMode."); return INVALID_OPERATION; } return startRecordingMode(); default: return UNKNOWN_ERROR; } }
startPreviewMode()
:
status_t CameraClient::startPreviewMode() { LOG1("startPreviewMode"); status_t result = NO_ERROR; // if preview has been enabled, nothing needs to be done if (mHardware->previewEnabled()) { return NO_ERROR; //如果预览已经存在,则直接返回成功信息。 } if (mPreviewWindow != 0) { mHardware->setPreviewScalingMode( //mHardware
是CameraHardwareInterface
的实例,在connect
过程的最后被初始化。 NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW); mHardware->setPreviewTransform(mOrientation); } mHardware->setPreviewWindow(mPreviewWindow); //通过mHardware
调用setPreviewWindow()
和startPreview()
接口。 result = mHardware->startPreview(); if (result == NO_ERROR) { mCameraService->updateProxyDeviceState( //进入HAL
层。 ICameraServiceProxy::CAMERA_STATE_ACTIVE, String8::format("%d", mCameraId)); } return result; }
4. HAL:
(1)frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
/** * Returns true if preview is enabled. */ int previewEnabled() { ALOGV("%s(%s)", __FUNCTION__, mName.string()); if (mDevice->ops->preview_enabled) //mDevice
即是通过hw_get_module()
相关流程进行初始化的设备实例,它的类型是camera_device_t
。 return mDevice->ops->preview_enabled(mDevice); //如果preview
存在,则返回true
。 return false; }
setPreviewWindow()
:
/** 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) { //通过 mDevice->ops
继续向下调用
mPreviewWindow = buf;
if (buf != nullptr) {
if (mPreviewScalingMode != NOT_SET) {
setPreviewScalingMode(mPreviewScalingMode);
}
if (mPreviewTransform != NOT_SET) {
setPreviewTransform(mPreviewTransform);
}
}
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;
}
startPreview()
:
/** 关于 mDevice,结合 Camera.open() 流程与 hw_get_module() 相关逻辑,可以知道它的逻辑是这样的: 在 CameraService 启动时,会调用 onFirstRef() 对 module 进行初始化,获取 module 实例。 在 open 过程中,CameraClient 连接 CameraServer 成功时,会实例化 CameraHardwareInterface,并传入 module 实例对其初始化。 在初始化过程中,通过 module 实例对应的 open 方法,我们获得一个 device 实例,即 mDevice,这对应了具体的摄像头设备。 通过 mDevice 就可以将对应的指令传达到硬件设备。 */ status_t startPreview() { ALOGV("%s(%s)", __FUNCTION__, mName.string()); if (mDevice->ops->start_preview) return mDevice->ops->start_preview(mDevice); return INVALID_OPERATION; }
(2)hardware/libhardware/include/hardware/camera.h
typedef struct camera_device { //这里就声明了要追踪的 camera_device_t
。
/**
* camera_device.common.version must be in the range
* HARDWARE_DEVICE_API_VERSION(0,0)-(1,FF). CAMERA_DEVICE_API_VERSION_1_0 is
* recommended.
*/
hw_device_t common;
camera_device_ops_t *ops;
void *priv;
} camera_device_t;
其中struct camera_device_ops:所有关于
Camera
设备的操作对应的函数指针都在这里声明了。
typedef struct camera_device_ops { int (*set_preview_window)(struct camera_device *, struct preview_stream_ops *window); void (*set_callbacks)(struct camera_device *, camera_notify_callback notify_cb, camera_data_callback data_cb, camera_data_timestamp_callback data_cb_timestamp, camera_request_memory get_memory, void *user); void (*enable_msg_type)(struct camera_device *, int32_t msg_type); void (*disable_msg_type)(struct camera_device *, int32_t msg_type); int (*msg_type_enabled)(struct camera_device *, int32_t msg_type); /** * Start preview mode. */ int (*start_preview)(struct camera_device *); void (*stop_preview)(struct camera_device *); int (*preview_enabled)(struct camera_device *); int (*store_meta_data_in_buffers)(struct camera_device *, int enable); int (*start_recording)(struct camera_device *); void (*stop_recording)(struct camera_device *); int (*recording_enabled)(struct camera_device *); void (*release_recording_frame)(struct camera_device *, const void *opaque); int (*auto_focus)(struct camera_device *); int (*cancel_auto_focus)(struct camera_device *); int (*take_picture)(struct camera_device *); int (*cancel_picture)(struct camera_device *); int (*set_parameters)(struct camera_device *, const char *parms); char *(*get_parameters)(struct camera_device *); void (*put_parameters)(struct camera_device *, char *); int (*send_command)(struct camera_device *, int32_t cmd, int32_t arg1, int32_t arg2); void (*release)(struct camera_device *); int (*dump)(struct camera_device *, int fd); } camera_device_ops_t;
(3)hardware/ti/omap4-aah/camera/CameraHal_Module.cpp
:
在
open
流程中,就指定了 ops
中指针的对应关系。
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; // -------- TI specific stuff -------- camera_device->cameraid = cameraid;
camera_start_preview()
:
int camera_start_preview(struct camera_device * device) { CAMHAL_LOG_MODULE_FUNCTION_NAME; int rv = -EINVAL; ti_camera_device_t* ti_dev = NULL; if(!device) return rv; ti_dev = (ti_camera_device_t*) device; rv = gCameraHals[ti_dev->cameraid]->startPreview(); //gCameraHals
是CameraHal *
。 return rv; }
(4)hardware/ti/omap4-aah/camera/CameraHal.cpp : 将
Camera Hardware Interface
映射到 V4L2
。
status_t CameraHal::startPreview() { LOG_FUNCTION_NAME; status_t ret = cameraPreviewInitialization(); //首先调用了cameraPreviewInitialization()
函数进行初始化。 if (!mPreviewInitializationDone) return ret; mPreviewInitializationDone = false; if(mDisplayAdapter.get() != NULL) { CAMHAL_LOGDA("Enabling display"); int width, height; mParameters.getPreviewSize(&width, &height); #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS ret = mDisplayAdapter->enableDisplay(width, height, &mStartPreview); #else ret = mDisplayAdapter->enableDisplay(width, height, NULL); #endif if ( ret != NO_ERROR ) { CAMHAL_LOGEA("Couldn't enable display"); CAMHAL_ASSERT_X(false, "At this stage mCameraAdapter->mStateSwitchLock is still locked, " "deadlock is guaranteed"); goto error; } } CAMHAL_LOGDA("Starting CameraAdapter preview mode"); ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_START_PREVIEW); //通过CameraAdapter
发送CAMERA_START_PREVIEW
指令,若成功执行,则完成流程。 if(ret!=NO_ERROR) { CAMHAL_LOGEA("Couldn't start preview w/ CameraAdapter"); goto error; } CAMHAL_LOGDA("Started preview"); mPreviewEnabled = true; mPreviewStartInProgress = false; return ret; error: CAMHAL_LOGEA("Performing cleanup after error"); //Do all the cleanup freePreviewBufs(); mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW); if(mDisplayAdapter.get() != NULL) { mDisplayAdapter->disableDisplay(false); } mAppCallbackNotifier->stop(); mPreviewStartInProgress = false; mPreviewEnabled = false; LOG_FUNCTION_NAME_EXIT; return ret; }
cameraPreviewInitialization()
:
- 代码中不断使用
mCameraAdapter->sendCommand()
来发送指令,并获取一些数据。 - 指令发送到对应的
Adapter
(如V4L Adapter
),就会调用相应的函数进行处理。
//////////// /** @brief Set preview mode related initialization -> Camera Adapter set params -> Allocate buffers -> Set use buffers for preview @param none @return NO_ERROR @todo Update function header with the different errors that are possible */ status_t CameraHal::cameraPreviewInitialization() { status_t ret = NO_ERROR; CameraAdapter::BuffersDescriptor desc; CameraFrame frame; unsigned int required_buffer_count; unsigned int max_queueble_buffers; #if PPM_INSTRUMENTATION || PPM_INSTRUMENTATION_ABS gettimeofday(&mStartPreview, NULL); #endif LOG_FUNCTION_NAME; if (mPreviewInitializationDone) { return NO_ERROR; } if ( mPreviewEnabled ){ CAMHAL_LOGDA("Preview already running"); LOG_FUNCTION_NAME_EXIT; return ALREADY_EXISTS; } if ( NULL != mCameraAdapter ) { ret = mCameraAdapter->setParameters(mParameters); //通过Adapter
设置相关参数; } if ((mPreviewStartInProgress == false) && (mDisplayPaused == false)){ ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW,( int ) &frame); if ( NO_ERROR != ret ){ CAMHAL_LOGEB("Error: CAMERA_QUERY_RESOLUTION_PREVIEW %d", ret); return ret; } ///Update the current preview width and height mPreviewWidth = frame.mWidth; mPreviewHeight = frame.mHeight; } ///If we don't have the preview callback enabled and display adapter, if(!mSetPreviewWindowCalled || (mDisplayAdapter.get() == NULL)){ CAMHAL_LOGD("Preview not started. Preview in progress flag set"); mPreviewStartInProgress = true; ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_SWITCH_TO_EXECUTING); if ( NO_ERROR != ret ){ CAMHAL_LOGEB("Error: CAMERA_SWITCH_TO_EXECUTING %d", ret); return ret; } return NO_ERROR; } if( (mDisplayAdapter.get() != NULL) && ( !mPreviewEnabled ) && ( mDisplayPaused ) ) { CAMHAL_LOGDA("Preview is in paused state"); mDisplayPaused = false; mPreviewEnabled = true; if ( NO_ERROR == ret ) { ret = mDisplayAdapter->pauseDisplay(mDisplayPaused); if ( NO_ERROR != ret ) { CAMHAL_LOGEB("Display adapter resume failed %x", ret); } } //restart preview callbacks if(mMsgEnabled & CAMERA_MSG_PREVIEW_FRAME) { mAppCallbackNotifier->enableMsgType (CAMERA_MSG_PREVIEW_FRAME); } signalEndImageCapture(); return ret; } required_buffer_count = atoi(mCameraProperties->get(CameraProperties::REQUIRED_PREVIEW_BUFS)); ///Allocate the preview buffers ret = allocPreviewBufs(mPreviewWidth, mPreviewHeight, mParameters.getPreviewFormat(), required_buffer_count, max_queueble_buffers); //申请Buffers
空间; if ( NO_ERROR != ret ) { CAMHAL_LOGEA("Couldn't allocate buffers for Preview"); goto error; } if ( mMeasurementEnabled ) { ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA, ( int ) &frame, required_buffer_count); if ( NO_ERROR != ret ) { return ret; } ///Allocate the preview data buffers ret = allocPreviewDataBufs(frame.mLength, required_buffer_count); if ( NO_ERROR != ret ) { CAMHAL_LOGEA("Couldn't allocate preview data buffers"); goto error; } if ( NO_ERROR == ret ) { //在申请Buffers
空间成功后设置相应的成员。 desc.mBuffers = mPreviewDataBuffers; desc.mOffsets = mPreviewDataOffsets; desc.mFd = mPreviewDataFd; desc.mLength = mPreviewDataLength; desc.mCount = ( size_t ) required_buffer_count; desc.mMaxQueueable = (size_t) required_buffer_count; mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW_DATA, ( int ) &desc); } } ///Pass the buffers to Camera Adapter desc.mBuffers = mPreviewBuffers; desc.mOffsets = mPreviewOffsets; desc.mFd = mPreviewFd; desc.mLength = mPreviewLength; desc.mCount = ( size_t ) required_buffer_count; desc.mMaxQueueable = (size_t) max_queueble_buffers; ret = mCameraAdapter->sendCommand(CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW, ( int ) &desc); if ( NO_ERROR != ret ) { CAMHAL_LOGEB("Failed to register preview buffers: 0x%x", ret); freePreviewBufs(); return ret; } ///Start the callback notifier ret = mAppCallbackNotifier->start(); //开启回调通知。 if( ALREADY_EXISTS == ret ) { //Already running, do nothing CAMHAL_LOGDA("AppCallbackNotifier already running"); ret = NO_ERROR; } else if ( NO_ERROR == ret ) { CAMHAL_LOGDA("Started AppCallbackNotifier.."); mAppCallbackNotifier->setMeasurements(mMeasurementEnabled); } else { CAMHAL_LOGDA("Couldn't start AppCallbackNotifier"); goto error; } if (ret == NO_ERROR) mPreviewInitializationDone = true; //将Buffers
对应到相应的回调函数中,以供上层APP
获取预览所需的数据。 mAppCallbackNotifier->startPreviewCallbacks(mParameters, mPreviewBuffers, mPreviewOffsets, mPreviewFd, mPreviewLength, required_buffer_count); return ret; error: CAMHAL_LOGEA("Performing cleanup after error"); //Do all the cleanup freePreviewBufs(); mCameraAdapter->sendCommand(CameraAdapter::CAMERA_STOP_PREVIEW); if(mDisplayAdapter.get() != NULL) { mDisplayAdapter->disableDisplay(false); } mAppCallbackNotifier->stop(); mPreviewStartInProgress = false; mPreviewEnabled = false; LOG_FUNCTION_NAME_EXIT; return ret; }
(5)hardware/ti/omap4-aah/camera/BaseCameraAdapter.cpp : 各常量分别对应不同的命令。
const LUT cameraCommandsUserToHAL[] = { { "CAMERA_START_PREVIEW", CameraAdapter::CAMERA_START_PREVIEW }, { "CAMERA_STOP_PREVIEW", CameraAdapter::CAMERA_STOP_PREVIEW }, { "CAMERA_START_VIDEO", CameraAdapter::CAMERA_START_VIDEO }, { "CAMERA_STOP_VIDEO", CameraAdapter::CAMERA_STOP_VIDEO }, { "CAMERA_START_IMAGE_CAPTURE", CameraAdapter::CAMERA_START_IMAGE_CAPTURE }, { "CAMERA_STOP_IMAGE_CAPTURE", CameraAdapter::CAMERA_STOP_IMAGE_CAPTURE }, { "CAMERA_PERFORM_AUTOFOCUS", CameraAdapter::CAMERA_PERFORM_AUTOFOCUS }, { "CAMERA_CANCEL_AUTOFOCUS", CameraAdapter::CAMERA_CANCEL_AUTOFOCUS }, { "CAMERA_PREVIEW_FLUSH_BUFFERS", CameraAdapter::CAMERA_PREVIEW_FLUSH_BUFFERS }, { "CAMERA_START_SMOOTH_ZOOM", CameraAdapter::CAMERA_START_SMOOTH_ZOOM }, { "CAMERA_STOP_SMOOTH_ZOOM", CameraAdapter::CAMERA_STOP_SMOOTH_ZOOM }, { "CAMERA_USE_BUFFERS_PREVIEW", CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW }, { "CAMERA_SET_TIMEOUT", CameraAdapter::CAMERA_SET_TIMEOUT }, { "CAMERA_CANCEL_TIMEOUT", CameraAdapter::CAMERA_CANCEL_TIMEOUT }, { "CAMERA_START_BRACKET_CAPTURE", CameraAdapter::CAMERA_START_BRACKET_CAPTURE }, { "CAMERA_STOP_BRACKET_CAPTURE", CameraAdapter::CAMERA_STOP_BRACKET_CAPTURE }, { "CAMERA_QUERY_RESOLUTION_PREVIEW", CameraAdapter::CAMERA_QUERY_RESOLUTION_PREVIEW }, { "CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE", CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_IMAGE_CAPTURE }, { "CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA", CameraAdapter::CAMERA_QUERY_BUFFER_SIZE_PREVIEW_DATA }, { "CAMERA_USE_BUFFERS_IMAGE_CAPTURE", CameraAdapter::CAMERA_USE_BUFFERS_IMAGE_CAPTURE }, { "CAMERA_USE_BUFFERS_PREVIEW_DATA", CameraAdapter::CAMERA_USE_BUFFERS_PREVIEW_DATA }, { "CAMERA_TIMEOUT_EXPIRED", CameraAdapter::CAMERA_TIMEOUT_EXPIRED }, { "CAMERA_START_FD", CameraAdapter::CAMERA_START_FD }, { "CAMERA_STOP_FD", CameraAdapter::CAMERA_STOP_FD }, { "CAMERA_SWITCH_TO_EXECUTING", CameraAdapter::CAMERA_SWITCH_TO_EXECUTING }, { "CAMERA_USE_BUFFERS_VIDEO_CAPTURE", CameraAdapter::CAMERA_USE_BUFFERS_VIDEO_CAPTURE }, #ifdef OMAP_ENHANCEMENT_CPCAM { "CAMERA_USE_BUFFERS_REPROCESS", CameraAdapter::CAMERA_USE_BUFFERS_REPROCESS }, { "CAMERA_START_REPROCESS", CameraAdapter::CAMERA_START_REPROCESS }, #endif };
BaseCameraAdapter::sendCommand()
:利用 switch
将不同的命令对应到各自的逻辑中。
case CameraAdapter::CAMERA_START_PREVIEW: //BaseCameraAdapter::startPreview()
具体操作在其子类中实现,后面通过子类V4LCameraAdapter
继续分析。 { CAMHAL_LOGDA("Start Preview"); if ( ret == NO_ERROR ) { ret = setState(operation); } if ( ret == NO_ERROR ) { ret = startPreview(); } if ( ret == NO_ERROR ) { ret = commitState(); } else { ret |= rollbackState(); } break; }
(6)hardware/ti/omap4-aah/camera/inc/V4LCameraAdapter/V4LCameraAdapter.h
private: class PreviewThread : public android::Thread { V4LCameraAdapter* mAdapter; //类V4LCameraAdapter
继承了BaseCameraAdapter
public: PreviewThread(V4LCameraAdapter* hw) : //该线程不断执行Adapter
中的previewThread()
函数。 Thread(false), mAdapter(hw) { } virtual void onFirstRef() { run("CameraPreviewThread", android::PRIORITY_URGENT_DISPLAY); } virtual bool threadLoop() { mAdapter->previewThread(); // loop until we need to quit return true; } }; //Used for calculation of the average frame rate during preview status_t recalculateFPS(); char * GetFrame(int &index); int previewThread();
(7)hardware/ti/omap4-aah/camera/V4LCameraAdapter/V4LCameraAdapter.cpp
startPreview()
:
status_t V4LCameraAdapter::startPreview() { status_t ret = NO_ERROR; LOG_FUNCTION_NAME; android::AutoMutex lock(mPreviewBufsLock); if(mPreviewing) { ret = BAD_VALUE; goto EXIT; } for (int i = 0; i < mPreviewBufferCountQueueable; i++) { mVideoInfo->buf.index = i; mVideoInfo->buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; mVideoInfo->buf.memory = V4L2_MEMORY_MMAP; ret = v4lIoctl(mCameraHandle, VIDIOC_QBUF, &mVideoInfo->buf); //通过v4lIoctl()
函数从硬件获取需要的数据,并存入Buffers
。 if (ret < 0) { CAMHAL_LOGEA("VIDIOC_QBUF Failed"); goto EXIT; } nQueued++; } ret = v4lStartStreaming();// Create and start preview thread for receiving buffers from V4L Camera if(!mCapturing) { mPreviewThread = new PreviewThread(this); //启动一个PreviewThread
,用于接收从V4L
摄像头设备传回的数据。 CAMHAL_LOGDA("Created preview thread"); } //Update the flag to indicate we are previewing(设置标志,
表明预览功能已开启) mPreviewing = true; mCapturing = false; EXIT: LOG_FUNCTION_NAME_EXIT; return ret; }
previewThread()
:
int V4LCameraAdapter::previewThread() { status_t ret = NO_ERROR; int width, height; CameraFrame frame; void *y_uv[2]; int index = 0; int stride = 4096; char *fp = NULL; mParams.getPreviewSize(&width, &height); if (mPreviewing) { fp = this->GetFrame(index); if(!fp) { ret = BAD_VALUE; goto EXIT; } CameraBuffer *buffer = mPreviewBufs.keyAt(index); CameraFrame *lframe = (CameraFrame *)mFrameQueue.valueFor(buffer); if (!lframe) { ret = BAD_VALUE; goto EXIT; } debugShowFPS(); if ( mFrameSubscribers.size() == 0 ) { ret = BAD_VALUE; goto EXIT; } y_uv[0] = (void*) lframe->mYuv[0]; //y_uv[1] = (void*) lframe->mYuv[1]; //y_uv[1] = (void*) (lframe->mYuv[0] + height*stride); convertYUV422ToNV12Tiler ( (unsigned char*)fp, (unsigned char*)y_uv[0], width, height); //获取设备传回的数据,并进行一些格式转换操作. CAMHAL_LOGVB("##...index= %d.;camera buffer= 0x%x; y= 0x%x; UV= 0x%x.",index, buffer, y_uv[0], y_uv[1] ); #ifdef SAVE_RAW_FRAMES unsigned char* nv12_buff = (unsigned char*) malloc(width*height*3/2); //Convert yuv422i to yuv420sp(NV12) & dump the frame to a file convertYUV422ToNV12 ( (unsigned char*)fp, nv12_buff, width, height); saveFile( nv12_buff, ((width*height)*3/2) ); free (nv12_buff); #endif //给帧数据进行一些必要的参数设置,如帧大小、时间戳等。 frame.mFrameType = CameraFrame::PREVIEW_FRAME_SYNC; frame.mBuffer = buffer; frame.mLength = width*height*3/2; frame.mAlignment = stride; frame.mOffset = 0; frame.mTimestamp = systemTime(SYSTEM_TIME_MONOTONIC); frame.mFrameMask = (unsigned int)CameraFrame::PREVIEW_FRAME_SYNC; if (mRecording) { frame.mFrameMask |= (unsigned int)CameraFrame::VIDEO_FRAME_SYNC; mFramesWithEncoder++; } ret = setInitFrameRefCount(frame.mBuffer, frame.mFrameMask); if (ret != NO_ERROR) { CAMHAL_LOGDB("Error in setInitFrameRefCount %d", ret); } else { ret = sendFrameToSubscribers(&frame); //将帧数据发送给用户 } } EXIT: return ret; }
(8)hardware/ti/omap4-aah/camera/AppCallbackNotifier.cpp:预览功能初始化的部分,调用到了
AppCallbackNotifier
类的函数。
status_t AppCallbackNotifier::startPreviewCallbacks(android::CameraParameters ¶ms, CameraBuffer *buffers, uint32_t *offsets, int fd, size_t length, size_t count) { unsigned int *bufArr; int size = 0; LOG_FUNCTION_NAME; android::AutoMutex lock(mLock); if ( NULL == mFrameProvider ) { CAMHAL_LOGEA("Trying to start video recording without FrameProvider"); return -EINVAL; } if ( mPreviewing ) { CAMHAL_LOGDA("+Already previewing"); return NO_INIT; } int w,h; ///Get preview size params.getPreviewSize(&w, &h); // save preview pixel format, size and stride mPreviewWidth = w; mPreviewHeight = h; mPreviewStride = 4096; mPreviewPixelFormat = CameraHal::getPixelFormatConstant(params.getPreviewFormat()); size = CameraHal::calculateBufferSize(mPreviewPixelFormat, w, h); mPreviewMemory = mRequestMemory(-1, size, AppCallbackNotifier::MAX_BUFFERS, NULL); if (!mPreviewMemory) { return NO_MEMORY; } for (int i=0; i < AppCallbackNotifier::MAX_BUFFERS; i++) { mPreviewBuffers[i].type = CAMERA_BUFFER_MEMORY; mPreviewBuffers[i].opaque = (unsigned char*) mPreviewMemory->data + (i*size); mPreviewBuffers[i].mapped = mPreviewBuffers[i].opaque; } if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_FRAME ) ) { mFrameProvider->enableFrameNotification(CameraFrame::PREVIEW_FRAME_SYNC); } if ( mCameraHal->msgTypeEnabled(CAMERA_MSG_POSTVIEW_FRAME) ) { mFrameProvider->enableFrameNotification(CameraFrame::SNAPSHOT_FRAME); //同步预览帧 } mPreviewBufCount = 0; mPreviewing = true; LOG_FUNCTION_NAME_EXIT; return NO_ERROR; }
以上回调函数在这里设置:
void AppCallbackNotifier::setCallbacks(CameraHal* cameraHal, camera_notify_callback notify_cb, camera_data_callback data_cb, camera_data_timestamp_callback data_cb_timestamp, camera_request_memory get_memory, void *user) { android::AutoMutex lock(mLock); LOG_FUNCTION_NAME; mCameraHal = cameraHal; mNotifyCb = notify_cb; mDataCb = data_cb; mDataCbTimestamp = data_cb_timestamp; mRequestMemory = get_memory; mCallbackCookie = user; LOG_FUNCTION_NAME_EXIT; }
notifyEvent()
:
case CameraHalEvent::EVENT_METADATA: //预览元数据 metaEvtData = evt->mEventData->metadataEvent; if ( ( NULL != mCameraHal ) && ( NULL != mNotifyCb) && ( mCameraHal->msgTypeEnabled(CAMERA_MSG_PREVIEW_METADATA) ) ) { // WA for an issue inside CameraService camera_memory_t *tmpBuffer = mRequestMemory(-1, 1, 1, NULL); //申请一个camera_memory_t
对应的Buffers
空间后,就调用回调函数将元数据往上层进行传输了。 mDataCb(CAMERA_MSG_PREVIEW_METADATA, tmpBuffer, 0, metaEvtData->getMetadataResult(), mCallbackCookie); metaEvtData.clear(); if ( NULL != tmpBuffer ) { tmpBuffer->release(tmpBuffer); } } break;
简图总结: HAL
层中,CameraHardwareInterface
是通用的入口,而真正实现与驱动层的对接是与平台相关,不同平台有不同的实现方案。
五、Camera.takePicture()流程
Camera API 1
中,数据流主要是通过函数回调的方式,依照从下往上的方向,逐层 return
到 Applications 中。
1.Open 时设置回调:frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
/** Set the notification and data callbacks */ void setCallbacks(notify_callback notify_cb, data_callback data_cb, data_callback_timestamp data_cb_timestamp, void* user) { mNotifyCb = notify_cb; //设置notify
回调,这用来通知数据已经更新。 mDataCb = data_cb; //置data
回调以及dataTimestamp
回调,对应的是函数指针mDataCb
与mDataCvTimestamp
。 mDataCbTimestamp = data_cb_timestamp; mCbUser = user; ALOGV("%s(%s)", __FUNCTION__, mName.string()); if (mDevice->ops->set_callbacks) { //注:设置mDevice->ops
对应回调函数时,传入的不是之前设置的函数指针,而是__data_cb
这样的函数。在该文件中,实现了__data_cb
,将回调函数做了一层封装。 mDevice->ops->set_callbacks(mDevice, __notify_cb, __data_cb, __data_cb_timestamp, __get_memory, this); } }
__data_cb()
:对原 callback
函数简单封装,附加了一个防止数组越界判断。
static void __data_cb(int32_t msg_type, const camera_memory_t *data, unsigned int index, camera_frame_metadata_t *metadata, void *user) { ALOGV("%s", __FUNCTION__); CameraHardwareInterface *__this = static_cast<CameraHardwareInterface *>(user); sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle)); if (index >= mem->mNumBufs) { ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__, index, mem->mNumBufs); return; } __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser); }
2.控制流:
(1)frameworks/base/core/java/android/hardware/Camera.java
takePicture()
:
public final void takePicture(ShutterCallback shutter, PictureCallback raw, PictureCallback postview, PictureCallback jpeg) { mShutterCallback = shutter; //设置快门回调。 mRawImageCallback = raw; //设置各种类型的图片数据回调。 mPostviewCallback = postview; mJpegCallback = jpeg; // If callback is not set, do not send me callbacks. int msgType = 0; if (mShutterCallback != null) { msgType |= CAMERA_MSG_SHUTTER; } if (mRawImageCallback != null) { msgType |= CAMERA_MSG_RAW_IMAGE; } if (mPostviewCallback != null) { msgType |= CAMERA_MSG_POSTVIEW_FRAME; } if (mJpegCallback != null) { msgType |= CAMERA_MSG_COMPRESSED_IMAGE; } native_takePicture(msgType); //调用JNI takePicture
方法,传入的参数msgType
是根据相应CallBack
是否存在而确定的,每种Callback
应该对应一个二进制中的数位(如 1,10,100 中 1 的位置) mFaceDetectionRunning = false; }
3.Android Runtime:frameworks/base/core/jni/android_hardware_Camera.cpp
static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz, jint msgType) { ALOGV("takePicture"); JNICameraContext* context; sp<Camera> camera = get_native_camera(env, thiz, &context); //获取已经打开的camera
实例,调用其takePicture()
接口。 if (camera == 0) return; /* * When CAMERA_MSG_RAW_IMAGE is requested, if the raw image callback * buffer is available, CAMERA_MSG_RAW_IMAGE is enabled to get the * notification _and_ the data; otherwise, CAMERA_MSG_RAW_IMAGE_NOTIFY * is enabled to receive the callback notification but no data. * * Note that CAMERA_MSG_RAW_IMAGE_NOTIFY is not exposed to the * Java application. * 注意,在这个函数中,对于 RAW_IMAGE 有一些附加操作: 如果设置了 RAW 的 callback ,则要检查上下文中,是否能找到对应 Buffer。 若无法找到 Buffer ,则将 CAMERA_MSG_RAW_IMAGE 的信息去掉,换成 CAMERA_MSG_RAW_IMAGE_NOTIFY。 替换后,就只会获得 notification 的消息,而没有对应的图像数据。 */ if (msgType & CAMERA_MSG_RAW_IMAGE) { ALOGV("Enable raw image callback buffer"); if (!context->isRawImageCallbackBufferAvailable()) { ALOGV("Enable raw image notification, since no callback buffer exists"); msgType &= ~CAMERA_MSG_RAW_IMAGE; msgType |= CAMERA_MSG_RAW_IMAGE_NOTIFY; } } if (camera->takePicture(msgType) != NO_ERROR) { jniThrowRuntimeException(env, "takePicture failed"); return; } }
4.C/C++ Libraries
(1)frameworks/av/camera/Camera.cpp
// take a picture status_t Camera::takePicture(int msgType) { ALOGV("takePicture: 0x%x", msgType); sp <::android::hardware::ICamera> c = mCamera; if (c == 0) return NO_INIT; return c->takePicture(msgType); //获取一个ICamera
,调用其takePicture
接口。 }
(2)frameworks/av/camera/ICamera.cpp
// take a picture - returns an IMemory (ref-counted mmap) status_t takePicture(int msgType) { ALOGV("takePicture: 0x%x", msgType); Parcel data, reply; data.writeInterfaceToken(ICamera::getInterfaceDescriptor()); data.writeInt32(msgType); remote()->transact(TAKE_PICTURE, data, &reply); //利用Binder
机制发送相应指令到服务端,实际调用到的是CameraClient::takePicture()
函数。 status_t ret = reply.readInt32(); return ret; }
(3)frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp
// take a picture - image is returned in callback status_t CameraClient::takePicture(int msgType) { LOG1("takePicture (pid %d): 0x%x", getCallingPid(), msgType); Mutex::Autolock lock(mLock); status_t result = checkPidAndHardware(); if (result != NO_ERROR) return result; if ((msgType & CAMERA_MSG_RAW_IMAGE) && //注:CAMERA_MSG_RAW_IMAGE
指令与CAMERA_MSG_RAW_IMAGE_NOTIFY
指令不能同时有效,需要进行对应的检查。 (msgType & CAMERA_MSG_RAW_IMAGE_NOTIFY)) { ALOGE("CAMERA_MSG_RAW_IMAGE and CAMERA_MSG_RAW_IMAGE_NOTIFY" " cannot be both enabled"); return BAD_VALUE; } // We only accept picture related message types // and ignore other types of messages for takePicture(). int picMsgType = msgType //对传入的指令过滤,只留下与takePicture()
操作相关的。 & (CAMERA_MSG_SHUTTER | CAMERA_MSG_POSTVIEW_FRAME | CAMERA_MSG_RAW_IMAGE | CAMERA_MSG_RAW_IMAGE_NOTIFY | CAMERA_MSG_COMPRESSED_IMAGE); enableMsgType(picMsgType); return mHardware->takePicture(); //调用CameraHardwareInterface
中的takePicture()
接口。 }
5.数据流:由于数据流是通过 callback
函数实现的,所以探究其流程的时候我是从底层向上层进行分析的
(1)HAL:frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
/** * Take a picture. */ status_t takePicture() { ALOGV("%s(%s)", __FUNCTION__, mName.string()); if (mDevice->ops->take_picture) return mDevice->ops->take_picture(mDevice); //通过mDevice
中设置的函数指针,调用HAL
层中具体平台对应的takePicture
操作的实现逻辑。 return INVALID_OPERATION; }
__data_cb()
:该回调函数是在同文件中实现的 setCallbacks()
函数中设置的,Camera
设备获得数据后,就会往上传输,在 HAL
层中会调用到这个回调函数。
static void __data_cb(int32_t msg_type, const camera_memory_t *data, unsigned int index, camera_frame_metadata_t *metadata, void *user) { ALOGV("%s", __FUNCTION__); CameraHardwareInterface *__this = static_cast<CameraHardwareInterface *>(user); sp<CameraHeapMemory> mem(static_cast<CameraHeapMemory *>(data->handle)); if (index >= mem->mNumBufs) { ALOGE("%s: invalid buffer index %d, max allowed is %d", __FUNCTION__, index, mem->mNumBufs); return; } __this->mDataCb(msg_type, mem->mBuffers[index], metadata, __this->mCbUser); //mDataCb
指针对应的是CameraClient
类中实现的dataCallback()
。 }
(2)C/C++ Libraries:
frameworks/av/services/camera/libcameraservice/api1/CameraClient.cpp
void CameraClient::dataCallback(int32_t msgType, //该回调在initialize()
函数中设置到CameraHardwareInterface
中。 const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata, void* user) { LOG2("dataCallback(%d)", msgType); sp<CameraClient> client = static_cast<CameraClient*>(getClientFromCookie(user).get()); //启动这个回调后,就从Cookie
中获取已连接的客户端。 if (client.get() == nullptr) return; if (!client->lockIfMessageWanted(msgType)) return; if (dataPtr == 0 && metadata == NULL) { ALOGE("Null data returned in data callback"); client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); return; } switch (msgType & ~CAMERA_MSG_PREVIEW_METADATA) { //根据msgType
,启动对应的handle
操作。 case CAMERA_MSG_PREVIEW_FRAME: client->handlePreviewData(msgType, dataPtr, metadata); break; case CAMERA_MSG_POSTVIEW_FRAME: client->handlePostview(dataPtr); break; case CAMERA_MSG_RAW_IMAGE: client->handleRawPicture(dataPtr); break; case CAMERA_MSG_COMPRESSED_IMAGE: client->handleCompressedPicture(dataPtr); break; default: client->handleGenericData(msgType, dataPtr, metadata); break; } }
handleRawPicture()
:
// picture callback - raw image ready void CameraClient::handleRawPicture(const sp<IMemory>& mem) { disableMsgType(CAMERA_MSG_RAW_IMAGE); ssize_t offset; size_t size; sp<IMemoryHeap> heap = mem->getMemory(&offset, &size); sp<hardware::ICameraClient> c = mRemoteCallback; //在open
流程中,connect()
函数调用时,mRemoteCallback
已经设置为一个客户端实例,其对应的是ICameraClient
的强指针。 mLock.unlock(); if (c != 0) { c->dataCallback(CAMERA_MSG_RAW_IMAGE, mem, NULL); //基于Binder
机制来启动客户端的dataCallback
客户端的,dataCallback
是实现在Camera
类中。 } }
frameworks/av/camera/Camera.cpp
// callback from camera service when frame or image is ready void Camera::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) { sp<CameraListener> listener; { Mutex::Autolock _l(mLock); listener = mListener; } if (listener != NULL) { listener->postData(msgType, dataPtr, metadata); //调用CameraListener
的postData
接口(android_hardware_Camera.cpp
中实现),将数据继续向上传输。 } }
(3)Android Runtime :frameworks/base/core/jni/android_hardware_Camera.cpp
void JNICameraContext::postData(int32_t msgType, const sp<IMemory>& dataPtr, camera_frame_metadata_t *metadata) //postData是JNICameraContext
类的成员函数,该类继承了CameraListener
。 { // VM pointer will be NULL if object is released Mutex::Autolock _l(mLock); JNIEnv *env = AndroidRuntime::getJNIEnv(); //首先获取虚拟机指针 if (mCameraJObjectWeak == NULL) { ALOGW("callback on dead camera object"); return; } int32_t dataMsgType = msgType & ~CAMERA_MSG_PREVIEW_METADATA; //然后过滤掉CAMERA_MSG_PREVIEW_METADATA
信息 // return data based on callback type switch (dataMsgType) { case CAMERA_MSG_VIDEO_FRAME: // should never happen break; // For backward-compatibility purpose, if there is no callback // buffer for raw image, the callback returns null. case CAMERA_MSG_RAW_IMAGE: ALOGV("rawCallback"); if (mRawImageCallbackBuffers.isEmpty()) { env->CallStaticVoidMethod(mCameraJClass, fields.post_event, mCameraJObjectWeak, dataMsgType, 0, 0, NULL); } else { copyAndPost(env, dataPtr, dataMsgType); //关键是在于copyAndPost()
函数 } break; // There is no data. case 0: break; default: ALOGV("dataCallback(%d, %p)", dataMsgType, dataPtr.get()); copyAndPost(env, dataPtr, dataMsgType); break; } // post frame metadata to Java if (metadata && (msgType & CAMERA_MSG_PREVIEW_METADATA)) { postMetadata(env, CAMERA_MSG_PREVIEW_METADATA, metadata); } }
copyAndPost()
:
void JNICameraContext::copyAndPost(JNIEnv* env, const sp<IMemory>& dataPtr, int msgType) { jbyteArray obj = NULL; // allocate Java byte array and copy data if (dataPtr != NULL) { //首先确认Memory
中数据是否存在 ssize_t offset; size_t size; sp<IMemoryHeap> heap = dataPtr->getMemory(&offset, &size); ALOGV("copyAndPost: off=%zd, size=%zu", offset, size); uint8_t *heapBase = (uint8_t*)heap->base(); if (heapBase != NULL) { const jbyte* data = reinterpret_cast<const jbyte*>(heapBase + offset); if (msgType == CAMERA_MSG_RAW_IMAGE) { obj = getCallbackBuffer(env, &mRawImageCallbackBuffers, size); } else if (msgType == CAMERA_MSG_PREVIEW_FRAME && mManualBufferMode) { obj = getCallbackBuffer(env, &mCallbackBuffers, size); if (mCallbackBuffers.isEmpty()) { ALOGV("Out of buffers, clearing callback!"); mCamera->setPreviewCallbackFlags(CAMERA_FRAME_CALLBACK_FLAG_NOOP); mManualCameraCallbackSet = false; if (obj == NULL) { return; } } } else { ALOGV("Allocating callback buffer"); obj = env->NewByteArray(size); } if (obj == NULL) { ALOGE("Couldn't allocate byte array for JPEG data"); env->ExceptionClear(); } else { env->SetByteArrayRegion(obj, 0, size, data); } } else { ALOGE("image heap is NULL"); } } // post image data to Java env->CallStaticVoidMethod(mCameraJClass, fields.post_event, //将图像传给Java
端 mCameraJObjectWeak, msgType,0, 0, obj); if (obj) { env->DeleteLocalRef(obj); } }
(4)frameworks/base/core/java/android/hardware/Camera.java
private static void postEventFromNative(Object camera_ref, //继承了Handler
类 int what, int arg1, int arg2, Object obj) { Camera c = (Camera)((WeakReference)camera_ref).get(); //首先确定Camera
是否已经实例化。 if (c == null) return; if (c.mEventHandler != null) { Message m = c.mEventHandler.obtainMessage(what, arg1, arg2, obj); //通过Camera
的成员mEventHandler
的obtainMessage
方法将从Native
环境中获得的数据封装成Message
类的一个实例, c.mEventHandler.sendMessage(m); //然后调用sendMessage()
方法将数据传出。 } }
@Override public void handleMessage(Message msg) { //继承了Handler
类 switch(msg.what) { case CAMERA_MSG_SHUTTER: if (mShutterCallback != null) { mShutterCallback.onShutter(); } return; case CAMERA_MSG_RAW_IMAGE: if (mRawImageCallback != null) { mRawImageCallback.onPictureTaken((byte[])msg.obj, mCamera); } return; case CAMERA_MSG_COMPRESSED_IMAGE: if (mJpegCallback != null) { mJpegCallback.onPictureTaken((byte[])msg.obj, mCamera); } return; case CAMERA_MSG_PREVIEW_FRAME: PreviewCallback pCb = mPreviewCallback; if (pCb != null) { if (mOneShot) { // Clear the callback variable before the callback // in case the app calls setPreviewCallback from // the callback function mPreviewCallback = null; } else if (!mWithBuffer) { // We're faking the camera preview mode to prevent // the app from being flooded with preview frames. // Set to oneshot mode again. setHasPreviewCallback(true, false); } pCb.onPreviewFrame((byte[])msg.obj, mCamera); } return; case CAMERA_MSG_POSTVIEW_FRAME: if (mPostviewCallback != null) { mPostviewCallback.onPictureTaken((byte[])msg.obj, mCamera); //通过调用这个方法,底层传输到此的数据最终发送到最上层的 Java 应用中,上层应用通过解析Message
得到图像数据。 } return; case CAMERA_MSG_FOCUS: AutoFocusCallback cb = null; synchronized (mAutoFocusCallbackLock) { cb = mAutoFocusCallback; } if (cb != null) { boolean success = msg.arg1 == 0 ? false : true; cb.onAutoFocus(success, mCamera); } return; case CAMERA_MSG_ZOOM: if (mZoomListener != null) { mZoomListener.onZoomChange(msg.arg1, msg.arg2 != 0, mCamera); } return; case CAMERA_MSG_PREVIEW_METADATA: if (mFaceListener != null) { mFaceListener.onFaceDetection((Face[])msg.obj, mCamera); } return; case CAMERA_MSG_ERROR : Log.e(TAG, "Error " + msg.arg1); if (mErrorCallback != null) { mErrorCallback.onError(msg.arg1, mCamera); } return; case CAMERA_MSG_FOCUS_MOVE: if (mAutoFocusMoveCallback != null) { mAutoFocusMoveCallback.onAutoFocusMoving(msg.arg1 == 0 ? false : true, mCamera); } return; default: Log.e(TAG, "Unknown message type " + msg.what); return; } }
简图总结:
总结:
不管是控制流还是数据流,都是要通过五大层次依次执行下一步的。控制流是将命令从顶层流向底层,而数据流则是将底层的数据流向顶层。如果要自定义一个对数据进行处理的 C++ 功能库,并将其加入相机中,可以通过对 HAL 层进行一些修改,将 RAW 图像流向自己的处理库,再将处理后的 RAW 图像传回 HAL 层(需要在 HAL 层对 RAW 格式进行一些处理才能把图像上传),最后通过正常的回调流程把图像传到顶层应用中。