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

时间:2012-05-20 05:14:46

标签: java android c camera java-native-interface

我一直在搜索谷歌和StackOverflow,并且找不到这个。也许我错过了一些明显的东西。谢谢!

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

3 个答案:

答案 0 :(得分:25)

我对话题进行了一些调查。 presentation(来自p.277,中文)有很多帮助。

相机预览调用链

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

  1. 用户调用Camera.startPreview()这是一个原生函数。
  2. android_hardware_Camera_startPreview调用C ++ startPreview类的Camera方法。
  3. Camera调用startPreview接口
  4. ICamera方法
  5. ICamera对远程客户端进行IPC调用。
  6. 它调用setCameraMode类的CameraService方法。
  7. CameraService设置一个窗口以显示预览,并调用startPreview类的CameraHardwareInterface方法。
  8. 后者尝试在特定start_preview设备上调用camera_device_t方法。
    我没有进一步向上看,但应该给司机打电话。
  9. 当图片到达时,会调用dataCallback的{​​{1}}。
  10. 它将数据传递给客户端的CameraService方法。
  11. 客户端可以复制缓冲区或直接将其发送到handlePreviewData
  12. ICameraClient通过ICameraClient将其发送至IPC
  13. Camera调用已注册的侦听器并将缓冲区传递给Camera
  14. 它在Java类中调用回调。如果用户提供了JNI的缓冲区,则它首先复制到缓冲区。
  15. 最后,Java类Camera.addCallbackBuffer处理邮件并调用Camera的{​​{1}}方法。
  16. 正如您所看到的那样,调用了2 onPreviewFrame个调用,并且在步骤10,11中至少复制了两次缓冲区。Camera.PreviewCallback返回的原始缓冲区的第一个实例托管在另一个进程中由于IPC中的安全检查,无法访问它。

    预览表面

    但是,当您使用camera_device_tCameraService设置预览曲面时,它会直接传递到相机设备并实时刷新,而无需参与上述所有链。正如它的文件说:

      

    处理由屏幕合成器管理的原始缓冲区。

    Java类Camera.setPreviewTexture有一个方法来检索它的内容:

    Camera.setPreviewDisplay

    但是这个API是隐藏的。有关使用它的方法,请参见this question

答案 1 :(得分:5)

没有公共API可以做你想要的事情;唯一的官方(即保证工作)方法是通过调用Camera.setPreviewCallback()设置的Java级预览回调。在Android> 3.0,您还可以使用Camera.setPreviewTexture()将预览数据路由到GPU,并使用GLES处理它(或将其读回CPU)。 GPU路径是ICS AOSP相机应用程序用于视频效果的路径。

据推测,OpenCV和其他人已经浏览了Android框架本机代码,并绕过了Java Camera API,直接与下面的服务交谈。

这是相当危险的,因为绝对不能保证这些界面不会在Android版本之间发生变化,因为它们不是公共API的一部分。使用它们现在可能没问题,然后当用户升级他们的设备时,您的应用程序将停止工作。

答案 2 :(得分:1)

你看过OpenCV for Android了吗?他们的advanced tutorials显示了如何使用JNI,并且他们的相机包中有一个NativeProcessor对象。