Iphone 将纹理复制到PixelBufferRef(CVPixelBufferRef)

Iphone 将纹理复制到PixelBufferRef(CVPixelBufferRef),iphone,ios,opengl-es,textures,avassetwriter,Iphone,Ios,Opengl Es,Textures,Avassetwriter,我使用的API只提供纹理对象的整数id,我需要将该纹理的数据传递给AVAssetWriter来创建视频 我知道如何从pixel buffer(CVPixelBufferRef)创建CVOpenGLESTexture对象,但在我的例子中,我必须以某种方式复制只有id可用的纹理的数据 换句话说,我需要将opengl纹理复制到基于pixelbuffer的纹理对象。可能吗?如果是,那怎么办 在我的示例代码中,我有如下内容: void encodeFrame(Gluint textureOb)

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

我知道如何从pixel buffer(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];

    }
谢谢你的提示和答案

注意:iOS上不提供glGetTexImage

更新:

@拉森博士,我无法设置API的纹理ID。实际上,我不能要求第三方API使用我自己创建的纹理对象

在阅读了这些答案之后,我明白了我需要:

1-将像素缓冲区关联的纹理对象作为颜色附着附着到texFBO。 对于每个帧:

2-绑定从API获得的纹理

3-绑定texFBO和调用抽屉元件

我在这个代码中做错了什么

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

更新2:
在Brad Larson回答的帮助下,使用正确的着色器解决了问题。我不得不使用着色器,这是Opengl ES 2.0的基本要求。是的,非常不幸的是,glGetTexImage不是ios。当我为cocos2d实现我的CCMutableTexture2D类时,我很难做到这一点

在推送到gpu之前缓存图像 如果您查看源代码,您会注意到,最终我将图像的像素缓冲区缓存到我的CCMutableTexture2D类中,而不是在推送到gpu后丢弃它的正常路径

使用FBO和glReadPixels 可悲的是,我认为这种方法可能不适合您,因为您正在使用纹理数据创建某种视频,并且保留我们缓存的每个像素缓冲区会占用大量内存。另一种方法是动态创建FBO,以便使用glReadPixels填充像素缓冲区。我不太确定这种方法会有多成功,但这里有一个很好的例子:

要在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的后备方法)。

如果你打算创建纹理,那么从iOS 5.0开始,有一种更快的方法来访问它后面的字节。您可以使用纹理缓存直接读取和写入纹理后面的备份字节,如我在此处所述:。这是一种直接内存访问,不依赖于
glReadPixels()
glTexImage2D()
。非常感谢,请查看问题的“更新”部分。@Usman.3D-如果您无法提供用于纹理的ID,并且无法访问纹理渲染的时间,您需要将其重新渲染到屏幕外FBO以提取其颜色字节。然后,您可以使用我描述的任何一种方法:glReadPixels()从FBO中提取,或者使用绑定纹理与纹理缓存配对以更快地捕获结果。非常感谢Larson博士。非常感谢你的帮助。我在为你刚才提到的东西编码。拉森,我再次需要你的宝贵意见。请参阅更新2。非常感谢.@Usman.3D-上面的glReadPixels()在哪里?如果没有使用该方法读取像素,则需要正确设置纹理缓存,并将相关纹理绑定到渲染FBO。确保您遵循了此处的所有设置步骤:并且使用相同的OpenGL ES上下文进行纹理上载和纹理缓存。