将纹理复制到PixelBuffer(CVPixelBufferRef)

Usm*_*.3D 3 iphone textures opengl-es ios avassetwriter

我使用的API只给出了纹理对象的整数id,我需要将该纹理的数据传递给AVAssetWriter来创建视频.

我知道如何从像素缓冲区(CVPixelBufferRef)创建CVOpenGLESTexture对象,但在我的情况下,我必须以某种方式复制只有id可用的纹理数据.

换句话说,我需要将opengl纹理复制到基于pixelbuffer的纹理对象.可能吗?如果是,那怎么样?

在我的示例代码中,我有类似的东西:

   void encodeFrame(Gluint textureOb)
    {

    CVPixelBufferPoolCreatePixelBuffer (NULL, [assetWriterPixelBufferAdaptor pixelBufferPool], &pixelBuffer[0]);

    CVOpenGLESTextureCacheCreateTextureFromImage (kCFAllocatorDefault, coreVideoTextureCache, pixelBuffer[0],
                                                          NULL, // texture attributes
                                                          GL_TEXTURE_2D,
                                                          GL_RGBA, // opengl format
                                                          (int)FRAME_WIDTH,
                                                          (int)FRAME_HEIGHT,
                                                          GL_BGRA, // native iOS format
                                                          GL_UNSIGNED_BYTE,
                                                          0,
                                                          &renderTexture[0]);


    CVPixelBufferLockBaseAddress(pixelBuffer[pixelBuffernum], 0);

//Creation of textureOb is not under my control. 
//All I have is the id of texture. 
//Here I need the data of textureOb somehow be appended as a video frame. 
//Either by copying the data to pixelBuffer or somehow pass the textureOb to the Adaptor.

    [assetWriterPixelBufferAdaptor appendPixelBuffer:pixelBuffer[0] withPresentationTime:presentationTime];

    }
Run Code Online (Sandbox Code Playgroud)

感谢您的提示和解答.

PS glGetTexImage不适用于iOS.

更新:

@Dr.Larson,我无法为API设置纹理ID.实际上我不能指示第三方API使用我自己创建的纹理对象.

经过答案之后,我理解的是我需要:

1-将与pixelbuffer相关联的纹理对象作为颜色附件附加到texFBO.对于每个帧:

2-绑定从API获得的纹理

3-绑定texFBO并调用drawElements

我在这段代码中做错了什么?

PS我还不熟悉着色器,所以我现在很难使用它们.

更新2: 借助Brad Larson的答案并使用正确的着色器解决了这个问题.我不得不使用着色器,这是Opengl ES 2.0的基本要求

Bra*_*son 5

要从iOS上的OpenGL ES读取数据,您基本上有两个路径:使用glReadPixels()或使用纹理缓存(仅限iOS 5.0+).

事实上,你只有一个纹理ID,并且没有别的东西,这有点奇怪,并限制你的选择.如果您无法在此第三方API中设置要使用的纹理,则需要将该纹理重新渲染到屏幕外帧缓冲区,以便使用glReadPixels()纹理缓存或为纹理缓存提取像素.要做到这一点,你可以使用尺寸与纹理尺寸相同的FBO,一个简单的四边形(两个三角形组成一个矩形),以及一个直通着色器,它只显示输出帧缓冲区中纹理的每个纹素.

此时,您可以使用glReadPixels()将您的字节拉回到CVPixelBufferRef的内部字节数组中,或者最好使用纹理缓存来消除对该读取的需要.我将介绍如何在此答案中为该方法设置缓存,以及如何将其提供给AVAssetWriter.您需要将屏幕外FBO设置为使用CVPixelBufferRef的关联纹理作为渲染目标,以使其工作.

但是,如果您可以设置用于此渲染纹理的ID,则可以避免重新渲染它以获取其像素值.像我在上面链接的答案中描述的那样设置纹理缓存,并将该像素缓冲区的纹理ID传递给您正在使用的第三方API.然后它将渲染到与像素缓冲区关联的纹理中,您可以直接从中进行记录.这是我在GPUImage框架中用来加速从OpenGL ES录制视频的glReadPixels()方法(该方法是iOS 4.x的后备).