Принципы сжатия видео: "тонкая" настройка MPEG

Эта публикация открывает цикл статей, посвященный вопросам обработки цифрового видео в домашних условиях. Данный материал поможет освоить «тонкую» настройку MPEG-кодеков для максимального сжатия с минимальными потерями. Будут рассмотрены примеры улучшение качества «левых» DVD и «криво пожатых» AVI. Информация будет полезна и тем, кто смотрит видео на КПК, телефонах и смартфонах.

Научно-технический прогресс приучает все делать одним взмахом мыши. Пользователь становится ленивым и уже не вникает в особенности технологий, что «нечестному производителю» только на руку. В результате чего на свет появляются DVD-диски от SUPERBIT и EXTRABIT «непревзойденного качества», подготовленные с помощью программы Ahead Nero. Об этом честно свидетельствует поле Source Media Implementation Identifier на DVD-диске вместе с прочей служебной информацией. Эти диски записаны с грубейшими нарушениями стандарта. В результате получаем все что угодно: от «артефактов» до полной невозможности воспроизведения диска на определенных моделях DVD-плееров.

Подавляющее большинство пользователей оставляет настройки по умолчанию или пытается манипулировать ими вслепую. Журналы часто пестрят сравнительными тестами различных кодеков, демонстрирующими один и тот же кадр, рассматриваемый под большим увеличением.

Зная, как работает кодек, мы сможем осмысленно «крутить» его настройки для достижения максимального сжатия с минимальной потерей качества. Источником видеоматериала может выступать и цифровая камера, и карта видеозахвата, и TV-тюнер, и прочие устройства, которые работают с видеофайлами. Но мы остановимся на DVD как на самом удобном и «послушном» носителе информации.

Естественно, законы многих стран запрещают перезапись лицензионных 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 никак не желала укладываться. Пришлось пойти на рад хитростей.

Считается, что нормальный человеческий глаз способен распознать около 4 тысяч цветов, в то время как 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. Эта формула переводит RGB-сигнал в YUV-форму.

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

Естественно, перед выводом на экран приходится осуществлять обратное преобразование: R = Y + U, B = Y + V, G = Y — 0.509U — 0.194V.

Подробнее об этом можно прочитать в любой толковой книге по ремонту и настройке цветных телевизоров или в этом материале.

Какое отношение имеют телевизоры к компьютерам и (тем более!) к сжатию информации? Поскольку сжимать в основном приходится не RGB32, «пожатый» с экрана, а видеоматериал, предназначенный для эфирной трансляции, то в нем уже отсутствует вся информация о 2^32 (два в тридцать второй степени), то есть о 4.294.967.296 оттенках, и потому MPEG-кодеры работают с «телевизионными» цветовыми схемами. В MPEG1 это YUV420 (она же YUV12 и YV12), в которой значение яркости (Y) сохраняется для каждого пикселя, а цветоразностные компоненты (UV) получаются путем усреднения значений 4 пикселей, образующих матрицу 2x2. На все компоненты отводится по 8 бит, в результате чего на один пиксель приходится 12 бит (отсюда и название). Главным недостатком подобной схемы становится не только низкое цветовое разрешение, но и невозможность работы с черезстрочечным (interlaced) видеоматериалом, т. к. из-за объединения соседних вертикальных линий возникают сильные искажения.

В MPEG-2 используется более продвинутая цветовая схема YUV422 (она же YUY2). Она, как и предыдущая, сохраняет яркостной сигнал (Y) для всех точек, а вот сигнал цветности усредняется у двух соседних пикселей по горизонтали, в результате чего появляется возможность работать с черезстрочечным видеоматериалом, цветовое разрешение возрастает вдвое, а на один пиксель уже приходится 16 бит.

В MPEG-4 кодеках может использоваться как та, так и другая схема. YV12 встречается гораздо чаще, поскольку обладает более высоким сжатием, экономящим 35% бит, по сравнению с YUY2. Кстати, именно по этой причине многие MPEG-4 кодеки первого поколения (такие как DivX, например) не могли работать с черезстрочечным видео, и перед его сжатием приходилось выполнять операцию de-interlaced, что не только требовало времени, приводило к появлению «артефактов», но и ухудшало «сжимаемость». Постепенно разработчики кодеков решили эту проблему. О том, как им это удалось, мы поговорим во второй статье, посвященной проблемам сжатия черезстрочечного видео.

ЧАСТЬ ВТОРАЯ: ПРАКТИКА Цветопередача

Итак, что же мы имеем? При сжатии MPEG-4 кодеком видеоматериала, представленного в формате YUY2 (например, DVD), искажения будут происходить не только из-за потери информации о цветности, но и ошибок (!) преобразования YUY2 в YV12 и последующей конвертации YV12 в RGB при выводе на экран монитора. Искажения цветопередачи зачастую оказываются весьма значительными. Жаль, но кристально чистая небесная голубизна превращается в унылую серую грязь. Чтобы понять, почему так происходит (и что сделать, чтобы этого не происходило), необходимо разобраться в этом вопросе более подробно и основательно.

Начнем, как водится, с канонов. Группа MSSG (MPEG Software Simulation Group) прилагает к стандарту референсную (reference — эталон) версию библиотеки mpeg2, последнюю версию которой можно скачать по этому адресу. Или утянуть ее отсюда прямо из института Беркли, без всяких логинов и паролей.

В файле \src\mpeg2enc\readpic.c содержится исходный код функции readpic.c, преобразующий RGB в YUV2, ключевой фрагмент которой приведен.

for (i=0; i

{

yp = frame[0] + i*width;

up = u444 + i*width;

vp = v444 + i*width;

for (j=0; 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 */

}

Первое, что бросается в глаза, это, конечно же, вещественная арифметика, которая проигрывает целочисленной и пожирает процессорные такты со страшной силой. Но это еще не самое страшное (в конце концов, оптимизация — вопрос реализации). Хуже всего то, что отображение цветового диапазона RGB на цветовой диапазон YUV2 выполняется неправильно, с грубыми ошибками, допущенными умышленно и даже отмеченными в комментарии. Для увеличения степени сжатия уровень каждой из компонент сужается с 0..255 до 16..235, и обратное преобразование (естественно) приходится выполнять в том же порядке. Для телевизора (и CRT-монитора времен ранней молодости MS-DOS с подсевшей трубкой) эта схема работает на ура, поскольку по краям диапазона оттенки яркости практически неразличимы. А для современного LCD-монитора с S-IPS матрицей — уровень 16 это уже не черный, а серый (точнее говоря, слегка белесоватый). В результате фильмы, действие которых разворачивается в мрачных замках, куда не проникает дневной свет, смотреть становится практически невозможно. Все тени приобретают грязноватый оттенок.

«Умные» декодеры (к которым, в частности, относится тот же FFDShow) позволяют исправить ситуацию либо коррекцией уровней (levels), либо модификацией функции конвертации (это совсем несложно сделать, исходные тексты доступны и хорошо структурированы). Только не берите версию FFShow на , она безнадежно устарела (поскольку по непонятным причинам разработчикам отрубили доступ к проекту). В настоящее время скачать самую последнюю версию FFDShow можно с сервера (более точная ссылка не приводится, поскольку она постоянно мигрирует в широких пределах).

Естественно, референсная библиотека — это совсем не Коран и LCD-мониторы появились не вчера и даже не позавчера. Другими словами, «правильный» DVD должен записываться с использованием «правильной» схемы конвертации. Но даже среди абсолютно лицензионных дисков за $15-20 встречается куча откровенного негодяйства! Вот только один пример.

Наблюдение за уровнями яркости в FFDShow

Нижний порог яркости начинается не с нуля, а верхний — заканчивается задолго до достижения максимального насыщения (естественно, для снятия этого screenshot'а была специально выбрана соответствующая сцена из фильма, содержащая и предельно черные, и предельно белые — в ее понимании — уровни яркости).

Таким образом, мнение, что «DVD-качество» — это эталон, выше которого не запрыгнуть, глубоко неверно. И часто случается так, что при правильном «перегоне» DVD на 2 CD мы выигрываем в размере. Да, за счет потери несущественных деталей (которые все равно не видны) и качества — за счет устранения грубых ошибок мастеринга, сразу же бросающихся в глаза при просмотре оригинала.

Но уровни — это еще полбеды. Естественно, с той оговоркой, что при растяжке уровня с 16..235 до 0..255 происходит неизбежная потеря информации о яркости. «Отрезанные» биты ведь не из воздуха берутся — хотя в целом картинка смотрится намного естественнее.

Большинство коммерческих (да и некоммерческих) кодеков для достижения максимального быстродействия используют целочисленную арифметику. Вот фрагмент функции преобразования YUV в RGB, выдранный из XviD'а и находящийся в файле \src\image\colorspace.c. Сами же исходные тексты можно найти на официальном сайте.

Это пример макроса из XviD'а, отвечающего за преобразование YUV в RGB

#define WRITE_RGB16(ROW,UV_ROW,C1)\

rgb_y = RGB_Y_tab[ y_ptr[y_stride*(ROW) + 0] ]; \

b[ROW] = (b[ROW] 0x7) + ((rgb_y + b_u##UV_ROW) >> SCALEBITS_OUT);\

g[ROW] = (g[ROW] 0x7) + ((rgb_y — g_uv##UV_ROW) >> SCALEBITS_OUT);\

r[ROW] = (r[ROW] 0x7) + ((rgb_y + r_v##UV_ROW) >> SCALEBITS_OUT);\

*(uint16_t *) (x_ptr+((ROW)*x_stride)+0) = C1(r[ROW], g[ROW], b[ROW]);\

rgb_y = RGB_Y_tab[ y_ptr[y_stride*(ROW) + 1] ];\

b[ROW] = (b[ROW] 0x7) + ((rgb_y + b_u##UV_ROW) >> SCALEBITS_OUT);\

g[ROW] = (g[ROW] 0x7) + ((rgb_y — g_uv##UV_ROW) >> SCALEBITS_OUT);\

r[ROW] = (r[ROW] 0x7) + ((rgb_y + r_v##UV_ROW) >> SCALEBITS_OUT);\

*(uint16_t *) (x_ptr+((ROW)*x_stride)+2) = C1(r[ROW], g[ROW], b[ROW]);

Чем плоха целочисленная арифметика? А тем, что ошибки округления приводят к искажению цветопередачи, которое в ряде случаев оказывается просто драматическим (особенно, если сравнивать сконвертированное изображение с оригиналом).

Для борьбы с этим явлением разработчики видеокарт придумали такую штуку, как оверлей (overlay mode), позволяющую части экрана иметь цветовую схему, отличную от текущей. В overlay mode видеоинформация проходит «транзитом» сквозь карту и поступает на монитор, не затрагивая остальные узлы, минуя в видеопамять и... освобождая центральный процессор от необходимости выполнения преобразования одной цветовой схемы в другую. Вот только монитор — он ведь на входе совсем не YUV ожидает увидеть, и потому оверлей не снимает проблему конвертации, а просто перекладывает ее на плечи карты. Причем, если программный алгоритм преобразования цветовых пространств легко поменять (выбрав из всех самый удачный), то с железом не поспоришь, и карта выдает то, что в нее заложено.

Часть карт вообще не поддерживает overlay mode, часть — поддерживает, но выдает изображение такого скверного качества, что на него практически невозможно смотреть (в особенности это относится к картам NVIDA).

Стандартный Microsoft Media Player всегда стремится использовать оверлей и никакой возможности отключить эту функцию у него, похоже, нет. Плееры сторонних производителей — в частности BSPlayer — позволяют отключать оверлей установкой галочки «Force RGB mode».

Форсирование RGB-режима в BSPlayer'е

Ниже приводятся два кадра из одного и того же фильма. Первый получен в форсированном RGB-режиме, второй — в overlay mode на карте NVIDA GeForce 6600. Как говорится, почувствуйте разницу!

Кадр, полученный в RGB-режиме (с кодеком FFDShow)

 

Кадр, полученный в RGB-режиме (с кодеком FFDShow)

А разница такова, что в RGB mode у актера вид крепко выпившего грузчика. Зато в overlay mode море и сгустившийся над ним туман приобретают грязно-серый цвет, а низ каната окрашивается в зеленый цвет, словно водоросли!

Уже упомянутый кодек FFDShow имеет функцию высококачественного преобразования YV12 в RGB, активируемую установкой флажка «High quality VY12 to RGB conversion». Она отнимает дополнительные такты, но дает значительно лучший результат.

Активирование функции высококачественного преобразования YV12 в RGB в кодеке FFDShow

Лицо приобретает нормальный телесный оттенок, но вот океан... Впрочем, не видя оригинала, трудно сказать, насколько качественно (некачественно?) выполнено преобразование. Но, по крайней мере, мы можем выбирать из всех вариантов преобразования тот, что к месту.

Форсированный RGB-режим, кодек FFDShow (функция высококачественного цветового преобразования)

Дискретное косинусное преобразование

Фундаментом всех систем сжатия с потерями (JPEG, MP3, MPEG-1/2/4) является дискретное косинусное преобразование (Discrete Cosine Transform или, сокращенно, DCT), представляющее собой разновидность косинусного ортогонального преобразования для вектора действительных чисел. Понять, что такое DTC, можно на примере широко известного дискретного преобразования Фурье — Discrete Fourier Transform, или DFT (дискретное косинусное преобразование представляет собой гомоморфизм его векторного пространства).

В общем случае DTC-преобразование осуществляется умножением вектора на матрицу преобразования: [Y] = [C]x[X]x[CT]. Эта формула показывает DTC-преобразование, записанное в матричной форме, здесь [X] — начальная матрица, [C] и [CT] — матрицы с коэффициентами преобразования, где CT означает транспонированную матрицу.

Алгоритмы MPEG-1, MPEG-2 и MPEG-4 разбивают каждый кадр (фрейм) на блоки по 8x8 пикселей, над которыми осуществляется DCT-преобразование — сначала для каждой строки, а затем для каждого столбца матрицы, поэтому такое преобразование часто обозначается как DCT8 (число «восемь» означает 8 векторов).

После выполнения дискретного косинусного преобразования в Y-матрице уже нет пикселей и она превращается в совокупность волн с различными частотами и амплитудами. Низкие частоты, сосредоточенные в левом вернем углу матрицы, соответствуют крупным деталям исходного изображения. Высокие частоты, соответствующие мелким деталям, оккупируют правый нижний угол.

Наглядная демонстрация DFT- и DCT-преобразований

Обходя матрицу в зигзагообразном порядке от левого верхнего угла к правому нижнему, кодируем ее содержимое методом Хаффмана, или Арифметическим кодированием, или любым другим методом энтропийного кодирования, использующего коды переменной длины. Как уже несложно догадаться, наиболее короткие коды достаются коэффициентам, расположенным в левом верхнем углу. Уже за счет одно лишь DCT-преобразования мы добиваемся некоторого сжатия, причем это сжатие происходит без потерь, что, впрочем, не дает никаких оснований для радости, поскольку степень сжатия невелика и сопоставима с обычными архиваторами.

Чтобы увеличить сжатие, необходимо отсечь наименее значимые детали, практически не воспринимаемые человеческим глазом, но кодируемые наиболее длинными кодами. После выполнения DСT-преобразования эта задача выполняется элементарно, поскольку детали уже разделены на значимые и незначимые. Как говорится, отсекай и властвуй. Операция отсечения осуществляется при помощи матрицы квантования, подробно описанной в одноименном разделе, там же, где описан процесс квантования, определяющий качество сжатия в целом.

Закодированная матрица (или, точнее, все, что от нее осталось, поскольку после квантования большинство коэффициентов правого нижнего угла обращаются в нули) помещается в сжатый MPEG-файл и кодировщик переходит к обработке следующего 8x8 блока.

Для вывода картинки на экран декодер, естественно, должен превратить совокупность волн в привычные нам пиксели, выполняя операцию обратного дискретного косинусного преобразования — Inverse Discrete Cosine Transformation или, сокращенно, IDCT. Понятное дело, что она уже не будет соответствовать оригиналу и часть деталей окажется безвозвратно утеряна.

Матрица квантования

После выполнения DCT-преобразования мы получаем матрицу, наиболее значимые детали которой сосредоточены в левом вернем углу, а наименее значимые — в левом нижнем. Возникает естественное желание — отбросить незначимые детали, сократив размер целевого файла. Это достигается путем квантования.

Квантованием (применительно к обработке сигналов) называется деление величины сигнала на некоторое целое число, называемое квантом (quant), обычно обозначаемое буквой Q, а обратный ему процесс  деквантированием. С математической точки зрения X/Q = X*Q, но целочисленная арифметика «огрубляет» сигнал, причем это «огрубление» тем сильнее, чем больше квант. При Q = 1 мы не теряем никаких деталей, при Q, превышающем половину амплитуды сигнала, — теряем все.

Сигнал, переведенный в цифровую форму

 

Оцифрованный сигнал после квантования

Применительно к MPEG-сжатию операция квантования выполняется дважды — первый раз при наложении на DCT-матрицу специальной Матрицы Квантования (Quantization Matrix, или QM) и второй раз — при квантовании коэффициентов матрицы, образующейся после наложения.

Стандартная MPEG-2 Матрица Квантования выглядит так:

08 16 19 22 26 27 29 34

16 16 22 24 27 29 34 37

19 22 26 27 29 34 34 38

22 22 26 27 29 34 37 40

22 26 27 29 32 35 40 48

26 27 29 32 35 40 48 58

26 27 29 34 38 46 56 69

27 29 35 38 46 56 69 83

В литературе, посвященной сжатию, процесс наложения матрицы квантования обычно описывается слегка неточно. Утверждается, что коэффициенты исходной DCT-матрицы попарно сравниваются с коэффициентами матрицы квантования, и если Y[i] < QM[i], то данный коэффициент отбрасывается и вообще не кодируется ([Y] — матрица, полученная при DCT-преобразовании). То есть, в грубом приближении, коэффициенты QM-матрицы как бы задают порог отсечения.

На самом деле квантование происходит так: X[i] = Y[i]/QM[i], где [X] — матрица, полученная после квантования (примечание: тот факт, что фреймы разбиваются на inter- и intra-блоки, квантование которых выполняется слегка различно, мы пока опускаем, т. к. для его объяснения требуется иметь представление о типах фреймов I, P, B и S, разговор о которых еще впереди; на всякий случай отметим, что сейчас мы разбираем кодирование intra-блоков).

Теперь становится ясно, почему в левом верхнем углу QM-матрицы находятся небольшие числа, планомерно растущие во всех трех направлениях. Крупные детали квантуются минимально, мелкие — после квантования исчезают совсем. Увеличение коэффициентов матрицы квантования ведет к росту потерь деталей, а градиент (т. е. скорость нарастания коэффициентов по мере продвижения к трем остальным углам) задает «весовую» ценность деталей различного размера, что в конечном счете определяет резкость изображения.

Большинство MPEG-4 кодеков работают как минимум с двумя матрицами — MPEG-2 (резкое изображение, среднее сжатие) и H.263 (сглаженное изображение, высокое сжатие). Некоторые кодеки (и, в частности, XviD) поддерживают пользовательские матрицы квантования, что открывает практически неограниченные перспективы для качественного сжатия. Но об этом чуть позже, а пока разберемся с одним весьма щекотливым моментом, вызывающим путаницу и недопонимание.

Пример QM-матрицы, обеспечивающей большее сжатие за счет намного более агрессивного выбрасывания деталей, приведен ниже:

20 20 20 20 31 63 127 255

20 40 40 40 63 127 255 255

20 20 31 63 127 255 255 255

20 31 63 127 255 255 255 255

31 63 127 255 255 255 255 255

63 127 255 255 255 255 255 255

127 255 255 255 255 255 255 255

255 255 255 255 255 255 255 255

Достоинство алгоритмов семейства MPEG в том, что они позволяют ужать видеофайл до любого требуемого размера. За счет чего этого достигается? А все за счет того же квантования. Матрица, образовавшаяся после наложения QM-матрицы, подвергается повторному квантованию, то есть делению на некоторое целое (!) число, называемое quantizer'ом и обозначаемое буквой Q.

В упрощенном виде процесс квантования, включающий в себя наложение QM-матрицы, выглядит так:

#define DIV_DIV(a,b)        (((a)>0) ? ((a)+((b)>>1))/(b) : ((a)-((b)>>1))/(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)        ((1UL << SCALEBITS) / (X) + 1)

static const uint32_t multipliers[32] =

{

0, FIX(2), FIX(4), FIX(6),

FIX(8), FIX(10), FIX(12), FIX(14),

FIX(16), FIX(18), FIX(20), FIX(22),

FIX(24), FIX(26), FIX(28), FIX(30),

FIX(32), FIX(34), FIX(36), FIX(38),

FIX(40), FIX(42), FIX(44), FIX(46),

FIX(48), FIX(50), FIX(52), FIX(54),

FIX(56), FIX(58), FIX(60), FIX(62)

};

/* quantize intra-block

*

* const int32_t quantd = DIV_DIV(VM18P*quant, VM18Q);

* const uint32_t mult = multipliers[quant];

* uint32_t level = DIV_DIV(16 * data[i], default_intra_matrix[i]);

* coeff[i] = ((level + quantd) * mult) >> SCALEBITS;

*/

Quantizer представляет собой целое число от 1 до 31 включительно. При Q = 1 мы сохраняем максимум деталей, а при Q = 31 — теряем все («теряем все» — в пределах одного 8x8 блока, который заливается одним цветом, и мы получаем мозаику из 8x8 квадратов, из которой еще кое-что можно разобрать).

На самом деле, 31 — это очень большое число и уже при Q > 6 на изображение без содрогания смотреть становится невозможно. С другой стороны, учитывая, что DVD-диски обычно записываются с Q = 2, становится ясно, что для большинства видеоматериалов имеет смысл использовать только Q от 2 до 6.

Ниже представлен ряд изображений, сжатых с разными quantizer'ами для сравнения:

Изображение, сжатое с Q = 1

 

Левая половина — Q = 1, правая — Q = 6

 

Левая половина — Q = 1, правая — Q = 13

 

Левая половина — Q = 1, правая — Q = 31

Откуда взялись эти числа — 1 и 31? Ну, с 1 все понятно. Поскольку, на ноль делить нельзя, то 1 — это наименьший возможный quantizer, кстати говоря, не выполняющий никакого квантования, поскольку от деления на единицу коэффициенты матрицы не меняются. Но вот почему максимальный quantizer равен 31?

Ответ хранится в исходных текстах кодека MPEG-2, а точнее — в функции квантования quant_intra(), находящейся в файле \src\mpeg2enc\quantize.c, ключевой фрагмент которой приведен ниже.

for (i=1; i<64; i++)

{

x = src[i];

d = quant_mat[i];

y = (32*(x>=0 ? x : -x) + (d>>1))/d;        /* round(32*x/quant_mat) */

d = (3*mquant+2)>>2;

y = (y+d)/(2*mquant); /* (y+0.75*mquant) / (2*mquant) */

/* clip to syntax limits */

if (y > 255) if (mpeg1) y = 255; else if (y > 2047) y = 2047;

dst[i] = (x>=0) ? y : -y;

}

Максимальное значение индекса матрицы равно 255 (в MPEG-2 — 2047 или 7FFh). Минимальный коэффициент квантования в левом верхнем углу матрицы — 8. Тогда при quantizer <= 31 весь блок 8x8 гарантированно обращается в ноль. Теряется вся информация, хотя, как уже говорилось выше, использование таких высоких Q бессмысленно.

Чем больше Q, тем выше степень сжимаемости видеоматериала, но и тем ниже его качество. Варьируя значение Q, можно получить файл заданного размера, например, ужать DVD до размеров одного CD. Но часто бывает так, что при Q = 4 файл на диск никак не влезает, а при Q = 5 влезает с большим запасом.

Практически во всех популярных кодеках quantizer представляется дробным числом с несколькими знаками после запятой.

Задание дробного quantizer'а в настойках XviD'a

Непосвященному в тонкости кодирования это кажется вполне нормальным, но после разбора приведенных выше фрагментов исходных текстов кодеков MPEG-2 и XviD возникает резонный вопрос: как же quantizer может быть дробным, если он в принципе целый?! Дробных quantizer’ов не бывает! Просто не встречается в живой природе. Выбор нецелого quantizer'а приводит к тому, что часть фреймов кодируется с одним Q, а часть — с другим. Усредненное значение и даст нужное нам (псевдодробное) значение Q.

Результат использования дробного quantizer'а — различные фреймы сжимаются с различным Q, и все вместе они дают усреднение (по горизонтали откладывается Q, по вертикали — количество фреймов, сжатых с данным Q; типы фреймов [I/P/B] мы рассмотрим в следующий раз)

Психофизическая модель, используемая кодеками, отталкивается от того факта, что при быстром мелькании качественных (т. е. детализированных) и некачественных (т. е. с потерей деталей) кадров, человеческий глаз, а точнее мозг, улавливает детали и игнорирует размытость, в результате чего при чередовании кадров с Q и Q + 1 субъективное качество приближается к Q.

Это можно сравнить с тем, что газетный лист кажется белым до тех пор, пока рядом с ним не окажется кусок мелованной бумаги.

Отсюда вывод: выбор целого значения quantizer'а обеспечит лучшее качество изображения, чем дробное. А как же в этом случае «подгонять» сжатый файл под требуемый размер? Целочисленный quantizer — слишком уж грубое средство... Действительно грубое, ведь он квантует сигнал, уже подвергшийся квантованию!

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

Кстати говоря, в XviD'е имеется экспериментальный «Modulated QM», стремящийся выбрать наиболее адекватную матрицу квантования для данного Q. Увы, алгоритм его работы постоянно меняется. Сначала он использовал H.263-матрицы (обеспечивающие лучшее сжатие, но дающие более высокую размытость) для фреймов с Q <= 3 и MPEG-2 матрицы (выше резкость, хуже сжимаемость) для фреймов с Q >= 4, что вызывало массу негативных откликов. Действительно, зачем портить качество «мыльной» матрицей на низкий Q и зачем подчеркивать резкость потерянных деталей при высоких Q?! В следующий версиях стратегия модулятора изменилась на прямо противоположную и теперь он стал выбирать MPEG-2 матрицы для фреймов с Q <= 3 и H.263-матрицы для фреймов с Q >= 4, что обеспечивает лучше качество при большей степени сжатия (примечание: quantizer выбирается для каждого 8x8 блока индивидуально, хотя в подавляющем большинстве случаев весь блок кодируется с одним Q).

Битрейт

Битрейт — это просто количество битов в секунду. Зная размер (в битах) и частоту (в fps) кадров, не составит труда рассчитать размер конечного файла, равно как и наоборот — размер файла однозначно обусловлен его битрейтом. Величина самого битрейта, естественно, зависит от степени сжимаемости видеоматериала, и поскольку кодек — не пророк, он сжимает исходный видеоматериал за два прохода. В первом проходе никакого сжатия не выполняется, а лишь оценивается степень сжимаемости каждого фрейма, затем на основе полученной информации вычисляется необходимый quantizer, с которым видеоматериал реально сжимается во втором проходе.

Для достижения максимального качества кодек стремится отдать больше битов тем сценам, которые сильнее всего в них нуждаются, отобрав их у остальных. Алгоритмы перераспределения битов по фильму непрерывно совершенствуются, но до сих пор находятся в зачаточном состоянии. Наиболее типичная ошибка — выделив некоторым сценам низкий Q (соответствующий, как мы помним, высокому качеству), кодек вынужден сжимать остальные сцены с высоким Q (соответствующим низкому качеству).

Диаграмма квантования фильма, сжатого с переменным битрейтом

Из-за того, что кодек выделил некоторым сценам Q < 8, для достижения заданного размера, он оказался вынужден закодировать подавляющее большинство фреймов с Q = 10. Большое количество фреймов оказалось сжато с Q от 11 до 16 включительно, а некоторые фреймы кодировались с Q = 22! И хотя средний Q = 12.15, при постоянном quantizer'е тот же самый фильм с теми же самыми настройками сжимается тем же самым кодеком за один проход с Q = 7, занимая даже чуть-чуть меньший размер и чудовищно выигрывая в качестве (и это без редактирования матрицы квантования и прочих шаманских ритуалов).

Чем уже «гора», образующаяся на диаграмме XviD'а, — тем выше качество сжатия. Наличие нескольких несмежных пиков указывает на то, что в первом проходе кодек неверно выполнил расчет сжимаемости видеоматериала и на определенных сценах ему катастрофически не хватило битрейта. Получается, что он и сжал их с неоправданно завышенным Q. Другая возможная причина — выбор профиля, ограничивающего максимальный пиковый битрейт. Обычно увеличение битрейта позволяет удалить лишние пики, сузив ширину «горы» и увеличив тем самым качество.

Замечено, что XviD страдает хроническим оптимизмом — к концу фильма ему постоянно недостает битрейта и он вынужден увеличивать Q, сжимая финальные сцены с гораздо худшим качеством.

Видимо, придется полностью отказаться от двухпроходного сжатия и «сжимать» в один проход с фиксированным Q.

Кодек FFDShow позволяет отображать в реальном времени quantizer для каждого из 8x8 блоков и строить диаграмму размеров сжатых фреймов, что невероятно полезно для объективной оценки качества видеоматериала. Чтобы задействовать этот режим, откройте FFDShow (Программы FDShow Video decoder configuration), найдите вкладку «Visualization» и поставьте галочки «Quantizers» и «Graph», не забыв отметить и саму «Visualization» (или сделайте тоже самое во время просмотра фильма, кликнув по иконке в системном трее, которую FFDShow будет отображать, если в графе «Try, Dialogs Paths» поставить галочку напротив «Show tray icon»).

Визуализация quantizer'а и построение диаграммы размера фреймов в реальном времени кодеком FFDShow

Для покадрового просмотра фильма удобно использовать бесплатный видеоредактор AviDemux. Качество соседних кадров, закодированных с различным Q, меняется весьма значительно. Особенно это хорошо заметно на крупных планах, когда отчетливо видны волосы, глаза, ресницы. То есть предполагается, что они должны быть видны, но высокий Q все «замыливает»...

Quantizer равный 3 обладает одним очень интересным свойством — убирая наименее значимые детали, он действует как отличный «шумодав», что весьма актуально для очистки «зашумленных» DVD (а таких среди них — большинство). Ниже приведены два кадра. Один — с оригинального DVD, другой — после сжатия XviD'ом с Q = 3 и H.263-матрицей.

Кадр с оригинального DVD (обратите внимание на шум)

 

Тот же самый кадр после сжатия. Заметное снижение уровня шума

ВЕРДИКТ

Любой процесс, связанный с компрессией звука или видео, выполняется по определенным правилам. Чтобы получить качественный результат, недостаточно просто знать название программ и основных кнопок в них. Необходимо углубится в теорию. Надеюсь, этот материал подтолкнет вас к самостоятельному изучению темы. В следующем материале мы продолжим знакомство с теорией сжатия цифрового видео. Оставайтесь с нами!






Рекомендуемый контент




Copyright © 2010-2019 housea.ru. Контакты: info@housea.ru При использовании материалов веб-сайта Домашнее Радио, гиперссылка на источник обязательна.