我希望在AVAssetWriter
的帮助下将使用OpenGL渲染的图像记录到电影文件中。问题出现了,从OpenGL帧缓冲区访问像素的唯一方法是使用glReadPixels,它只支持iOS上的RGBA像素格式。但AVAssetWriter
不支持此格式。在这里,我可以使用ARGB或BGRA。由于可以忽略alpha值,我得出结论,将RGBA转换为ARGB的最快方法是给glReadPixels缓冲移位一个字节:
UInt8 *buffer = malloc(width*height*4+1);
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer+1);
问题是,glReadPixels
电话会导致EXC_BAD_ACCESS
崩溃。如果我不将缓冲区移动一个字节,它可以很好地工作(但显然在视频文件中有错误的颜色)。这有什么问题?
答案 0 :(得分:5)
我得出结论,将RGBA转换为ARGB的最快方法是给glReadPixels缓冲移一个字节
然而,这也会将您的Alpha值移动1个像素。这是另一个建议:
将图片渲染为纹理(使用带有该纹理的FBO作为颜色附件)。接下来将纹理渲染到另一个帧缓冲区,使用一个混合片段着色器:
#version ...
uniform sampler2D image;
uniform vec2 image_dim;
void main()
{
// we want to address texel centers by absolute fragment coordinates, this
// requires a bit of work (OpenGL-ES SL doesn't provide texelFetch function).
gl_FragColor.rgba =
texture2D(image, vec2( (2*gl_FragCoord.x + 1)/(2*image_dim.y),
(2*gl_FragCoord.y + 1)/(2*image_dim.y) )
).argb; // this swizzles RGBA into ARGB order if read into a RGBA buffer
}
答案 1 :(得分:1)
如果在缓冲区的末尾添加额外的128字节松弛会怎样?可能是OpenGL试图一次填充4/8/16 / etc字节以获得性能,并且当缓冲区未对齐或某事时有错误。这不是第一次OpenGL中的性能优化在边缘情况下出现问题:)
答案 2 :(得分:1)
尝试拨打
glPixelStorei(GL_PACK_ALIGNMENT,1)
在glReadPixels之前。
来自docs:
GL_PACK_ALIGNMENT
指定内存中每个像素行开头的对齐要求。 允许的值是 1(字节对齐), 2(行与偶数字节对齐), 4(字对齐),和 8(行以双字边界开始)。
默认值为4(请参阅glGet)。这通常被称为各种“OpenGL pitfalls”类型lists中的麻烦制造者,尽管这通常更多地与其行填充效果相关,而不是缓冲区对齐。
作为一种替代方法,如果你使用malloc 4个额外字节会发生什么,将glReadPixels作为4字节对齐从缓冲区+4开始,然后传递你的AVAssetWriter缓冲区+3(虽然我不知道AVAssetWriter是否更多容忍对齐问题)?
答案 3 :(得分:0)
您需要通过执行memcpy或其他复制操作来移位字节。修改指针将使它们不对齐,这可能是也可能不在任何底层硬件的能力范围内(DMA总线宽度,磁贴粒度等)。
答案 4 :(得分:-1)
使用buffer+1
意味着数据不会写入malloc内存的开头,而是写入一个字节,因此它将写入malloc内存的末尾,导致崩溃
如果iOS的glReadPixels只接受GL_RGBA,那么我认为你必须自己完成并重新安排它们。
更新,对不起我错过了你的malloc中的+1,StilesCrisis可能是关于坠机原因的。