java - 如何使用 JNI 在 C 中获取原始 Android 相机缓冲区?

标签 java android c camera java-native-interface

我一直在彻底搜索 Google 和 StackOverflow,但找不到这个。也许我错过了一些明显的东西。谢谢!

(这是因为预览回调的Java实现[即使有缓冲区]效率太低。)

最佳答案

我对主题进行了一些调查。这个presentation (从第277页开始,中文)帮助很大。

相机预览调用链

正如其他人提到的,您可以使用 Camera.setPreviewCallback 方法获取缓冲区。
以下是它的发生方式(详细版本):

  1. 用户调用 Camera.startPreview() 这是一个原生函数。
  2. android_hardware_Camera_startPreview 调用C++ Camera 类的startPreview 方法。
  3. Camera调用ICamera接口(interface)的startPreview方法
  4. ICamera 对远程客户端进行 IPC 调用。
  5. 调用CameraService类的setCameraMode方法。
  6. CameraService 设置一个窗口显示预览并调用CameraHardwareInterface 类的startPreview 方法。
  7. 后者尝试在特定 camera_device_t 设备上调用 start_preview 方法。
    我没有进一步查找,但它应该会调用驱动程序。
  8. 当图片到达时,调用CameraServicedataCallback
  9. 将数据传递给客户端的handlePreviewData方法。
  10. 客户端要么复制缓冲区,要么直接将其发送到 ICameraClient
  11. ICameraClient 通过IPC 将其发送到Camera
  12. Camera 调用已注册的监听器并将缓冲区传递给 JNI
  13. 它调用 Java 类中的回调。如果用户使用 Camera.addCallbackBuffer 提供了一个缓冲区,则它首先复制到缓冲区。
  14. 最后,Java 类 Camera 处理消息并调用 Camera.PreviewCallbackonPreviewFrame 方法。

如您所见,调用了 2 个 IPC 调用,并且在步骤 10、11 中至少复制了两次缓冲区。camera_device_t 返回的原始缓冲区的第一个实例是托管在另一个进程中,由于 CameraService 中的安全检查,您无法访问它。

预览表面

但是,当您使用 Camera.setPreviewTextureCamera.setPreviewDisplay 设置预览表面时,它会直接传递给相机设备并实时刷新,而无需上面的所有链条。正如它的文档所说:

Handle onto a raw buffer that is being managed by the screen compositor.

Java 类 Surface 有一个方法来检索它的内容:

public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);

但是这个 API 是隐藏的。见即this question一种使用它的方法。

关于java - 如何使用 JNI 在 C 中获取原始 Android 相机缓冲区?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10670953/

相关文章:

java - 使用 Java 应用程序更改默认 Windows 语言

java - 使用页面在 jsp 中显示长列表的值

java - 使用输出流将文件上传到 Google Drive

ios - 是否可以将旧的 xcode 代码更新为最新的 xcode?

java - 错误 : sqlite returned: error code = 1, msg = 没有这样的表

android - 当主要 Activity 处于焦点状态时,用于滑过主要 Activity 的自定义 View 是否可以部分显示自己。

java - AsyncTask 在后台方法 try/catch 中执行,两者都被执行

Android MapView半屏白屏错误

c++ - 将宏设置为值,如果为空

c - 运行 libspotify 示例