Cocoa 如何使用AVFoundation从视频中获取openGL纹理?
构建64位本机OSX而非针对10.7+的iOS ap。在可可世界中处理视频文件有些陌生 我希望能够打开视频文件并在openGL渲染IE中显示输出,我希望能够高效地访问视频的帧缓冲区,并将每个帧转换为openGL纹理 从概念上讲,这似乎很简单,但我很难涉过各种旧的和不推荐的示例和选项,所有这些示例和选项最近似乎都被弃用以支持AVFoundation。我可能遗漏了一些东西,但将AVFoundation与OpenGL结合使用的例子似乎不多 更进一步地说,它或多或少完全符合我的要求,只是它是围绕不推荐的QTKit构建的,因此它甚至不会以64位编译 我现在正在阅读AVFoundation的文档,但我仍然不确定尝试从AVFoundation中获取glTexture是否有意义,或者我是否应该在其他地方寻找 使现代化 这就是我最终采用的解决方案。thisLayer.layerSource.videoPlayerOutput是AVPlayerItemVideoOutput对象Cocoa 如何使用AVFoundation从视频中获取openGL纹理?,cocoa,opengl,avfoundation,qtkit,Cocoa,Opengl,Avfoundation,Qtkit,构建64位本机OSX而非针对10.7+的iOS ap。在可可世界中处理视频文件有些陌生 我希望能够打开视频文件并在openGL渲染IE中显示输出,我希望能够高效地访问视频的帧缓冲区,并将每个帧转换为openGL纹理 从概念上讲,这似乎很简单,但我很难涉过各种旧的和不推荐的示例和选项,所有这些示例和选项最近似乎都被弃用以支持AVFoundation。我可能遗漏了一些东西,但将AVFoundation与OpenGL结合使用的例子似乎不多 更进一步地说,它或多或少完全符合我的要求,只是它是围绕不推荐的
if ([thisLayer.layerSource.videoPlayerOutput hasNewPixelBufferForItemTime:playerTime]){
frameBuffer= [thisLayer.layerSource.videoPlayerOutput copyPixelBufferForItemTime:playerTime itemTimeForDisplay:NULL];
CVReturn result= CVOpenGLTextureCacheCreateTextureFromImage(NULL,
textureCache,
frameBuffer,
NULL,
&textureRef);
if(result == kCVReturnSuccess){
// These appear to be GL_TEXTURE_RECTANGLE_ARB
thisLayer.layerSource.vid_glTextureTarget=CVOpenGLTextureGetTarget(textureRef);
thisLayer.layerSource.vid_glTexture=CVOpenGLTextureGetName(textureRef);
thisLayer.layerSource.vid_glTextureSize=NSMakeSize(CVPixelBufferGetWidth(frameBuffer), CVPixelBufferGetHeight(frameBuffer));
thisLayer.layerSource.vid_ciimage=[CIImage imageWithCVImageBuffer:frameBuffer];
CFRelease(textureRef);
CVOpenGLTextureCacheFlush(textureCache, 0);
}else{
NSLog(@"INTERNAL ERROR FAILED WITH CODE: %i",result);
}
CVBufferRelease(frameBuffer);
}
添加到AVAssetReaderTrackOutput的AVAssetReader将输出一个CVPixelBufferRef,您可以指定通过glTexImage或glTexSubImage上传到OpenGL的首选格式。我也在研究这个问题,这是我当前的解决方案:
- (BOOL) renderWithCVPixelBufferForTime: (NSTimeInterval) time
{
CMTime vTime = [self.playeroutput itemTimeForHostTime:CACurrentMediaTime()];
if ([self.playeroutput hasNewPixelBufferForItemTime:vTime]) {
if (_cvPixelBufferRef) {
CVPixelBufferUnlockBaseAddress(_cvPixelBufferRef, kCVPixelBufferLock_ReadOnly);
CVPixelBufferRelease(_cvPixelBufferRef);
}
_cvPixelBufferRef = [self.playeroutput copyPixelBufferForItemTime:vTime itemTimeForDisplay:NULL];
CVPixelBufferLockBaseAddress(_cvPixelBufferRef, kCVPixelBufferLock_ReadOnly);
GLsizei texWidth = CVPixelBufferGetWidth(_cvPixelBufferRef);
GLsizei texHeight = CVPixelBufferGetHeight(_cvPixelBufferRef);
GLvoid *baseAddress = CVPixelBufferGetBaseAddress(_cvPixelBufferRef);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, self.textureName);
glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGB, texWidth, texHeight, 0, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, baseAddress);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
}
return YES;
}
但是,我想知道是否有更有效的解决方案,我也有一个关于同一主题的问题,有几种方法:
lock base address调用是一个hog,我不确定是否确实需要它。很好。。。最后我用pixelbuffer做了类似的事情,并把它放到了一个texturecache中。我实际上还没有试着分析你的代码和我的代码,所以我不确定什么更快,但我会在另一个答案中发布代码,时间太长,无法发表评论。我没有做任何锁定-也许我应该做,但在一段时间的生产环境中工作得很好,甚至一次运行几个高清视频。