2012-10-07 74 views
1

对于整整3天,我一直在尝试改进基于glReadPixels的AVAssetWriter的性能。我已经浏览了Apple的RosyWriter和Camera Ripple代码以及Brad Larson的GPUImage,但我仍然在挠头。我也一直在尝试使用这些链接放下实现:CVOpenGLESTextureCacheCreateTextureFromImage而不是glReadPixels

rendering-to-a-texture-with-ios-5-texture-cache-api

faster-alternative-to-glreadpixels-in-iphone-opengl-es-2-0

...等等,但不管我怎么努力,我只是无法得到它上班。视频最终没有得到处理,或者出现黑屏,或者出现各种错误。我不会在这里完成所有的事情。

为了简化我的问题,我想我会专注于从屏幕上的OpenGL预览FBO抓取快照。如果我能得到这个工作的单一实现,我应该能够解决其余的问题。我尝试从上面的第一个链接看起来像这样的实现:

CVOpenGLESTextureCacheCreate(kCFAllocatorDefault, NULL, [glView context], 
          NULL, &texCacheRef); 

CFDictionaryRef empty = CFDictionaryCreate(kCFAllocatorDefault, 
          NULL, 
          NULL, 
          0, 
          &kCFTypeDictionaryKeyCallBacks, 
          &kCFTypeDictionaryValueCallBacks); 

CFMutableDictionaryRef attrs = CFDictionaryCreateMutable(kCFAllocatorDefault, 
            1, 
            &kCFTypeDictionaryKeyCallBacks, 
            &kCFTypeDictionaryValueCallBacks); 

CFDictionarySetValue(attrs, 
        kCVPixelBufferIOSurfacePropertiesKey, 
        empty); 

CVPixelBufferRef renderTarget = NULL; 
CVPixelBufferCreate(kCFAllocatorDefault, 
        width, 
        height, 
        kCVPixelFormatType_32BGRA, 
        attrs, 
        &renderTarget); 

CVOpenGLESTextureRef renderTexture; 
CVOpenGLESTextureCacheCreateTextureFromImage (kCFAllocatorDefault, 
               texCacheRef, 
               renderTarget, 
               NULL, 
               GL_TEXTURE_2D, 
               GL_RGBA, 
               width, 
               height, 
               GL_BGRA, 
               GL_UNSIGNED_BYTE, 
               0, 
               &renderTexture); 

CFRelease(attrs); 
CFRelease(empty); 
glBindTexture(CVOpenGLESTextureGetTarget(renderTexture), CVOpenGLESTextureGetName(renderTexture)); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

GLuint renderFrameBuffer; 
glGenRenderbuffers(1, &renderFrameBuffer); 
glBindFramebuffer(GL_FRAMEBUFFER, renderFrameBuffer); 
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 
         GL_TEXTURE_2D, CVOpenGLESTextureGetName(renderTexture), 0); 

//Is this really how I pull pixels off my context? 
CVPixelBufferLockBaseAddress(renderTarget, 0); 
buffer = (GLubyte *)CVPixelBufferGetBaseAddress(renderTarget); 
CVPixelBufferUnlockBaseAddress(renderTarget, 0); 

究竟应该发生在这里?我的缓冲区结束了一堆零,所以我想我需要做额外的事情从上下文拉像素? ...或者我错过了什么?

所有我想要实现的是一个快速的等价物是什么我今天使用的:

int pixelsCount = w * h; 
buffer = (GLubyte *) malloc(pixelsCount * 4); 
glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer); 
+0

在上面的代码中不显示任何实际的渲染。一旦你有你的纹理支持的FBO,并且纹理缓存已经提供了纹理,你需要将你的内容渲染到该FBO中。只有这样你才能从用于支持FBO的纹理读回像素数据。您可能需要在读取缓冲区中的像素数据之前插入'glFinish()',以确保OpenGL ES有足够的时间完成渲染到纹理中。 –

+0

啊,不敢相信我错过了。我在印象之下渲染主FBO就足够了,然后我可以从glReadPixels类似地拉出它。我只是试图用这个替换我的FBO,那就做到了这一点。非常感谢!如果你把你的评论作为回应,我会接受它。 – BlueVoodoo

+0

虽然我知道它的工作原理,但我仍对CVOpenGLESTeureureCacheCreate调用感到困惑。在这里传入的EAGLContext是预期来自另一个FBO,我已经提出了......或者可以使用一个新的上下文以仅渲染一次(直接传递给上述代码中的一个)?只要我使用另一个上下文,我只在我的缓冲区中返回零。 – BlueVoodoo

回答

1

布拉德指出,我误解的概念,并没有做任何实际的渲染。当我添加它时工作得很好。

+0

我遇到同样的问题。而我的屏幕是黑色的......你能告诉我你如何解决它? – CPT

+0

我的问题是,我没有渲染之前,我拉缓冲区。换句话说,我没有调用glDrawArrays。 – BlueVoodoo

+0

感谢您的回复!我尝试在我的项目中放入这样的'glDrawArrays(GL_TRIANGLE_STRIP,0,4)'代码,它仍然无法工作。此外,我指的是GitHub上的GPUImage项目,我认为这对我来说可能有些困难。你可以提供一些关于渲染细节的提示吗?源代码更好......谢谢。 – CPT