如何使用 JNI 以 C 语言获取原始 Android 相机缓冲区?
我一直在详尽地搜索Google和StackOverflow,但找不到这个。也许我错过了一些明显的东西。谢谢!
(这是因为预览回调的 Java 实现(即使使用缓冲区)效率太低。
我一直在详尽地搜索Google和StackOverflow,但找不到这个。也许我错过了一些明显的东西。谢谢!
(这是因为预览回调的 Java 实现(即使使用缓冲区)效率太低。
我对这个话题做了一些调查。这个演讲(来自第277页,中文)帮助很大。
正如其他人所提到的,您可以使用方法获取缓冲区。
以下是它在那里发生的方式(详细版本):Camera.setPreviewCallback
Camera.startPreview()
android_hardware_Camera_startPreview
调用C++类的方法。startPreview
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
Camera.addCallbackBuffer
Camera
onPreviewFrame
Camera.PreviewCallback
如您所见,在步骤 10、11 中调用了 2 次调用,并且至少复制了两次缓冲区。返回的原始缓冲区的第一个实例托管在另一个进程中,由于 中的安全检查,您无法访问它。IPC
camera_device_t
CameraService
但是,当您使用任一设置预览图面时,或者直接将其传递到相机设备并实时刷新,而无需上述所有链的参与。正如它的文档所说:Camera.setPreviewTexture
Camera.setPreviewDisplay
处理到由屏幕合成器管理的原始缓冲区上。
Java类有一个方法来检索它的内容:Surface
public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);
但是这个 API 是隐藏的。请参阅即此问题以获取使用它的方法。
没有公共API可以做你想做的事;唯一的官方(即保证工作)方法是通过调用Camera.setPreviewCallback()设置的Java级预览回调。在Android > 3.0中,您还可以使用Camera.setPreviewTexture()将预览数据路由到GPU,并使用GLES对其进行处理(或将其读回CPU)。GPU 路径是 ICS AOSP 相机应用程序用于其视频效果的路径。
据推测,OpenCV和其他人已经查看了Android框架的原生代码,并绕过了Java Camera API,直接与下面的服务进行了交谈。
这是相当危险的,因为绝对不能保证这些接口不会在Android版本之间更改,因为它们不是公共API的一部分。现在使用它们可能很好,然后当用户升级其设备时,你的应用将停止工作。