<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Блоги &#187; Dmitry Serkin (Intel)</title>
	<atom:link href="http://software.intel.com/ru-ru/blogs/author/dmitry-serkin/feed/" rel="self" type="application/rss+xml" />
	<link>http://software.intel.com/ru-ru/blogs</link>
	<description></description>
	<lastBuildDate>Thu, 24 May 2012 12:16:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1.3</generator>
		<item>
		<title>Непростая арифметика: декодирование</title>
		<link>http://software.intel.com/ru-ru/blogs/2011/12/27/2006586/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2011/12/27/2006586/#comments</comments>
		<pubDate>Tue, 27 Dec 2011 08:11:53 +0000</pubDate>
		<dc:creator>Dmitry Serkin (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[Графика]]></category>
		<category><![CDATA[arithmetic coding]]></category>
		<category><![CDATA[entropy coding]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2011/12/27/2006586/</guid>
		<description><![CDATA[Небольшая заметка-продолжение темы арифметического кодирования, на сей раз речь пойдет о декодировании.]]></description>
			<content:encoded><![CDATA[<p>Небольшая заметка-продолжение темы арифметического кодирования. Но на сей раз речь пойдет о декодировании. <a href="http://software.intel.com/ru-ru/blogs/2011/12/20/2006336/">Вспомним</a>, что с помощью техники вложенных интервалов мы получили некоторый код, который однозначно определяет всю входную последовательность. Декодирование же восстанавливает оригинальные символы, тем самым образуя множество элементов:</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/114.png" />
</div>
<p>Процесс декодирования восстанавливает последовательность в том же порядке в каком она кодировалась. Определим множество нормализованных кодов (нормализация на целый интервал):</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/211.png" />
</div>
<p>Естественно предположить, что рекурсия, применяемая для кодирования, действует и в обратную сторону. Начиная с исходного кода алгоритм шаг за шагом находит закодированный символ:</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/310.png" />
</div>
<p>Если до этого момента понятно так и не стало, то нас спасет только пример. <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Следуя примеру из <a href="http://software.intel.com/ru-ru/blogs/2011/12/20/2006336/">предыдущей заметки</a>, входная последовательность символов: a2a1a0a0a1a3. Распределение вероятностей: p = [0.2, 0.5, 0.2, 0.1]. Код: 0.74267578125.</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/48.png" />
</div>
<p>В таком ключе находим все 6 символов. Но так как мы работаем с интервалами действительных чисел, то есть риск не закончить эту работу никогда. Поэтому для завершения декодеру необходимо знать либо количество символов, либо иметь некоторый маркер конца.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2011/12/27/2006586/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Непростая арифметика: ода индукции</title>
		<link>http://software.intel.com/ru-ru/blogs/2011/12/26/2006581/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2011/12/26/2006581/#comments</comments>
		<pubDate>Mon, 26 Dec 2011 07:57:07 +0000</pubDate>
		<dc:creator>Dmitry Serkin (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[arithmetic coding]]></category>
		<category><![CDATA[entropy coding]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2011/12/26/2006581/</guid>
		<description><![CDATA[Ода математической индукции на примере арифметического кодирования]]></description>
			<content:encoded><![CDATA[<p><a href="http://ru.wikipedia.org/wiki/%D0%9C%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%B8%D0%BD%D0%B4%D1%83%D0%BA%D1%86%D0%B8%D1%8F">Математическая индукция</a> один из самых известных методов доказательства. Помню, что меня впечатлила простота и количество проблем, которые решает цепная реакция метода.</p>
<p>Вспомнил я о индукции не просто так, а в продолжении темы арифметического кодирования. В <a href="http://software.intel.com/ru-ru/blogs/2011/12/20/2006336/">прошлый раз</a> мы остановились на том, что определили рекурсивный метод нахождения конечного интервала из которого, в результате, получили код входной последовательности символов. Вот он в двоичной системе счисления: 0.10111110001(2)</p>
<p>Выбрали мы его не просто так, а руководствуясь некоторым предположением оптимальности, согласно которому из финального интервала  необходимо выбрать такое действительное число для передачи, которое потребует минимальное количество бит. Существует ли какая-то оценка числа бит? Конечно.</p>
<p>Процесс нахождения «лучшего» бинарного представления довольно прост и нагляден на примере математической индукции. Центральная идея состоит в том, что для довольно длинных интервалов мы можем найти оптимальное значение путем тестирования нескольких бинарных представлений. Далее, уполовинивая длину интервала, количество бинарных значений удваивается, тем самым, на единицу инкрементируется количество бит на их представления. Процесс строится следующим образом:</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/113.png" />
</div>
<p>Дальнейшие индукционные переходы повторяют явный логарифмический паттерн, который гласит, что необходимое минимальное количество бит для представления кода в конечном интервале известной длины равно:</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/210.png" />
</div>
<p>Вспомним пример из <a href="http://software.intel.com/ru-ru/blogs/2011/12/20/2006336/">предыдущей заметки</a>. Длина конечного интервала составила 0.0002. Тогда полученная выше оценка составит 13 бит. Но, итоговое представление заняло только 11 бит. Источником этой несостыковки является тот факт, что мы всегда можем выбрать представление удовлетворяющее обозначенной оценке, но завершающееся непрерывной последовательностью нулей, которые в итоге и обрезаются. Однако, доказано, что среднее количество бит, которые можно сэкономить подобным образом, равно единице, то есть на практике редко удасться сэкономить более одного бита.</p>
<p>Вот такая вот ода математике.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2011/12/26/2006581/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Непростая арифметика: кодирование</title>
		<link>http://software.intel.com/ru-ru/blogs/2011/12/20/2006336/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2011/12/20/2006336/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 11:47:38 +0000</pubDate>
		<dc:creator>Dmitry Serkin (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[arithmetic coding]]></category>
		<category><![CDATA[entropy coding]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2011/12/20/2006336/</guid>
		<description><![CDATA[Не так давно мы бегло прошлись по основным понятиям и методам энтропийного сжатия. Сегодняшняя запись будет посвящена арифметическому кодированию, которое славится эффективностью и элегантностью.]]></description>
			<content:encoded><![CDATA[<p>Существует множество подходов и стандартов сжатия видео/аудио/информации. Все они, так или иначе, используют схожие алгоритмы и  преобразования, отличаясь лишь деталями реализаций, эффективностью и сложностью. Можно наверняка говорить, что большинство систем сжатия используют энтропийное кодирование, как завершающую стадию всей работы. Порой на этом этапе происходит львиный процент сжатия, а порой он лишь чуть дополняет то, что было сделано на предыдущих шагах.</p>
<p>Не так давно мы <a href="http://software.intel.com/ru-ru/blogs/2011/10/13/2005406/">бегло прошлись по основным понятиям и методам энтропийного сжатия</a>. Сегодняшняя запись будет посвящена арифметическому кодированию, которое славится эффективностью и элегантностью.</p>
<p>До некоторых пор арифметическое кодирование не получало своего должного распространения в силу ряда причин. В период становления мало кто понимал суть подхода, он казался сложным и ресурсоемким. Эффективные реализации защищались непреодолимыми патентными барьерами. Но время шло, патенты старились, а вычислительная сложность уступила под натиском прогресса. Новые наработки облегчили алгоритмы с точки зрения реализации и понимания, незатронув эффективность.</p>
<p>Существенное отличие арифметического кодирования от других подходов энтропийного сжатия состоит в том, что метод не пытается построить взаимнооднозначное соответствие между символом или группой символов и кодовым словом, подобно тому, как это делают алгоритмы семейства variable length coding. Арифметическое кодирование кодирует всю информацию целиком. Символ за символом метод формирует конечное битовое представление, действительное число в интервале [0, 1). Чтобы понять, нужно разобраться в природе кода.</p>
<p>Код последовательности есть действительное число с дробной частью, которая равна этой последовательность.  То есть переход от последовательности к коду есть ничто иное как добавление в начало «0.». В качестве примера, возьмем последовательность выходных бит 01010010110, которые порождает арифметическое кодирование, тогда 01010010110 – есть ничто иное как закодированная последовательность, 0.01010010110 = 0.6898797800010 – кодовое значение, действительное число.</p>
<p>Подобная конструкция создает удобную связь между бесконечной последовательностью символов из D-символьного (в нашем примере 2х или 10-ти) алфавита и реальными числами в полуинтервале [0, 1), где любая последовательность может быть представлена в виде действительного числа и наоборот.</p>
<p>Процесс арифметического кодирования состоит в создании последовательности вложенных интервалов следующей формы:</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/112.png" />
</div>
<p>Где S – входная последовательность, а α и β действительные числа, такие что:</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/29.png" />
</div>
<p>Для упрощения принято представлять интервалы в иной форме:</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/39.png" />
</div>
<p>Тогда интервалы представляют следующим множеством рекурсивных выражений:</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/47.png" />
</div>
<p>Процесс кодирования необходимо проиллюстрировать примером. Рассмотрим алфавит из 4 элементов со следующим распределением вероятностей p = [0.2, 0.5, 0.2, 0.1]. Входная последовательность: a2a1a0a0a1a3. Разберем шаги алгоритма арифметического кодирования:</p>
<ol>
<li>Сперва задается «текущий интервал» [0,1).</li>
<li>Далее повторяем следующие действия до последнего входного элемента: делим  текущий интервал на части пропорционально вероятностям каждого символа, выбираем подынтервал, соответствующий текущему входному символу, и назначаем его новым текущим интервалом.</li>
<li>Результатом будет любая  точка внутри конечного интервала.</li>
</ol>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/steps.png" />
</div>
<p>Графическая иллюстрация:</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/illustration.png" />
</div>
<p>Обработав последний входной символ (понять, что он последний можно по специальному маркеру или дополнительно передав информацию о размере входного потока), мы получили интервал [0.7426, 0.7428] внутри которого содержится бесконечное множество действительных чисел. Осталось выбрать одно, тем самым сделав финальный шаг всего процесса. Кодовое значение не может быть передано в форме действительного числа, его необходимо представить в форме выбранной системы счисления. Так как число из интервала может быть абсолютно любым, то естестевенно выбрать наиболее удобный вариант для представления, то есть наиболее короткий. В нашем примере, в случае десятичной системы наиболее короткое число 0.7426, в двоичной 0.10111110001 = 0.74267578125.</p>
<p>Вкратце, все. Нужно заметить, что все выше описанное относится преимущественно к теории арифметического кодирования, нежели к практическому применению в тех же кодеках. На практике естественно отказываются от вычислений с плавающий запятой в пользу целочисленных, а алфавит входного сообщения состоит из всего лишь двух символов 0 и 1.</p>
<p>При написании заметки использовалась <a href="http://www.hpl.hp.com/techreports/2004/HPL-2004-76.pdf">замечательная статья</a> в которой вы можете найти информацию для дальнейшего погружения в тему.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2011/12/20/2006336/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Оценка качества видеокодирования</title>
		<link>http://software.intel.com/ru-ru/blogs/2011/12/05/2006272/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2011/12/05/2006272/#comments</comments>
		<pubDate>Mon, 05 Dec 2011 12:08:03 +0000</pubDate>
		<dc:creator>Dmitry Serkin (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2011/12/05/2006272/</guid>
		<description><![CDATA[Вы когда-нибудь задумывались, как оценивается качество закодированного видео? Как разработчики кодеков определяют влияние тех или иных алгоритмических изменений?]]></description>
			<content:encoded><![CDATA[<p>Вы когда-нибудь задумывались, как оценивается качество закодированного видео? Как разработчики кодеков определяют влияние тех или иных алгоритмических изменений? Ведь даже самые незначительные из них могут привести к крайне неприятным последствиям.</p>
<p>Интуитивно, мы все понимаем, что качество видео крайне субъективная мера. Одному человеку может нравится эффект легкой размытости, плавности, другой сильно восприимчив к деталям, динамике изменений. То есть на всех не угодишь. Однако, в нашей области все еще практикуется что-то наподобие «фокус-групп» со специальными методиками принятие решений и оценок.</p>
<p>Но речь мы поведем не о них, а о буднях разработчика кодеков, которому нужны объективные подходы, с возможностью автоматизации и, желательно, дающие результаты в разумные сроки.</p>
<p>Важность этих требований обусловлена огромным количеством путей внутри такой программы, как кодек. И выбор пути определяется не только набором входных параметров, коих великое множество сочетаний, но и поступающим на кодировку видео. В зависимости от характера движения на видео, кодек может вести себя по-разному. Например, наиболее важными и часто применяемыеми для тестирования кодека видео-последовательностями являются мультики. Как вы догадываетесь, это не имеет ничего общего с нашей любовью к данному жанру, точнее, не всегда имеет, но связано с характерными свойствами подобного контента. Мультики, как правило, содержат очень много «однотонных» областей, большие области высокой корелляции пикселей. Вторым примером служит видео с постоянным движением камеры, например, слева направо. Очень полезно посмотреть, как на таком примере ведет себя оценка движения. Принимает ли она объективные решения, находит ли лучшие совпадения и какой ценой, насколько длинны вектора движения.</p>
<p>Я надеюсь, что затянувшийся посыл дает понять, что тестирование кодека дело очень непростое и хлопотное в плане ресурсов. Например, еженедельное тестирование <a href="http://software.intel.com/en-us/articles/vcsource-tools-media-sdk-beta">Intel Media SDK</a> ведется силами десятков топовых машин и занимает до четырех суток. За это время исполняется порядка 50 тысяч различных тестов, ~95% из которых функциональные, то есть происходит реальное транскодирование, кодирование и декодирование видео. И это только время исполнения тестов, без учета затрат на анализ, баг репортов и общего отчета по валидации.</p>
<p>Но вернемся к разработчикам, именно они на начальном этапе создают и внедряют новые подходы для сжатия. Так как, кодек всегда производит сжатие с потерей информации, то неплохо было бы определить метрику, которая покажет расхождение между оригинальным «сырым» видео и восстановленным после кодирования. Сложно придумать размерность для подобных измерений, но хочется, чтобы ее увеличение говорило о лучшем совпадении. Такую метрику придумали и назвали «пиковое отношение сигнал/шум» - PSNR – «peak signal to noise ratio». Метрика общепринята, используется практически всеми для сравнения качества кодеков и имеет сравнительно невысокую вычислительную сложность.</p>
<p>Формулы для вычисления несложны. Метрика требует вычисления среднеквадратической ошибки (MSE, Mean Square Error). Итак, O – пикселы оригинального изображения, R – восстановленого после кодирования, тогда:</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/psnr.png" />
</div>
<p>Как уже было отмечено, PSNR величина безразмерная, однако из-за наличия логарифма она масштабируется в децибелах (dB).  Отметим, что в наихудшем случае, когда пикселы исходного изображения принимают значение из интервала [0, 255], и знаменатель равен 255 (максимум ошибки), мы имеем значение PSNR равное 0. Обратный случай, когда знаменатель равен 0 (изображения абсолютно совпадают), PSNR устремляется к бесконечности.</p>
<p>Между исходной (первая картинка) и восстановленной картинкой значение PSNR составляет 54.7 dB. Достаточно высокое значение, чтобы разглядеть видимую разницу. Придется напрячься. </p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/psnr_org.png" />
</div>
<p></p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/psnr_rec1.png" />
</div>
<p></p>
<p>Нет никакого смысла в том, чтобы судить о качестве видео по величине PSNR, скажем, равной 40 dB. Метрика не призвана отслеживать расхождения, которые мы можем оценить с помощью органов человеческого зрения. Ее высокое значение показывает только высокую схожесть оригинального и восстановленного изображения, что не значит, что результат «понравится» человеческому глазу. Но метрика полезна для анализа работы кодека и порог ее изменения, скажем, в 0.5 dB, будет заметен человеческому глазу. Ну, а если уж, в результате некоторых изменений в кодеке, значение PSNR скакнуло с 40 до 10 dB, то ждите беды.</p>
<p>Исходя из рассуждений выше, очевидно, что сравнивать кодеки по одной лишь метрике PSNR, мягко говоря, не очень правильно. И оное даже <a href="http://x264dev.multimedia.cx/archives/458">вызывает изжогу у разработчиков x264 энкодера</a>. Вообщем, как ни крути, а без визуального тестирования не обойтись.</p>
<p>Существуют более развитые метрики, такие как <a href="http://en.wikipedia.org/wiki/Structural_similarity">SSIM</a>, призванные устранить недостатки PSNR. Но это уже совсем другая история...</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2011/12/05/2006272/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Слово за видео транскодирование</title>
		<link>http://software.intel.com/ru-ru/blogs/2011/10/31/2005567/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2011/10/31/2005567/#comments</comments>
		<pubDate>Sun, 30 Oct 2011 21:35:44 +0000</pubDate>
		<dc:creator>Dmitry Serkin (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[Intel Media SDK]]></category>
		<category><![CDATA[Intel Quick Sync Video]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2011/10/31/2005567/</guid>
		<description><![CDATA[Если вы понимаете все четыре слова из заголовка, то вы почти уникальны.]]></description>
			<content:encoded><![CDATA[<p><img src="http://www.intel.com/content/dam/staging/image/Kim/vt-intel-quick-sync-video.png" style="float:left;padding-right: 8px" /></p>
<p>Если вы понимаете все четыре слова использованные в заголовке, то примите мои поздравления.  Вы, как минимум, грамотны и упрекнуть вас в незнании русского языка (и английской терминологии) невозможно глупо. Однако, сие знание ярко выделяет вас из общей толпы людей,  запнувшихся и разбивших носы на последнем слове.</p>
<p>На давно минувшей выставке Consumer Electronics Show’11 некий мужчина в забавном головном уборе позволил себе вопросить у зала, почти дословно: «Как часто, в вашей повседневной жизни, вы занимаетесь транскодированием? Поднимите ваши руки!». На что зал стыдливо потупил глаза. Лишь единицы смело подняли руки, да и то, наверняка, потому, что просто неправильно расслышали вопрос. «Окей», - приободрившись продолжил он. «Теперь поднимите руки те, кто ежедневно загружает видео на YouTube и на свои яблочные девайсы». Зал рук. «Поздравляю! Это и есть транскодирование».</p>
<p>Сложно упрекнуть людей в том, что они не знают, что происходит за кулисами простых манипуляций с файлами. Все благоразумно сопрятано от обывательских глаз. Не все ли им равно,  что видео в разрешении 1280p не может проигрываться его медиа устройством. И что оно вообще формата MPEG-2 формата, а устройство способно проигрывать только H.264. Однако пользователю точно будет интересно, почему «простой перенос» файла загружает 90% центрального процессора на довольно продолжительное время. Ему невдомек, что декодирование, предобработка и кодирование (все три стадии транскодирования) видео по сей день остаются одной из самых трудоемких задач.</p>
<p>Так вот, того самого человека зовут Мули Иден и представлял он тогда еще новую линейку процессоров Sandy Bridge. И подобные вопросы он задавал отнюдь не для того, чтобы самоутвердиться за счёт зрителей, а чтобы представить новую технологию аппаратно-акселерированной обработки видео под названием <a href="http://www.intel.com/content/www/us/en/architecture-and-technology/quick-sync-video/quick-sync-video-general.html">Intel(R) Quick Sync Video</a>. Впервые, в рамках майнстрим процессоров, Intel анонсировала технологию позволяющую перенести задачу транскодирования видео с плеч процессора на узкоспециализированные графические юниты, тем самым освобождая процессор от тонны вычислений и экономя ватты батерейки ноутбука.</p>
<p>Уже много лет практически все графические чипы, как интегрированные, так и дискретные, несут на борту обособленную логику аппаратного декодирования популярных форматов видео, таких как: MPEG2, H264 и VC1. Качество видео улучшалось с каждым годом, что естественным образом сказывалось на увеличение нагрузок на процессор и батарейку при декодировании. Появлялись все новые и новые медиа устройства, где подобные чипы уже стоят дефакто. Все ради того, чтобы разгрузить центральный процессор и уменьшить энергопотребление ноутбука или планшета. Даже сегодня маркетологи с гордостью выставляют на передний план этикетку с надписью «HD playback». Признаем, что с декодированием разобрались быстро и эффективно.</p>
<p>А где же кодирование? Уже некоторое продолжительно время монструозные дискретные графические карты предоставляют возможность кодирования с использованием GPU. Однако, соотношение скорость/качество и сложность разработки нивелировали все преимущества такого подхода. Технология <a href="http://www.intel.com/content/www/us/en/architecture-and-technology/quick-sync-video/quick-sync-video-general.html">Intel(R) Quick Sync Video</a> показала, что оптимальное соотношение существует, а сложность разработки несравнимо ниже, чем у конкурентных  решений.</p>
<p>И, наконец, центральный вопрос: а как часто Вы занимаетесь транскодированием? Говорят, что для здоровья процедуру надо повторять 5-6 раз в неделю <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2011/10/31/2005567/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Motion Estimation Library (часть третья, интерфейсы)</title>
		<link>http://software.intel.com/ru-ru/blogs/2011/10/24/motion-estimation-library-3/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2011/10/24/motion-estimation-library-3/#comments</comments>
		<pubDate>Mon, 24 Oct 2011 07:38:33 +0000</pubDate>
		<dc:creator>Dmitry Serkin (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[Motion Estimation]]></category>
		<category><![CDATA[Video Codecs]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2011/10/24/motion-estimation-library-3/</guid>
		<description><![CDATA[Продолжение блокбастера с блэкджеком и ... ]]></description>
			<content:encoded><![CDATA[<p>Давно я не писал заметок с кодом. Связано это с моим неумением объяснять «на бумаге» (да и чего уж там, вообще) и приличными объемами кода. При этом, увеличение объемов кода, как ни странно, ведет к усложнению процесса пояснения. Но выкручиваться как-то надо.</p>
<p><a href="http://software.intel.com/ru-ru/blogs/2011/08/10/motion-estimation-library-2/">В последний раз</a> мы остановились на демонстрации использования нашей библиотеки оценки движения. Для тех кто не <del datetime="2011-10-22T15:18:20+00:00">читал</del> помнит, я напомню, что весь процесс был разбит на несколько частей: инициализация, подготовка входных данных, подготовка выходных структур и запуск процесса. Сегодня мы обсудим некоторые из частей.</p>
<p>Пара центов про архитектуру библиотеки. Картинка ниже иллюстрирует основную концепцию. Дело в том, что приложение, использующее нашу библиотеку, ничего не знает о деталях ее реализации. Оно лишь оперирует примитивами: инициализация, уничтожение, запрос результата. Это позволяет нам скрыть детали внутри библиотеки. Библиотека реализует специальный объект HANDLE, с которым приложение общается через интерфейсные примитивы. HANDLE – ядро библиотеки и отвечает за ресурсы, алгоритмы, реализует схему параллелизации и синхронизации. Мощная такая штука.</p>
<div style="text-align:center;padding: 5 5 5 5">
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/mel_arch.png" /></p>
</div>
<p>Главная особенность в том, что HANDL'ов может быть несколько. Каждый под свою железку. Например, библиотека может предоставлять объект-ядро для софтовой реализации алгоритмов и для железо-специфичной Nvidia и ATI. Понятно, что для каждого объекта механизмы инициализации, синхронизации и управления памятью будут особенными.</p>
<div style="text-align:center;padding: 5 5 5 5">
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/mel_handle.png" /></p>
</div>
<p>После небольшого экскурса в архитектуру рассмотрим основные интерфейсные функции доступные приложению. Благо их немного.</p>
<h2>Начинаем с инициализации</h2>
<p> Вспомним, как выглядела инициализации с точки зрения приложения.</p>
<pre name="code" class="cpp">

// the main hardware me structure
hw_me_handle_t hwhandle = new _HW_ME_HANDLE;

// parameters of hardware me
HW_ME_PARAMETERS hwPar;

// auxiliary variables
Ipp32u sts, numMb, imageStep, imageSize;

// initialize hardware me parameters
hwPar.codecStandard = HW_ME_H264;
hwPar.meType = HW_ME_WHOLE_PIXEL;
hwPar.algType = HW_ME_RESIDUAL;
hwPar.strictWithinFrame = ippFalse;
hwPar.minSubblockSize = HW_ME_DIV_16X16;
hwPar.imageSize.width = width;
hwPar.imageSize.height = height;

pMeInfo.pMbInfo = NULL;

// number of reference frames for motion estimation
hwPar.maxNumRef = 2;

// initialize me handle by me parameters
InitializeHWME(&amp;hwPar, &amp;hwhandle);</pre>
<p>Довольно просто, не так ли? Так вот внутренность интерфейсной функции не намного сложнее.</p>
<pre name="code" class="cpp">
IppStatus InitializeHWME(const HW_ME_PARAMETERS *pHWMEParams, hw_me_handle_t *pHandle)
{
    hw_me_handle_t handle;

    // release the existing object
    if (*pHandle)
    {
        ReleaseHWME(*pHandle);
        *pHandle = NULL;
    }

    // create new handle object
    handle = new _HW_ME_HANDLE();

    if (NULL == handle)
    {
        return ippStsMemAllocErr;
    }

    // initialize handle
    handle-&gt;Init(pHWMEParams);

    switch (pHWMEParams-&gt;meType)
    {
    case HW_ME_QUARTER_PIXEL:

        switch (pHWMEParams-&gt;codecStandard)
        {
            case HW_ME_H264:
                handle-&gt;pEst = new H264EstimatorQuarter;
                break;
            case HW_ME_VC1:
                break;
            case HW_ME_MPEG2:
                break;
            default: // MPEG4 standard
                break;
        }
        break;

    case HW_ME_HALF_PIXEL:

        switch (pHWMEParams-&gt;codecStandard)
        {
            case HW_ME_H264:
                handle-&gt;pEst = new H264EstimatorHalf;
                break;
            case HW_ME_VC1:
                break;
            case HW_ME_MPEG2:
                break;
            default: // MPEG4 standard
                break;
        }
        break;

    default:

        handle-&gt;pEst = new CEstimatorWhole;
        break;
    }

    handle-&gt;pEst-&gt;Initialize(pHWMEParams);

    *pHandle = handle;

    return ippStsNoErr;

} // IppStatus InitializeHWME(HW_ME_PARAMETERS *pHWMEParams, hw_me_handle_t *pHandle)
</pre>
<p>Функция принимает на вход параметры оценки движения и указатель на объект-ядро, осуществляет проверку на повторную инициализацию, создает определенный объект оценки движения (тут приведено только для h264 стандарта) и возвращает готовый к употреблению объект-ядро. Вуаля.</p>
<h2>Загрузка данных в объект-ядро</h2>
<p>Выделенную память следует заполнить данными, а данные прикрепить к объекту оценки движения. Приложение делает:</p>
<pre name="code" class="cpp">

// YUV reader
CYUVReader reader;

// initialize YUV reader
sts = reader.Init(filename, width, height);
CHECK_STS(sts);

// read the first frame
sts = reader.ReadYUVData();
CHECK_STS(sts);

// copy data from yuv reader to source image memory
IppiSize iSize;
iSize.height = height;
iSize.width = width;

CopyPlane(reader.m_pYUVData[0], width, hwSrcImage.pPlanes[0], imageStep, iSize);

iSize.width = iSize.width / 2;
iSize.height = iSize.height / 2;

CopyPlane(reader.m_pYUVData[1], width / 2, hwSrcImage.pPlanes[1], imageStep / 2, iSize);
CopyPlane(reader.m_pYUVData[2], width / 2, hwSrcImage.pPlanes[2], imageStep / 2, iSize);

sts = CopyHWMESource(hwhandle, &amp;hwSrcImage);
CHECK_STS(sts);

// start preparing of reference frames
for (Ipp32u i = 0; i &lt; hwPar.maxNumRef; i += 1)
{
    // read the next frame
    reader.ReadYUVData();

    // copy data from YUV reader to reference image memory

    iSize.height = height;
    iSize.width = width;

    CopyPlane(reader.m_pYUVData[0], width, hwRefImage.pPlanes[0], imageStep, iSize);

    iSize.width = iSize.width / 2;
    iSize.height = iSize.height / 2;

    CopyPlane(reader.m_pYUVData[1], width / 2, hwRefImage.pPlanes[1], imageStep / 2, iSize);
    CopyPlane(reader.m_pYUVData[2], width / 2, hwRefImage.pPlanes[2], imageStep / 2, iSize);

    // add reference image to the handle
    sts = CopyHWMEReference(hwhandle, i, &amp;hwRefImage);
    CHECK_STS(sts);
}
</pre>
<p>А внутри все просто - копирование данных во внутренние структуры объекта-ядра.</p>
<pre name="code" class="cpp">

static
IppStatus CopyPlane(const Ipp8u* pSrc, Ipp32s srcStep, Ipp8u* pDst, Ipp32s dstStep, IppiSize roiSize)
{
    Ipp32s y;

    for (y = 0; y &lt; roiSize.height; y++)
    {
        memcpy(pDst, pSrc, roiSize.width);
        pSrc += srcStep;
        pDst += dstStep;
    }

    return ippStsNoErr;

} // IppStatus CopyPlane(const Ipp8u* pSrc, Ipp32s srcStep, Ipp8u* pDst, Ipp32s dstStep, IppiSize roiSize)

IppStatus CopyHWMESource(hw_me_handle_t handle,const HW_ME_IMAGE *pImage)
{

    if (NULL == handle || NULL == pImage)
    {
        return ippStsNullPtrErr;
    }

    HW_ME_IMAGE* sImage = handle-&gt;pSource;

    sImage-&gt;imageStructure = pImage-&gt;imageStructure;

    // copy 3 planes by line
    CopyPlane(pImage-&gt;pPlanes[0], pImage-&gt;imageStep, sImage-&gt;pPlanes[0], sImage-&gt;imageStep, iSize);

    iSize.width = iSize.width / 2;
    iSize.height = iSize.height / 2;

    CopyPlane(pImage-&gt;pPlanes[1], pImage-&gt;imageStep / 2, sImage-&gt;pPlanes[1], sImage-&gt;imageStep / 2, iSize);
    CopyPlane(pImage-&gt;pPlanes[2], pImage-&gt;imageStep / 2, sImage-&gt;pPlanes[2], sImage-&gt;imageStep / 2, iSize);

    return ippStsNoErr;

} // IppStatus CopyHWMESource(hw_me_handle_t handle, const HW_ME_IMAGE *pImage)

IppStatus CopyHWMEReference(hw_me_handle_t handle, const Ipp32u refIdx, const HW_ME_IMAGE *pImage)
{

    if (NULL == handle || NULL == pImage)
    {
        return ippStsNullPtrErr;
    }

    if (handle-&gt;params.maxNumRef pReferences + refIdx;

    IppiSize iSize = handle-&gt;params.imageSize;

    sImage-&gt;imageStructure = pImage-&gt;imageStructure;

    // copy 3 planes by line
    CopyPlane(pImage-&gt;pPlanes[0], pImage-&gt;imageStep, sImage-&gt;pPlanes[0], sImage-&gt;imageStep, iSize);

    iSize.width = iSize.width / 2;
    iSize.height = iSize.height / 2;

    CopyPlane(pImage-&gt;pPlanes[1], pImage-&gt;imageStep / 2, sImage-&gt;pPlanes[1], sImage-&gt;imageStep / 2, iSize);
    CopyPlane(pImage-&gt;pPlanes[2], pImage-&gt;imageStep / 2, sImage-&gt;pPlanes[2], sImage-&gt;imageStep / 2, iSize);

    handle-&gt;m_numRef++;

    return ippStsNoErr;

} // IppStatus CopyHWMEReference(hw_me_handle_t handle, Ipp32u refIdx, const HW_ME_IMAGE *pImage)
</pre>
<h2>Нажимаем красную кнопку</h2>
<p>Запуск процесса оценки движения мы осуществляли следующим образом:</p>
<pre name="code" class="cpp">

// results storage of me
HW_ME_INFO pMeInfo;

pMeInfo.numFrameRefs[1] = hwPar.maxNumRef;

// calculate the number of macro blocks
numMb = (width * height) / (16 * 16);

// allocate mb info
pMeInfo.pMbInfo = new HW_ME_MB_INFO [numMb];
pMeInfo.numFrameRefs[1] = hwPar.maxNumRef;

sts = DoHWME(hwhandle, &amp;pMeInfo);
CHECK_STS(sts);
</pre>
<p>Соответствующая интерфейсная функция обращается к объекту эстиматора.</p>
<pre name="code" class="cpp">

IppStatus DoHWME(hw_me_handle_t handle, HW_ME_INFO *pMeInfo, void **ppEvent)
{
    IppStatus sts;
    Ipp32u width;
    Ipp32u height;

    HW_ME_IMAGE *pRefImages, *pSrcImage;

    // touch unreferenced parameters
    ppEvent = ppEvent;

    // check error(s)
    if (NULL == handle || NULL == pImage || NULL == pMeInfo)
    {
        return ippStsNullPtrErr;
    }

    // set initial parameters
    width =  handle-&gt;params.imageSize.width;
    height =  handle-&gt;params.imageSize.height;

    pRefImages = handle-&gt;pReferences;
    pSrcImage = handle-&gt;pSource;

    sts = handle-&gt;pEst-&gt;EstimateByFrames(pRefImages, NULL, pSrcImage, pMeInfo);

    return sts;

} // IppStatus DoHWME(hw_me_handle_t handle, HW_ME_INFO *pMeInfo, void **ppEvent)
</pre>
<h2>Все!</h2>
<p>Собственно, да. На этом покончено с интерфейсными функциями. Они по сути являются лишь обертками вокруг объекта-ядра. Что дальше? А дальше мы запустим руки во внутренности объекта-ядра и эстиматора. Надеюсь будет продолжение.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2011/10/24/motion-estimation-library-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Неопеределенность Клода Шеннона</title>
		<link>http://software.intel.com/ru-ru/blogs/2011/10/17/2005429/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2011/10/17/2005429/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 10:03:56 +0000</pubDate>
		<dc:creator>Dmitry Serkin (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[entropy]]></category>
		<category><![CDATA[entropy coding]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2011/10/17/2005429/</guid>
		<description><![CDATA[Публикуя предыдущую заметку я не учел одной важной вещи. Позвольте исправиться.]]></description>
			<content:encoded><![CDATA[<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/Shannon_42.jpg" style="float:left;padding-right: 8px" /></p>
<p>Публикуя <a href="http://software.intel.com/ru-ru/blogs/2011/10/13/2005406">предыдущую заметку</a> я не учел одной важной вещи и был наказан <del datetime="2011-10-17T08:37:45+00:00">плеткой</del> упреками коллег и недобрыми взглядами сбитых с толку простых обывателей. Я заикнулся о энтропийном кодировании, но не ввел понятие энтропии. Позор мне и порицание. Я исправляюсь.</p>
<p>Все началось с моего давнего хорошего друга, Клода Шеннона, который в 1948 году заложил фундамент нового, в то время неизвестного, научного направления – теории информации. Для многих страждущих сей факт послужил предметом многих и долгих споров. Ведь как же так? Человечество привыкло воспринимать информацию лишь качественно, но никак не количественно. Как часто это бывало, сама мысль о теории информации настигла Шеннона во время работы над правительственным проектом в области криптографии. Во времена Второй Мировой Войны. Война - извечный двигатель прогресса.</p>
<p>Вклад Шеннона в современную жизнь невероятно велик. Информация повсюду - она управляет, создает, уничтожает, является ключом ко всему. Скорость и точность ее передачи – жизненно важные характеристики современного мира. Шеннон не просто придал информации математическую форму, но и доказал ряд гениальных теорем, практическую пользу от которых человечество получило лишь спустя много лет, с приходом интегральных микросхем и больших вычислительных ресурсов. Обязательно прочтите его <a href="http://en.wikipedia.org/wiki/Claude_Shannon#Biography">биографию</a>.</p>
<p>Полагаю, что некоторым знакомо понятие энтропии, определенного в рамках химии и термодинамики. Так вот, у нас энтропия информационная и определяется она, конечно, иначе.</p>
<p>Информационная энтропия — мера неопределённости информации. Например, у вас есть источник, который генерирует поток  символов некоторого алфавита. Алфавит состоит из 5 элементов и известно, что один из символов в рамках данного алфавита имеет гораздо большую вероятность появления, допустим 0.5, а другие делят между собой 0.1 и 0.2. Тогда неопределенность появления символа с большей вероятностью мала, но велика для других символов. То есть появление первым символа с вероятностью 0.1 станет большей неожиданностью.</p>
<p>Математически двоичная энтропия символа  a  с вероятностью появления p(a) определяется не иначе как</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/19.png" style="margin-left:auto;margin-right:auto" />
</div>
<p>Оперируя понятием энтропии теория информации предсказывает среднее количество бит для оптимального сжатия символа алфавита. Строка s = a1a1a1a2a3a4a4a5 состоящая из 8 элементов рассмотренного выше алфавита будет иметь следующую энтропию:</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/27.png" />
</div>
<p>Значение энтропии показывает среднее минимальное количество бит требуемых для шифрования или оптимального сжатия строки без потери информации. В нашем примере она равна 27 битам. Размерность энтропии (бит) вытекает из основания логарифма равного 2.</p>
<p>Для наглядной иллюстрации возьмем алфавит из двух символов. Вероятности символов определяют энтропию алфавита. Равновероятные символы порождают максимальную энтропию и минимальное количество бит необходимое для кодирования символа алфавита равно 1. Во втором случае энтропия минимальна, так как известно, что символ a1 почти всегда будет выходом с источника. Количество требуемых бит для кодирования символа составляет 0.08 бита. Третий случай подобен первому и имеет очень высокий показатель энтропии.</p>
<div style="text-align:center;padding: 5 5 5 5">
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/37.png" />
</div>
<p>Заметим, что получаемая цифра лишь теоретическая оценка. Для практического применения еще необходимо разработать алгоритм, который будет ей удовлетворять.</p>
<p>Ну, и наконец, что же за процесс такой – «энтропийное кодирование»? Известная теорема Шеннона гласит, что «существует предел сжатия без потерь, зависящий от энтропии источника». То есть чем более предсказуема получаемая информация, тем лучше её можно сжать. Таким образом, энтропийное кодирование есть процесс максимизации энтропии символов исходного сигнала путем усреднения вероятностей их появления с источника.</p>
<p><a href="http://www.youtube.com/watch?v=z2Whj_nL-x8">Гений</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2011/10/17/2005429/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Уменьшая определенность: энтропийное кодирование</title>
		<link>http://software.intel.com/ru-ru/blogs/2011/10/13/2005406/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2011/10/13/2005406/#comments</comments>
		<pubDate>Thu, 13 Oct 2011 14:58:51 +0000</pubDate>
		<dc:creator>Dmitry Serkin (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[arithmetic coding]]></category>
		<category><![CDATA[cabac]]></category>
		<category><![CDATA[cavlc]]></category>
		<category><![CDATA[entropy coding]]></category>
		<category><![CDATA[Video Codecs]]></category>
		<category><![CDATA[vlc]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2011/10/13/2005406/</guid>
		<description><![CDATA[Энтропийное кодирование неотъемлимый элемент любого стандарта видеокодирования. Данные, пропущенные через мясорубку временной и пространственной модели, необходимо представить в виде сжатого битового потока для последующей передачи по сети или сохранения на жестком диске - финальный шаг любого видеокодека.]]></description>
			<content:encoded><![CDATA[<p>Энтропийное кодирование неотъемлимый элемент любого стандарта видеокодирования. Данные, пропущенные через мясорубку временной и пространственной модели, необходимо представить в виде сжатого битового потока для последующей передачи по сети или сохранения на жестком диске - финальный шаг любого видеокодека.</p>
<p>Итак, на входе мы имеем поток векторов, коэффициентов и служебной информации (заголовки, точки синхронизации, ...) – вообщем все то, что породили временная и пространственная модель в процессе своей работы, и что необходимо с одной лишь целью – восстановить оригинальное изображение с определенной степенью точности.</p>
<p>На этом этапе впору говорить о кодировании информации в отрыве от видео. Методов предостаточно, однако наиболее широко используются коды переменной длины (variable length coding, VLC) и арифметическое кодирование (arithmetic coding, AC).</p>
<p>В данной заметке я дам обзор существующий схем. Некоторые из них будут рассмотрены отдельно в последующих заметках. Прежде, скажу, что все описанные схемы сжимают данные без потерь; все что можно было отсечь уже отфильтровано на предыдущих этапах.</p>
<h2 class="sectionHeading">VLC и CAVLC</h2>
<p>Смысл <a href="http://en.wikipedia.org/wiki/Variable-length_code">VLC</a> – отображение входных символов в кодовые слова, имеющие переменную длину. Если те или иные входные символы встречаются чаще, то их кодовые слова более короткие. Реже – кодовые слова более длинные. Наиболее известный пример – это <a href="http://en.wikipedia.org/wiki/Huffman_coding">код Хаффмана</a>, который предварительно вычисляет вероятность вхождения каждого символа и, согласно построенной вероятностной модели, присвает каждому символу код VLC. Метод требует предварительного анализа всей входной последовательности, что приводит к значительной задерже на стороне приемника сигнала. Также динамическое построения таблицы вероятностей на уровне энкодера требует ее передачи в рамках битового потока для последующего декодирования сигнала, что сокращает степень сжатия.  Так как оба этих недостатка связанны с динамическим построением таблицы вероятностей, то разработчики стандартов видеокодирования предложили подход предварительного построения таблицы на основе обобщенных видеоматериалов. То есть каждый стандарт использующий схему VLC, будь то код Хаффмана или его модификации, определяет статическую таблицу кодов, построенную на основе предварительного анализа специально подобранного видеоматериала. Замечу, впрочем, что <a href="http://en.wikipedia.org/wiki/Adaptive_Huffman_coding">адаптивный Хаффман</a> решает обозначенные выше проблемы.</p>
<p><a href="http://en.wikipedia.org/wiki/Context-adaptive_variable-length_coding">Context-based adaptive variable length coding</a> (CAVLC) представляет собой модификацию VLC. Схема определяется стандартом H264 и используется для кодирования блоков остаточных коэффицентов. Схема специально разработанна с учетом особенностей и характеристик блоков: расположение элементов, количество нулей и прочее. Все эти знания влияют на построение вероятностной модели.</p>
<p>VLC отображает входные символы в кодовые слова, которые имеют целую длину бит. Согласно теории информации, выше изложенный факт не способствует получению теоретически оптимального сжатия, так как информационная емкость зачастую не является целым числом. Таким образом, символы имеющие наиболее высокую вероятность вхождения могут быть закодированы кодовыми словами минимум в 1 бит длиной, то есть наименьшей допустимой длиной кодового слова. В подобных случаях мы рискуем получить крайне слабый показатель сжатия.</p>
<h2 class="sectionHeading">AC и СABAC</h2>
<p>Побороть эту проблему призвано арифметическое кодирование (<a href="http://en.wikipedia.org/wiki/Arithmetic_coding">arithmetic coding</a>, AC), которое позволяет наиболее плотно приблизиться к теоретическим оценкам сжатия. Однако за эффективность приходиться платить более высокой вычислительной сложностью.</p>
<p><a href="http://en.wikipedia.org/wiki/Context-adaptive_binary_arithmetic_coding">Context-adaptive binary arithmetic coding</a> (CABAC), подобно тому как CAVLC расширяет собой VLC, представляет собой расширение для AC. Расширение использует стандартную схему AC, но при этом:</p>
<ul>
<li> работает только с двоичными символами. Все символы имеющие недвоичные значения (коэффиценты, координаты векторов) приводятся в двоичный вид;</li>
<li> вводит сбор локальной статистики на основе которой выбирается вероятностная модель для кодирования последующих бит информации.</li>
</ul>
<p>CABAC позиционируется как очень эффективная, но тяжелая схема энтропийного кодера. Является одним из преимуществ стандарта H264 и антогонизмом по отношению к более быстрому, но менее эффективному CAVLC.</p>
<p>Все вышеописанное даст лишь крайне общие представления о существующих схемах энтропийного кодирования. Далее мы отдельно остановимся на VLC и AC, а также их расширениях. А пока просто знайте.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2011/10/13/2005406/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>«О эволюции рыб в белок», теперь в 3D!</title>
		<link>http://software.intel.com/ru-ru/blogs/2011/09/29/3d-3/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2011/09/29/3d-3/#comments</comments>
		<pubDate>Thu, 29 Sep 2011 09:12:24 +0000</pubDate>
		<dc:creator>Dmitry Serkin (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[Графика]]></category>
		<category><![CDATA[DCT]]></category>
		<category><![CDATA[Video Coding]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2011/09/29/3d-3/</guid>
		<description><![CDATA[В предыдущей статье я дал опрометчивое обещание завершить серию записей о математических преобразованиях. Не тут-то было.]]></description>
			<content:encoded><![CDATA[<p>В предыдущей статье я дал опрометчивое обещание завершить серию записей о математических преобразованиях. Не тут-то было.</p>
<p>До сих пор я искренне старался донести «на пальцах» (их уже почти не осталось) краеугольные принципы методов видео-кодирования. Затронул основы устранения <a href="http://software.intel.com/ru-ru/blogs/2011/07/28/motion-estimation-library/">временной</a> и <a href="http://software.intel.com/ru-ru/blogs/2011/09/20/dct-3/">пространственной избыточности</a>. Напоследок я предлагаю ознакомиться с 3D-DCT преобразованием, которое так удачно, в смысле идеи, объединяет в себе оба пройденных понятия.<br />
С места в карьер, преобразование математически описывается так:</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/dct3d.png" /></p>
<p>Тем, кто читал <a href="http://software.intel.com/ru-ru/blogs/2011/08/29/dct-2/">заметку о преобразованиях</a> - перечитайте еще раз! И вы поймете, что _в основном_, преобразования работают в 2D простанстве. Прямоугольные блоки размером 8x8, в частности.</p>
<p style="padding: 5px 0px 5px 20px">
<em><strong>Примечание</strong> <br />
Как я ранее уже говорил, существует поверие, что блоки большего размера (например 16x16) показывают лучшие результаты. Почему бы и нет. В конечном счете, это зависит от структуры кадра (количества движения в нем, наличие либо отсутствие статических структур и прочее).</em></p>
<p>Но что, если мы увеличим размерность до трех?  То есть, кроме вертикальной и горизонтальной размерности, введем временную? Вспомним, как математики смешно описывают 2D-DCT:</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/dct2d.png" /></p>
<p>Сравнив формулы можно заметить, что в случае 3D мы добавляем еще один цикл суммы, нормирующий множитель и косинус под суммой. Точка имеет 3 координаты, а это означает, что введя еще одну размерность, - временную, мы образуем уже не квадрат значений, но куб. Представьте себе коробку с восемью 3.5’’ дискетами, где каждая дискета есть блок 8x8, но все вместе они образуют куб – наш новый атомарный элемент. В одной такой коробочке содержится 8 блоков  размером 8x8 c одинаковым расположением в рамках 8 кадров.</p>
<p>Математически можно объяснить связь трехмерного преобразования с двухмерным. Вкратце, трехмерное преобразование обусловленно применением так называемых дельта и эпсилон модификаций , учитывающих изменения кадра во времени. Математические выкладки я упразднил ввиду отсутствия интереса к ним у местной публики <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Для интересующихся, некоторые выкладки можно найти <a href="http://www.google.ru/url?sa=t&amp;source=web&amp;cd=4&amp;ved=0CDkQFjAD&amp;url=http%3A%2F%2Fciteseerx.ist.psu.edu%2Fviewdoc%2Fdownload%3Fdoi%3D10.1.1.91.5561%26rep%3Drep1%26type%3Dpdf&amp;ei=an6DTp7hBeOy0QWn37m5AQ&amp;usg=AFQjCNE4Hk_IyqiNJJnMDfwEjyOV3hzIMA&amp;sig2=7nShzNaWt66ZMKPg7">здесь</a>.</p>
<p>Рассмотрим 8 последовательных кадров. Движение практически отсутствует. Разве, что мех на хвосте у белки чуть шевелится, да меняются отражения воды и блики айсберга. Но сильного движения нет. В таком случае, вполне резонно применить 3х мерное преобразование Фурье.</p>
<p style="padding: 5px 0px 5px 20px">
<em><strong>Примечание</strong> <br />
Замечу, впрочем, что в рамках популярных стандартов видеокодирования, такой вопрос вообще не стоит, так как все они используют блок оценки движения. Однако, для некоторых форматов можно добиться значительного преимущества в сжатии. Такого, например, как motion jpeg, широко любимого многими  веб-камерами и не подразумевающего схемы оценки движения, как таковой.</em></p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/set3.png" /></p>
<p>Применив на данной последовательности кадров алгоритм 3D-DCT, получим следующую картину (только  компонента яркости):</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/18.png" /></p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/26.png" /></p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/36.png" /></p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/45.png" /></p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/53.png" /></p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/63.png" /></p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/73.png" /></p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/83.png" /></p>
<p>На вход алгоритм получает восемь кадров и работая с каждым кубом сэмплов образует матрицы коэффицентов той же размерности. О пользе (устранение избыточности) этих коэффицентов я упоминал ранее. Интересно заметить, что первый кадр выглядит как выход с двухмерного преобразования. Крайне сильная блочность и угловые коэффиценты. Остальные же кадры менее блочны и содержат меньшие по модули коэффиценты. Блоки появляются лишь там, где присутствует малейшее движение. Ярко выделяется силуэт неподвижной белки весь заполненный нулями. Таким образом, первый кадр содержит общую информацию для всей последовательности, остальные семь несут в себе информацию о движении в рамках последовательности.</p>
<p>Пользу трехмерного преобразования возможно оценить только в рамках полнофункционального кодека (такого как, например, mjpeg) экспериментируя с различными видео последовательностями и применяя известные в видеокодировании критерии. Однако, уже сейчас можно сказать, что алгоритм позволяет значительно улучшить уровень компресии ценой относительно небольшого увеличения сложности вычислений, но неприятным увеличением потребления памяти (необходимо хранить все восемь кадров в памяти).</p>
<p>Теперь уже точно все про преобразования. Почти точно, или почти все.</p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2011/09/29/3d-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>DCT или Вниз по кроличьей норе (часть третья, Фурье)</title>
		<link>http://software.intel.com/ru-ru/blogs/2011/09/20/dct-3/</link>
		<comments>http://software.intel.com/ru-ru/blogs/2011/09/20/dct-3/#comments</comments>
		<pubDate>Tue, 20 Sep 2011 12:00:39 +0000</pubDate>
		<dc:creator>Dmitry Serkin (Intel)</dc:creator>
				<category><![CDATA[Intel Software Network]]></category>
		<category><![CDATA[DCT]]></category>
		<category><![CDATA[IDCT]]></category>
		<category><![CDATA[Video Codec]]></category>

		<guid isPermaLink="false">http://software.intel.com/ru-ru/blogs/2011/09/20/dct-3/</guid>
		<description><![CDATA[Сложно назвать область науки в которой бы не нашлось места для применения преобразования Фурье. Гений Фурье открыл уникальный инструмент, который связывает непрерывные и дискретные миры. Инструмент, полезность которого доказана не только на бумаге, но и, в больше степени, при решении реальных проблем. Инструмент, позволяющий увидеть проблему в новой, более ясной перспективе]]></description>
			<content:encoded><![CDATA[<p style="padding: 20px 0px 20px 400px"><em>«Подумать только, что из-за какой-то вещи<br />
можно так уменьшиться, что превратиться в ничто»<br />
Льюис Кэрролл, «Алиса в стране чудес»</em></p>
<p>Сложно назвать область науки в которой бы не нашлось места для применения преобразования Фурье. Гений Фурье открыл уникальный инструмент, который связывает непрерывные и дискретные миры. Инструмент, полезность которого доказана не только на бумаге, но и, в больше степени, при решении реальных проблем. Инструмент, позволяющий увидеть проблему в новой, более ясной перспективе.</p>
<p>К сожалению, в подобном лирическом стиле, невозможно описать суть. Поэтому спустимся с небес и попытаемся понять, какую пользу в себе таит дискретное косинусное преобразование, как частность преобразования Фурье, для решения нашей задачи.</p>
<p>Вспомним преобразование, которое мы построили <a href="http://software.intel.com/ru-ru/blogs/2011/08/29/dct-2/">в прошлый раз</a> руководствуясь эвристическими рассуждениями:</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/DCT_3_1.png" /></p>
<p>Оно удовлетворяет всем предъявляемым требованиям и прекрасно делает свою работу. Однако, сложно назвать его эффективным, хотя бы в силу того, что сделать его таковым не входило в наши планы.</p>
<p>Поэтому воспользуемся опытом предков, которые десятилетия назад сказали, что одним из наиболее эффективных ортогональных преобразований является <a href="http://en.wikipedia.org/wiki/Discrete_cosine_transform">дискретное косинусное преобразование</a>.</p>
<p>И как же связано дискретно-косинусное преобразование с задачей декорреляции?</p>
<p>Вспомним, что при построении выше упомянутого преобразования мы предъявляли специальные требования  к его базисным векторам. Первый вектор базиса должен целиком состоять из положительных чисел и усиливать энергию, остальные же должны варьировать свой знак, чтобы в результате дать почти нулевую энергию. Все коэффиценты преобразования были сведены по модулю к единице по одной простой причине – преобразование не должно быть зависимым от входных данных и подбирая лучшие коэффиценты для одной группы данных, мы тем самым ухудшаем результат для другой группы.</p>
<p>Посмотрим, что из себя представляют базисные вектора дискретно-косинусного преобразования Фурье. Вот они, косинусы :</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/DCT_3_2.png" /><br />
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/DCT_3_3.png" /><br />
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/DCT_3_4.png" /></p>
<p>Ничего не напоминает? Характер каждого базисного вектора повторяет характер векторов нашего простого преобразования. Первый вектор положительная константа. Остальные периодично варьируют свой знак. Осталось только определить восемь точек на каждом векторе и построить по их значения искомую матрицу размером 8x8. </p>
<p>Определяем абсциссы для данных синусоид:</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/Untitled2.png" /></p>
<p>Идем по волнам и считаем значения:</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/DCT_3_6.png" /></p>
<p style="padding: 5px 0px 5px 20px">
<em><br />
<strong>Примечание.</strong> <br />
Почему значения абсцисс выбранны такие? Ответ связан с одним из требований к природе преобразования.</em></p>
<p>Маленький пример для понимания. Рассмотрим одномерное преобразование на следующем исходном векторе значений сэмплов яркости:</p>
<blockquote><p>56,  57, 56,  53,  60, 53,  56, 58</p></blockquote>
<p>Применив преобразование получим вектор коэффицентов:</p>
<blockquote><p>449.0, 2.36396103, 4.0, -10.36396103,  7.0, -10.36396103, 4.0, 2.36396103</p></blockquote>
<p>Сильно квантуем его, тем самым невосполнимо потеряв часть информации:</p>
<blockquote><p>449, 0, 0, -10, 7, -10, 0, 0</p></blockquote>
<p>Применим обратное преобразование:</p>
<blockquote><p>54.5, 57.01776695, 57.0, 53.48223305,  59.5,  53.48223305,  57.0,  57.01776695</p></blockquote>
<p>Обратное преобразование восстановило последовательность достаточно точно, учитывая грубое квантование и округление.</p>
<p>Говорят, что пост без картинок не пост <img src='http://software.intel.com/ru-ru/blogs/wordpress/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> . Вот так выглядит картинка до и после преобразования:</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/DCT_3_7.png" /></p>
<p>Этой записью я завершаю разговор про математические преобразования и их роли в современных стандартах видеокодирования. Мы поговорили о их предназначении и правилах построения. Время сделать шаг вперед и затронуть тему энтропийного кодирования.</p>
<h2>Немного формул</h2>
<p>Математически, для блока n x n с элементами S<sup>ij</sup>, прямое DCT преобразование задается следующими формулами:</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/DCT_3_8.png" /></p>
<p>Обратное преобразование:</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/DCT_3_9.png" /></p>
<p>Формулы всего лишь расписанные матричные операции. Иначе прямое преобразование можно описать в виде матричного произведения:</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/DCT_3_10.png" /></p>
<p>Где S – это матрица сэмплов исходного блока, S'- матрица коэффицентов, а A – матрица преобразования элементы, которой заданы:</p>
<p><img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/DCT_3_11.png" /><br />
<img src="http://software.intel.com/ru-ru/blogs/wordpress/wp-content/uploads/DCT_3_13.png" /></p>
]]></content:encoded>
			<wfw:commentRss>http://software.intel.com/ru-ru/blogs/2011/09/20/dct-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

