3

我想在AVAssetWriter. 问题出现了,从 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崩溃。如果我不将缓冲区移动一个字节,它就可以完美地工作(但显然视频文件中的颜色错误)。这里有什么问题?

4

5 回答 5

5

我得出的结论是,将 RGBA 转换为 ARGB 的最快方法是给 glReadPixels 缓冲区移动一个字节

但是,这也会将您的 alpha 值移动 1 个像素。这是另一个建议:

将图片渲染为纹理(使用带有该纹理的 FBO 作为颜色附件)。接下来将该纹理渲染到另一个帧缓冲区,使用 swizzling 片段着色器:

#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
}
于 2012-01-07T18:35:19.533 回答
1

试着打电话

glPixelStorei(GL_PACK_ALIGNMENT,1) 

在 glReadPixels 之前。

文档

GL_PACK_ALIGNMENT

指定内存中每个像素行开头的对齐要求。允许的值为 1(字节对齐)、2(与偶数字节对齐的行)、4(字对齐)和 8(行从双字边界开始)。

默认值为 4(请参阅glGet)。这经常在各种“ OpenGL 陷阱”类型列表中被称为麻烦制造者,尽管这通常更多地与其行填充效果有关,而不是缓冲区对齐。

作为一种替代方法,如果您 malloc 4 个额外字节,glReadPixels 从缓冲区 + 4 开始以 4 字节对齐,然后传递您的 AVAssetWriter 缓冲区 + 3 会发生什么(尽管我不知道 AVAssetWriter 是否更容忍对齐问题) ?

于 2012-01-07T18:12:36.480 回答
1

如果你在缓冲区的末尾放了一个额外的 128 字节的 slack 会发生什么?可能是 OpenGL 试图一次填充 4/8/16/etc 字节以提高性能,并且在缓冲区未对齐或其他情况下出现错误。这不是 OpenGL 中的性能优化第一次在边缘情况下出现问题 :)

于 2012-01-07T17:20:33.450 回答
0

您需要通过执行 memcpy 或其他复制操作来移动字节。修改指针会使它们不对齐,这可能在也可能不在任何底层硬件的能力范围内(DMA 总线宽度、切片粒度等)

于 2012-01-07T17:18:43.177 回答
-1

使用buffer+1将意味着数据不是在 malloc 内存的开头写入,而是一个字节,因此它将写入 malloc 内存的末尾,从而导致崩溃。

如果 iOS 的 glReadPixels 只接受 GL_RGBA 那么我认为你必须自己重新安排它们。

更新,抱歉我错过了你的 malloc 中的 +1,StilesCrisis 可能是正确的崩溃原因。

于 2012-01-07T17:21:14.400 回答