我一直在详尽地搜索 Google 和 StackOverflow,但找不到这个。也许我错过了一些明显的东西。谢谢!
(这是因为预览回调的 Java 实现 [即使有缓冲区] 效率太低。)
我一直在详尽地搜索 Google 和 StackOverflow,但找不到这个。也许我错过了一些明显的东西。谢谢!
(这是因为预览回调的 Java 实现 [即使有缓冲区] 效率太低。)
我对主题进行了一些调查。此演示文稿(来自第 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
ofCameraService
被调用。handlePreviewData
客户端的方法。ICameraClient
.ICameraClient
将其发送IPC
到Camera
.Camera
调用已注册的侦听器并将缓冲区传递给JNI
.Camera.addCallbackBuffer
则它首先复制到缓冲区。Camera
处理消息并调用onPreviewFrame
.Camera.PreviewCallback
如您所见IPC
,在步骤 10、11 中调用了 2 个调用,并且缓冲区至少被复制了两次。由返回的原始缓冲区的第一个实例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 的一部分。现在使用它们可能没问题,然后当用户升级他们的设备时,您的应用程序将停止工作。
你看过OpenCV for Android吗?他们的高级教程展示了如何使用 JNI,并且他们的相机包中有一个 NativeProcessor 对象。