zhz*_*zhy 4 video opengl-es ios
我使用opengl es在iPad上显示bgr24数据,我是关于opengl es的新手,所以在显示视频部分我使用来自RosyWriter的代码一个APPLE样本.它可以工作,但CVOpenGLESTextureCacheCreateTextureFromImage函数的成本超过30毫秒,而在RosyWriter中它的成本可以忽略不计.我所做的是先将BGR24转换为BGRA像素格式,然后使用CVPixelBufferCreateWithBytes函数创建一个CVPixelBufferRef,然后通过CVOpenGLESTextureCacheCreateTextureFromImage获取CVOpenGLESTextureRef.我的代码如下,
- (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);
}
Run Code Online (Sandbox Code Playgroud)
并且在变换之后,将生成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;
}
Run Code Online (Sandbox Code Playgroud)
其他代码几乎与RosyWriter样本类似,包括着色器.所以我想知道为什么,如何解决这个问题.
随着我在这一天的研究,我发现为什么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);
Run Code Online (Sandbox Code Playgroud)
使用这个新创建的pixelBuffer,您可以快速完成.
将以下配置添加到attribtes可以使其性能达到最佳,小于1ms.
NSDictionary *IOSurfaceProperties = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], @"IOSurfaceOpenGLESFBOCompatibility",[NSNumber numberWithBool:YES], @"IOSurfaceOpenGLESTextureCompatibility",nil];
[attributes setObject:IOSurfaceProperties forKey:(NSString*)kCVPixelBufferIOSurfacePropertiesKey];
Run Code Online (Sandbox Code Playgroud)