我正在使用OpenGL ES 2.0编写一个iOS视频应用程序来执行图像处理。在OpenGl ES 2.0 for iOS中写入单通道像素缓冲区
我的输入和输出格式是YUV 4:2:0,这是iPhone 3GS之后大多数设备的原生像素格式。对于A5处理器及更高版本,我只需创建一个亮度纹理和色度纹理,然后将它们附加到屏幕外帧缓冲区。创建我texutre如下:
CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault,
_videoTextureCache,
pixelBuffer,
NULL,
GL_TEXTURE_2D,
GL_RED_EXT,
(int)CVPixelBufferGetWidthOfPlane(pixelBuffer, 0),
(int)CVPixelBufferGetHeightOfPlane(pixelBuffer, 0),
GL_RED_EXT,
GL_UNSIGNED_BYTE,
0,
&lumaTexture);
,然后我把它安装到程序,如:
glActiveTexture([self getTextureUnit:textureUnit]);
glBindTexture(CVOpenGLESTextureGetTarget(texture), CVOpenGLESTextureGetName(texture));
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
if(uniform != -1)
{
glUniform1i(uniforms[uniform], textureUnit);
}
在我的着色器那么我可以简单地做:
gl_FragColor.r = texture2D(SamplerY, textureRead).r;
来分配亮度值添加到缓冲区,并将生成的视频帧保存到磁盘。
不幸的是我遇到了iPhone 4的问题,因为它没有使用A5处理器,因此不支持GL_RED_EXT
。
然后我试图找出一种方法来写入OpenGL ES中的1通道luma缓冲区,但仍然遇到问题。我尝试将GL_RED_EXT
更改为GL_LUMINANCE
,但发现无法写入GL_LUMINANCE
。
我然后试图登记颜色附件和深度附件为:
GLuint colorRenderbuffer;
glGenRenderbuffers(1, &colorRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGB8_OES, (int)CVPixelBufferGetWidthOfPlane(renderData.destinationPixelBuffer, 0), (int)CVPixelBufferGetHeightOfPlane(renderData.destinationPixelBuffer, 0));
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, colorRenderbuffer);
GLuint depthRenderbuffer;
glGenRenderbuffers(1, &depthRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, (int)CVPixelBufferGetWidthOfPlane(renderData.destinationPixelBuffer, 0), (int)CVPixelBufferGetHeightOfPlane(renderData.destinationPixelBuffer, 0));
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
GL_RENDERBUFFER, depthRenderbuffer);
写入深度缓冲器在我的片段着色器:
gl_FragDepth.z = texture2D(SamplerY, textureRead).r;
然后将结果写入到像素缓冲器作为:
glReadPixels(0, 0, (int)CVPixelBufferGetWidthOfPlane(renderData.destinationPixelBuffer, 0), (int)CVPixelBufferGetHeightOfPlane(renderData.destinationPixelBuffer, 0), GL_LUMINANCE, GL_UNSIGNED_BYTE, CVPixelBufferGetBaseAddressOfPlane(renderData.destinationPixelBuffer, 0));
但我再次读到的规格,OpenGL ES 2.0没有支持直接写入深度缓冲区。
所以我没有明显的方式来创建一个单通道颜色附件,我不知道如何写入到RGB颜色附件,只复制一个通道到我的像素缓冲区。
对不起,很长的文章,只是想给尽可能多的信息。
任何想法?
如果我正确理解你,你想要通过OpenGL ES处理保持Y和UV通道分离,而不是像大多数情况下那样简单地将它们转换为RGB?我不确定在整个过程中保持YUV内容的好处将抵消必须为Y和UV渲染场景两次的缺点。唯一可能会受益的情况是AV基金会最终录制的电影,但即使在那里,它似乎也很好地利用BGRA帧。 –
您好@BradLarson,实际上如果您在内存中保存了几帧用于流畅的视频录制,那么保留YUV420帧可能会有好处,因为它们占用的内存要少得多。任何想法如何在一次传递中将YUV帧渲染为YUV? –
@DeepakSharma - OpenGL ES纹理是RGBA,因此您需要为整个Y和UV维护单独的平面。同样,您需要执行多个渲染通道或使用OpenGL ES 3.0并具有多个渲染目标。你需要编写所有的片段着色器来在每个阶段支持这些独立的平面。 –