MPEG-pro-I
профессиональное сжатие видео
крис касперски ака мыщъх, no-email
эта публикация открывает цикл статей, посвященный вопросам обработки видеоинформации в домашних условиях, и в первую очередь — осмысленной настройке MPEG2/MPEG4 кодеков, увеличивающей степень сжатия (без видимой потери качества) в несколько раз по сравнению с «сертифицированными профилями», установленными по умолчанию.
введение
Научно-технический прогресс развращает, приучая все делать одним взмахом мыши, в результате чего мы имеем DVD-диск от SUPERBIT и EXTRABIT «непревзойденного качества», подготовленные с помощью AheadNero (о чем честно свидетельствует поле SourceMediaImplementationIdentifier, хранящееся на DVD-диске вместе с прочей служебной информацией) и записанные с грубыми нарушениями стандарта, в результате чего мы имеем проблемы — от появления «артефактов» и ухудшения качества, до полной невозможности воспроизведения диска на определенных моделях DVD-плееров (особенно стационарных).
Сжатие цифрового видео — очень сложная тема, намного более кромешная и запутанная, чем это кажется до попытки основательно разобраться в ней. Начав исправлять ошибки лицензионных DVD (исключительно в целях домашнего просмотра!), автор зарылся в стандарты, обложился спецификациями, скачал исходные коды всех доступных кодеков и… на несколько месяцев погрузился в пучину бесчисленных экспериментов, в результате чего стал сжимать намного качественнее и плотнее, чем окружающие. «Качественнее» — это значит лучше, чем на _оригинальном_ DVD-носителе (см. рис. 18, 19). Не верите? Говорите: «чудес не бывает»? А разве алгоритмы сжатия звука и видео — это уже само по себе не чудо? Немного людей знает на каких принципах они базируются и еще меньше готовы написать свой собственный кодек или усовершенствовать имеющийся.
Да что там! Подавляющее большинство использует настройки по умолчанию или пытается манипулировать ими вслепую. Журналы и пестрят сравнительными тестами различных кодеков, демонстрирующими один и тот же кадр, рассматриваемый под большим увеличением. И невдомек им, что при популярном двухпроходном сжатии и дробном quantizer'e разные кадры сживаются с разным качеством (поскольку quantizer дробным не бывает и если для достижения заданного объема целевого файла кодер решил, что нужно использовать quantizer == 2.5, в практическом плане это означает, что половина кадров закодируется с quantizer == 2, а половина — с 3 и результаты теста в большой степени зависят от того какой кадр мы возьмем). Так же, при динамическом битрейте кодек стремиться отдать больше битов тем сценам, в которых по ему мнению они сильнее всего нуждаются, отнимая их у всех остальных. Алгоритм перераспределения битов у всех кодеков разный и потому сравнивая _один_ и _тот_ _же_ кадр, сжатый разными кодеками, мы можем получить драматический разрыв в качестве, но… делать глобальные выводы на этом основании нельзя!
Это, так сказать, для затравки. Чтобы пробудить исследовательский интерес. Зная, как работает кодек, мы сможем осмысленно крутить его настройки для достижения максимального сжатия с минимальной потерей качества. Источником видеоматериала может выступать и цифровая камера, и карта видео-захвата, и TV-тюнер, и куча прочего потребительского барахла… но мы (для удобства) остановимся на DVD как на самом удобном и «послушном» носителе информации.
Естественно, законы многих стран запрещают перезапись лицензионных DVD даже в домашних целях (что есть полный абсурд), но в нашей стране Фемида намного более лояльна и до тех пор, пока мы не начнем _распространять_ скопированный (и пережатый) DVD тем или иным образом, можно смело экспериментировать и ничего не опасаться.
Причин же для копирования DVD имеется как минимум две: во-первых, лицензионные DVD (да и не лицензионные тоже) сплошь и рядом записаны с теми или иными ошибками, которые неплохо бы устранить (тем более, что технически это возможно), а во-вторых, DVD-диски занимают слишком много места (геометрического) и каждый раз рыться с завалах коробок — занятие не из приятных. Намного удобнее держать фильмы на жестком диске (кстати, законы — даже Американские — это позволяют, при условии, что диск используется только как кэш и дальше его фильмы никуда не уходят).
Короче, будем считать, что я вас заинтриговал. Правда, первую часть статьи, посвященную основам теории сжатия, придется поскучать и пошевелить мозгами, зато во второй пройдет чистая практика с кучей полезных советов.
требование к читателю
Предполагается, что читатель уже имеет некоторое представление о цифровом видео и хотя бы в общих чертах понимает, чем MPEG отличается от AVI. На всякий случай, вот несколько хороших FAQ по этому поводу:
- Introduction to MPEG:
- The Unofficial XviD FAQ:
- Современные методы и стандарты экономного кодирования видеоинформации:
свет и цвет
Существует множество систем кодирования светоцветовой информации, воспринимаемой человеком. Большинство методов построено на сложении (вычитании) трех или четырех основных цветов. В частности, CRT-телевизоры формируют изображение путем трех лучевых пушек — красной (Red), зеленой (Green) и синей (Blue) и соответствующая ей цветовая схема называется RGB. Она же используется и в большинстве видео-карт. Популярный режим RGB32 (True-Color 32) на кодирование каждого пикселя расходует по 8 бит, плюс еще 8 бит отводится под канал прозрачности. Итого 3*8+8 = 32.
Нетрудно подсчитать, сколько байт потребуется для кодирования «картинки» с любым разумным разрешением. Такое количество информации очень трудно сохранить и еще труднее передать по радиоканалу. А при проектировании цветных телевизоров перед разработчиками поставили задачу — любой ценой вложиться в полосу пропускания отведенную для Ч/Б телевизоров, в которую RGB никак не желала укладываться и пришлось пойти на рад хитростей.
Считается, что нормальный человеческий глаз (художников мы не берем в расчет) способен распознать до 16 миллионов цветовых оттенков, в то время как 32-битный RGB дает 4.294.967.296, что _намного_ больше, то есть явный перебор. Сколько же бит _реально_ необходимо? Прибегнув к логарифмам нетрудно подсчитать, что 24 бита кодируют 16.777.216 оттенков. Но 24 бита это все равно очень и очень много. С другой стороны, далеко не все оттенки равнозначны…
Цветоощущенье — подарок природы, появившийся на поздних стадиях эволюции (многие животные его лишены и до сих пор!), в силу чего, глаз гораздо более чувствителен к изменению яркости, чем к положению в спектре (т. е. цветности). Отталкиваясь от этого факта, перед передачей в эфир исходные RGB-сигналы преобразуются в сигнал яркости Y (он же Luminance или Luma) и два цветоразностных сигнала U и V (Chroma), вычисляемых по следующей формуле:
Y = 0.299R + 0.587G + 0.114B, U = R - Y, V = B - Y
Формула 1 перевод RGB-сигналов в YUV форму
Коэффициенты подобраны с учетом особенной человеческого восприятия: максимум воспринимаемой глазом световой энергии сосредоточено в зеленой (точнее, желто-зеленой) области спектра, поэтому ему выделяется наибольшее количество бит. Как видно, кодирование сигнала происходит с большими потерями, но… это неизбежная плата за узкие полосы пропускания. Радиодиапазон ведь не резиновый, а вещать хотят все…
Естественно, перед выводом на экран приходится осуществлять обратное преобразование:
R = Y + U, B = Y + V, G = Y - 0.509U - 0.194V
Формула 2 перевод YUV сигналов в RGB
Подробнее об этом можно прочитать в любой книжке по ремонту и настройке цветных телевизоров или в следующей статье: http://www.videoton.ru/Articles/Article2.html. Какое отношение имеют телевизоры к компьютерам и (тем более!) к сжатию информации? Самое прямое!!! Поскольку, сжимать в основном приходится не RGB32, сграбленный с экрана, а видеоматериал, предназначенный для эфирной трансляции, то в нем _уже_ отсутствует _вся_ информация о 2^32 оттенках и потому MPEG-кодеры работают с «телевизионными» цветовыми схемами. В MPEG1 это YUV420 (она же YUV12 и YV12), в которой значение яркости (Y) сохраняется для каждого пикселя, а цветоразностные компоненты (U&V) получаются путем усреднения значений 4'х пикселей, образующий матрицу 2×2. На все компоненты отводится по 8 бит, в результате чего на одни пиксель приходится 12 бит (отсюда и название). Главным недостатком подобной схемы становится не только низкое цветовое разрешение, но и невозможность работы с черезстрочечным (interlaced) видеоматериалом, т. к. из-за объединения соседних вертикальных линий возникают сильные искажения.
В MPEG2 используется более продвинутая цветовая схема YUV422 (она же YUY2), которая, так же, как и предыдущая сохраняет яркостной сигнал (Y) для всех точек, а вот сигнал цветности усредняется у двух соседних пикселей по горизонтали, в результате чего появляется возможность работать с черезстрочечным видеоматериалом, цветовое разрешение возрастает вдвое, а на один пиксель уже приходится 16 бит.
В MPEG4-кодеках может использоваться как та, так и другая схема. YV12 встречается гораздо чаще, поскольку обладает более высоким сжатием, экономящим 35% бит по сравнению с YUY2. Кстати, именно по этой причине многие MPEG-4 кодеки первого поколения (такие, как DivX, например) не могли работать с черезстрочечным видео и перед его сжатием приходилось выполнять операцию de-interlaced, что не только требовало время, приводило к появлению «артефактов», но и ухудшало сжимаемость, но постепенно разработчики кодеков решили эту проблему и теперь при включении одноименной опции, черные промежуточные полосы _не_ сжимаются вообще, существенно сокращая размер выходного файла.
Ладно, это все была сухая теория. Переходим к суровой практике. При сжатии MPEG4-кодеком видеоматериала, представленного в формате YUY2 (например, DVD), искажения будут происходить не только из-за потери информации о цветности, но и… ошибок преобразования YUY2 в YV12 и последующей конвертации YV12 в RGB при выводе на экран монитора. Искажения цветопередачи зачастую оказываются весьма значительными и кристально чистая небесная голубизна превращается в унылую серую грязь. Чтобы понять почему так происходит (и что сделать, чтобы этого не происходило) необходимо разобраться в этом вопросе более подробно и основательно.
Начнем, как водится с канонов. Группа MSSG (MPEGSoftwareSimulationGroup) прилагает к стандарту рефересную (reference – эталон) версию библиотеки mpeg2, последнюю версию которой можно скачать по адресу: ftp://ftp.mpegtv.com/pub/mpeg/mssg/mpeg2v12.zip (для доступа требуется логин и пароль) или утянуть ее прямо из института Беркли без всяких логинов и паролей: http://bmrc.berkeley.edu/ftp/pub/multimedia/mpeg/mpeg2/software/mpeg2v12.zip
В файле \src\mpeg2enc\readpic.c содержится исходный код функции readpic.c, преобразующий RGB в YUV2, ключевой фрагмент которой приведен ниже:
for (i=0; i<vertical_size; i++)
{
yp = frame[0] + i*width;
up = u444 + i*width;
vp = v444 + i*width;
for (j=0; j<horizontal_size; j++)
{
r=getc(fd); g=getc(fd); b=getc(fd);
/* convert to YUV */
y = cr*r + cg*g + cb*b;
u = cu*(b-y);
v = cv*(r-y);
yp[j] = (219.0/256.0)*y + 16.5; /* nominal range: 16..235 */
up[j] = (224.0/256.0)*u + 128.5; /* 16..240 */
vp[j] = (224.0/256.0)*v + 128.5; /* 16..240 */
}
}
Листинг 1 фрагмент функции перевода RGB в YUV2, выданный из рефересной библиотеки mpeg2
Первое, что бросается в глаза, это, конечно же, вещественная арифметика, которая проигрывает целочисленной и пожирает процессорные такты со страшной силой. Но это еще не самое страшное (в конце концов, оптимизация — вопрос реализации). Хуже всего то, что отображение цветового диапазона RGB на цветовой диапазон YUV2 выполняется _неправильно_ с грубыми ошибки, допущенными _умышленно_ и даже отмеченными в комментарии. Для увеличения степени сжатия, уровень каждой из компонент сужается с 0..255 до 16..235 и обратное преобразование (естественно), приходится выполнять в том же порядке. Для телевизора (и CRT-монитора времен ранней молодости MS-DOS с подсевшей трубкой), эта схема работает на ура, поскольку по краям диапазона оттенки яркости практически не различимы, а вот для современного LCD монитора с S-IPS матрицей (каким, в частности, является мой NEC 1970NX) — уровень 16 это уже не черный, а серый (или, точнее говоря, слегка белесоватый). В результате, фильмы, действие которых разворачивается во мрачных замках, куда не проникает дневной свет, смотреть становится практически невозможно. Все тени приобретают грязноватый оттенок.
Умные декодеры (к которым, в частности, относиться мной любимый FFDShow) позволяют исправить ситуацию, либо коррекцией уровней (levels), либо модификацией функции конвертации (это совсем несложно сделать, исходные тексты доступны и хорошо структурированы). Только не берите версию FFShow, лежащую на www.sourceforge.net. Она безнадежно устарела (поскольку по непонятным причинам разработчикам отрубили доступ к проекту). В настоящее время скачать самую последнюю версию FFDShow можно с сервера www.free-codecs.com (более точная ссылка не приводится, поскольку она постоянно мигрирует в широких пределах).
Естественно, референсная библиотека — это совсем не Коран и LCD мониторы появились не вчера и даже не позавчера. Другими словами, «правильный» DVD должен записываться с использованием «правильной» схемы конвертации, но… даже среди абсолютно лицензионных дисков за $15-$20 встречается куча откровенного барахла… Вот только один пример (см. рис. 1). Видите? Нижний порог яркости начинается не с нуля, а верхний — заканчивается задолго до достижения максимального насыщения (естественно, для снятия этого screenshot'а была специально выбрана соответствующая сцена из фильма, содержащая и предельно черные — в ее понимании — и предельно белые — опять-таки, в ее понимании — уровни яркости).
Рисунок 1 наблюдение за уровнями яркости в FFDShow
Таким образом, мнение, что «DVD-качество» это — эталон, выше которого не запрыгнуть, глубоко неверно. И часто случается так, что при _правильном_ «перегоне» DVD на 1/2CD мы _выигрываем_ в размере за счет потери несущественных деталей (которые все равно не видны) и в качестве — за счет устранения грубых ошибок мастеринга, сразу же бросающихся в глаза при просмотре оригинала.
Ладно, уровни это ерунда. С ними и ребенок справится (естественно, с той оговоркой, что при растяжке уровня с 16..235 до 0..255 происходит неизбежная потеря информации о яркости — отрезанные биты ведь не из воздуха берутся — хотя, в целом картинка смотрится намного естественнее). Большинство коммерческих (да и некоммерческих) кодеков для достижения максимального быстродействия используют целочисленную арифметику. Вот фрагмент функции преобразования YUV в RGB, выдранный из XviD'а, и находящийся в файле \src\image\colorspace.c. Сами же исходные тексты можно найти на официальном сайте: http://downloads.xvid.org/downloads/xvidcore-1.1.2.zip
#define WRITE_RGB16(ROW,UV_ROW,C1)\
rgb_y = RGB_Y_tab[ y_ptr[y_stride*(ROW) + 0] ];\
b[ROW] = (b[ROW] & 0x7) + 1)/(b) : 2)/(b))
#define VM18P 3
#define VM18Q 4
/* divide-by-multiply table
* needs 17 bit shift (16 causes slight errors when q > 19) */
#define SCALEBITS 17
#define FIX(X)3)


















