您的位置:首页 > 移动开发 > Android开发

Android中Camera的调用流程

2012-06-25 17:06 357 查看
转自:http://www.open-open.com/lib/view/open1338475410714.html

Android中Camera的调用流程可分为以下几个层次:

Package->Framework->JNI->Camera(cpp)--(binder)-->CameraService->Camera HAL->Camera Driver

以拍照流程为例:

1. 各个参数设置完成,对焦完成后,位于Package的Camera.java会调用Framework中Camera.java的takePicture函数,如下:

1
public
final
void
takePicture(ShutterCallback
shutter, PictureCallback raw,
2
PictureCallback
postview, PictureCallback jpeg) {
3
mShutterCallback
= shutter;
4
mRawImageCallback
= raw;
5
mPostviewCallback
= postview;
6
mJpegCallback
= jpeg;
7
native_takePicture();
8
}
此函数保存Package层传下的callback函数,同时调用JNI层的native_takePicture

2. JNI层的native_takePicture自己并没有做太多事情,只是简单地调用cpp的Camera中的takePicture函数。此前已经把JNI中的一个对象注册成了Camera.cpp的listener

3. 位于frameworks/base/libs/camera是向CameraService请求服务的客户端,但它本身也继承了一个BnCameraClient类,用于CameraService回调自己。

1
class
ICameraClient:
public
IInterface
2
{
3
public
:
4
DECLARE_META_INTERFACE(CameraClient);
5
6
virtual
void
notifyCallback(int32_t
msgType, int32_t ext1, int32_t ext2) =
0
;
7
virtual
void
dataCallback(int32_t
msgType,
const
sp<IMemory>&
data) =
0
;
8
virtual
void
dataCallbackTimestamp(nsecs_t
timestamp, int32_t msgType,
const
sp<IMemory>&
data) = 
0
;
9
};
从上面的接口定义可以看到,这个类就是用于回调。

Camera.cpp的takePicture函数是利用open Camera时得到的ICamera对象来继续调用takePicture

4. 接下来通过binder转到另一个进程CameraService中的处理。CameraService中之前已经实例化了一个HAL层的 CameraHardware,并把自己的data
callback传递给了CameraHardware,这些工作都是由CameraService的内部类Client来完成的,这个Client类继承自BnCamera,是真正提供Camera操作API的类

5. 然后自然是调用HAL层CameraHardware的takePicture函数。从HAL层向下就不是Android的标准代码了,各个厂商有自己不同的实现。但思路应该都是相同的:Camera遵循V4L2架构,利用ioctl发送VIDIOC_DQBUF命令得到有效的图像数据,接着回调HAL层的data
callback接口以通知CameraService,CameraService会通过binder通知Camera.cpp,如下:

01
void
CameraService::Client::dataCallback(int32_t
msgType,
02
const
sp<IMemory>&
dataPtr,
void
*
user) {
03
LOG2(
"dataCallback(%d)"
,
msgType);
04
05
sp<Client>
client = getClientFromCookie(user);
06
if
(client
== 0)
return
;
07
if
(!client->lockIfMessageWanted(msgType))
return
;
08
09
if
(dataPtr
== 0) {
10
LOGE(
"Null
data returned in data callback"
);
11
client->handleGenericNotify(CAMERA_MSG_ERROR,
UNKNOWN_ERROR, 0);
12
return
;
13
}
14
15
switch
(msgType)
{
16
case
CAMERA_MSG_PREVIEW_FRAME:
17
client->handlePreviewData(dataPtr);
18
break
;
19
case
CAMERA_MSG_POSTVIEW_FRAME:
20
client->handlePostview(dataPtr);
21
break
;
22
case
CAMERA_MSG_RAW_IMAGE:
23
client->handleRawPicture(dataPtr);
24
break
;
25
case
CAMERA_MSG_COMPRESSED_IMAGE:
26
client->handleCompressedPicture(dataPtr);
27
break
;
28
default
:
29
client->handleGenericData(msgType,
dataPtr);
30
break
;
31
}
32
}
33
//
picture callback - compressed picture ready
34
void
CameraService::Client::handleCompressedPicture(
const
sp<IMemory>&
mem) {
35
int
restPictures
=  mHardware->getPictureRestCount();
36
if
(!restPictures)
37
{
38
disableMsgType(CAMERA_MSG_COMPRESSED_IMAGE);
39
}
40
41
sp<ICameraClient>
c = mCameraClient;
42
mLock.unlock();
43
if
(c
!= 0) {
44
c->dataCallback(CAMERA_MSG_COMPRESSED_IMAGE,
mem);
45
}
46
}
6. Camera.cpp会继续通知它的listener:

01
//
callback from camera service when frame or image is ready
02
void
Camera::dataCallback(int32_t
msgType,
const
sp<IMemory>&
dataPtr)
03
{
04
sp<CameraListener>
listener;
05
{
06
Mutex::Autolock
_l(mLock);
07
listener
= mListener;
08
}
09
if
(listener
!= NULL) {
10
listener->postData(msgType,
dataPtr);
11
}
12
}
7. 而这个listener就是我们的JNI层的JNICameraContext对象了:

01
void
JNICameraContext::postData(int32_t
msgType,
const
sp<IMemory>&
dataPtr)
02
{
03
//
VM pointer will be NULL if object is released
04
Mutex::Autolock
_l(mLock);
05
JNIEnv
*env = AndroidRuntime::getJNIEnv();
06
if
(mCameraJObjectWeak
== NULL) {
07
LOGW(
"callback
on dead camera object"
);
08
return
;
09
}
10
11
//
return data based on callback type
12
switch
(msgType)
{
13
case
CAMERA_MSG_VIDEO_FRAME:
14
//
should never happen
15
break
;
16
//
don't return raw data to Java
17
case
CAMERA_MSG_RAW_IMAGE:
18
LOGV(
"rawCallback"
);
19
env->CallStaticVoidMethod(mCameraJClass,
fields.post_event,
20
mCameraJObjectWeak,
msgType, 0, 0, NULL);
21
break
;
22
default
:
23
//
TODO: Change to LOGV
24
LOGV(
"dataCallback(%d,
%p)"
,
msgType, dataPtr.get());
25
copyAndPost(env,
dataPtr, msgType);
26
break
;
27
}
28
}
8. 可以看到JNI层最终都会调用来自java层的函数postEventFromNative,这个函数会发送对应的消息给自己的 eventhandler,收到消息后就会根据消息的类型回调Package层Camera.java最初传下来的callback函数。至此,我们就在最上层拿到了图像数据。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: