iPad2上的CVOpenGLESTextureCacheCreateTextureFromImage太慢了,需要差不多30ms,太疯狂了

我使用opengl es在iPad上显示bgr24数据,我是关于opengl es的新的,所以在显示video部分,我使用了来自RosyWriter的一个代码。 它工作,但CVOpenGLESTextureCacheCreateTextureFromImage函数花费超过30毫秒,而在RosyWriter它的成本是微不足道的。 我所做的是首先将BGR24转换为BGRA像素格式,然后使用CVPixelBufferCreateWithBytes函数创build一个CVPixelBufferRef,然后通过CVOpenGLESTextureCacheCreateTextureFromImage获得一个CVOpenGLESTeureureRef。 我的代码如下,

- (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样本类似,包括着色器。 所以我想知道为什么,如何解决这个问题。

随着我在这几天的研究,我发现为什么CVOpenGLESTextureCacheCreateTextureFromImage花费了大量的时间,当数据量大的时候,这里是3M,成本相当的configuration,复制和移动操作 ,特别是Copy操作。 然后用像素缓冲池CVOpenGLESTextureCacheCreateTextureFromImage性能从30ms提高到5ms,与glTexImage2D()的性能CVOpenGLESTextureCacheCreateTextureFromImage 。 我的解决scheme如下:

 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); 

有了这个新创build的pixelBuffer,你可以使它快速。

将以下configuration添加到属性可以使其性能达到最佳状态,小于1ms。

  NSDictionary *IOSurfaceProperties = [NSDictionary dictionaryWithObjectsAndKeys: [NSNumber numberWithBool:YES], @"IOSurfaceOpenGLESFBOCompatibility",[NSNumber numberWithBool:YES], @"IOSurfaceOpenGLESTextureCompatibility",nil]; [attributes setObject:IOSurfaceProperties forKey:(NSString*)kCVPixelBufferIOSurfacePropertiesKey];