Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone 从视频读取帧时,如何转换为16位像素格式以在OpenGL ES 2.0中使用(AV Foundation)_Iphone_Opengl Es_Avfoundation_Neon - Fatal编程技术网

Iphone 从视频读取帧时,如何转换为16位像素格式以在OpenGL ES 2.0中使用(AV Foundation)

Iphone 从视频读取帧时,如何转换为16位像素格式以在OpenGL ES 2.0中使用(AV Foundation),iphone,opengl-es,avfoundation,neon,Iphone,Opengl Es,Avfoundation,Neon,我正在使用OpenGL对1280x720 quicktime视频的每一帧进行一些图像处理。然后将帧读回,并根据这些帧创建新的视频。问题是需要在OpenGL之间传输大量数据(使用glTexImage2D和glReadPixels),导致过程非常缓慢 目前,我正在使用kCVPixelFormatType_32BGRA作为我的AvassetraderTrackOutput实例的像素格式。为了减少时间消耗,我想改用16位像素格式。不幸的是,当调用AvassetraderTrackOutput的copyN

我正在使用OpenGL对1280x720 quicktime视频的每一帧进行一些图像处理。然后将帧读回,并根据这些帧创建新的视频。问题是需要在OpenGL之间传输大量数据(使用glTexImage2DglReadPixels),导致过程非常缓慢

目前,我正在使用kCVPixelFormatType_32BGRA作为我的AvassetraderTrackOutput实例的像素格式。为了减少时间消耗,我想改用16位像素格式。不幸的是,当调用AvassetraderTrackOutput的copyNextSampleBuffer方法时,更改为这种格式会给我带来空帧。有没有使用AV基础的16位像素格式的经验?


<如果我不能让AV基金会改变我的格式,我想我可以从32位转换为16位“手动”,也许使用霓虹灯指令?非常感谢您的帮助。

这是一个进一步的修订,现在是社区维基,因为我在回答这个问题时犯了很多错误,这是有意义的

尽管CoreGraphics表面上可以使用以下代码为您进行32位到16位的转换,但它报告“4整数位/分量;16位/像素;3分量颜色空间;KCGimageAlphaPremultipledLast”是不受支持的参数组合。因此,CoreGraphics似乎无法在内部理解4位/通道图像

CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, buffer, width*height*4, NULL);
CGImageRef inputImage = CGImageCreate(  width, height,
                                        8, 32, width*4, 
                                        colourSpace, 
                                        kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big,
                                        dataProvider,
                                        NULL, NO,
                                        kCGRenderingIntentDefault);
CGDataProviderRelease(dataProvider);

unsigned char *outputImage = (unsigned char *)malloc(width*height*2);
CGContextRef targetContext = CGBitmapContextCreate( outputImage,
                                                    width, height,
                                                    4, width*2,
                                                    colourSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGContextDrawImage(targetContext, CGRectMake(0, 0, width, height), inputImage);

/* uplopad outputImage to OpenGL here! */

CGContextRelease(targetContext);
CGImageRelease(inputImage);
CGColorSpaceRelease(colourSpace);
free(outputImage);
但是,根据文件:

支持的像素格式包括 kCVPixelFormatTypeƤYPCBCRC8BIPLANARVIDERANGE, kCVPixelFormatTypeƤYPCBCRC8BIPLANARFULLRANGE 和kCVPixelFormatType_32BGRA,但 在iPhone 3G上,支持 像素格式是 kCVPixelFormatType_422YpCbCr8和 kCVPixelFormatType_32BGRA

因此,为了减小接收到的内容的大小,您可以切换到YCbCr颜色空间。当缓冲区返回双平面时(即,整个图像的所有y组件,然后所有Cb和Cr组件作为一个单独的块),您可以将它们作为两个单独的纹理上载到OpenGL并在着色器中重新组合,假设您乐于将自己限制在3GS及以上,并且可以花费SGX iOS设备上提供的8个纹理单元中的2个

YCbCr是一个颜色空间,分别以亮度(Y)和颜色(CbCr)表示颜色。经验表明,颜色通道可以以比亮度更低的频率进行采样,而没有人知道。像素格式的“420”部分描述了每4个Y分量有多少个Cb和Cr分量——本质上它告诉你每4个Y分量有一个Cb和一个Cr样本。因此,你总共有6个字节来描述4个像素,在RGB中是12位/像素,而不是24位/像素。这将为您节省50%的存储空间


出于总账目的,您可能会产生额外的成本,因为这是两次上传,而不是一次上传。如果要避免依赖纹理读取,您还需要使用三个变量,我认为SGX仅限于其中八个。

进一步修订,现在这是社区wiki,因为我在单独回答这个问题时犯了很多错误,这是有意义的

尽管CoreGraphics表面上可以使用以下代码为您进行32位到16位的转换,但它报告“4整数位/分量;16位/像素;3分量颜色空间;KCGimageAlphaPremultipledLast”是不受支持的参数组合。因此,CoreGraphics似乎无法在内部理解4位/通道图像

CGColorSpaceRef colourSpace = CGColorSpaceCreateDeviceRGB();
CGDataProviderRef dataProvider = CGDataProviderCreateWithData(NULL, buffer, width*height*4, NULL);
CGImageRef inputImage = CGImageCreate(  width, height,
                                        8, 32, width*4, 
                                        colourSpace, 
                                        kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big,
                                        dataProvider,
                                        NULL, NO,
                                        kCGRenderingIntentDefault);
CGDataProviderRelease(dataProvider);

unsigned char *outputImage = (unsigned char *)malloc(width*height*2);
CGContextRef targetContext = CGBitmapContextCreate( outputImage,
                                                    width, height,
                                                    4, width*2,
                                                    colourSpace, kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big);
CGContextDrawImage(targetContext, CGRectMake(0, 0, width, height), inputImage);

/* uplopad outputImage to OpenGL here! */

CGContextRelease(targetContext);
CGImageRelease(inputImage);
CGColorSpaceRelease(colourSpace);
free(outputImage);
但是,根据文件:

支持的像素格式包括 kCVPixelFormatTypeƤYPCBCRC8BIPLANARVIDERANGE, kCVPixelFormatTypeƤYPCBCRC8BIPLANARFULLRANGE 和kCVPixelFormatType_32BGRA,但 在iPhone 3G上,支持 像素格式是 kCVPixelFormatType_422YpCbCr8和 kCVPixelFormatType_32BGRA

因此,为了减小接收到的内容的大小,您可以切换到YCbCr颜色空间。当缓冲区返回双平面时(即,整个图像的所有y组件,然后所有Cb和Cr组件作为一个单独的块),您可以将它们作为两个单独的纹理上载到OpenGL并在着色器中重新组合,假设您乐于将自己限制在3GS及以上,并且可以花费SGX iOS设备上提供的8个纹理单元中的2个

YCbCr是一个颜色空间,分别以亮度(Y)和颜色(CbCr)表示颜色。经验表明,颜色通道可以以比亮度更低的频率进行采样,而没有人知道。像素格式的“420”部分描述了每4个Y分量有多少个Cb和Cr分量——本质上它告诉你每4个Y分量有一个Cb和一个Cr样本。因此,你总共有6个字节来描述4个像素,在RGB中是12位/像素,而不是24位/像素。这将为您节省50%的存储空间


出于总账目的,您可能会产生额外的成本,因为这是两次上传,而不是一次上传。如果要避免依赖纹理读取,还需要使用三个变量,我认为SGX仅限于其中八个。

谢谢您的回答。你的意思是我可以提供32位的像素数据给glTexImage2D,它会自动转换成16位吗?如果是这种情况,那么必须更改哪些参数?我的调用看起来像glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,bufferWidth,bufferHeight,0,GL_BGRA,GL_UNSIGNED_BYTE,CVPixelBufferGetBaseAddress(imageBuffer));实际上,它将是2个纹理。一个纹理用于Y平面(GL_亮度),另一个纹理用于UV平面(GL_亮度_ALPHA)。那就是