转载来自:http://blog.csdn.net/wsb1321/article/details/21938655
接着上一篇:
Camera显示之app实现简单camera
mCamera.setPreviewDisplay(mSurfaceHolder);函数往下分析。
一.调用关系图:
二.1.mCamera为:android.hardware.Camera。
最终:
- public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {
- if (holder != null) {
- setPreviewDisplay(holder.getSurface());
- } else {
- setPreviewDisplay((Surface)null);
- }
- }
- private native final void setPreviewDisplay(Surface surface) throws IOException;
2.调用到jni层:
- static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, jobject jSurface)
- {
- ALOGV("setPreviewDisplay");
- sp<Camera> camera = get_native_camera(env, thiz, NULL);//这里是拿到一个和CameraService通信的客户端。目的是和CameraService进行通信
- if (camera == 0) return;
- sp<Surface> surface = NULL;
- if (jSurface != NULL) {
- surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));//将java层的Surface转化成native的Surface对象指针。
- }
- if (camera->setPreviewDisplay(surface) != NO_ERROR) {//通过CameraService的客户端最终和CameraService进行通信。
- jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed");
- }
- }
- }
我们来关注下:camera->setPreviewDisplay(surface)中的camera是如何获取的?
1).jni层
- // connect to camera service
- static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,
- jobject weak_this, jint cameraId)//在Cameraopen的时候会调用
- {
- sp<Camera> camera = Camera::connect(cameraId); //调用Camera的静态方法连接获取的。
- if (camera == NULL) {
- jniThrowRuntimeException(env, "Fail to connect to camera service");
- return;
- }
- // make sure camera hardware is alive
- if (camera->getStatus() != NO_ERROR) {
- jniThrowRuntimeException(env, "Camera initialization failed");
- return;
- }
- jclass clazz = env->GetObjectClass(thiz);
- if (clazz == NULL) {
- jniThrowRuntimeException(env, "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.
- //!++
- #ifdef MTK_CAMERA_BSP_SUPPORT
- sp<JNICameraContext> context = new MtkJNICameraContext(env, weak_this, clazz, camera);//将camera通过MtkJNICameraContext保存到这个实例, 要用的时候直接通过这个类实例获取。
- #else
- sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);//Android原生的也是这个涉及思路。
2).Camera.cpp
继续1)中:sp<Camera> camera = Camera::connect(cameraId);
- sp<Camera> Camera::connect(int cameraId)
- {
- ALOGV("connect");
- sp<Camera> c = new Camera();
- const sp<ICameraService>& cs = getCameraService();//获取CameraService实例指针:
- if (cs != 0) {
- c->mCamera = cs->connect(c, cameraId);//调用CameraService的connect的方法。
- }
- if (c->mCamera != 0) {
- c->mCamera->asBinder()->linkToDeath(c);
- c->mStatus = NO_ERROR;
- } else {
- c.clear();
- }
- return c;
- }
3). CameraService.cpp
由于此方法代码较多, 我们只关注部分关键点:
- sp<ICamera> CameraService::connect(
- const sp<ICameraClient>& cameraClient, int cameraId) {
- #ifdef MTK_CAMERAPROFILE_SUPPORT
- initCameraProfile();
- AutoCPTLog cptlog(Event_CS_connect);
- #endif
- int callingPid = getCallingPid();
- LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);
- .............................
- ............................
- int deviceVersion;
- if (mModule->common.module_api_version == CAMERA_MODULE_API_VERSION_2_0) {
- deviceVersion = info.device_version;
- } else {
- deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;
- }
- switch(deviceVersion) {//从这个里面可以看到client是CameraClient
- case CAMERA_DEVICE_API_VERSION_1_0:
- client = new CameraClient(this, cameraClient, cameraId,
- info.facing, callingPid, getpid());//Android原生设计。
- break;
- case CAMERA_DEVICE_API_VERSION_2_0://这里应该是MTK自己进行了扩展。
- client = new Camera2Client(this, cameraClient, cameraId,
- info.facing, callingPid, getpid());
- break;
- default:
- ALOGE("Unknown camera device HAL version: %d", deviceVersion);
- return NULL;
- }
- .....................................................
- ....................................................
- mClient[cameraId] = client;
- LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid());
- return client;//最终返回的是client, 也即是CameraClient。
- }
通过以上的调用关系, 可以知道camera->setPreviewDisplay(surface)调用到了CameraClient中的对应的方法, 注意这里已经是两个不同的进程了(一个是app进程, 一个是CameraService所在的mediaserver进程), 在jni层通过Camera.cpp里面实现的客户端通过Binder机制连接到CameraService端, 后面的通信都是通过Binder来进行,而不是直接调用。
3.CameraService端:
继续2中的camera->setPreviewDisplay(surface):
可以知道最终会通过Binder调用到CameraClient端。
- // set the Surface that the preview will use
- status_t CameraClient::setPreviewDisplay(const sp<Surface>& surface) {
- #ifdef MTK_CAMERAPROFILE_SUPPORT
- AutoCPTLog cptlog(Event_CS_setPreviewDisplay);
- #endif
- LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());
- sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);
- sp<ANativeWindow> window(surface);//将Surface么与ANativeWindow绑定。
- return setPreviewWindow(binder, window);
- }
- status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder,
- const sp<ANativeWindow>& window) {
- Mutex::Autolock lock(mLock);
- status_t result = checkPidAndHardware();
- if (result != NO_ERROR) return result;
- // return if no change in surface.
- if (binder == mSurface) {
- return NO_ERROR;
- }
- if (window != 0) {
- result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);
- if (result != NO_ERROR) {
- ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),
- result);
- return result;
- }
- }
- // If preview has been already started, register preview buffers now.
- if (mHardware->previewEnabled()) {
- if (window != 0) {
- native_window_set_scaling_mode(window.get(),
- NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);
- native_window_set_buffers_transform(window.get(), mOrientation);
- result = mHardware->setPreviewWindow(window);
- }
- }
- //!++
- else if ( window == 0 ) {
- result = mHardware->setPreviewWindow(window);//将window设置到hal层, Android代码架构真正的实现就止于此,hal层的东西就看具体厂家根据自身情况进行实现了。
- }
- //!--
- if (result == NO_ERROR) {
- // Everything has succeeded. Disconnect the old window and remember the
- // new window.
- disconnectWindow(mPreviewWindow);
- mSurface = binder;
- mPreviewWindow = window;
- } else {
- // Something went wrong after we connected to the new window, so
- // disconnect here.
- disconnectWindow(window);
- }
- return result;
- }
三. 关键点, 这里jni层后涉及到camera所在的app进程和CameraService所在mediaserver两个不同的进程, 他们之间会通过Binder进行通信。 对于这部分, 后面会继续和大家分享。
在CameraService的下一层就是hal层了, 这部分是各个厂家根据自己芯片的特色进行设计构建的。 所以这下面的实现肯定多种多样, 但是可以从去学习代码架构, 看看一帧数据是如何一步一步的进行显示的。
通过上面我们可以看到, 对于显示部分, 我们其实只是设置了一个surface, 在中间层, 又和 ANativeWindow的绑定, 最后完全交个hal层去实现。
后面的分析, 我会以ktm平台的实现去分析。