不幸的是,没有关于这些新功能的任何文档。你现在能找到的最好的是在CVOpenGLESTextureCache.h 头文件中,你会在其中看到函数参数的基本描述:
/*!
@function CVOpenGLESTextureCacheCreate
@abstract Creates a new Texture Cache.
@param allocator The CFAllocatorRef to use for allocating the cache. May be NULL.
@param cacheAttributes A CFDictionaryRef containing the attributes of the cache itself. May be NULL.
@param eaglContext The OpenGLES 2.0 context into which the texture objects will be created. OpenGLES 1.x contexts are not supported.
@param textureAttributes A CFDictionaryRef containing the attributes to be used for creating the CVOpenGLESTexture objects. May be NULL.
@param cacheOut The newly created texture cache will be placed here
@result Returns kCVReturnSuccess on success
*/
CV_EXPORT CVReturn CVOpenGLESTextureCacheCreate(
CFAllocatorRef allocator,
CFDictionaryRef cacheAttributes,
void *eaglContext,
CFDictionaryRef textureAttributes,
CVOpenGLESTextureCacheRef *cacheOut) __OSX_AVAILABLE_STARTING(__MAC_NA,__IPHONE_5_0);
更难的元素是属性字典,不幸的是,您需要找到它的示例才能正确使用这些功能。 Apple 提供了 GLCameraRipple 和 RosyWriter 示例,展示了如何使用带有 BGRA 和 YUV 输入颜色格式的快速纹理上传路径。 Apple 还在 WWDC 上提供了 ChromaKey 示例(可能仍可与视频一起访问),演示了如何使用这些纹理缓存从 OpenGL ES 纹理中提取信息。
我刚刚在我的GPUImage 框架中进行了这种快速纹理上传(该链接中提供了源代码),所以我将列出我能够从中解析出的内容。首先,我使用以下代码创建纹理缓存:
CVReturn err = CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, (__bridge void *)[[GPUImageOpenGLESContext sharedImageProcessingOpenGLESContext] context], NULL, &coreVideoTextureCache);
if (err)
{
NSAssert(NO, @"Error at CVOpenGLESTextureCacheCreate %d");
}
这里引用的上下文是为 OpenGL ES 2.0 配置的 EAGLContext。
我使用它来将来自 iOS 设备摄像头的视频帧保存在视频内存中,我使用以下代码来执行此操作:
CVPixelBufferLockBaseAddress(cameraFrame, 0);
CVOpenGLESTextureRef texture = NULL;
CVReturn err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, coreVideoTextureCache, cameraFrame, NULL, GL_TEXTURE_2D, GL_RGBA, bufferWidth, bufferHeight, GL_BGRA, GL_UNSIGNED_BYTE, 0, &texture);
if (!texture || err) {
NSLog(@"CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err);
return;
}
outputTexture = CVOpenGLESTextureGetName(texture);
glBindTexture(GL_TEXTURE_2D, outputTexture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// Do processing work on the texture data here
CVPixelBufferUnlockBaseAddress(cameraFrame, 0);
CVOpenGLESTextureCacheFlush(coreVideoTextureCache, 0);
CFRelease(texture);
outputTexture = 0;
这会从纹理缓存中创建一个新的 CVOpenGLESTextureRef,代表 OpenGL ES 纹理。此纹理基于相机传入的 CVImageBufferRef。然后从 CVOpenGLESTextureRef 中检索该纹理并为其设置适当的参数(这在我的处理中似乎是必要的)。最后,我对纹理进行处理并在完成后进行清理。
这种快速上传过程对 iOS 设备产生了真正的影响。在 iPhone 4S 上上传和处理单个 640x480 帧视频的时间从 9.0 毫秒缩短到了 1.8 毫秒。
我也有heard that this works in reverse,这可能允许在某些情况下替换glReadPixels(),但我还没有尝试过。