【问题标题】:Android camera native access : startPreview() vs startRecording()Android 相机原生访问:startPreview() vs startRecording()
【发布时间】:2014-02-17 10:22:21
【问题描述】:

尝试使用 Android ICS 中的本机代码让相机工作: 大多数手册参考 startPreview() 方法。但浏览 AOSP 代码时,我还发现 <Camera.h> 中的 'startRecording()' 方法。 Here说是来自接口ICameraRecordingProxy "允许录像机在录制过程中接收视频帧"

所以问题是 - 就性能而言,“startRecording”方法是否比“startPreview”更有效?

进入本机代码的唯一目标是性能,Java 'Camera' 太慢,而且 OpenCV 也没有提供所需的 FPS 水平。..

编辑:目标平台为:API level=17,设备 Allwinner A31 开发板,1280x720x30FPS。 任务是从相机捕获帧,修改它们,编码(H264)并存储到 SD 卡。 纯 java MediaRecorder 用 1280x720x30 写入 mp4 文件。不需要在屏幕上显示实时预览。

本机模式下的 OpenCV-demo1 提供 1920x1080x2(在 java 模式下相同)。具有空 PreviewCallback 最大 FPS 的简单 java 方法是 15。

提前谢谢你..

【问题讨论】:

  • Grafika 可以从相机预览中录制——在 2012 Nexus 7 上以 30fps 的速度工作,除了 Java 代码什么都没有。 (不过,MediaCodec 确实需要 API 16+。)请参阅 github.com/google/grafika 中的“显示 + 捕获相机”。如果您主要对直接录音感兴趣,也许您想要的是MediaRecorder (developer.android.com/reference/android/media/…)?
  • 感谢您提供链接,但 Grafika “一个 SDK 应用程序,为 API 18 (Android 4.3) 开发”,我的目标 SDK 是 17 :( 尝试构建和启动 - 不走运。MediaRecorder 很好并且效果很好,但我需要即时修改帧
  • Grafika 所做的一些工作将在 API 16 中运行。在 API 18 之前您无法获得的是 Surface 输入到 MediaCodec,不幸的是,这对于您的性能很重要正在做。根据您计划进行的帧修改类型,API 18 提供的内容可以通过其他方式为您提供帮助……可以在此处找到使用一些简单的基于 GPU 着色器的图像过滤器的 Grafika 演示:youtube.com/watch?v=kH9kCP2T5Gg
  • 非常感谢,'grafika' 很有趣,但问题是目标设备无法升级到 API 18 :(
  • 针对较旧的 API 非常普遍,通常是出于市场份额的原因。您应该在问题中提及目标 API,并了解您计划对帧进行什么样的修改(即简单的帧插入/删除、精美的图像过滤,无论您是想在 YUV 还是 RGB 中工作)空间等)。您是否需要在录制的同时在屏幕上显示预览?您说您没有达到目标 FPS 速率;你需要什么速率,什么分辨率?你的目标设备是什么?

标签: android android-ndk camera


【解决方案1】:

就性能而言,使用原生相机没有任何好处。在 Java 中使用 Camera.setPreviewCallbackWithBuffer() (off UI thread) 每秒可提供与任何本机替代方案一样多的帧数。但在某些 SOC 上,例如三星,相机输出可以直接(0-copy)与HW h264编码器连接,这自然提供了出色的吞吐量。这就是 pure java MediaRecorder 在后台所做的。如果涉及对缓冲区的任何操作,您将无法实现相同的效果。

【讨论】:

  • 为什么?根据stackoverflow.com/questions/10670953/… 框架数据至少复制了几次才来到java 世界。因此任何对框架的 java 访问都应该比本机慢。我正在考虑从 AOSP 获取 MediaRecorder 源并对其进行修改以使用略低于 MediaRecorder 提供的 FPS 完成工作。它应该工作吗?
  • 这个解释没有说服力。他们算作 2 个 memcpy 通常只传递指针、切换虚拟地址等。我应该重复一遍,在同一系统进程中将摄像机直接连接到编码器确实给 MediaRecoder 带来了一些优势。使用 A31 CPU,如果您使用 2 个切片线程进行超快 x264 编码,您应该能够以 15 FPS 或更高的速度实现 720p。
  • 修改 AOSP MediaRecorder 无济于事,因为实际繁重的工作发生在系统媒体服务中,当您尝试修改数据时,您将立即失去所有优势。
  • 你认为原则上(java/native)有可能达到 1280x720x30 FPS 捕获、水印、编码和存储视频到 SD 卡吗?
  • 我所知道的 x264 在现代四核设备(三星 Note 10)上的最佳结果大约是吞吐量的一半:我们可以达到 800x480x30。使用硬件编码器(通过 stagefright),1280x720x30 是可能的,但我没有 A31 的第一手经验。
【解决方案2】:

关闭主题: 使用本机访问相机并使用硬件 H264 编码器,我能够在 FPS=30 的情况下达到 1280x720。还可以动态修改(水印)数据,保持高 FPS。 没有其他方法 - 任何 JAVA 或 OpenCV 都可以提供超过 15 FPS(可能是我没有努力......)

startRecording() 完美运行

感谢cmets

【讨论】:

  • 您使用的是原生全志编码器 c 代码吗?像 AWcodecTest.cpp 之类的东西? dl.linux-sunxi.org/SDK/A23-v1.0/unpacked/A23/android/hardware/…
  • 不,我使用了 AOSP 的一部分:#include
  • 你能提供一些示例代码吗?非常感谢。
  • 如果你能分享一个它的示例项目将会非常有帮助。
  • 显示代码会有很大帮助!毕竟这就是 SO 的目的。
【解决方案3】:
dataCallbackTimestamp(nsecs_t timestamp, int32_t msgType, const sp<IMemory>& data) 

msgType==CAMERA_MSG_VIDEO_FRAME

以内部形式提供数据。不保证纯 yuv 帧数据。例如,data.get()-&gt;size() 可以大于 yuv 帧大小,或者可以是一些 20 字节大小的数据结构,用于保存在相机缓冲区列表中某处的真实(?)帧缓冲区。

所以,这个话题还没有完成。 :)

【讨论】:

  • 是的,它发生了,我的 3 个测试设备之一提供了正确的 yuv 帧而没有跨步(如在预览模式下),在这种情况下一切正常。
  • 有些相机可以在流模式下提供 yuv 帧。尝试设置 camera->storeMetaDataInBuffers(false)。成功后,相机工作正常,但可能会发生一次复制操作(例如从 GPU 内存到 HOST)。在 Android API21 之前,没有任何通用案例可以让 yuv 处于流模式。一些元数据表示仅用于硬件到硬件的数据传输,在这种情况下,只有供应商知道如何解释它们。它也解决了问题,但仅适用于特定情况,而不是一般情况。
  • 一些元数据格式很简单。在 libstagefright 中查找 extractGrallocDatakMetadataBufferTypeGrallocSource 案例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多