将Android内存映射到具有零拷贝的GraphicBuffer

时间:2017-05-17 00:54:18

标签: android c++ graphics android-ndk ion

我正在用C ++编写一个Android应用程序,并希望从包含YUV420sp图像的内存块中获取GraphicBuffer。具体来说,我有一个来自相机的dataCallbackTimestamp回调函数的IMemory,它给了我一块带有视频帧图像的内存块,我想把它添加到BufferQueue而不用做memcpy。我正在使用HAL,并且我的客户端硬件上没有可用的HAL3或Camera2(这会使这个变得微不足道)。

特别是,如何从void *中创建零拷贝ANativeWindowBuffer或GraphicBuffer?我需要能够为4K视频每秒映射30个这样的GraphicBuffers。  我已经浏览了互联网和示例,但无法弄清楚如何在没有memcpy(这会杀死我的帧率)的情况下做到这一点。

我可以处理像素格式等,但只需要帮助从内存创建实际的GraphicBuffer。

2 个答案:

答案 0 :(得分:1)

简短的回答是你不能。必须由操作系统根据需要访问它的硬件单元(gpu,摄像机,视频编解码器,显示器等)的要求分配GraphicBuffer背后的内存,必须跨进程安全地共享,等等。不符合这些要求。

我不熟悉相机API,但你要做的是从任何消耗缓冲区的系统中获取Surface,并将Surface提供给相机API以便它们生成缓冲区。在下面,这将分配一组与生产者(相机)和消费者兼容的GraphicBuffers,并且如果硬件具有这种能力,则通过零流复制流帧。

答案 1 :(得分:0)

除了Jesse所说的,IMemory是一个与GraphicBuffer不同的共享内存缓冲区(基于ashmem),并且它们不是直接兼容的。

此外,通过直接挂钩到dataCallbackTimestamp,您将步入公共摄像头API之外的实现细节。 这些不能保证保持相同的发布版本,因此您可能会冒着使用它在未来(或过去)OS版本上破坏应用程序的风险。

由于您正在使用已弃用的相机API(以及它的内部)和旧的HAL,因此如果没有某种类型的memcpy,您就无法做到这一点。

您可以尝试将GPU SurfaceTexture作为预览传递给相机API,然后将EGL中的4K纹理从MediaCodec绘制到Surface(假设您正在尝试对视频进行编码,无论如何 - 不确定您的GraphicBuffers在哪里)。