Ios YUV-NV12视频缓冲区的连续性&x27;s-y平面和uv平面
我有一个Ios YUV-NV12视频缓冲区的连续性&x27;s-y平面和uv平面,ios,opencv,video-processing,yuv,cvpixelbuffer,Ios,Opencv,Video Processing,Yuv,Cvpixelbuffer,我有一个(CMSampleBufferRef)imageBuffer,它是yuv_nv12(4:2:0)的类型 现在我运行以下代码,发现结果令人困惑 UInt8 *baseSRC = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer); UInt8 *yBaseSRC = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0); UInt8 *uvBaseSRC = (UInt8 *)
(CMSampleBufferRef)imageBuffer
,它是yuv_nv12(4:2:0)的类型
现在我运行以下代码,发现结果令人困惑
UInt8 *baseSRC = (UInt8 *)CVPixelBufferGetBaseAddress(imageBuffer);
UInt8 *yBaseSRC = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 0);
UInt8 *uvBaseSRC = (UInt8 *)CVPixelBufferGetBaseAddressOfPlane(imageBuffer, 1);
int width = (int)CVPixelBufferGetWidthOfPlane(imageBuffer, 0); //width = 480;
int height = (int)CVPixelBufferGetHeightOfPlane(imageBuffer, 0); //height = 360;
int y_base = yBaseSRC - baseSRC; //y_base = 64;
int uv_y = uvBaseSRC-yBaseSRC; //uv_y = 176640;
int delta = uv_y - width*height; //delta = 3840;
我对这个结果有几个问题
1:为什么baseSRC
不等于yBaseSRC
2:为什么yBaseSRC+width*height
不等于uvBaseSRC
?理论上,y平面数据之后是uv平面数据,没有任何中断,对吗?现在它被大小为3840字节的东西打断了,我不明白
3:我试着用下面的代码将这个示例像素转换成cvmat,在大多数iOS设备上,这可以正常工作,但在iPhone 4s上不行。在iPhone 4s上,
转换后,像素缓冲区在侧面得到一些绿线
Mat nv12Mat(height*1.5,width,CV_8UC1,(unsigned char *)yBaseSRC);
Mat rgbMat;
cvtColor(nv12Mat, rgbMat, CV_YUV2RGB_NV12);
现在rgbMat看起来像这样:
最终找到了解决方案,基本上解决方案是分配一块新内存,将y平面数据和uv平面数据连接起来。然后将其转换为cvmat即可 以下是代码片段:
UInt8 *newBase = (UInt8 *)malloc(landscapeWidth*landscapeHeight*1.5);
memcpy(newBase, yBaseSRC, landscapeWidth*landscapeHeight);
memcpy(newBase+landscapeWidth*landscapeHeight, uvBaseSRC, landscapeWidth*landscapeHeight*0.5);
Mat nv12Mat(landscapeHeight*1.5,landscapeWidth,CV_8UC1,(unsigned char *)newBase);
CVPixelBuffers是不透明类型,我可以推断您找到的增量是属于CVPixelBuffer数据类型的数据。由于数据类型没有文档记录,而且苹果提供了提取所需数据的API,因此我不会对数据的组织方式做出假设。至于opencv垫,为什么使用高度为(高度*1.5)。你应该只传递“height”。@blackirishman因为“height”是y平面的高度,uv平面的高度等于“height/2.0”,所以缓冲区的总大小应该是“widthheight+widthheight/2.0”,这与“width*height*1.5”的含义相同。当你第一次写这篇文章时,你是在创建y平面的一个垫子,对吗?您对CVPixelBufferGetWidthOfPlane和CVPixelBufferGetHeightOfPlane的调用为您提供了应该输入到垫子中的宽度和高度。@blackirishman否,我正在创建一个包含所有平面(包括y、u、v)的垫子。绿色数据必须是CVPixelBuffer中的任何平面。delta除以高度是10.66,这看起来像你刚刚发布的图像中的10个像素。