我对这个话题做了一些调查。该演讲(来自第277页,中文)很有帮助。
相机预览通话链
如其他人所述,您可以使用
Camera.setPreviewCallback方法获得缓冲区。
这是那里发生的情况(详细版本):
- 用户调用
Camera.startPreview()
这是一个本机函数。 android_hardware_Camera_startPreview
调用startPreview
C ++Camera
类的方法。Camera
调用接口startPreview
方法ICamera
ICamera
使一个IPC
远程客户端调用。- 它调用类的
setCameraMode
方法CameraService
。 CameraService
设置一个窗口以显示预览并调用类的startPreview
方法CameraHardwareInterface
。后者尝试
start_preview
在特定camera_device_t
设备上调用方法。
我没有进一步查找,但是它应该执行呼叫驱动程序。当图像到达时,
dataCallback
的CameraService
被调用。- 它将数据传递给
handlePreviewData
客户端的方法。 - 客户端要么复制缓冲区,要么直接将其发送到
ICameraClient
。 ICameraClient
将其发送IPC
到Camera
。Camera
调用注册的侦听器并将缓冲区传递给JNI
。- 它调用Java类中的回调。如果用户提供了缓冲区,
Camera.addCallbackBuffer
则它将首先复制到缓冲区。 - 最后,Java类
Camera
处理消息并调用的onPreviewframe
方法Camera.PreviewCallback
。
如您所见
IPC,在步骤10、11上,调用了2个调用,并且缓冲区被复制了至少两次。所返回的raw缓冲区的第一个实例
camera_device_t托管在另一个进程中,由于中的安全检查,您无法访问它
CameraService。
预览表面
但是,当您使用
Camera.setPreviewTexture或设置预览图面时,或将
Camera.setPreviewDisplay其直接传递到摄像头设备并实时刷新,而无需上面所有链条的参与。正如文档所述:
处理到由屏幕合成器管理的原始缓冲区。
Java类
Surface具有一种检索其内容的方法:
public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);
但是此API是隐藏的。请参阅此问题以获取使用方法。



