YCgCo - некорректные цвета [Исправлено]

Автор V0lt, 17 января 2016, 20:56:45

« назад - далее »

0 Пользователи и 1 гость просматривают эту тему.

Aleksoid1978

Одна матрица yuv2rgb - из наших шейдеров. Вторую - из интернета, на пример отсюда https://de.wikipedia.org/wiki/YCgCo-Farbmodell так же и из исходников zimg - https://github.com/sekrit-twc/zimg/blob/master/src/zimg/colorspace/colorspace_param.cpp#L119
[merge_posts_bbcode]Добавлено: 2016-09-21 17:03:49[/merge_posts_bbcode]

Но скажу так - небольшая неточность в цветах в любом случае будет, т.к. у нас сперва рендерер(либо декодер) делает YUV->RGB с неверными коэффициентами, а потом мы уже делаем шейдером RGB->YUV->RGB.

[merge_posts_bbcode]Добавлено: 2016-09-21 17:37:46[/merge_posts_bbcode]

И вот еще один вариант шейдера:
// $MinimumShaderProfile: ps_2_0
sampler s0 : register(s0);

static float4x4 rgb2yuv = {
     0.299,  0.587,  0.114, 0.000,
    -0.147, -0.289,  0.436, 0.000,
     0.615, -0.515, -0.100, 0.000,
     0.000,  0.000,  0.000, 0.000
};

static float4x4 yuv2rgb = {
    1.000, -1.000,  1.000, 0.000,
    1.000,  1.000,  0.000, 0.000,
    1.000, -1.000, -1.000, 0.000,
    0.000,  0.000,  0.000, 0.000
};

float4 main(float2 tex : TEXCOORD0) : COLOR {
    // original pixel
    float4 c0 = tex2D(s0, tex);
   
    // convert RGB to YUV using YCgCo matrix
    c0 = mul(rgb2yuv, c0);
    // convert YUV to RGB
    c0 = mul(yuv2rgb, c0);

    return c0;
}

По мне он более корректный, т.к. в нем мы преобразуем RGB -> YUV обычным способом(стандартной матрицей), а уже потом полученный "оригинальный" YUV(который на самом деле YCgCo) преобразуем в RGB как и описано в документации.

В итоге работа 2-х этих шейдеров(итоговая картинка) немного отличаются, с последним вариантом немного сочнее и ярче, хоть с RGB выводом в декодере хоть с YUV.
[merge_posts_bbcode]Добавлено: 2016-09-21 18:39:25[/merge_posts_bbcode]

Естественно - шейдер надо применять до ресайза, на оригинальном видео.
AMD Ryzen 5 3600 /GIGABYTE B450 Gaming X /AMD Radeon R9 16Gb@3200 /Kingston 500Gb M.2 /GTX 1650 /Samsung U28R550UQI /OLED Philips 55OLED707 /Yamaha RX-V471 + NS-555 + NS-C444 + NS-333 + YST-SW215

V0lt

Тут проблема двоякая.

Если на вход рендерера приходит AYUV с матрицей YCgCo, то тут сам рендерер должен разруливать вышеуказанным шейдером. Подобное как раз делает madVR.

Если же на вход рендерера приходит неправильный RGB, тогда рендерер трогать не надо. Т.к. матрицу YCgCo передавать в свойствах неправильно - не бывает таких матриц в RGB формате. Здесь нужно в самом конвертере декодера править. Судя по матрице из шейдера это несложно будет.

Aleksoid1978

Полностью согласен. Правда MadVR делает это в момент преобразован в RGB,  мы так не сможем. А если идет на вход RGB - то конечно это надо в декодере делать, но там libswscale.

И я опять предлагаю перенести код yuv2rgb из LAV, он и быстрее и это умеет.
[merge_posts_bbcode]Добавлено: 2016-09-21 19:33:08[/merge_posts_bbcode]

Свойства передавать только для YUV,  как сейчас и есть.

[merge_posts_bbcode]Добавлено: 2016-09-21 19:36:00[/merge_posts_bbcode]

Вообщем с тебя работа в видео-рендерерах - получение типа матрицы и прикручивание шейдера,  второго - он более правильный. Я же в декодере - передача матрицы и наверное переделка yuv2rgb.
[merge_posts_bbcode]Добавлено: 2016-09-21 19:44:31[/merge_posts_bbcode]

В libswscale так наворочен код что без бутылки не разобрать. Может тикет сделаешь, ссылку на вики дать - я думаю они сами быстрее чем я там буду ковыряться.
AMD Ryzen 5 3600 /GIGABYTE B450 Gaming X /AMD Radeon R9 16Gb@3200 /Kingston 500Gb M.2 /GTX 1650 /Samsung U28R550UQI /OLED Philips 55OLED707 /Yamaha RX-V471 + NS-555 + NS-C444 + NS-333 + YST-SW215

V0lt

Вывожу формат AYUV с матрицей YCgCo

EVRcp:
VIDEOINFOHEADER2:
dwInterlaceFlags: 0x00000081
dwCopyProtectFlags: 0x00000000
dwPictAspectRatioX: 16
dwPictAspectRatioY: 9
dwControlFlags: 0x00001581
- VideoChromaSubsampling: 5
- NominalRange          : 1 (0-255)
- VideoTransferMatrix   : 0
- VideoLighting         : 0
- VideoPrimaries        : 0
- VideoTransferFunction : 0
dwReserved2: 0x00000000

madVR:
VIDEOINFOHEADER2:
dwInterlaceFlags: 0x00000081
dwCopyProtectFlags: 0x00000000
dwPictAspectRatioX: 16
dwPictAspectRatioY: 9
dwControlFlags: 0x00039581
- VideoChromaSubsampling: 5
- NominalRange          : 1 (0-255)
- VideoTransferMatrix   : 7 (YCgCo)
- VideoLighting         : 0
- VideoPrimaries        : 0
- VideoTransferFunction : 0
dwReserved2: 0x00000000

Надо устранить сию дискриминацию!

Aleksoid1978

Я же сказал - это я сделаю, прям завтра с утра, по Владивостоку конечно же :)
AMD Ryzen 5 3600 /GIGABYTE B450 Gaming X /AMD Radeon R9 16Gb@3200 /Kingston 500Gb M.2 /GTX 1650 /Samsung U28R550UQI /OLED Philips 55OLED707 /Yamaha RX-V471 + NS-555 + NS-C444 + NS-333 + YST-SW215

Angel

это как раз то, о чем я писал на руборде. правда я не мог подкрепить свои слова цифрами и такими вот выкладками, но факт остаётся фактом: лучше для просмотра аниме чем мадВР еще ничего не придумали и об этом предупреждают почти во всех ветках на трекерах где раздается 10-битный контент.

Aleksoid1978

Вот патч для видео-декодера. Я немного усложнил - передаем данные пл YCgCo матрице ТОЛЬКО для EVR Custom/Sync, т.е. только для Custom Allocator.

https://yadi.sk/d/SWQy37WBvVFz6
AMD Ryzen 5 3600 /GIGABYTE B450 Gaming X /AMD Radeon R9 16Gb@3200 /Kingston 500Gb M.2 /GTX 1650 /Samsung U28R550UQI /OLED Philips 55OLED707 /Yamaha RX-V471 + NS-555 + NS-C444 + NS-333 + YST-SW215

V0lt

А почему не передавать всем рендерерам? Они ведь должны игнорировать неизвестные им данные. Баг, который наблюдался на XP, нас ведь теперь не ограничивает?
[merge_posts_bbcode]Добавлено: 2016-09-21 21:26:42[/merge_posts_bbcode]

Я просто заменил
if (dxvaExtFormat->VideoTransferMatrix > DXVA2_VideoTransferMatrix_SMPTE240M) {
    dxvaExtFormat->VideoTransferMatrix = DXVA2_VideoTransferMatrix_Unknown;
}
на
if (dxvaExtFormat->VideoTransferMatrix > 7) {
    dxvaExtFormat->VideoTransferMatrix = DXVA2_VideoTransferMatrix_Unknown;
}
И все рендереры такое переварили без проблем. В свойствах входного пина всех EVR-ов появилась строка VideoTransferMatrix   : 7 (YCgCo). На остальных не было, но это и не важно - главное работают.

Только системный на тестах затупил и подцепился к MEDIASUBTYPE_P010, но он так тупит и без этого изменения.

Aleksoid1978

Можно конечно и так, по простому.
AMD Ryzen 5 3600 /GIGABYTE B450 Gaming X /AMD Radeon R9 16Gb@3200 /Kingston 500Gb M.2 /GTX 1650 /Samsung U28R550UQI /OLED Philips 55OLED707 /Yamaha RX-V471 + NS-555 + NS-C444 + NS-333 + YST-SW215