【问题标题】:Map Android memory to GraphicBuffer with zero-copy使用零拷贝将 Android 内存映射到 GraphicBuffer
【发布时间】:2017-05-17 00:54:17
【问题描述】:

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

特别是,如何从 void* 创建零拷贝 ANativeWindowBuffer 或 GraphicBuffer ?我需要能够为 4K 视频每秒映射 30 个这样的 GraphicBuffers。 我搜索了互联网和示例,但不知道如何在没有 memcpy 的情况下执行此操作(这会降低我的帧速率)。

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

【问题讨论】:

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


    【解决方案1】:

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

    我不熟悉相机 API,但您想要做的是从任何将使用缓冲区的系统获取 Surface,并将该 Surface 提供给相机 API,以便它们生成缓冲区。在下面,这将分配一组与生产者(相机)和消费者兼容的 GraphicBuffers,如果硬件能够做到这一点,则通过它们以零副本流式传输帧。

    【讨论】:

      【解决方案2】:

      补充一下 Jesse 所说的,IMemory 是与 GraphicBuffer 不同的共享内存缓冲区(基于 ashmem),它们不直接兼容。

      此外,通过直接连接到 dataCallbackTimestamp,您可以跨出公共相机 API 进入实施细节。 这些不能保证在不同版本之间保持相同,因此使用它可能会在未来(或过去)操作系统版本中破坏您的应用程序。

      由于您使用的是已弃用的相机 API(好吧,它的内部)和旧的 HAL,如果没有某种 memcpy,您将无能为力。

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

      【讨论】:

        猜你喜欢
        • 2015-06-13
        • 2020-01-05
        • 2019-02-21
        • 1970-01-01
        • 1970-01-01
        • 2011-06-27
        • 1970-01-01
        • 1970-01-01
        • 2014-10-25
        相关资源
        最近更新 更多