В параметрах видеопотока через MediaInfo иногда можно увидеть параметр "Matrix coefficients" (не путать с "Color primaries" и "Transfer characteristics"). Обычно там записано BT.709. Но есть ролик, в котором значится YCgCo.
Сам ролик называется 静流MAD - 恋文 [Game 1920X1080 30.000fps AVC-yuv444p10 FLAC ASS] - mawen1250.mkv
Оригинала нет. Есть кусок (https://www.sendspace.com/file/ehoqzv).
Теперь самое интересное.
EVR показывает неправильно.
madVR только начиная с версии v0.90.1 показывает правильно.
Наш декодер преобразует из YUV в RGB неправильно.
В LAV Video Decoder при выводе в RGB формате получаются корректные цвета.
Хорошие скриншоты сделал wanezhiling
MPC-BE: http://i.imgur.com/ndwMJMD.png
MPC-HC: http://i.imgur.com/HFsZe4c.png
На самом деле девочка блондинка, а не розоволосая. :D
Причина проста. Никто не понимает матричные коэффициенты YCgCo. Поэтому nevcairiel написал свои функции преобразования YUV в RGB (см. pixconv/yuv2rgb.cpp (https://github.com/Nevcairiel/LAVFilters/blob/master/decoder/LAVVideo/pixconv/yuv2rgb.cpp)).
Баг конечно некритичный и неприоритетный, но упомянуть его стоит.
Цитата: V0ltОригинала нет.
оно?
Эх - не дошли в свое время у меня руки для переноса его код для YUV->RGB. Он не только корректнее в некоторых случаях(ну вот как этот) - так еще и НАМНОГО быстрее(сам код SSE оптимизирован + используется много-поточность).
Ну и помимо этого у нас свои опции - которые ессно только libswscale.
Если решить вопросы по опциям - то я могу взяться за перенос ...
Цитата: z_mashineоно?
Вроде оно. Видеоряд длиннее, а вот сабов нет.
Цитата: Aleksoid1978Если решить вопросы по опциям - то я могу взяться за перенос ...
Там только с одной опцией могут быть проблемы - "Выходные уровни RGB", но я бы ее вообще удалил, т.к. RGB должен быть всегда 0-255.
Убирать не надо, но я еще бы добавил один пункт - авто(как есть), чтобы механизм преобразования сам определял что надо на выходе.
А вот я бы убрал остальные 2 параметра:
1 - Пресет. У нас сейчас почти все преобразования минуя libswscale, поэтому уже не актуально.
2 - Стандарт. Тоже не нужен - пусть работает авто-определение.
Цитата: V0ltВроде оно. Видеоряд длиннее, а вот сабов нет.
Скачай, они вшитые. У меня такой же ролик лежит.
Цитата: Aleksoid1978Эх - не дошли в свое время у меня руки для переноса его код для YUV->RGB. Он не только корректнее в некоторых случаях(ну вот как этот) - так еще и НАМНОГО быстрее(сам код SSE оптимизирован + используется много-поточность).
Звучит очень вкусно!
Цитата: V0ltсделал wanezhiling
Это она ;)
Так - а получается что, libswscale не поддерживает это ?? Кто знает как а ffplay указать выходной тип(ну там NV12/RGB32 и т.д.) ??
(http://i.imgur.com/KMFweOm.png)
Like LAV, PotPlayer also outputs correct color even with EVR.
Pot\'s color is right, but NV12 output is totally wrong. For this video type, 10 bit 4:4:4 - must use RGB32 output. Not right auto select in PotPlayer :)
[merge_posts_bbcode]Добавлено: 2016-01-18 21:05:44[/merge_posts_bbcode]
И, кстати, LAV корректно только в RGB выводит данный ролик для любых рендереров кроме madVR. Если же в другие типы - то плохо. С madVR все хорошо - за счет передачи параметра VideoTransferMatrix = 7.
Разработчик Pot тут конечно сделал правильнее - корректную трансформацию в самом декодере делает.
Цитата: Aleksoid1978Убирать не надо, но я еще бы добавил один пункт - авто(как есть), чтобы механизм преобразования сам определял что надо на выходе.
Хочу узнать,
по какому критерии можно
автоматически преобразовывать в RGB 16-232 вместо стандартных 0-255?
ЦитироватьА вот я бы убрал остальные 2 параметра:
1 - Пресет. У нас сейчас почти все преобразования минуя libswscale, поэтому уже не актуально.
2 - Стандарт. Тоже не нужен - пусть работает авто-определение.
1. Тут заковырка с "почти". И это не только редкие форматы, но и обычные, которые при определенных условиях могут не работать на оптимизированных функциях LAV.
Также перед удалением опции, хорошо бы сравнить производительность пресетов и функций LAV.
2. Тут согласен.
ЦитироватьРазработчик Pot тут конечно сделал правильнее - корректную трансформацию в самом декодере делает.
Там совсем неправильно.
Неправильно из YUV 4:4:4 делать YUV 4:2:0.
[merge_posts_bbcode]Добавлено: 2016-01-22 20:16:26[/merge_posts_bbcode]
Есть альтернативная библиотека для конвертирования цветовых форматов -
ZIMG.
По описанию и заголовочным файлам там вроде есть все что надо.
В общем ffmpeg содержит фильтр zscale (https://ffmpeg.org/ffmpeg-filters.html#zscale), который как раз использует библиотеку zimg, которая понимает YCgCo.
В результате выполнения следующей команды получаем картинку с правильными цветами.
ffplay -i "MAD - [Game 1280x720 30.000fps AVC-yuv444p10 FLAC ASS] v2 - mawen1250.mkv" -vf zscale=min=\'ycgco\':m=\'709\'
[merge_posts_bbcode]Добавлено: 2016-03-07 18:08:38[/merge_posts_bbcode]
Можно min=\'ycgco\' не указывать, т.к. zscale получет этот параметр от декодера.
[merge_posts_bbcode]Добавлено: 2016-03-07 21:20:06[/merge_posts_bbcode]
Но добавлять фильтр zscale, что-то не сильно хочется.
Причина простая. swscale поддерживает все пиксельные форматы ffmpeg, а zscale только часть. Поэтому придется держать две либы, которые в некоторых случаях будут работать одновременно и последовательно. Бред.
Хотелось бы просто дождаться, когда доработают swscale.
Да не стоит из-за одного-двух файлов прикручивать целый фильтр видео-обработки. Как никак - это лишняя затрата процессорного времени(а это влечет за собой повышение нагрузки CPU), даже с учетом того что не будет никакого scale изображения.
[merge_posts_bbcode]Добавлено: 2016-09-21 11:10:06[/merge_posts_bbcode]
По поводу работы с YCgCo - возможно ли шейдерами выполнить 2-х этапное преобразование ??
Поясню - для того чтобы "подкорректировать" конечный RGB можно попробовать сперва перевести RGB -> YUV, а потом уже YUV -> RGB(по нужному алгоритму YCgCo->RGB).
Вот тут есть описание алгоритма https://wiki.multimedia.cx/index.php?title=YCoCg
[merge_posts_bbcode]Добавлено: 2016-09-21 11:20:45[/merge_posts_bbcode]
А вот даже есть что-то связанное с Pixel Shader - http://www.gamedev.net/topic/517500-ycocg-to-rgb-in-a-pixel-shader-almost-there-one-last-problem/
Есть механизм внешних шейдеров. Пробуй.
Я в них не шарю совершенно.
Видео-рендереры - это по твоей части :)
[merge_posts_bbcode]Добавлено: 2016-09-21 15:54:43[/merge_posts_bbcode]
Хм ... я смог :)
вот код шейдера
// $MinimumShaderProfile: ps_2_0
sampler s0 : register(s0);
static float4x4 rgb2yuv = {
0.250, 0.500, 0.250, 0.000,
-0.250, 0.500, -0.250, 0.000,
0.500, 0.000, -0.500, 0.000,
0.000, 0.000, 0.000, 0.000
};
static float4x4 yuv2rgb = {
1.000, 0.000, 1.140, 0.000,
1.000, -0.394, -0.581, 0.000,
1.000, 2.028, 0.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;
}
и вот скрины
EVR Custom + шейдер:
(http://s018.radikal.ru/i506/1609/2e/cff40598b1eet.jpg) (http://radikal.ru/big/8cw0ics610saw)
madVR:
(http://s018.radikal.ru/i527/1609/cc/17755dd5e8b8t.jpg) (http://radikal.ru/big/vifdohx6uu191)
[merge_posts_bbcode]Добавлено: 2016-09-21 16:02:42[/merge_posts_bbcode]
Хотя - все равно отличается от madVR и PotPlayer. Возможно что rgb2yuv должен быть немного другим(я его взял их zimg). У madVR/Pot картинка более сочная/яркая.
Я понял почему такая разница в сочности/яркости - у нас идет вывод в RGB32. Убрал RGB, пошел вывод в YUY2, картинка с шейдером стала более похожая на madVR
Пожалуйста, дай ссылки на код откуда эти матрицы получил.
Одна матрица 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]
Естественно - шейдер надо применять до ресайза, на оригинальном видео.
Тут проблема двоякая.
Если на вход рендерера приходит AYUV с матрицей YCgCo, то тут сам рендерер должен разруливать вышеуказанным шейдером. Подобное как раз делает madVR.
Если же на вход рендерера приходит неправильный RGB, тогда рендерер трогать не надо. Т.к. матрицу YCgCo передавать в свойствах неправильно - не бывает таких матриц в RGB формате. Здесь нужно в самом конвертере декодера править. Судя по матрице из шейдера это несложно будет.
Полностью согласен. Правда 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 так наворочен код что без бутылки не разобрать. Может тикет сделаешь, ссылку на вики дать - я думаю они сами быстрее чем я там буду ковыряться.
Вывожу формат 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
Надо устранить сию дискриминацию!
Я же сказал - это я сделаю, прям завтра с утра, по Владивостоку конечно же :)
это как раз то, о чем я писал на руборде. правда я не мог подкрепить свои слова цифрами и такими вот выкладками, но факт остаётся фактом: лучше для просмотра аниме чем мадВР еще ничего не придумали и об этом предупреждают почти во всех ветках на трекерах где раздается 10-битный контент.
Вот патч для видео-декодера. Я немного усложнил - передаем данные пл YCgCo матрице ТОЛЬКО для EVR Custom/Sync, т.е. только для Custom Allocator.
https://yadi.sk/d/SWQy37WBvVFz6
А почему не передавать всем рендерерам? Они ведь должны игнорировать неизвестные им данные. Баг, который наблюдался на 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, но он так тупит и без этого изменения.
Можно конечно и так, по простому.