Какую матрицу YCbCr использовать? BT.709 или BT.601

Я работаю над проектом видеоплеера на iOS.

Он использует AVFoundation для извлечения CVPixelBuffer из видеофайла, а затем отправить этот буфер в OpenGL в виде текстур.

Код для проверки концепции основан на образец кода Apple. AVFoundation предоставляет каждый кадр в цветовом пространстве YCbCr, и его необходимо преобразовать в 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, и возвращаемый результат 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. Как определить, какое преобразование использовать?
  2. Если невозможно решить [1.], могу ли я жестко закодировать любой из них? каковы последствия этого?

person Nandin Borjigin    schedule 19.12.2016    source источник
comment
Чтобы узнать, какую матрицу декодирования использовать, вам нужно знать, какая из них использовалась для кодирования вашего видео, здесь нет никаких реальных безопасных предположений, но я бы выбрал BT.709, поскольку BT.601 предназначен для поэтапного отказа от SDTV. .   -  person Kel Solaar    schedule 19.12.2016
comment
@KelSolaar, как мне запросить матрицу, используемую для кодирования в AVFoundation?   -  person Nandin Borjigin    schedule 20.12.2016
comment
Честно говоря, я понятия не имею, я ничего не знаю об AVFoundation, однако в качестве продолжения предположения об использовании BT.709 в качестве матрицы декодирования, вот изображение, показывающее статистику кодирования цветовых пространств Youtube: lh5.googleusercontent.com/. BT.709 - это наиболее часто используемое цветовое пространство в настоящее время на Youtube, что означает, что большинство людей кодируют свое видео с его помощью.   -  person Kel Solaar    schedule 20.12.2016
comment
Поддерживается BOOL = (CFStringCompare (CVBufferGetAttachment (cvPixelBuffer, kCVImageBufferYCbCrMatrixKey, NULL), kCVImageBufferYCbCrMatrix_ITU_R_709_2, 0) == kCFCompareEqualTo);   -  person MoDJ    schedule 31.12.2018


Ответы (1)


Использование takeUnretendedValue () даст вам CFTypeRef. Затем его необходимо понизить до 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
person Jan Rüegg    schedule 31.01.2018