Конвертировать цвета из RGB в NV12 - PullRequest
0 голосов
/ 21 сентября 2018

Я работаю над приложением, которое кодирует видео с помощью кодировщика Media Foundation H264.Sink Writer аварийно завершает работу в Windows 7 с входом RGB в VRAM, говоря «0x8876086C D3DERR_INVALIDCALL», поэтому я реализовал собственное преобразование RGB-> NV12 в графическом процессоре, сэкономив более 60% пропускной способности PCI Express.

Вот что в моих типах мультимедиа, как на входе (NV12), так и на выходе (h264):

mt->SetUINT32( MF_MT_VIDEO_CHROMA_SITING, MFVideoChromaSubsampling_MPEG2 ); // Specifies the chroma encoding scheme for MPEG-2 video. Chroma samples are aligned horizontally with the luma samples, but are not aligned vertically. The U and V planes are aligned vertically.
mt->SetUINT32( MF_MT_YUV_MATRIX, MFVideoTransferMatrix_BT709 ); // ITU-R BT.709 transfer matrix.
mt->SetUINT32( MF_MT_VIDEO_NOMINAL_RANGE, MFNominalRange_0_255 ); // The normalized range [0...1] maps to [0...255] for 8-bit samples or [0...1023] for 10-bit samples.
mt->SetUINT32( MF_MT_TRANSFER_FUNCTION, MFVideoTransFunc_10 );  // Linear RGB (gamma = 1.0).

Лучший результат, который у меня пока получился с этой формулой:

inline float3 yuvFromRgb(float3 rgba)
{
    float3 res;
    res.x = dot( rgba, float3( 0.182585880, 0.614230573, 0.0620070584 ) );
    res.y = dot( rgba, float3( -0.121760942, -0.409611613, 0.531372547 ) );
    res.z = dot( rgba, float3( 0.531372547, -0.482648790, -0.0487237722 ) );
    res += float3( 0.0627451017, 0.500000000, 0.500000000 );
    return saturate( res );
}

Меня беспокоит то, что формула противоречит всему, что я читал в Интернете, образцам кода и официальным спецификациям МСЭ.

Для формулы Y в порядке, я взял коэффициенты BT.709 и масштабировал их линейно, чтобы отобразить[0..255] в [16..235], как написано в спецификации.Яркость в порядке.

В спецификациях сказано, что я должен масштабировать U и V, чтобы отобразить из [0..255] в [16..240].Мои глаза, однако, говорят мне, что это ненасыщенно.Для получения правильных цветов я должен масштабировать U & V другим способом, из [0..255] во что-то вроде [-8, 255 + 8].

Почему мне нужно масштабировать другой способ для достиженияправильные цвета после кодирования и декодирования h264?Будет ли этот код работать на компьютерах других людей?

1 Ответ

0 голосов
/ 21 сентября 2018

Проблема заключалась в артефактах выборки цветности.Когда я задал вопрос, я смотрел на цветной текст консоли.

Сегодня я попытался кодировать более качественное изображение, вот это: enter image description here С этим изображением стало очевидно, что правильноформула - это то, что указано в этих стандартах.

Итак, вот правильные коэффициенты:

// Convert RGB color into ITU-R BT.709 YUV color
inline float3 yuvFromRgb( float3 rgb )
{
    float3 res;
    res.x = dot( rgb, float3( 0.18258588, 0.61423057, 0.06200706 ) );
    res.y = dot( rgb, float3( -0.10064373, -0.33857197, 0.43921569 ) );
    res.z = dot( rgb, float3( 0.43921569, -0.39894217, -0.04027352 ) );
    res += float3( 0.06274510, 0.50196081, 0.50196081 );
    return res;
}

Они по-прежнему дают ошибку "по одной", но для моей конкретной проблемы эта ошибка 0,39%приемлемо.

...