Mik*_*ney 8 android opengl-es android-camera egl mediacodec
我正在尝试了解Android中的图形内存使用/流,特别是关于使用编码来自相机的帧的方面MediaCodec。为了做到这一点,我必须了解许多我不清楚的图形,OpenGL和Android术语/概念。我已经阅读了Android图形体系结构材料,一系列SO问题和大量资源,但我仍然感到困惑,主要是因为在不同的上下文中术语似乎具有不同的含义。
我已经从fadden的站点这里查看了CameraToMpegTest 。我的具体问题是如何MediaCodec::createInputSurface()与结合使用Camera::setPreviewTexture()。似乎先创建了OpenGL纹理,然后将其用于创建一个Android SurfaceTexture,然后可以将其传递给setPreviewTexture()。我的具体问题:
setPreviewTexture()帧从相机转到哪个内存缓冲区,调用实际上会做什么?SurfaceTexture提到它允许您“将图像流式传输到给定的OpenGL纹理”:https : //developer.android.com/reference/android/graphics/SurfaceTexture.html#SurfaceTexture(int)。SurfaceTexture在OpenGL纹理之上做什么?MediaCodec::createInputSurface()返回一个Android Surface。据我了解,Android Surface代表缓冲区队列的生产方,因此它可能是多个缓冲区。该API参考提到,“表面必须用硬件加速API来呈现,如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似乎主要是作为的一部分实现的GLConsumer,而魔术似乎在中updateTexImage()。是否为OpenGL(ES)纹理分配了其他缓冲区,或者是否可以使用相机填充的同一gralloc缓冲区?是否需要在此处进行一些内存复制,才能将相机像素数据从gralloc缓冲区获取到OpenGL(ES)纹理中?我想我不明白打电话的updateTexImage()意思。这意味着相机通过不透明的手柄提供输出帧,而不是在应用程序地址空间(如果使用setPreviewCallback或setPreviewCallbackWithBuffer)中用户提供的缓冲区中提供输出帧。这种不透明的手柄(纹理)可以在OpenGL绘图中使用。
几乎。在这种情况下,OpenGL纹理不是物理内存块,而是EGL上下文中可变内存块的句柄。在这种情况下,示例代码本身实际上并没有分配纹理或调整纹理的大小,它仅使用glGenTextures- 为纹理创建“名称” /句柄-它基本上只是一个整数。在普通的OpenGL(ES)中,您将使用OpenGL函数为纹理分配实际的存储空间并为其填充内容。在此设置中,SurfaceTexture提供了一个Android级API /抽象来用数据填充纹理(即,使用正确的标志为其分配存储空间,提供其大小和内容)-允许您将传递SurfaceTexture给其他可以填充纹理的类数据(无论是Camera采用一个SurfaceTexture直接,或包裹在Surface类,以便能够在其他上下文中使用它)。这样就可以有效地用内容填充OpenGL纹理,而不必将原始数据的缓冲区传递到应用程序的进程中,也无需将应用程序将其上载到OpenGL。
(以相反的顺序回答点3和4。)OpenGL(ES)是用于绘制的通用API。在正常/原始设置中,考虑一个游戏,您会为游戏内容的不同部分(背景,道具,演员等)设置许多纹理,然后使用OpenGL API将其绘制到屏幕上。可以或多或少地将纹理直接复制到屏幕上,或将其包裹在由三角形构成的3D对象周围。这就是称为“渲染”的过程,将输入的纹理和三角形集进行绘制。在最简单的情况下,您可以将内容直接呈现到屏幕上。GPU通常也可以对任何其他输出缓冲区进行相同的渲染。在游戏中,通常将某些场景渲染为纹理,
创建一个EGL上下文,用于将摄像机的输出传递到编码器输入。EGL上下文基本上是用于执行OpenGL渲染的上下文。渲染的目标是来自编码器的Surface。也就是说,使用OpenGL绘制的任何图形最终都将出现在编码器输入缓冲区中,而不是在屏幕上。现在,使用OpenGL绘制的场景可以是OpenGL函数调用的任何序列,从而将游戏场景渲染到编码器中。(这是Android Breakout游戏记录器示例的工作。)在上下文中,创建纹理手柄。而不是像通常的游戏图形渲染那样通过从磁盘上加载图片来填充内容的纹理,而是将其制作为SurfaceTexture,以Camera用相机图片填充纹理。的SurfaceTexture类提供了回调,在Camera更新内容时发出信号。收到此回调后,将激活EGL上下文,并将一帧呈现到EGL上下文输出目标(这是编码器输入)中。渲染本身并没有做任何花哨的事情,但是会更多地进行复制,或者直接将输入纹理复制到输出中。
这听起来似乎有些round回,但确实带来了一些好处:
setPreviewCallback当涉及到更高分辨率时,API是一个瓶颈。| 归档时间: |
|
| 查看次数: |
2288 次 |
| 最近记录: |