本文是在http://blog.csdn.net/wing12345678910/article/details/79088511
的基础上进一步分析学习,camera 在framwork层的如何实现操作控制流程,以及数据的回调流程
1、实际操作的控制流程:
client与server 连接成功后,server返回一个client给客户端
sp <::android::hardware::ICamera> c = mCamera;
在framworks/av/camera/camera.cpp中,通过binder机制,通过控制mCamera,就会在cameraserver执行相应操作
以startpreview为例:
status_t Camera::startPreview()
{
sp <::android::hardware::ICamera> c = mCamera;
if (c == 0) return NO_INIT;
return c->startPreview();
//通过mCamera直接控制cameraserver
}
跳转到framworks/av/service/camera/libmmcameraservices/api1/CameraClient.cpp
status_t CameraClient::startPreview() {
return startCameraMode(CAMERA_PREVIEW_MODE);
//文件内调用
}
status_t CameraClient::startCameraMode(camera_mode mode) {
switch(mode) {
case CAMERA_PREVIEW_MODE:
if (mSurface == 0 && mPreviewWindow == 0) {
LOG1("mSurface is not set yet.");
}
return startPreviewMode();
//区分是preview模式还是recording模式
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;
}
}
status_t CameraClient::startPreviewMode() {
status_t result = NO_ERROR;
if (mPreviewWindow != 0) {
mHardware->setPreviewScalingMode(
NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
mHardware->setPreviewTransform(mOrientation);
}
mHardware->setPreviewWindow(mPreviewWindow);
result = mHardware->startPreview();
//mHardware为初始化的实例,用于调到interface接口
if (result == NO_ERROR) {
mCameraService->updateProxyDeviceState(
ICameraServiceProxy::CAMERA_STATE_ACTIVE,
String8::format("%d", mCameraId));
}
return result;
}
framworks/av/service/camera/libmmcameraservice/devices1/CameraHardwareInterface.h
status_t startPreview()
{
if (mDevice->ops->start_preview)
return mDevice->ops->start_preview(mDevice);
//这里就调用到了HAL提供的相关接口
return INVALID_OPERATION;
}
至此就要调用到HAL相关接口,CameraHardwareInterface与HAL接口如何实现对接:
在frameorks/av/service/camera/libmmcameraservice/device1/CameraHardwareInterface.h文件的
initialize函数中:
rc = module->open(mName.string(), (hw_device_t **)&mDevice);
其中:
1、camera_module_t *module对应定义在:hardware/qcom/camera/QCamera2/QCamera2Hal.cpp中
2、输出结果到 camera_device_t *mDevice,对应定义在:hardware/qcom/cameraQcamera2/HAL/QCamera2HAL.cpp中,此后就可以直接通过mDevice调用HAL的接口
hardware/qcom/camera/QCamera2/QCamera2Hal.cpp
static hw_module_t camera_common = {
.tag = HARDWARE_MODULE_TAG,
.module_api_version = CAMERA_MODULE_API_VERSION_2_4,
.hal_api_version = HARDWARE_HAL_API_VERSION,
.id = CAMERA_HARDWARE_MODULE_ID,
.name = "QCamera Module",
.author = "Qualcomm Innovation Center Inc",
.methods = &qcamera::QCamera2Factory::mModuleMethods,
//这里对应了调用的open接口
.dso = NULL,
.reserved = {0}
};
camera_module_t HAL_MODULE_INFO_SYM = {
.common = camera_common,
.get_number_of_cameras = qcamera::QCamera2Factory::get_number_of_cameras,
.get_camera_info = qcamera::QCamera2Factory::get_camera_info,
.set_callbacks = qcamera::QCamera2Factory::set_callbacks,
.get_vendor_tag_ops = qcamera::QCamera3VendorTags::get_vendor_tag_ops,
.open_legacy = qcamera::QCamera2Factory::open_legacy,
.set_torch_mode = qcamera::QCamera2Factory::set_torch_mode,
.init = NULL,
.reserved = {0}
};
hardware/qcom/cameraQcamera2/HAL/QCamera2HAL.cpp
camera_device_ops_t QCamera2HardwareInterface::mCameraOps = {
.set_preview_window = QCamera2HardwareInterface::set_preview_window,
.set_callbacks = QCamera2HardwareInterface::set_CallBacks,
.enable_msg_type = QCamera2HardwareInterface::enable_msg_type,
.disable_msg_type = QCamera2HardwareInterface::disable_msg_type,
.msg_type_enabled = QCamera2HardwareInterface::msg_type_enabled,
.start_preview = QCamera2HardwareInterface::start_preview,
.stop_preview = QCamera2HardwareInterface::stop_preview,
.preview_enabled = QCamera2HardwareInterface::preview_enabled,
.store_meta_data_in_buffers= QCamera2HardwareInterface::store_meta_data_in_buffers,
.start_recording = QCamera2HardwareInterface::start_recording,
.stop_recording = QCamera2HardwareInterface::stop_recording,
.recording_enabled = QCamera2HardwareInterface::recording_enabled,
.release_recording_frame = QCamera2HardwareInterface::release_recording_frame,
.auto_focus = QCamera2HardwareInterface::auto_focus,
.cancel_auto_focus = QCamera2HardwareInterface::cancel_auto_focus,
.take_picture = QCamera2HardwareInterface::take_picture,
.cancel_picture = QCamera2HardwareInterface::cancel_picture,
.set_parameters = QCamera2HardwareInterface::set_parameters,
.get_parameters = QCamera2HardwareInterface::get_parameters,
.put_parameters = QCamera2HardwareInterface::put_parameters,
.send_command = QCamera2HardwareInterface::send_command,
.release = QCamera2HardwareInterface::release,
.dump = QCamera2HardwareInterface::dump,
};
//这里的函数都对接在CmaeraHardwareInterface.h文件中
2、数据的回调流程
高通在回调数据只提供数据地址,并不会把真正的数据上传
回调函数的设置:
hardware/qcom/camera/QCamera/HAL/QCamera2HWI.cpp
void QCamera2HardwareInterface::set_CallBacks(struct camera_device *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)
{
QCamera2HardwareInterface *hw =
reinterpret_cast
(device->priv);
qcamera_sm_evt_setcb_payload_t payload;
//设置回调类型,定义在hardware/qcom/camera/QCamera2/HAL/QCameraStateMachine.h
payload.notify_cb = notify_cb;
payload.data_cb = data_cb;
payload.data_cb_timestamp = data_cb_timestamp;
payload.get_memory = get_memory;
payload.user = user;
hw->lockAPI();
qcamera_api_result_t apiResult;
int32_t rc = hw->processAPI(QCAMERA_SM_EVT_SET_CALLBACKS, (void *)&payload);
hw->unlockAPI();
}
framworks/av/service/camera/libmmcameraservice/device1/CameraHardwareInterface.h
void setCallbacks(notify_callback notify_cb,
data_callback data_cb,
data_callback_timestamp data_cb_timestamp,
void* user)
{
mNotifyCb = notify_cb;
mDataCb = data_cb;
mDataCbTimestamp = data_cb_timestamp;
mCbUser = user;
//把从client传参进来的函数指针进行赋值,后续就可以直接回调到Client对应的函数
if (mDevice->ops->set_callbacks) {
mDevice->ops->set_callbacks(mDevice,
__notify_cb,
__data_cb,
__data_cb_timestamp,
__get_memory,
this);
//调用HAL层的回调函数接口
}
}
framworks/av/services/camera/libmmcameraservice/api1/CameraClient.cpp
该文件initialize的过程中有设置:
mHardware->setCallbacks(notifyCallback,
dataCallback,
dataCallbackTimestamp,
(void *)(uintptr_t)mCameraId);
//设置CameraHardwareInterface的回调函数
并且根据不同的回调函数对应执行,这里以dataCallbackTimestamp为例:
void CameraClient::dataCallbackTimestamp(nsecs_t timestamp,
int32_t msgType, const sp& dataPtr, void* user) {
sp client = static_cast(getClientFromCookie(user).get());
client->handleGenericDataTimestamp(timestamp, msgType, dataPtr);
//同文件调用
}
void CameraClient::handleGenericDataTimestamp(nsecs_t timestamp,
int32_t msgType, const sp& dataPtr) {
sp c = mRemoteCallback;
mLock.unlock();
if (c != 0 && dataPtr != nullptr) {
native_handle_t* handle = nullptr;
if (dataPtr->size() == sizeof(VideoNativeHandleMetadata)) {
VideoNativeHandleMetadata *metadata =
(VideoNativeHandleMetadata*)(dataPtr->pointer());
if (metadata->eType == kMetadataBufferTypeNativeHandleSource) {
handle = metadata->pHandle;
}
}
if (handle != nullptr) {
{
Mutex::Autolock l(mAvailableCallbackBuffersLock);
mAvailableCallbackBuffers.push_back(dataPtr);
}
c->recordingFrameHandleCallbackTimestamp(timestamp, handle);
} else {
c->dataCallbackTimestamp(timestamp, msgType, dataPtr);
//这里的sp c作为client端在server端的代理,通过binder调用client端的对应操作
}
}
}
client端执行通过binder传输过来的指令
framworks/av/camera/Camera.cpp
void Camera::dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr)
{
sp proxylistener;
{
Mutex::Autolock _l(mLock);
proxylistener = mRecordingProxyListener;
}
if (proxylistener != NULL) {
proxylistener->dataCallbackTimestamp(timestamp, msgType, dataPtr);
//这里有初始化时设置的监听相应回调
return;
}
sp listener;
{
Mutex::Autolock _l(mLock);
listener = mListener;
}
if (listener != NULL) {
listener->postDataTimestamp(timestamp, msgType, dataPtr);
} else {
ALOGW("No listener was set. Drop a recording frame.");
releaseRecordingFrame(dataPtr);
}
}
对应不同的回调有监听执行不同方法,生明在:framworks/av/camera/Camera.h
class CameraListener: virtual public RefBase
{
public:
virtual void notify(int32_t msgType, int32_t ext1, int32_t ext2) = 0;
virtual void postData(int32_t msgType, const sp& dataPtr,
camera_frame_metadata_t *metadata) = 0;
virtual void postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr) = 0;
virtual void postRecordingFrameHandleTimestamp(nsecs_t timestamp, native_handle_t* handle) = 0;
};
具体的监听设置在:framworks/base/core/jni/android_hardware_camera.cpp文件的
android_hardware_Camera_native_setup函数中
sp context = new JNICameraContext(env, weak_this, clazz, camera);
context->incStrong((void*)android_hardware_Camera_native_setup);
camera->setListener(context);
void JNICameraContext::postDataTimestamp(nsecs_t timestamp, int32_t msgType, const sp& dataPtr)
{
// TODO: plumb up to Java. For now, just drop the timestamp
postData(msgType, dataPtr, NULL);
//后续就把回调返回给了java层
}
目前梳理回调函数的流程,具体的数据流程还没有搞清楚
MediaRecorder的数据回调方法是_data_cb_timestamp