使用哪个 YCbCr 矩阵? BT.709 或 BT.601
Which YCbCr matrix to use? BT.709 or BT.601
我正在 iOS 上开发视频播放器项目。
它使用视频文件中的 AVFoundation to extract CVPixelBuffer,然后将该缓冲区作为纹理发送到 OpenGL。
概念验证代码的灵感来自 Apple's sample code。
AVFoundation 以 YCbCr 颜色 space 提供每个帧,需要将其转换为 RGB 才能在 OpenGL 中渲染。根据不同的 YCbCr 标准(例如 ITU-R BT.709, ITU-R BT.601),此转换似乎有多个转换矩阵选项。示例代码通过以下代码确定使用哪一个:
CFTypeRef colorAttachments = CVBufferGetAttachment(pixelBuffer, kCVImageBufferYCbCrMatrixKey, NULL);
if (colorAttachments == kCVImageBufferYCbCrMatrix_ITU_R_601_4) {
_preferredConversion = kColorConversion601;
}
else {
_preferredConversion = kColorConversion709;
}
但是,我使用的是 swift 并且 return colorAttachment
是 Unmanaged<CFTypeRef>
类型,而常量 kCVImageBufferYCbCrMatrix_ITU_R_601_4
是 CFString
所以他们不能直接相等。我做了一些研究,结果是:
CFEqual(colorAttachments, kCVImageBufferYCbCrMatrix_ITU_R_601_4) // returns false
CFEqual(colorAttachments, kCVImageBufferYCbCrMatrix_ITU_R_709_2) // returns false too!!
//-----------------------------------------
CFGetType(colorAttachments) // returns 1
CFStringGetType() // returns 7, note kCVImageBufferYCbCrMatrix_ITU_R_601_4 is of type CFString
// so I still can't check their equality
// because the retrieved colorAttachments is not of type CFString at all
我通过对矩阵进行硬编码来逐一尝试两个变换,结果(渲染的场景)对人眼来说似乎没有什么不同,这是可以预见的,因为两个变换矩阵差别不大。
我的问题:
- 如何确定要使用的变换?
- 如果无法解决 [1.],我可以硬编码其中一个吗?这样做的后果是什么?
使用 takeUnretainedValue() will give you a CFTypeRef
. This then needs to be 到 CFString
。例如,您的代码可能如下所示:
if let colorAttachment = CVBufferGetAttachment(image, kCVImageBufferYCbCrMatrixKey, nil)?.takeUnretainedValue(),
CFGetTypeID(colorAttachment) == CFStringGetTypeID() {
let colorAttachmentString = colorAttachment as! CFString
print(colorAttachmentString)
print(colorAttachmentString == kCVImageBufferYCbCrMatrix_ITU_R_601_4)
print(colorAttachmentString == kCVImageBufferYCbCrMatrix_ITU_R_709_2)
}
打印:
ITU_R_601_4
true
false
我正在 iOS 上开发视频播放器项目。
它使用视频文件中的 AVFoundation to extract CVPixelBuffer,然后将该缓冲区作为纹理发送到 OpenGL。
概念验证代码的灵感来自 Apple's sample code。 AVFoundation 以 YCbCr 颜色 space 提供每个帧,需要将其转换为 RGB 才能在 OpenGL 中渲染。根据不同的 YCbCr 标准(例如 ITU-R BT.709, ITU-R BT.601),此转换似乎有多个转换矩阵选项。示例代码通过以下代码确定使用哪一个:
CFTypeRef colorAttachments = CVBufferGetAttachment(pixelBuffer, kCVImageBufferYCbCrMatrixKey, NULL); if (colorAttachments == kCVImageBufferYCbCrMatrix_ITU_R_601_4) { _preferredConversion = kColorConversion601; } else { _preferredConversion = kColorConversion709; }
但是,我使用的是 swift 并且 return colorAttachment
是 Unmanaged<CFTypeRef>
类型,而常量 kCVImageBufferYCbCrMatrix_ITU_R_601_4
是 CFString
所以他们不能直接相等。我做了一些研究,结果是:
CFEqual(colorAttachments, kCVImageBufferYCbCrMatrix_ITU_R_601_4) // returns false
CFEqual(colorAttachments, kCVImageBufferYCbCrMatrix_ITU_R_709_2) // returns false too!!
//-----------------------------------------
CFGetType(colorAttachments) // returns 1
CFStringGetType() // returns 7, note kCVImageBufferYCbCrMatrix_ITU_R_601_4 is of type CFString
// so I still can't check their equality
// because the retrieved colorAttachments is not of type CFString at all
我通过对矩阵进行硬编码来逐一尝试两个变换,结果(渲染的场景)对人眼来说似乎没有什么不同,这是可以预见的,因为两个变换矩阵差别不大。
我的问题:
- 如何确定要使用的变换?
- 如果无法解决 [1.],我可以硬编码其中一个吗?这样做的后果是什么?
使用 takeUnretainedValue() will give you a CFTypeRef
. This then needs to be CFString
。例如,您的代码可能如下所示:
if let colorAttachment = CVBufferGetAttachment(image, kCVImageBufferYCbCrMatrixKey, nil)?.takeUnretainedValue(),
CFGetTypeID(colorAttachment) == CFStringGetTypeID() {
let colorAttachmentString = colorAttachment as! CFString
print(colorAttachmentString)
print(colorAttachmentString == kCVImageBufferYCbCrMatrix_ITU_R_601_4)
print(colorAttachmentString == kCVImageBufferYCbCrMatrix_ITU_R_709_2)
}
打印:
ITU_R_601_4
true
false