今天小编给大家分享一下android7相机拍照流程是怎样的的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
在 Camera 流程中,还有一个重要的部分,即数据流。
Camera API 1 中,数据流主要是通过函数回调的方式,依照从下往上的方向,逐层 return 到 Applications 中。
由于数据流的部分相对来说比较简单,所以我就将其与 Camera 的控制流结合起来,从 takePicture() 方法切入,追踪一个比较完整的 Camera 流程。
位置:frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
setCallback():
设置 notify 回调,这用来通知数据已经更新。
设置 data 回调以及 dataTimestamp 回调,对应的是函数指针 mDataCb 与 mDataCvTimestamp 。
注意到,设置 mDevice->ops 对应回调函数时,传入的不是之前设置的函数指针,而是 __data_cb 这样的函数。在该文件中,实现了 __data_cb ,将回调函数做了一层封装。
/** 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;
mDataCb = data_cb;
mDataCbTimestamp = data_cb_timestamp;
mCbUser = user;
ALOGV("%s(%s)", __FUNCTION__, mName.string());
if (mDevice->ops->set_callbacks) {
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);
}
位置:frameworks/base/core/jni/android_hardware_Camera.cpp
takePicture():
获取已经打开的 camera 实例,调用其 takePicture() 接口。
注意,在这个函数中,对于 RAW_IMAGE 有一些附加操作:
如果设置了 RAW 的 callback ,则要检查上下文中,是否能找到对应 Buffer。
若无法找到 Buffer ,则将 CAMERA_MSG_RAW_IMAGE 的信息去掉,换成 CAMERA_MSG_RAW_IMAGE_NOTIFY。
替换后,就只会获得 notification 的消息,而没有对应的图像数据。
static void android_hardware_Camera_takePicture(JNIEnv *env, jobject thiz, jint msgType)
{
ALOGV("takePicture");
JNICameraContext* context;
//先前有分析,https://my.oschina.net/u/920274/blog/5034592
sp<Camera> camera = get_native_camera(env, thiz, &context);
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.
*/
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;
}
}
调用camera->takePicture(msgType)后,来到下面的地方。
位置:frameworks/av/camera/Camera.cpp
takePicture():
获取一个 ICamera,调用其 takePicture 接口。
这里直接用 return 的方式调用,比较简单。
// take a picture
status_t Camera::takePicture(int msgType)
{
ALOGV("takePicture: 0x%x", msgType);
//https://my.oschina.net/u/920274/blog/5034592 有分析
sp <ICamera> c = mCamera;
if (c == 0) return NO_INIT;
return c->takePicture(msgType);
}
然后跳转到
位置:frameworks/av/camera/ICamera.cpp
takePicture():
利用 Binder 机制发送相应指令到服务端。
实际调用到的是 CameraClient::takePicture() 函数。
// 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);
status_t ret = reply.readInt32();
return ret;
}
remote()->transact(TAKE_PICTURE, data, &reply);
binder调用到文件的CameraService.cpp的CameraService::onTransact方法
status_t CameraService::onTransact(uint32_t code, const Parcel& data, Parcel* reply,
uint32_t flags) {
const int pid = getCallingPid();
const int selfPid = getpid();
// Permission checks
switch (code) {
case BnCameraService::CONNECT:
case BnCameraService::CONNECT_DEVICE:
case BnCameraService::CONNECT_LEGACY: {
if (pid != selfPid) {
// we're called from a different process, do the real check
if (!checkCallingPermission(
String16("android.permission.CAMERA"))) {
const int uid = getCallingUid();
ALOGE("Permission Denial: "
"can't use the camera pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
}
}
break;
}
case BnCameraService::NOTIFY_SYSTEM_EVENT: {
if (pid != selfPid) {
// Ensure we're being called by system_server, or similar process with
// permissions to notify the camera service about system events
if (!checkCallingPermission(
String16("android.permission.CAMERA_SEND_SYSTEM_EVENTS"))) {
const int uid = getCallingUid();
ALOGE("Permission Denial: cannot send updates to camera service about system"
" events from pid=%d, uid=%d", pid, uid);
return PERMISSION_DENIED;
}
}
break;
}
}
return BnCameraService::onTransact(code, data, reply, flags); //然后会调用到这来
}
继续往下到文件ICameraService.cpp
status_t BnCameraService::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
。。。
。。。
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
继续会调用到文件ICamera.cpp
status_t BnCamera::onTransact(
uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)
{
switch(code) {
case TAKE_PICTURE: {
ALOGV("TAKE_PICTURE");
CHECK_INTERFACE(ICamera, data, reply);
int msgType = data.readInt32();
reply->writeInt32(takePicture(msgType));
return NO_ERROR;
} break;
default:
return BBinder::onTransact(code, data, reply, flags);
}
}
会调用到文件CameraClient.cpp下的takePicture(),是因为CameraClient继承 BnCamera
继续往下看文件 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) &&
(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
& (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();
}
位置:frameworks/av/services/camera/libcameraservice/device1/CameraHardwareInterface.h
takePicture():
通过 mDevice 中设置的函数指针,调用 HAL 层中具体平台对应的 takePicture 操作的实现逻辑。
接下来就是与具体的平台相关的流程了,这部分内容对我并非主要,而且在上一篇笔记中已经有比较深入的探索,所以在这里就不继续向下挖掘了。
控制流程到了 HAL 层后,再向 Linux Drivers 发送控制指令,从而使具体的 Camera 设备执行指令,并获取数据。
/**
* Take a picture.
*/
status_t takePicture()
{
ALOGV("%s(%s)", __FUNCTION__, mName.string());
if (mDevice->ops->take_picture)
return mDevice->ops->take_picture(mDevice);
return INVALID_OPERATION;
}
后面就是 数据流
由于数据流是通过 callback 函数实现的,所以探究其流程的时候我是从底层向上层进行分析的。
以上就是“android7相机拍照流程是怎样的”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。