我固执的喜欢着Android_Camera,希望有一天自己能作Camera_Driver相关的东西。下面在我能力范围内,我会介绍下我对Camera的学习心得。主要通过讲解preview的过程来分析camera的数据流向。
从Camera的AP层开始分析。首先在Camera 应用启动之后,最先启动的是Camera的预览线程。在Camera.java@/packages/apps/Camera的onCreate()函数中,会开启预览线程。调用startPreview()---->call---->mCameraDevice.startPreview()。然后看下面的一张图。
下面这张图描述camera = Camera::connect(cameraId)的调用过程。
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
总结一下上述过程:
startPreview();//Camera.java@ packages/apps/camera的onCreate函数中
-
-
-
-
ensureCameraDevice();
-
-
-
-
该函数通过调确保在java层有一个可用的mCameraDevice实例。
mCameraDevice = android.hardware.Camera.open(cameraId);//该函函数的实现如下
public static Camera open(int cameraId) {
return new Camera(cameraId);
}
Camera(int cameraId) {
mShutterCallback = null;
mRawImageCallback = null;
mJpegCallback = null;
mPreviewCallback = null;
mPostviewCallback = null;
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;
}
native_setup(new WeakReference<Camera>(this), cameraId);
}
注意到目前为止我们已经有一个java层的实例,mCameraDevice即android.hardware.Camera类型。在mCameraDevice实例化的过程中,我们调用了native_setup()函数。该函数也是一个native函数。native_setup函数的作用后面会做解释。
-
-
-
-
//在Camera.java@ packages/apps/camera的 startPreview函数中,接着被调用到,在//android.hardware.Camera。java中 startPreview()是一个native函数。
mCameraDevice.startPreview();
-
-
-
-
代码跟到这里,native_setup的作用也不得不说了。先看下native_setup的代码:
// connect to camera service
static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
jobject weak_this, jint cameraId)
{
sp<Camera> camera = Camera::connect(cameraId);
if (camera == NULL) {
jniThrowException(env, "java/lang/RuntimeException",
"Fail to connect to camera service");
return;
}
// make sure camera hardware is alive
if (camera->getStatus() != NO_ERROR) {
jniThrowException(env, "java/lang/RuntimeException", "Camera initialization failed");
return;
}
jclass clazz = env->GetObjectClass(thiz);
if (clazz == NULL) {
jniThrowException(env, "java/lang/RuntimeException", "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.
//可以看到Camera::connect(cameraId)返回的camera被保存在了 context中
sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);
context->incStrong(thiz);
camera->setListener(context);
// save context in opaque field,这个 context被保存了,当我们需要使用这个camera的时候,
//可以通过getIntField把保存的context取出来。
//在函数get_native_camera()@android_hardware_camera.cpp中就是这么做的。
env->SetIntField(thiz, fields.context, (int)context.get());
}
sp<Camera> Camera::connect(int cameraId)
{
LOGV("connect");
sp<Camera> c = new Camera();
const sp<ICameraService>& cs = getCameraService();
if (cs != 0) {
//CameraService::connect返回的CameraService::client给了c->mCamera
c->mCamera = cs->connect(c, cameraId);
}
if (c->mCamera != 0) {
c->mCamera->asBinder()->linkToDeath(c);
c->mStatus = NO_ERROR;
} else {
c.clear();
}
return c;
}
首先该函数通过Camera::connect(cameraId);----》CameraService::connect()-----》在CameraService::connect函数中会new一个CameraService::client,这个Client是CameraService中对客户端请求做出相应的真正worker。然后这个new 出来的CameraService::Client会被返回给客户端的Camera client,随后Camera通过这个sp<ICamera> mCamera对象调用函数就如同直接调用CameraService::Client类的函数。
到目前为止总结下。在Camera框架中,我们有了一个android.hardware.camera在java层的实例,与之对应的变量是mCameraDevice,然后我们在native层有了一个可以和CameraService进行交互的mCamera。被保存在 JNICameraContext context中,当客户端Camera Client发出请求需要CameraService提供服务的时候,可以使用get_native_camera()来获得一个mCamera,通过这个mCamera就可以获得想要的服务。
分析到这里,再看前面mCameraDevice.startPreview();中调用的native层的startPreview()函数在JNI层具体的实现如下:
static void android_hardware_Camera_startPreview(JNIEnv *env, jobject thiz)
{
LOGV("startPreview");
sp<Camera> camera = get_native_camera(env, thiz, NULL);
if (camera == 0) return;
if (camera->startPreview() != NO_ERROR) {
jniThrowException(env, "java/lang/RuntimeException", "startPreview failed");
return;
}
}
其startPreview()的具体实现肯定是有CameraService::Client::startPreview()函数来完成的。
---------------------------------------------文章写的很乱,希望看的人耐心点,本人菜鸟能力有限,还希望与大家一起进步。