如果你想了解一下android的camera的大致框架内容看看我附带的图片就可以达到要求。不过图片毕竟比较抽象,还是然我们看下源码吧! 源码从APP到硬件抽象层,以这中从上到下的调用流程非常清晰。大家可以很容易看懂。我想带大家看的是camera从摄像头捕获一帧数据如何送到android的surface并且显示出来的。在framework\base\libs\camera.cpp 中有setPreviewDisplay,当然这个Surface是从应用层的Surface.java一步一步传进来的。Camera.java(activity)里面的startPreview函数就是开始预览的,这里就调用了setPreviewDisplay(mSurfaceHolder);至于SurfaceHolder是什么东西不用我多说了。再到Camera.java(hardware)这个实际就是与jni的接口了 这里面就会通过Holder来获取Surface,然后通过jni将Surface设置进来: static void android_hardware_Camera_setPreviewDisplay(JNIEnv *env, jobject thiz, jobject jSurface) { LOGV("setPreviewDisplay"); sp<Camera> camera = get_native_camera(env, thiz, NULL); if (camera == 0) return; sp<Surface> surface = NULL; if (jSurface != NULL) { surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface)); } if (camera->setPreviewDisplay(surface) != NO_ERROR) { jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed"); } } 从代码可以看到surface是做了一些变化的,surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));具体你看下Surface.java就知道了,这个Surface实际是native层的surface(class Surface : public EGLNativeBase<ANativeWindow, Surface, RefBase>);回到jni来,紧接着就将这个Surface设到了camera的客户端了(BnCameraClient)这个可以看图。 status_t Camera::setPreviewDisplay(const sp<Surface>& surface) { LOGV("setPreviewDisplay"); sp <ICamera> c = mCamera; if (c == 0) return NO_INIT; if (surface != 0) { return c->setPreviewDisplay(surface->getISurface()); } else { LOGD("app passed NULL surface"); return c->setPreviewDisplay(0); } } 这里又对调用了getISurface来获取另一个surface,此处的surface才是真做事的surface,管理它的正是surfaceFlinger,这个会在下一篇博客中解释。在这里可以说这个Surface其实就是SurfaceLayer(继承自LayerBaseClient::Surface),回到BnCameraClient,继续调用BnCamera的setPreviewDisplay将surface进行了保存mSurface = surface; 来到startPreview可以看到会点调用mHardware->startPreview();然后registerPreviewBuffers;对于mHardware它是不同的厂家来实现的,就是开了一个线程不断的从camera传感器获取数据,至于registerPreviewBuffers是关键,它将CameraHardware里面的内存(存储帧数据的缓存)注册到了Surface。仔细看的话你会发现这写内存可以存储8帧(不同厂家不一样)它是一块类似环形的buffer。看过代码的人应该都知道,在预览之前我们会先设置两个回调dataCallback和dataCallbackTimestamp,这两个的区别在于前者用于预览,而后者用于录制。我们看dataCallback: void CameraService::Client::dataCallback(int32_t msgType, const sp<IMemory>& dataPtr, void* user) { LOG2("dataCallback(%d)", msgType); sp<Client> client = getClientFromCookie(user); if (client == 0) return; if (!client->lockIfMessageWanted(msgType)) return; if (dataPtr == 0) { LOGE("Null data returned in data callback"); client->handleGenericNotify(CAMERA_MSG_ERROR, UNKNOWN_ERROR, 0); return; } switch (msgType) { case CAMERA_MSG_PREVIEW_FRAME: client->handlePreviewData(dataPtr); break; case CAMERA_MSG_POSTVIEW_FRAME: client->handlePostview(dataPtr); break; case CAMERA_MSG_RAW_IMAGE: client->handleRawPicture(dataPtr); break; case CAMERA_MSG_COMPRESSED_IMAGE: client->handleCompressedPicture(dataPtr); break; default: client->handleGenericData(msgType, dataPtr); break; } } 因为是Preview所以会到 client->handlePreviewData(dataPtr);而这个里面会有这样一句话mSurface->postBuffer(offset);看到了吧,就是说标号为offset的这块内存有数据拉,通知surfaceFlinger刷新这块内存将画面绘制到用户可见的Surface上面去。 先就这样吧,下回继续。 |
|
来自: liluvu > 《Camera Framework》