2012-10-07 105 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