How do I get the raw Android camera buffer in C using JNI?(如何使用 JNI 在 C 中获取原始 Android 相机缓冲区?)
问题描述
我一直在彻底搜索 Google 和 StackOverflow,但找不到这个.也许我错过了一些明显的东西.谢谢!
I've been searching Google and StackOverflow exhaustively and cannot find this. Maybe I'm missing something obvious. Thanks!
(这是因为预览回调的Java实现[即使有缓冲区]效率太低.)
(This is because the Java implementation of the preview callback [even with buffer] is too inefficient.)
推荐答案
我对主题做了一点调查.这个介绍(来自p.277,中文)帮助很大.
I made a little investigation on topic. This presentation (from p.277, Chinese) helped a lot.
正如其他人提到的,您可以使用 Camera.setPreviewCallback 方法获取缓冲区.
以下是它的发生方式(详细版本):
As others mentioned, you can get a buffer using a Camera.setPreviewCallback method.
Here's how it happens there (a verbose version):
- 用户调用
Camera.startPreview()这是一个原生函数. android_hardware_Camera_startPreview调用C++Camera类的startPreview方法.Camera调用ICamera接口的startPreview方法ICamera对远程客户端进行IPC调用.- 调用
CameraService类的setCameraMode方法. CameraService设置一个窗口显示预览并调用CameraHardwareInterface类的startPreview方法.- 后者尝试在特定
camera_device_t设备上调用start_preview方法.
我没有进一步查找,但它应该会调用驱动程序. - 当图片到达时,调用
CameraService的dataCallback. - 将数据传递给客户端的
handlePreviewData方法. - 客户端要么复制缓冲区,要么直接将其发送到
ICameraClient. ICameraClient通过IPC将其发送到Camera.Camera调用已注册的监听器并将缓冲区传递给JNI.- 它调用 Java 类中的回调.如果用户使用
Camera.addCallbackBuffer提供了一个缓冲区,则它首先复制到缓冲区. - 最后,Java 类
Camera处理消息并调用Camera.PreviewCallback的onPreviewFrame方法.
- User calls
Camera.startPreview()which is a native function. android_hardware_Camera_startPreviewcallsstartPreviewmethod of C++Cameraclass.Cameracalls astartPreviewmethod ofICamerainterfaceICameramakes anIPCcall to remote client.- It calls a
setCameraModemethod ofCameraServiceclass. CameraServicesets a window to display a preview and calls astartPreviewmethod ofCameraHardwareInterfaceclass.- The latter tries to call a
start_previewmethod on particularcamera_device_tdevice.
I didn't looked up further but it should perform a call to the driver. - When image arrives,
dataCallbackofCameraServiceis invoked. - It passes data to
handlePreviewDatamethod of client. - Client either copies the buffer or sends it directly to the
ICameraClient. ICameraClientsends it overIPCto theCamera.Cameracalls a registered listener and passes buffer toJNI.- It invokes a callback in Java class. If user provided a buffer with
Camera.addCallbackBufferthen it copies to the buffer first. - Finally Java class
Camerahandles the message and invokes aonPreviewFramemethod ofCamera.PreviewCallback.
如您所见,调用了 2 个 IPC 调用,并且在步骤 10、11 中至少复制了两次缓冲区.camera_device_t 返回的原始缓冲区的第一个实例是托管在另一个进程中,由于 CameraService 中的安全检查,您无法访问它.
As you can see 2 IPC calls were invoked and buffer was copied at least twice on steps 10, 11. First instance of raw buffer which is returned by camera_device_t is hosted in another process and you cannot access it due to security checks in CameraService.
但是,当您使用 Camera.setPreviewTexture 或 Camera.setPreviewDisplay 设置预览表面时,它会直接传递给相机设备并实时刷新,而无需上面的所有链条.正如它的文档所说:
However, when you set a preview surface using either Camera.setPreviewTexture or Camera.setPreviewDisplay it is be passed directly to the camera device and refreshed in realtime without participation of all the chain above. As it's documentation says:
处理一个由屏幕合成器管理的原始缓冲区.
Handle onto a raw buffer that is being managed by the screen compositor.
Java 类 Surface 有一个方法来检索它的内容:
Java class Surface has a method to retrieve it's contents:
public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);
但是这个 API 是隐藏的.参见 这个问题 了解使用方法.
But this API is hidden. See i.e. this question for a way to use it.
这篇关于如何使用 JNI 在 C 中获取原始 Android 相机缓冲区?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何使用 JNI 在 C 中获取原始 Android 相机缓冲区
基础教程推荐
- 如何在 Spring @Value 注解中正确指定默认值? 2022-01-01
- 如何在 JFrame 中覆盖 windowsClosing 事件 2022-01-01
- 多个组件的复杂布局 2022-01-01
- 验证是否调用了所有 getter 方法 2022-01-01
- Java Swing计时器未清除 2022-01-01
- 不推荐使用 Api 注释的描述 2022-01-01
- 从 python 访问 JVM 2022-01-01
- 在 Java 中创建日期的正确方法是什么? 2022-01-01
- Java 实例变量在两个语句中声明和初始化 2022-01-01
- 大摇大摆的枚举 2022-01-01
