2012-07-23 16 views
4

我使用opengl es在iPad上顯示bgr24數據,我是關於opengl es的新功能,所以在顯示視頻部分,我使用了RosyWriter的一個APPLE樣例代碼。它的工作原理,但CVOpenGLESTextureCacheCreateTextureFromImage函數花費超過30毫秒,而在RosyWriter 其成本可以忽略不計。 我所做的是首先將BGR24轉換爲BGRA像素格式,然後使用CVPixelBufferCreateWithBytes函數創建一個CVPixelBufferRef,然後通過CVOpenGLESTextureCacheCreateTextureFromImage獲得一個CVOpenGLESTeureureRef。我的如下碼,CVOpenGLESTextureCacheCreateTextureFromImage在iPad2上速度太慢,需要差不多30ms,太瘋狂了

- (void)transformBGRToBGRA:(const UInt8 *)pict width:(int)width height:(int)height 
{ 
rgb.data = (void *)pict; 

vImage_Error error = vImageConvert_RGB888toARGB8888(&rgb,NULL,0,&argb,NO,kvImageNoFlags); 
if (error != kvImageNoError) { 
    NSLog(@"vImageConvert_RGB888toARGB8888 error"); 
} 

const uint8_t permuteMap[4] = {1,2,3,0}; 

error = vImagePermuteChannels_ARGB8888(&argb,&bgra,permuteMap,kvImageNoFlags); 
if (error != kvImageNoError) { 
    NSLog(@"vImagePermuteChannels_ARGB8888 error"); 
} 

free((void *)pict); 
} 

和變換之後,將生成CVPixelBufferRef,碼作爲以下,

[self transformBGRToBGRA:pict width:width height:height]; 

CVPixelBufferRef pixelBuffer; 
CVReturn err = CVPixelBufferCreateWithBytes(NULL, 
          width, 
          height, 
          kCVPixelFormatType_32BGRA, 
          (void*)bgraData, 
          bytesByRow, 
          NULL, 
          0, 
          NULL, 
          &pixelBuffer); 

if(!pixelBuffer || err) 
{ 
    NSLog(@"CVPixelBufferCreateWithBytes failed (error: %d)", err); 
    return; 
} 

CVOpenGLESTextureRef texture = NULL; 
err = CVOpenGLESTextureCacheCreateTextureFromImage(kCFAllocatorDefault, 
                  videoTextureCache, 
                  pixelBuffer, 
                  NULL, 
                  GL_TEXTURE_2D, 
                  GL_RGBA, 
                  width, 
                  height, 
                  GL_BGRA, 
                  GL_UNSIGNED_BYTE, 
                  0, 
                  &texture); 


if (!texture || err) { 
    NSLog(@"CVOpenGLESTextureCacheCreateTextureFromImage failed (error: %d)", err); 
    CVPixelBufferRelease(pixelBuffer); 
    return; 
} 

的其他代碼幾乎相似RosyWriter樣品,包括着色器。所以我想知道爲什麼, 如何解決這個問題。

+1

什麼尺寸是您想上傳的圖片?你確定在30毫秒內沒有測量你的'-transformBGRToBGRA:'方法的時間嗎? – 2012-07-23 15:00:33

+0

是的,我確定。它是1024 * 768,transformBGRToBGRA的時間:我測得的是10ms。 – zhzhy 2012-07-24 01:01:15

+0

好的,所以你測量的30毫秒來自'CVPixelBufferCreateWithBytes()'調用之前,正好在'CVOpenGLESTextureCacheCreateTextureFromImage()'調用之後?這看起來非常高,因爲我已經看到iPad 2上傳1080p幀(2.6倍多像素),比30毫秒快得多。如果你只是對這些數據使用'glTexImage2D()',你的時間是什麼? – 2012-07-24 15:25:24

回答

5

與我這些天的研究,我發現爲什麼CVOpenGLESTextureCacheCreateTextureFromImage成本多少時間,當數據量大,這裏是3M的分配,複製和移動操作其成本是相當可觀的,尤其是複製操作。然後用像素緩衝池大大提高CVOpenGLESTextureCacheCreateTextureFromImage的性能,從30ms到5ms,與glTexImage2D()相同。我作爲以下解決方案:

NSMutableDictionary*  attributes; 
attributes = [NSMutableDictionary dictionary]; 


[attributes setObject:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA] forKey:(NSString*)kCVPixelBufferPixelFormatTypeKey]; 
[attributes setObject:[NSNumber numberWithInt:videoWidth] forKey: (NSString*)kCVPixelBufferWidthKey]; 
[attributes setObject:[NSNumber numberWithInt:videoHeight] forKey: (NSString*)kCVPixelBufferHeightKey]; 

CVPixelBufferPoolCreate(kCFAllocatorDefault, NULL, (CFDictionaryRef) attributes, &bufferPool); 

CVPixelBufferPoolCreatePixelBuffer (NULL,bufferPool,&pixelBuffer); 

CVPixelBufferLockBaseAddress(pixelBuffer,0); 

UInt8 * baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer); 

memcpy(baseAddress, bgraData, bytesByRow * videoHeight); 

CVPixelBufferUnlockBaseAddress(pixelBuffer,0); 

與這個新創建pixelBuffer你可以把它快。

將以下配置添加到屬性可以使其性能達到最佳狀態,小於1ms。

NSDictionary *IOSurfaceProperties = [NSDictionary dictionaryWithObjectsAndKeys: 
                     [NSNumber numberWithBool:YES], @"IOSurfaceOpenGLESFBOCompatibility",[NSNumber numberWithBool:YES], @"IOSurfaceOpenGLESTextureCompatibility",nil]; 

[attributes setObject:IOSurfaceProperties forKey:(NSString*)kCVPixelBufferIOSurfacePropertiesKey]; 
+1

我實現了這個建議,添加了表面屬性並利用了像素緩衝池。但是,我沒有看到iPad2的性能有所提高。現在我的代碼只運行memcpy()89%的時間。我不明白這種方法如何改進,因爲紋理上傳是這段代碼中時間關鍵的部分。如果像素數據已經在用戶緩衝區中,那麼通過執行另一個副本將內存移動到CVPixelBuffer中會獲得什麼? – MoDJ 2013-07-30 18:57:34

+0

這裏同樣的問題。如果你已經在內存中獲得了BGRA數據,爲什麼你不能用CVPixelBufferRef來包裝它呢? – jjxtra 2015-01-25 03:44:04