前两天被这个问题折磨的不成样子。 在stack overflow上查了一圈,基本来说总结出以下几个可能。
首先根据官方文件:
"Result is a CVImageBuffer of media data. The result will be NULL if the CMSampleBuffer does not contain a CVImageBuffer, or if the CMSampleBuffer contains a CMBlockBuffer, or if there is some other error."
也就是说如果 CMSampleBuffer 里没有 CVImageBuffer, 或者有 CMBlockBuffer 就会返回NULL。当然出了其他错误也会返回NULL。
那其他错误都有什么可能呢?那得看你怎么取的CVImageBuffer。
比如如果是在function里这样:
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); // sampleBuffer是function提供的
NSLog(@"PixelBuffer %@",pixelBuffer);
打印出来是NULL的话。有可能是类型不对。如果sampleBuffer的类型是video或者audio的话,里面当然不会有CVPixelBuffer了。那么检查一下type就可以了:
CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
CMFormatDescriptionRef formatDesc = CMSampleBufferGetFormatDescription(sampleBuffer);
CMMediaType mediaType = CMFormatDescriptionGetMediaType(formatDesc);
//Checking sample type before proceeding
if (mediaType == kCMMediaType_Audio){
return;
}else{
// do your work
}
如果是其他的什么function,就要follow他的规则。比如要求设置个什么才能取出东西来,像第一个ref链接里第二个回答解释的一样。
还有一种可能。如果你跟我一样这么取 CVPixelBufferRef 的话可能会犯同样的毛病:
CMSampleBufferRef cmBuf = (CMSampleBufferRef)CFArrayGetValueAtIndex(CFMutableArrayRef, index);
CVImageBufferRef referencedImageBuffer = CMSampleBufferGetImageBuffer(cmBuf);
注意这个CFMutableArrayRef是我自己的。也就是说 CMSampleBufferRef 的来源不是某个function自带的,而是我曾经在某刻自己放进去的。
如果当时放进去的是 CVImageBufferRef 类型的话,CFArrayGetValueAtIndex 也能给取出来!这时候返回去查一下你是在哪儿放进去的,看一下那个变量的地址,再回来看看cmBuf的地址,有可能是一样的!那么从已经是 CVImageBufferRef 的 CMSampleBufferRef 变量里面再取 CVImageBufferRef,怎么可能取得出来嘛ㄟ( ▔, ▔ )ㄏ。
那么问题来了,本是CVImageBufferRef 变量为什么能declare成 CMSampleBufferRef 类型呢??因为这两个类本身就是能相互cast的。。(o_ _)ノ 恕我才疏学浅不知道为啥。看起来一个属于 core video类,一个属于core media,但是两个变量好像有继承关系。
总之取出NULL的问题多多,分水岭在于是你在取别人function的sampleBuffer,还是在取你曾经自己放进去的。
ref:
https://stackoverflow.com/questions/16861047/why-does-cmsamplebuffergetimagebuffer-return-null
https://stackoverflow.com/questions/38591957/cmsamplebuffergetimagebuffer-returning-null