我正在尝试了解 Android 中的图形内存使用/流量,特别是关于使用 MediaCodec
对来自相机的帧进行编码的情况。 .为了做到这一点,我必须了解一堆我不清楚的图形、OpenGL 和 Android 术语/概念。我已经阅读了 Android 图形架构 Material 、一堆 SO 问题和一堆来源,但我仍然感到困惑,主要是因为这些术语似乎在不同的上下文中具有不同的含义。
我从 fadden 的网站查看了 CameraToMpegTest here .我的具体问题是如何 MediaCodec::createInputSurface()
与 Camera::setPreviewTexture()
一起使用.似乎创建了一个 OpenGL 纹理,然后将其用于创建 Android SurfaceTexture
然后可以传递给 setPreviewTexture()
.我的具体问题:
setPreviewTexture()
实际上根据帧从相机进入的内存缓冲区做些什么? SurfaceTexture
的Android描述提到它允许您“将图像流式传输到给定的 OpenGL 纹理”:https://developer.android.com/reference/android/graphics/SurfaceTexture.html#SurfaceTexture(int) . SurfaceTexture
是什么意思在OpenGL纹理之上做什么? MediaCodec::createInputSurface()
返回一个 Android Surface
.据我了解,它是一个 Android Surface
表示缓冲区队列的生产者端,因此它可能是多个缓冲区。 API reference提到“必须使用硬件加速 API 渲染 Surface,例如 OpenGL ES”。相机捕捉到的帧是如何从SurfaceTexture
获取的?对此Surface
那是编码器的输入?我看到 CameraToMpegTest 创建了一个 EGLSurface
使用这个Surface
不知何故,但对 EGL 知之甚少,我没有得到这部分。 编辑:跟进 mstorsjo 的回复:
SurfaceTexture
的代码和 CameraClient::setPreviewTarget()
在 CameraService
更多尝试了解 Camera::setPreviewTexture()
的内部工作原理更好,还有一些问题。对于我最初的理解内存分配的问题,它似乎是 SurfaceTexture
创建一个 BufferQueue
和 CameraService
通过相关的IGraphicBufferProducer
到平台相机 HAL 实现。然后,相机 HAL 可以适本地设置 gralloc 使用标志(例如 GRALLOC_USAGE_SW_READ_RARELY | GRALLOC_USAGE_SW_WRITE_NEVER | GRALLOC_USAGE_HW_TEXTURE
),还可以从此 BufferQueue
中取出缓冲区.所以相机捕捉帧的缓冲区是gralloc分配的缓冲区,带有一些特殊的使用标志,如GRALLOC_USAGE_HW_TEXTURE
。 .我在具有统一内存架构的 ARM 平台上工作,因此 GPU 和 CPU 可以访问相同的内存,那么 GRALLOC_USAGE_HW_TEXTURE
会产生什么样的影响?标志有关于如何分配缓冲区? SurfaceTexture
的 OpenGL (ES) 部分似乎主要作为 GLConsumer
的一部分来实现魔法似乎在updateTexImage()
.是否为 OpenGL (ES) 纹理分配了额外的缓冲区,或者是否可以使用由相机填充的同一个 gralloc 缓冲区?此处是否需要进行一些内存复制才能将相机像素数据从 gralloc 缓冲区获取到 OpenGL (ES) 纹理中?我想我不明白什么叫 updateTexImage()
做。 最佳答案
setPreviewCallback
或 setPreviewCallbackWithBuffer
)。这个不透明的句柄,即纹理,可以在 OpenGL 绘图中使用。 glGenTextures
为纹理创建一个“名称”/句柄。 - 它基本上只是一个整数。在普通的 OpenGL (ES) 中,您将使用 OpenGL 函数来为纹理分配实际存储空间并用内容填充它。在此设置中,SurfaceTexture
提供 Android 级别的 API/抽象来使用数据填充纹理(即,使用正确的标志为其分配存储空间,为其提供大小和内容) - 允许您传递 SurfaceTexture
到可以用数据填充它的其他类(Camera
直接采用 SurfaceTexture
,或者包装在 Surface
类中以便能够在其他上下文中使用它)。这允许使用内容有效地填充 OpenGL 纹理,而无需将原始数据缓冲区传递到应用程序的进程并让您的应用程序将其上传到 OpenGL。 SurfaceTexture
。 , 以允许 Camera
用相机图片填充它。 SurfaceTexture
类提供回调,当 Camera
时发出信号已更新内容。当接收到此回调时,将激活 EGL 上下文并将一帧渲染到 EGL 上下文输出目标(即编码器输入)中。渲染本身并没有做任何花哨的事情,而是将输入纹理直接复制到输出中。 这听起来可能很迂回,但它确实带来了一些好处:
setPreviewCallback
当涉及到更高分辨率时,API 是一个瓶颈。 关于android - 了解Android相机SurfaceTexture和MediaCodec Surface的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42756489/