二、Camera显示之Framework层设置显示窗口

转载来自:http://blog.csdn.net/wsb1321/article/details/21938655

接着上一篇:

Camera显示之app实现简单camera

mCamera.setPreviewDisplay(mSurfaceHolder);函数往下分析。 


一.调用关系图:



二.1.mCamera为:android.hardware.Camera。

最终:

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public final void setPreviewDisplay(SurfaceHolder holder) throws IOException {  
  2.        if (holder != null) {  
  3.            setPreviewDisplay(holder.getSurface());  
  4.        } else {  
  5.            setPreviewDisplay((Surface)null);  
  6.        }  
  7.    }  
  8.   
  9.   private native final void setPreviewDisplay(Surface surface) throws IOException;  


2.调用到jni层:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, jobject jSurface)  
  2.   
  3.   
  4. {  
  5.     ALOGV("setPreviewDisplay");  
  6.     sp<Camera> camera = get_native_camera(env, thiz, NULL);//这里是拿到一个和CameraService通信的客户端。目的是和CameraService进行通信  
  7.     if (camera == 0) return;  
  8.   
  9.     sp<Surface> surface = NULL;  
  10.     if (jSurface != NULL) {  
  11.         surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));//将java层的Surface转化成native的Surface对象指针。  
  12.     }  
  13.        if (camera->setPreviewDisplay(surface) != NO_ERROR) {//通过CameraService的客户端最终和CameraService进行通信。  
  14.         jniThrowException(env, "java/io/IOException""setPreviewDisplay failed");  
  15.     }  
  16.     }  
  17. }  


我们来关注下:camera->setPreviewDisplay(surface)中的camera是如何获取的?

1).jni层

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. // connect to camera service  
  2. static void android_hardware_Camera_native_setup(JNIEnv *env, jobject thiz,  
  3.     jobject weak_this, jint cameraId)//在Cameraopen的时候会调用  
  4. {  
  5.     sp<Camera> camera = Camera::connect(cameraId); //调用Camera的静态方法连接获取的。  
  6.   
  7.     if (camera == NULL) {  
  8.         jniThrowRuntimeException(env, "Fail to connect to camera service");  
  9.         return;  
  10.     }  
  11.   
  12.     // make sure camera hardware is alive  
  13.     if (camera->getStatus() != NO_ERROR) {  
  14.         jniThrowRuntimeException(env, "Camera initialization failed");  
  15.         return;  
  16.     }  
  17.   
  18.     jclass clazz = env->GetObjectClass(thiz);  
  19.     if (clazz == NULL) {  
  20.         jniThrowRuntimeException(env, "Can't find android/hardware/Camera");  
  21.         return;  
  22.     }  
  23.   
  24.     // We use a weak reference so the Camera object can be garbage collected.  
  25.     // The reference is only used as a proxy for callbacks.  
  26. //!++  
  27. #ifdef  MTK_CAMERA_BSP_SUPPORT  
  28.     sp<JNICameraContext> context = new MtkJNICameraContext(env, weak_this, clazz, camera);//将camera通过MtkJNICameraContext保存到这个实例, 要用的时候直接通过这个类实例获取。  
  29. #else  
  30.     sp<JNICameraContext> context = new JNICameraContext(env, weak_this, clazz, camera);//Android原生的也是这个涉及思路。  



2).Camera.cpp

继续1)中:sp<Camera> camera = Camera::connect(cameraId);

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. sp<Camera> Camera::connect(int cameraId)  
  2. {  
  3.     ALOGV("connect");  
  4.     sp<Camera> c = new Camera();  
  5.     const sp<ICameraService>& cs = getCameraService();//获取CameraService实例指针:  
  6.     if (cs != 0) {  
  7.         c->mCamera = cs->connect(c, cameraId);//调用CameraService的connect的方法。  
  8.     }  
  9.     if (c->mCamera != 0) {  
  10.         c->mCamera->asBinder()->linkToDeath(c);  
  11.         c->mStatus = NO_ERROR;  
  12.     } else {  
  13.         c.clear();  
  14.     }  
  15.     return c;  
  16. }  


3). CameraService.cpp


由于此方法代码较多, 我们只关注部分关键点:

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. sp<ICamera> CameraService::connect(  
  2.         const sp<ICameraClient>& cameraClient, int cameraId) {  
  3. #ifdef  MTK_CAMERAPROFILE_SUPPORT  
  4.     initCameraProfile();  
  5.     AutoCPTLog cptlog(Event_CS_connect);  
  6. #endif  
  7.     int callingPid = getCallingPid();  
  8.   
  9.     LOG1("CameraService::connect E (pid %d, id %d)", callingPid, cameraId);  
  10. .............................  
  11.   
  12. ............................  
  13.   
  14.  int deviceVersion;  
  15.     if (mModule->common.module_api_version == CAMERA_MODULE_API_VERSION_2_0) {  
  16.         deviceVersion = info.device_version;  
  17.     } else {  
  18.         deviceVersion = CAMERA_DEVICE_API_VERSION_1_0;  
  19.     }  
  20.   
  21.     switch(deviceVersion) {//从这个里面可以看到client是CameraClient  
  22.       case CAMERA_DEVICE_API_VERSION_1_0:  
  23.         client = new CameraClient(this, cameraClient, cameraId,  
  24.                 info.facing, callingPid, getpid());//Android原生设计。  
  25.         break;  
  26.       case CAMERA_DEVICE_API_VERSION_2_0://这里应该是MTK自己进行了扩展。  
  27.         client = new Camera2Client(this, cameraClient, cameraId,  
  28.                 info.facing, callingPid, getpid());  
  29.         break;  
  30.       default:  
  31.         ALOGE("Unknown camera device HAL version: %d", deviceVersion);  
  32.         return NULL;  
  33.     }  
  34.   
  35. .....................................................  
  36.   
  37. ....................................................  
  38.   
  39.   
  40.     mClient[cameraId] = client;  
  41.     LOG1("CameraService::connect X (id %d, this pid is %d)", cameraId, getpid());  
  42.     return client;//最终返回的是client, 也即是CameraClient。  
  43.   
  44. }  



通过以上的调用关系, 可以知道camera->setPreviewDisplay(surface)调用到了CameraClient中的对应的方法, 注意这里已经是两个不同的进程了(一个是app进程, 一个是CameraService所在的mediaserver进程), 在jni层通过Camera.cpp里面实现的客户端通过Binder机制连接到CameraService端, 后面的通信都是通过Binder来进行,而不是直接调用。


3.CameraService端:

继续2中的camera->setPreviewDisplay(surface):

可以知道最终会通过Binder调用到CameraClient端。

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. // set the Surface that the preview will use  
  2. status_t CameraClient::setPreviewDisplay(const sp<Surface>& surface) {  
  3. #ifdef  MTK_CAMERAPROFILE_SUPPORT  
  4.     AutoCPTLog cptlog(Event_CS_setPreviewDisplay);  
  5. #endif  
  6.     LOG1("setPreviewDisplay(%p) (pid %d)", surface.get(), getCallingPid());  
  7.   
  8.     sp<IBinder> binder(surface != 0 ? surface->asBinder() : 0);  
  9.     sp<ANativeWindow> window(surface);//将Surface么与ANativeWindow绑定。  
  10.     return setPreviewWindow(binder, window);  
  11. }  
  12.   
  13. status_t CameraClient::setPreviewWindow(const sp<IBinder>& binder,  
  14.         const sp<ANativeWindow>& window) {  
  15.     Mutex::Autolock lock(mLock);  
  16.     status_t result = checkPidAndHardware();  
  17.     if (result != NO_ERROR) return result;  
  18.   
  19.     // return if no change in surface.  
  20.     if (binder == mSurface) {  
  21.         return NO_ERROR;  
  22.     }  
  23.   
  24.     if (window != 0) {  
  25.         result = native_window_api_connect(window.get(), NATIVE_WINDOW_API_CAMERA);  
  26.         if (result != NO_ERROR) {  
  27.             ALOGE("native_window_api_connect failed: %s (%d)", strerror(-result),  
  28.                     result);  
  29.             return result;  
  30.         }  
  31.     }  
  32.   
  33.     // If preview has been already started, register preview buffers now.  
  34.     if (mHardware->previewEnabled()) {  
  35.         if (window != 0) {  
  36.             native_window_set_scaling_mode(window.get(),  
  37.                     NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW);  
  38.             native_window_set_buffers_transform(window.get(), mOrientation);  
  39.             result = mHardware->setPreviewWindow(window);  
  40.         }  
  41.     }  
  42.     //!++  
  43.     else if ( window == 0 ) {  
  44.         result = mHardware->setPreviewWindow(window);//将window设置到hal层, Android代码架构真正的实现就止于此,hal层的东西就看具体厂家根据自身情况进行实现了。  
  45.     }  
  46.     //!--  
  47.   
  48.     if (result == NO_ERROR) {  
  49.         // Everything has succeeded.  Disconnect the old window and remember the  
  50.         // new window.  
  51.         disconnectWindow(mPreviewWindow);  
  52.         mSurface = binder;  
  53.         mPreviewWindow = window;  
  54.     } else {  
  55.         // Something went wrong after we connected to the new window, so  
  56.         // disconnect here.  
  57.         disconnectWindow(window);  
  58.     }  
  59.   
  60.     return result;  
  61.   
  62. }  


三. 关键点, 这里jni层后涉及到camera所在的app进程和CameraService所在mediaserver两个不同的进程, 他们之间会通过Binder进行通信。 对于这部分, 后面会继续和大家分享。

在CameraService的下一层就是hal层了, 这部分是各个厂家根据自己芯片的特色进行设计构建的。 所以这下面的实现肯定多种多样, 但是可以从去学习代码架构, 看看一帧数据是如何一步一步的进行显示的。


通过上面我们可以看到, 对于显示部分, 我们其实只是设置了一个surface, 在中间层, 又和 ANativeWindow的绑定, 最后完全交个hal层去实现。

后面的分析, 我会以ktm平台的实现去分析。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值