本文档描述了通过RTSP、RTMP或HLS等协议获取H.264码流,由VideoToolbox解码,获取视频对应的颜色转换矩阵,确保YUV转换至RGB颜色空间的正确性。
有关YUV和RGB相互转换的说明,请参考我的另一个文档音视频开发:RGB与YUV相互转换问题。下面只描述从CVPixelBuffer获取颜色转换矩阵的方法。
// 以下代码位于Video Toolbox解码回调函数体
CFTypeRef colorAttachments = CVBufferGetAttachment(imageBuffer, kCVImageBufferYCbCrMatrixKey, NULL);
if (colorAttachments != NULL)
{
if(CFStringCompare(colorAttachments, kCVImageBufferYCbCrMatrix_ITU_R_601_4, 0) == kCFCompareEqualTo)
// ITU BT.601
if(CFStringCompare(colorAttachments, kCVImageBufferYCbCrMatrix_ITU_R_709_2, 0) == kCFCompareEqualTo)
// ITU BT.709
}
CVPixelBuffer才有颜色转换信息,CVBlockBuffer并不能直接解析到kCVImageBufferYCbCrMatrixKey等信息。一般情况,只有解码后才能得到CVPixelBuffer。然而,需要说明的是,使用AVAsset读取MP4等文件,可通过copyNextSampleBuffer方法得到CMSampleBuffer,然后由CMSampleBufferGetImageBuffer函数可取得像素信息,这属于通过AVFoundation框架利用硬件加速进行不解码显示H.264数据,可参考我的文档iOS 音视频高级编程:AVAssetReaderTrackOutput改变CMFormatDescription导致Video Toolbox解码失败与不解码GPU直接显示H.264帧中的描述。
CMSampleBufferRef sampleBufferRef = [readerVideoTrackOutput copyNextSampleBuffer];
CVImageBufferRef imageBufferRef = CMSampleBufferGetImageBuffer(sampleBufferRef);
得到合适的颜色空间转换矩阵后,为提升性能,一般在Fragment Shader中进行YUV至RGB的转换,在此需根据不同的YUV格式进行相应的处理,比如Full Range或Video Range。
网友评论
int width = 480, height = 640;
OSStatus status = VTCompressionSessionCreate(NULL, width, height, kCMVideoCodecType_H264, NULL, NULL, NULL, didCompressH264, (__bridge void *)(self), &EncodingSession);
也就是把宽度和高度对换就发生了变形?请问这个问题怎么解决