Привет, хабр! Я хотел бы рассказать вам о моем недавно проведенном исследовании, в котором я изучал проблему несоответствия диапазонов ТВ/ПК при сжатии/воспроизведении видео.
Проблема эта довольно незначительная, но в то же время довольно распространенная, из-за нее я часто обвинял в изменении цвета кодеки сжатия.
Пример
Представьте, вы только что вернулись из отпуска, были на месте N и сделали суперфотографии на мероприятии М своей, несомненно, отличной камерой F. Скачиваете фотографии на компьютер, и понимаете - руки чешутся сделать видеоколлаж и показать все эту красоту своим друзьям.Сказано-сделано, установите любимый видеоредактор, настройте контрастность, гамму, сделайте все, чтобы было максимально красиво.
И вот проект готов: перед вами свежесделанный видеофайл.
Запускаешь проверить и.
Что-то не так, как будто контраст и насыщенность уменьшились.
А что, если это другой кодек? Пробовали другой кодек - то же самое.
Ладно, главное, чтобы на DVD всё было хорошо.
Записываешь клип на DVD - и цвета действительно становятся на свои места.
Как такое может быть?
Фон
Все началось со времен аналоговых телевизоров, с такой удивительной вещи, как кинескоп.Первые кинескопы были бесцветными, то есть на нем отображались оттенки яркости – чем интенсивнее поток, который электронная пушка направляла в данную точку, тем ярче светилась эта точка, все просто.
Сигнал на этот телевизор передавался точно так же, то есть транслировалась яркостная составляющая картинки.
Но черно-белая картинка не очень-то удовлетворяла людей; ведь у нас есть цветовое зрение, поэтому очень скоро появилось цветное телевидение.
В цветных телевизорах также использовался кинескоп, но для передачи цвета в нем, как и в современных мониторах, использовались красно-зелено-синие пиксели.
Тогда встал вопрос, как передать сигнал, сохранив обратную совместимость с черно-белыми телевизорами? Можно было бы, конечно, на соседней частоте вещать помимо яркости еще и 3 цветовых канала, но, во-первых, выделенный каналу частотный диапазон был достаточно узок, а во-вторых, это сложнее, поскольку в в итоге мы получаем 4 цветовых канала.
Так математики и инженеры придумали передавать помимо канала яркости два «хроматических» цвета — синий и красный, получаемые как разница яркости от соответствующего цветового канала, получая цветовое пространство из RGB ( Y, Cb=B-Y, Cr=R-Y).
Весь цветовой диапазон можно рассчитать по этим трем каналам.
Более того, человеческое зрение менее чувствительно к цветам, поэтому это позволило уменьшить разрешение цветовых каналов вдвое, практически без потери качества изображения.
То есть разрешение канала яркости в кадре PAL составляет 720x576, а цвета для него передавались в разрешении 360x576 (так называемая цветовая субдискретизация 4:2:2).
Но как именно преобразовать яркость (Y) и цветовые хроматические каналы (Cb, Cr) в RGB и наоборот? Так, в 1982 году YCbCr<=> Был заложен стандарт преобразования RGB, он называется CCIR 601 (с 1992 года — BT.601).
По результатам многочисленных экспериментов по восприятию цвета человеком яркость определяется как сумма красного, зеленого и синего цветов с коэффициентами 77/256, 150/256 и 29/256 соответственно.
В результате преобразования из RGB=> YCbCr получается уменьшенный диапазон яркости (16-235) и цветности (16-240).
Как сказано в стандарте, для синхронизации можно использовать значения 0 и 255, но значения 1-15 и 236-254 считаются недействительными и будут отображаться в черно-белом виде.
Позже это сужение диапазонов было перенесено и на цифровое видео, в результате чего узкий диапазон стал стандартом для видео.
Хотя для видео высокой четкости уже разработан другой стандарт преобразования цвета — BT.709, который отличается от BT.601 только коэффициентами.
Как правильно сжимать и воспроизводить видео? Видеофайл, если он сжат в одной из яркостно-хроматических схем (а это подавляющее большинство кодеков; только несжатое видео использует RGB), должен быть закодирован в узкий телевизионный диапазон яркости (16-235).
Поскольку монитор по-прежнему использует выход RGB, декодер должен преобразовать YCbCr в RGB с полным диапазоном 0–255. Это почти идеальная схема, но почему почти? Вот почему:
- Искусственное сжатие диапазона — из 256 оттенков серого получаем 220 (из 8 бит на самом деле получаем чуть больше 7 бит), и объективных причин, по которым диапазон нужно сжимать, кроме как ради совместимость.
Мы намеренно ухудшаем качество изображения.
- Каждый пиксель видео проходит из файла в точку на мониторе через кучу разных фильтров (декодер, программа-плеер, рендеринг, видеодрайвер).
Попутно в этой длинной цепочке может быть произведено множество преобразований, приводящих к потере качества из-за постоянного сужения ассортимента.
- Поскольку некоторые фильтры игнорируют сужение полосы, а некоторые видео неправильно кодируются в полном диапазоне, а не в узком, другие фильтры пытаются это исправить, что приводит к еще большей путанице.
Ээксперимент
Я решил провести эксперимент, проверить, как ведут себя разные плееры/драйвера при воспроизведении стандартного узкого диапазона (16-235) и видео, закодированного в полном диапазоне (0-255).Для этого я взял PNG-изображение с градиентом серого от 0-255 и через AviSynth передал его самому популярному и современному кодировщику x264. Я использовал три avs-скрипта, первый читал картинку и отдавал «как есть», в формате RGB (как несжатое видео): rgb.avs
ImageReader("palette.png", end=24)Во втором и третьем файлах я конвертировал в цветовое пространство YV12 в полном диапазоне по двум стандартам BT.601 и BT.709: pc601.avs
ImageReader("palette.png", end=24) ConvertToYV12(matrix="PC.601")pc709.avs
ImageReader("palette.png", end=24) ConvertToYV12(matrix="PC.709")Далее я выполнил сжатие, используя несколько вариантов.
Дело в том, что в x264 есть два параметра, которые могут повлиять на результат: --input-range[TV, PC] и --range [TV, PC].
В старых версиях x264 за это отвечал параметр --fullrange. colortest.cmd
x264.exe --preset veryslow --crf 1 --output rgb.mp4 rgb.avs x264.exe --preset veryslow --crf 1 --input-range TV --range TV --output rgb-tv-tv.mp4 rgb.avs x264.exe --preset veryslow --crf 1 --input-range TV --range PC --output rgb-tv-pc.mp4 rgb.avs x264.exe --preset veryslow --crf 1 --input-range PC --range TV --output rgb-pc-tv.mp4 rgb.avs x264.exe --preset veryslow --crf 1 --input-range PC --range PC --output rgb-pc-pc.mp4 rgb.avs x264.exe --preset veryslow --crf 1 --output pc601.mp4 pc601.avs x264.exe --preset veryslow --crf 1 --input-range TV --range TV --output pc601-tv-tv.mp4 pc601.avs x264.exe --preset veryslow --crf 1 --input-range TV --range PC --output pc601-tv-pc.mp4 pc601.avs x264.exe --preset veryslow --crf 1 --input-range PC --range TV --output pc601-pc-tv.mp4 pc601.avs x264.exe --preset veryslow --crf 1 --input-range PC --range PC --output pc601-pc-pc.mp4 pc601.avs x264.exe --preset veryslow --crf 1 --output pc709.mp4 pc601.avs x264.exe --preset veryslow --crf 1 --input-range TV --range TV --output pc709-tv-tv.mp4 pc709.avs x264.exe --preset veryslow --crf 1 --input-range TV --range PC --output pc709-tv-pc.mp4 pc709.avs x264.exe --preset veryslow --crf 1 --input-range PC --range TV --output pc709-pc-tv.mp4 pc709.avs x264.exe --preset veryslow --crf 1 --input-range PC --range PC --output pc709-pc-pc.mp4 pc709.avsВ результате я получил 15 файлов.
Проверив гистограмму с помощью AviSynth, я обнаружил, что без указания параметров --range и --input-range видео сжимается в том виде, в каком оно подается, в противном случае диапазоны конвертируются с использованием x264. То есть только файлы pc601.mp4 и pc709.mp4 обеспечивают плавную гистограмму, но так как эти стандарты отличаются только коэффициентами для хроматических каналов, то для нашей шкалы серого разницы между ними не будет, я буду тестировать только два файла — rgb.mp4 и pc601.mp4 (узкий и полный диапазон соответственно).
Я тестировал воспроизведение этих файлов на 4 компьютерах, все под управлением Windows 7 и кодеков ffdswow и K-Lite Codec Pack. Результат занес в таблицу:
Пояснение к таблице:
нормальное - правильное отображение
in - неверное отображение, диапазон 16-235 не масштабируется до 0-255
out - некорректное отображение, диапазон 0-255 был масштабирован по ошибке, в результате чего диапазон обрезался.
Вот скриншоты результатов в плеере MPC-HC:
Стоит отметить, что настройки диапазона доступны практически в каждом фильтре.
В моем случае эта настройка есть в видеодекодере ffdshow, в рендерах Lav, Haali, в настройках драйвера видеокарты, а еще можно принудительно конвертировать диапазон в плеере (есть специальный шейдер).
Однако по каким-то причинам переключение диапазона в видеодекодере ffdshow не повлияло на результат. Настройка в драйвере не везде влияет на результат; где это было, я внес это в таблицу (строка настроек видеокарты).
Кроме того, при аппаратном ускорении DXVA и CUDA правильным считается только диапазон 16-235, не говоря уже о телевизорах.
Заодно я также протестировал два видеоредактора:
- VirtualDub - не трогает диапазон, если нет преобразования из YV12/YUV2 в RGB и наоборот, в противном случае делает преобразование диапазона, фильтры работают в RGB, а при отображении в программе делает преобразование ТВ-> ПК.
- AviDemux - диапазон не меняется (просто не работает с RGB источниками), фильтры работают с YUV2, при отображении в программе конвертация ТВ-> ПК.
Полученные результаты
Из таблицы видно, что в итоге мы получаем полную путаницу: то, как будет отображаться видео, зависит от многих параметров, таких как используемый кодек, плеер, тип рендеринга и драйверы.Здесь главное понять, в чем на самом деле проблема, и по возможности устранить ее.
Правильный (хотя и не совсем) диапазон сжатия видео — TV (16-235), иначе в большинстве случаев видео будет отображаться некорректно (с обрезанием чёрно-белого диапазона).
И хотя с точки зрения цифрового видео было бы логичнее хранить и отображать весь спектр без каких-либо преобразований, на текущем этапе появился стандарт, без которого мы получим некорректное отображение в большинстве устройств.
Как с этим справиться? Что сразу приходит на ум, так это указать используемый диапазон в метатегах; этот метод даже уже реализован (есть флаг полного диапазона), но, к сожалению, очень часто этот флаг игнорируется.
Вот почему:
- разработчикам — нужно позаботиться о реализации влияния такого флага, а также сделать так, чтобы видео отображалось корректно в своих плеерах/кодеках, если преобразование диапазона необходимо;
- пользователи, если есть проблема с цветами, попробуйте отрегулировать настройки (в кодеке/плеере/драйвере), либо попробуйте другой плеер;
- видеопроцессоры должны знать о существовании такой проблемы и правильно сжимать ее (кодировать в диапазоне 16-235 или хотя бы указывать флаг полного диапазона).
Ссылки
Википедия YCbCr Википедия Рек.601
Википедия Рек.709
Википедия 4:2:2 Википедия Цветовая субдискретизация Теги: #Работа с видео #видео #ТВ #RGB #YUV #bt.601 #BT.709 #fullrange-
Пулемет – Это Событие?
19 Oct, 24 -
Как И Зачем Делать Очередь Из Двух Стеков
19 Oct, 24 -
Вечерняя Школа Windows Phone
19 Oct, 24 -
Хабрамуг
19 Oct, 24 -
Ит Ос 2008, Версия 2.2007.51-3
19 Oct, 24 -
Переписка С Леонидом Кагановым
19 Oct, 24