Нежное интро к видео технологии, предназначено для программистов и инженеров, хотя информация тут изучаема любому заинтересованному. Эта идея родилась во время мини-семинара для новичков в области видео технологий.
Цель представить концепции цифрового видео простыми терминами, схемами и практикой. Не стесняйтесь добавлять свои исправления и предложения для улучшения документа.
Практические разделы требуют чтобы у вас был установлен docker и клонирован этот репо.
git clone https://github.com/leandromoreira/digital_video_introduction.git
cd digital_video_introduction
./setup.sh
ПРЕДУПРЕЖДЕНИЕ: когда вы видите команду
./s/ffmpeg
или./s/mediainfo
, это означает, что мы запускаем контейнерную версию этой программы, которая уже включает в себя все необходимые требования.
Все практические упражнения выполняются из клонированной папки. Для примеров jupyter вы должны запустить сервер ./s/start_jupyter.sh
, и посетить URL в браузере.
- added DRM system
- released version 1.0.0
- added simplified Chinese translation
- Интро
- Индекс
- Основные термины
- Удаление избыточности
- Как действует видео кодек?
- Онлайн трансляция
- Как использовать jupyter
- Конференции
- Ссылки
Изображение можно представлять в форме 2Д матрицы. Если мы думаем о цветах, то можно экстраполировать это представление в 3Д матрицу, где добавочные измерения показывают цветную информацию.
Если мы представляем эти цвета первичными цветами (красный, зеленый, синий), мы определяем три уровня, один для красного, один для зеленого, и последний для синего.
Мы назовем каждую точку на этой матрицы пикселем (элемент изображения). Один пиксел отражает интенсивность (обычно числовое значение) данного цвета. Например, красный пиксель имеет 0 зеленого, 0 синего, и максимально красного. Розовый пиксель состоит из комбинации трех цветов - Красный=255, Зеленый=192, Синиий=203.
Существует множество моделий которые описовают как расппределяються цвета на изображение. Например, в место трех битов, как для модели RGB (Красный, Зеленый, Синий) мы можем изпользовать только один бит. Ето использует меньше памяати но так же дает меньшые количество цветов.
На изображение снизу, первый снимок отражает все цветовые каналы. Остальные снимки только отражают красный, зеленый и синий канал.
Мы видим что красный канал будет самым ярким (белые части второго лица), и способствует главному оттенку в картинке. Синего мало, и видно в четвертой картинке, что он сконцентрирован в глазах и одежды Марио. Так же видно, что все каналы мало способствуют усам, самым темным частям картинки.
У каждого канала определённое количество битов, так называема битовая глубина. Если у нас 8 битов (между 0 и 255и) для каждого цвета, то битовая глубина у изображений RGB (8 бит * 3 цвета) в размере 24 бита, то есть 2^24 разных цвета.
Хорошо знать как озпбражения переводятся с настоящего мира в биты.
Другая характеристика изображений это разрешение, то есть количество пикселей в одном измерение. Обычно оно показывается в формате ширина х высота, как на 4х4 картинке снизу.
Можно играца с цветами в картинках используя jupyter (python, numpy, matplotlib и т.д).
Так же можшно понять как фильтры, (обострение, размытость...) работают.
Еще качество с которым мы встречаемся пре работе с видео и изображениями это соотношение сторон (AR) которое просто описывает пропорции ширины сравнительно с высотой изображения или пикселя.
Когда луди говорят что изображение или фильм 16х9, они называют цифры DAR (Соотношение сторон дисплея). Так же и бывает PAR (Соотношение сторон пикселя)
Хоть у DVD разрешение 704х480, формат все равно соблюдает DAR 4:3 потому что у него PAR 10:11 (703x10/480x11)
И конечно, "видео" мы определяем как последствие n-кадров во времени, что можно обозначить как дополнительное измерение поверху размера и цвета, где п это количество кадров в секунду (FPS).
битрейт это сколько нужно битов что бы показать секунду видео.
битрейт = ширина * высота * битовая глубина * кадры в секунду
Например, видео которое 30 FPS, 24 бита на пиксел, с разрешением 480х240 использует 82,944,000 битов в секунду или 82 мегабита/с (30*480х240х24) без компрессии/снижения качества.
Когда бит рейт постоянный то его называют постоянным битрейтом (CBR), когда он меняется со временем тогда это переменный битрейт (VBR).
Этот график показывает ограниченный VBR, который не тратит слишком много битов на черные кадры.
Раньше, инженеры придумали технику, что бы увеличить воспринятый FPS в два раза при этом не увеличения битрейт. Эта техника называется чересстрочное видео, где пол изображения посылается в одном "кадре" и другая половина в следующем "кадре".
Сегодня экраны обычно представляют видео техникой прогрессивного скана. Это способ показывания, хранения и перевода изображений в котором все линии каждого кадра нарисованы одна за другой.
Теперь у нас есть представление того как xраница изображение в цифровом формате, как его цвета расположены, сколько битов в секунду мы используем что бы показывать видео, если это постоянный битрейт (CBR) или переменный битрейт (VBR), и как это связано с разрешением при данной чистоте кадра. Так же мы более знакомы с терминами наподобие чересстрочное видео, PAR, и т.д.
Вам возможно увидеть оговоринные свойства с помощью ffmpeg или mediainfo.
Быстро становиться очевидно что работать с видео без компрессии практически не возможно; один час видео разрешение 720p, с частотой кадра 30fps занимает 278GB памяти*. Алгоритмы компрессии без потерь, наподобие DEFLATE (используется в PKZIP, Gzip, PNG) не сжимают видео достаточно нам надо искать другие способы сжатья видео.
* Эту цифру мы получаем умнажая 1280 х 720 х 24 х 30 х 3600 (ширина, высота, витовая глубина, чистота кадра и время в секундах).
Для этого мы можем использовать характеристики нашего зрения. Мы разбираем яркость лучше, чем цвета. Так же более заметные повторы частей изображения во времени.
Наши глаза более чувствительны к яркости чем к цветам, проверти для себя на этом изображение:
Если вам не видно, что цвета квадрата А и Б одинаковые у картинки с лева, то у вас все в порядке, наш мозг настроен уделять больше внимания на яркость/темноту чем на цвет. С право вы видите что цвета и в правду одинаковы.
Упрощенное обьяснение функций глаз Глаз сложный орган, составлин из многих частей, хотя нас интересует шишочные и палочные клетки. Глаз состоит из порядка 120 милион палочных клеток и 6 милион шишочныч клеток.
Упращая дальше, давайте посмотрим как цвет и яркость действуют на глаза. Палочные клетки по большенству отвецтвенны за восприятие яркости. Шишичные клетки отвецтвенны за восприятие цвета. Есты три типа шишки, каждая со своей окраской: S-шишки (Синий), M-шишки (Зеленый) и L-cones (Красный).
Потому что у нас больше палочных клеток (яркость) чем шишочных (цвет), мы делаем вывод что мы обробатываем больше яркостной информации.
Функции контрастной чувствительности
Есть много теорий описывая функции человеческое зрение. Одна из них называется "Функции контрастной чувствительности". Они описывают сколько изминения в цвете может произойти перед тем как наблюдающий его замечает. Функции измеряют не только чуствительность к черно белому, нo так же и яркость при цветах. Експерименты раз за разом показывают что мы более чуствительны к яркости чем к цветам.
Зная что мы чувствительны к яркости, мы можем попытаться использовать этот факт.
В начале мы изучали как распределять цвет на изображениях используя модель RGB. Существуют другие модели - например, YCbCr* делит luma/лума (яркость) от chrominance/хроминанц (цветность).
* есть другие модели которые так же разделяют между яркостью и цветом.
В этой модели Y канал яркости. Так же есть два канала цвета, Cb (синяя chroma/хрома) и Cr (красная chroma/хрома). Формат YCbCr возможно получить от RGB, и так же можно получить RGB от YCbCr. С помощью YCbCr мы можем составлять изображения в полном цвете:
Некоторые из вас может спрашивать, как можно показывать все цвета без зеленого?
Что бы понять ответ, давайте посмотрим как мы переводим цветовую модель RGB на YCbCr. Мы будем использовать коэффициенты из стандарта BT.601, который был создан группой ITU-R*. Первый шаг в этом процессе это высчитать яркость (luma) и заменить цифры RGB, используя константы рекомендованные группой ITU.
Y = 0.299R + 0.587G + 0.114B
После яркости, мы можем получить цвета (chroma синий и красный):
Cb = 0.564(B - Y)
Cr = 0.713(R - Y)
Можно перевести этот результат обратно, и даже получить зеленый используя YCbCr
R = Y + 1.402Cr
B = Y + 1.772Cb
G = Y - 0.344Cb - 0.714Cr
* Цыфровым видео правят группы и стандарты. Группы определяют стандарты, на пример что такое 4К? Какую чистоту кадра использоватъ? Решение? Цветную модель?.
Обычно, дисплеи работают только в режиме модели RGB, расположенные каким то образом. Некоторые из них показаны тут:
Когда изображение представлено компонентами яркости и цвета, мы можем воспользоваться чувствительностью глаза к яркости, что бы уменьшить количество информации. Цветовая дискретизация техника кодированья изображений с разрешением для цвета меньше чем для яркости.
Так как же уменьшается разрешение цвета?! Существуют схемы которые описывают, как получить цвет от разных разрешений для одного изображение (конечный цвет = Y + Cb + Cr
).
Эти схемы называются системами дискретизации, обычно показаны соотношением трех чисел - a:x:y
которое определяет разрешение цвета по отношению к a * 2
блоку пикселей яркости.
a
горизонтальная ширина (обычно 4)x
количество образцов цвета в первом рядуy
количество изменений цвета между первым и вторым рядом
В этой схеме есть изклучение, 4:1:0, где выберается только один цвет для каждего
4 x 4
блока разрешения яркости.
В современных кодеках обычно используются форматы: 4:4:4 (Без дискретизации), 4:2:2, 4:1:1, 4:2:0, 4:1:0 и 3:1:1.
Вы можете участовать в разговорах о цветовой подборке тут.
Подборка YCbCr 4:2:0
Тут видно как сливается цветовая информация с яркостной в режшиме YCbCr 4:2:0. Заметите, что мы только используем 12 битов на пиксель.
Тут показано изображение кодированное главными типами дискретизации. Первый ряд финальный YCbCr; на втором, видно разрешение цветных каналов. Качество изображения нормальное, при этом памяти используется на много меньше.
Ранее мы вычислили что нам надо 278GB памяти что бы сохранить час 720p/30fps видео. Используя режим YCbCr 4:2:0 мы можем убрать половину размера до 139GB*, хотя это все равно далеко от идеала.
* это число можно получить умнажая ширину, высоту, биты на пиксел, и чистоту кадра. Раньше мы пользовались 24 битами, теперь нам только надо 12.
Возможно проверить гистограмму YCbCr с помошью ffmpeg.. У этого изображение выше концентрация синего, что видно на гистограмме.
Отличное видео для тех кто хотят приобрести глубже понятие лумы, яркости, гаммы, и цвета.
Теперь мы можем сосредоточиться на удаление избыточности во времени. С начала, нам надо установить основные термины - скажем, что мы работаем с фильмом 30FPS, и первые 4 кадра выглядят так:
Мы видим много повторений между кадрами, например у синего фона который не меняется на кадрах 0 - 3. Что бы начать решать эту проблему, мы можем абстрактно классифицировать их как 3 разных типа кадра.
I кадр, (ссылка, ключевой кадр, внутренний) независимый кадр. Что бы его нарисовать не нужно дополнительной информации, и он похож на фотографию. Первый кадр обычно I кадр, но мы видем как I кадры регулярно вставляют среди других типов кадра.
P-кадр пользуется фактом, что почти всегда можно нарисовать изображение с помощью пре ведущего кадра. Например, во втором кадре, шар поменял расположение - все остальное осталось одинаковым. Мы можем построить первый кадр используя только разницу между двумя кадрами.
Если P-кадры используют меньше памяти, то почему бы нам не закодировать целое видео одним I-кадром и оставить все последующие кадры как P-кадры?
После кодировки этого видео, начните смотреть его и попробуйте перескочить к пожемму времини. Станит заметно что эта функция длица долгое време. P-кадрам нужны ссылочные кадры (например I-кадр) что бы их нарисовать.
Так же можно закодировать видео с одним I-кадром а потом попробовать закодировать его вставляя I-кадр каждие две секунды, сравнивая размера в конце.
Так же можно ссы лаца на будущие кадры, как и пре ведущие, метод который экономит еще больше памяти - как раз это и делают B-кадры.
Вы можете составить две версии видео, одну с B-кадрами и другую вообще без B-кадров. Обратите внимание на размер файла и качество видео.
Эти кадры используются для более эффективной компрессии. Мы уведем как это происходит в следующем отделе, на не теперешний момент нам достаточно помнить что I-кадр дорогой, P-кадр дешевле и B-кадр самый дешевый.
Давайте посмотрим как мы и можем понизить количество повторов во времени. Такого типа избыточности можно достичь техниками меж предсказания.
По попробуем потратить меньше битов кодируя кадры 0 и 1.
Один подход это просто вычитать разницу между кадром 1 и 0, и мы получим все что надо что бы закодировать остаток.
Не плохо, но есть еще лучше метод, который использует еще меньше битов. С начала, давай разрежем кадр 0
на серию разделов, после чего мы можем попытаться соответствовать разделы с кадра 0
до кадра 1
, действие наподобие оценки двежения.
Компенсаци движению блока делит текущий кадр на отдлеьные разделы, после чего векторы компенсации движения показывают от куда эти блоки появились (распостраненная ошыбка идея того что, разделив преведущий кадр на отдельные разделы, векторы показывают куда эти разделы двигаются). Исходные разделы обычно перекрывают друг друга в исходном кадре. Некотороя компрессия видео текущий кадр из кусков разных ранее переданных кадров.
Мы можем предсказать что шарик сдвинулся от x=0, y=25
до x=6, y=26
, и что х и y числа это векторы движения. Что бы сэкономить на битах дальше, мы можем закодировать только разницу в векторах движения между последним положением блока и предсказанным, так что финальный вектор движения получается x=6 (6-0), y=1 (26-25)
.
При настоящем использование этой техники, шар был бы разделен на
n
разделов. Процесс при этом остается одинаковым.
Обьекты на кадре могут двигатся 3Dобразно, шар может стать меньше когда он уходит в фон. Впольне возможно (и нормально) что мы не сможем найти идеальнoe совпадение для раздела которму мы ищим совпадение. Вот изображение сравняя наше предскозание с настоящим кадром.
Все равно, видно что когда мы используем предсказание движения информации которую нам надо кодировать меньше чем если мы бы использовали технику делта кадров.
Обычно эта техника используется для всех разделов, и обычно один шар как в преведущих кадрах будет разделен на несколько разделов.
Ссылка: https://web.stanford.edu/class/ee398a/handouts/lectures/EE398a_MotionEstimation_2012.pdf
Вы можете экспериментировать этими техниками в jupyter.
Мы можем создать видео с внешним предсказанием (векторами движения) с помощью ffmpeg.
Так же можно использовать Intel Video Pro Analyzer (програма платная, но есть бесплатная, пробная версия, которая ограничивает пользу на первые 10 кадров).
Если мы проанализируем каждый кадр в видео, мы увидим что есть много областей, которые имеют отношение друг к другу.
Давайте пройдемся по примеру. Эта сцена в основном состоит из синего и белого.
Это I-кадр
, и мы не можем использовать предыдущие кадры для прогнозирования - при этом, мы все еще можем сжать его. Мы закодируем информацию в красном разделе. Если мы посмотрим на его соседей, мы можем понять что существует тренд цветов вокруг него.
Мы предскажем, что в кадре будут распространятся цвета по вертикали, то есть цвета пикселей о которых мы не знаем в этой области будут содержать цвета соседей.
Наше предсказание может быть неверным, по этому нам надо применить этот метод (внутреннее предсказание), а затем вычесть реальные числа цветов, что дает нам остаточный раздел и дает нам более сжимаемою матрицу по сравнению с оригиналом.
Вы можете зделать видео с макро разделами и их предскозаниями в ffmpeg. Пожалуйста проверите документацию ffmpeg что бы понять значение каждего блока цвета.
Так же можно использовать Intel Video Pro Analyzer (програма платная, но есть бесплатная, пробная версия, которая ограничивает пользу на первые 10 кадров).
Что такое видео кодек? Это система, программная или физическая, которая сжимает или разжимает цифровое видео. За чем? Обществу, и в свою очередь рынку нужно видео высокого качества при ограниченном объёме передачи или хранения информации. Помните когда мы высчитали нужный объем передачи для видео у которого 30 кадров в секунду, с битовой глубинной 24 бита и разрешение 480х240? Это было 82.944mbps без компрессии. Только так можно передавать HD/FullHD/4K видео к телевизору или по интернету. Как? Мы проведём поверхностный обзор главный техники здесь.
Кодек или контейнер?
Очень часто путается цыфровой видео кодек и цыфровой видео контейнер. Контейнер можно представлять как оберток который содержит метаданные о видео (и возможно о звуке). Сжатое видео можно представить как его дoставочное содержaние.
Обычно, расширение файла указывает тип контейнера. Например, файл
video.mp4
скорее всяго контейнер MPEG-4 Part 14, а файл с названиемvideo.mkv
скорее всяго контейнер matroska. Что бы быть уверенным, можно использовать ffmpeg или mediainfo.
Прежде чем мы углубимся во механизмы универсального кодека, давайте посмотрим в прошлое, чтобы немного лучше понять некоторые старые видеокодеки.
Видео кодек H.261 официально родился в 1990, и был устроен работать при обмене информации скоростью 64 kbit/s. Уже используют методы на подобие цветовой десктирезации, макро блоки е т.д. В 1995 году, выпустили кодек H.263 - этот стандарт прожил до 2001ого, время на протяжение которого над ним постоянно работали и улучшали.
В 2003 году была завершена первая версия H.264 / AVC. В том же году компания под названием TrueMotion выпустила свой видеокодек без лицензионных отчислений для сжатия видео с потерями под названием VP3. В 2008 году Google купил эту компанию, выпустив VP8 в том же году. В декабре 2012 года Google выпустил VP9, и он поддерживается примерно на ¾ из всех браузеров (включая мобильные устройства).
AV1 - это новый бесплатный кодек, с открытым кодом, который разрабатывается Альянсом открытых медиа (AOMedia), в которую входят компании: Google, Mozilla, Microsoft, Amazon, Netflix, AMD, ARM, NVidia, Intel и Cisco и другие. Первая версия 0.1.0 эталонного кодека была опубликована 7 апреля 2016 года.
В начале 2015 года Google работали над VP10, Xiph (Mozilla) работали над Daala и Cisco открыли свой бесплатный видеокодек под названием Thor.
Затем MPEG LA объявили годовые ограничения для HEVC (H.265) и сtoймость использованья в 8 раз выше, чем H.264. Вскоре они снова изменили правила:
- нет годового лимита,
- плата за контент, (0,5% от выручки) и
- Плата за единицу продукции примерно в 10 раз выше, чем h264.
Альянс для открытых медиа был создан производителями оборудованья (Intel, AMD, ARM, Nvidia, Cisco), контент доставчиками (Google, Netflix, Amazon) создателями враузеров (Google, Mozilla) и другими.
У компаний была общая цель - бесплатный видео кодек, результат чаго является AV1, у которого патентная лицензия на много проще. Тимоти Б. Терриберри сделал потрясающую презентацию, которая является источником этого раздела, о концепции AV1, модели лицензии и ее текущем состоянии.
Вы будете удивлены, узнав что возможно проанализировать кодек AV1 через браузер: https://arewecompressedyet.com/analyzer/
PS: Если вы хотите узнать больше об истории кодеков, взгляните на патенты для сжатия видео.
Сейчас мы попытаемся описать основные механизмы универсального видеокодека, концепций которые полезны и используются в современных кодеках, на примере VP9, AV1 и HEVC. Это будут упрощенные схемы, хотя иногда мы будем использовать реальные примеры (в основном по отношению к H.264) для демонстрации техники.
Первым шагом действия кодека является разделение кадра на несколько разделов, подразделов и т.д.
Зачем? Есть много причин - разделяя картинку, мы можем точнее обрабатывать прогнозы, используя маленькие разделы для маленьких движущихся частей видео и большие разделы для статического фона.
Обычно кодеки организуют эти разделы в срезы (или фрагменты), макро (или блоки схемы кодирования) и множество подразделов. Максимальный размер этих разделов варьируется, HEVC устанавливает 64x64, в то время как AVC использует 16x16, но подразделы могут достигать размеров 4x4.
Вы помните разные типы кадров? Возможно применить эти идеи и к блокам, поэтому у нас могут быть I-Slice, B-Slice, I-Macroblock и т.д.
Мы можем использовать Intel Video Pro Analyzer (программа платная, хотя есть бестплатная версия где можно проанализировать первых десять кадров). Вот разделы VP9.
Как только у нас есть разделы, мы можем использовать их для предсказаний. Для меж кадрового предсказания нам нужно использовать векторы движения и остаток, а для внутрикадрового предсказания мы будем использовать предсказанное направление и остаток.
После того как мы получим остаточный блок (предсказанный раздел - реальный раздел
), мы можем трансформировать его образом которым даст нам знать, какие пиксели мы можем выбросить, сохраняя при этом общее качество. Есть некоторые трансформации которые тут нам помогут.
Хотя есть другие трансформации, мы более подробно рассмотрим дискретную косинусную трансформацию, ДСТ (DCT). Основные функции DCT:
- Переводит блоки пикселей в блоки одинакового размера частотных коэффициентов.
- Сжимает энергию, облегчая устранение пространственной избыточности.
- Является обратимым процессом, например, вы можете вернуться к пикселям.
2 февраля 2017 г. Синтра Р. Дж. И Байер Ф. М. опубликовали свою статью ДСТ-подобное преобразование для сжатия изображений требует только 14 дополнений.
Не беспокойтесь, если вы не поняли преимуществ каждого пункта, мы попытаемся провести несколько экспериментов, чтобы понять процесс подробнее.
Давайте возьмем следующий блок пикселей (8x8):
Который рендерится как изображение (8x8):
Когда мы применяем ДСТ к этому блоку пикселей, мы получаем блок коэффициентов (8x8):
И если мы отрендерим этот блок коэффициентов, мы получим это изображение:
Как видно, это не похоже на исходное изображение, и похоже, что первый коэффициент очень отличается от всех остальных. Этот первый коэффициент известен как коэффициент DC, представляя себе все выборки во входном массиве, что-то наподобие среднего числа.
Этот блок коэффициентов обладает интересным свойством, заключающимся в том, что он отделяет высокочастотные компоненты от низкочастотных.
На изображении большая часть энергии будет сосредоточена на более низких частотах, поэтому если мы трансформируем изображение в его частотные компоненты и отбросим более высокие частотные коэффициенты, мы можем уменьшить объем данных необходимо описать изображение, не жертвуя качеством сижком сильно.
частота означает, насколько быстро меняется сигнал
Давайте попробуем применить знания, которые мы получили в тесте, трансформируя исходное изображение в его частоту (блок коэффициентов), используя ДСТ, а затем отбрасывая часть наименее важных коэффициентов.
Сначала мы конвертируем его в частотную область.
Далее мы отбрасываем часть (67%) коэффициентов, в основном нижнюю правую часть.
Наконец, мы восстанавливаем изображение из этого отброшенного блока коэффициентов (помните, оно должно быть обратимым) и сравниваем его с оригиналом.
Как видно, оно похоже на исходное изображение, но в нем есть много отличий от оригинала. Мы выбросили 67,1875% и все же смогли получить хотя бы что-то похожее на оригинал. Мы могли бы более разумно отбросить коэффициенты, чтобы получить лучшее качество изображения, но это следующая тема.
Каждый коэффициент формируется с использованием всех пикселей
Важно отметить, что каждый коэффициент не отображается напрямую на один пиксель, а представляет собой взвешенную сумму всех пикселей. Этот удивительный график показывает, как рассчитывается первый и второй коэффициент с использованием весов, уникальных для каждого индекса.
Вы также можете попытаться визуализировать ДСТ, взглянув на это изображение. Например, вот создается символ "A" с помощю каждого веса коэффициента.
! [] (https://upload.wikimedia.org/wikipedia/commons/5/5e/Idct-animation.gif)
Вы можете поигратся с ДСТ трансформациями тут.
Когда мы выбрасываем коэффициенты, на последнем шаге (трансформация) мы делали некоторую форму квантования. На этом этапе мы решили потерять информацию или, проще говоря, мы квантовали коэффициенты для достижения сжатия.
Как мы можем квантовать блок коэффициентов? Одним простым методом было бы равномерное квантование, где мы берем блок, делим его на одно значение (10) и округляем это значение.
Как мы можем обратить (переквантовать) этот блок коэффициентов? Мы можем умножить одним и тем же значением (10), которым мы разделили.
Этот подход не лучший, потому что он не учитывает важность каждого коэффициента. Мы могли бы использовать матрицу квантователей вместо одного значения, эта матрица может использовать свойство ДСТ, квантовая больше нижнего правого и меньше верхнего левого, JPEG использует аналогичный подход. Вы можете проверить исходный код, чтобы увидеть эту матрицу.
Вы можете поиграть с [квантованием] (/ dct_experiences.ipynb).
После того как мы квантовали данные (блоки изображения / фрагменты / кадры), мы все еще можем сжимать их без потерь. Существует много способов (алгоритмов) сжатия данных. Мы собираемся кратко познакомиться с некоторыми из них, для более глубокого понимания вы можете прочитать удивительную книгу Понимание сжатия: сжатие данных для современных разработчиков.
Предположим, у нас есть поток символов: a, e, r и t, и их вероятность (от 0 до 1) представлена этой таблицей.
a | e | r | t | |
---|---|---|---|---|
вероятность | 0.3 | 0.3 | 0.2 | 0.2 |
Мы можем присвоить уникальные коды (предпочтительно маленькие) наиболее вероятным, а более крупные коды наименее вероятным.
a | e | r | t | |
---|---|---|---|---|
вероятность | 0.3 | 0.3 | 0.2 | 0.2 |
код | 0 | 10 | 110 | 1110 |
Давайте сожмем поток eat, предполагая что мы потратим 8 битов на каждый символ, то в общей сложности мы тратим 24 бита без какого-либо сжатия. Но в случае замены каждого символа на его код мы можем сэкономить место.
Первый шаг заключается в кодировании символа e, который равен 10
, второй символ а добавляется что бы получить [10][0]
и, наконец, третий символ t, который делает наш окончательный сжатый поток битов равным [10][0][1110]
или 1001110
, которому нужно только 7 битов (т.е 3.4 раза меньше места, чем оригинальный поток).
Обратите внимание, что каждый код должен иметь уникальный префикс код Хаффман может помочь вам найти эти номера. Хотя у этого метода есть проблемы, есть видеокодеки, которые все еще предлагают его, и это алгоритм для многих приложений, который требует сжатия.
Кодер и декодер должны знать таблицу символов с ее кодом, поэтому вам также необходимо отправлять таблицу.
Давай скажем что у нас есть поток символов: a, e, r, s, t и их вероятность показана на таблице:
a | e | r | s | t | |
---|---|---|---|---|---|
вероятность | 0.3 | 0.3 | 0.15 | 0.05 | 0.2 |
Зная об этой таблице, мы можем построить области со всеми возможными символами, отсортированные теми которые появляются чаще всего.
Теперь давайте закодируем поток eat, мы выбираем первый символ a, который находится в новом поддиапазоне 0.3 до 0.6 (но не включен), и мы берем этот поддиапазон и снова разделяем его, используя те же пропорции, которые использовались ранее, но в этом новом диапазоне.
Давайте продолжим кодировать наш поток eat, мы выберем второй символ a, который находится в новом поддиапазоне 0.3 до 0.39, а затем мы берем наш последний символ t, повторяя процесс что бы получить последний поддиапазон 0.354 до 0.372.
Нам просто нужно выбрать число в последнем поддиапазоне 0.354 до 0.372, давайте выберем 0.36, но мы можем выбрать любое число в этом поддиапазоне. С только этим номером мы сможем восстановить наш оригинальный поток eat. Если подумать об этом, мы как бы нарисовали линию в пределах диапазонов для кодирования нашего потока.
Обратный процесс (т.е. декодирование) одинаково прост, с нашим числом 0,36 и нашим исходным диапазоном мы можем запустить тот же процесс, но теперь используя это число, чтобы показать поток, закодированный за этим номером.
С первым диапазоном мы заметили что наше число соответствует срезу, поэтому это наш первый символ, теперь мы снова разбиваем этот поддиапазон, выполняя тот же процесс что и раньше, и мы можем заметить, что 0.36 соответствует символу a и после того, как мы повторим процесс, мы подходим к последнему символу t (формируя наш оригинальный кодированный поток eat).
Кодер и декодер должны знать таблицу вероятностей символов, поэтому вам необходимо отправлять таблицу.
Не плохо, правда? Люди чертовски умны, чтобы придумать такое решение, некоторые видеокодеки используют эту технику (или, по крайней мере, предлагают ее в качестве опции).
Идея состоит в том, чтобы сжать без потерь квантованный поток битов, наверняка в этой статье отсутствуют тонны деталей, причин, компромиссов и т. Д. Но вы должны узнать больше в качестве разработчика. Более новые кодеки пытаются использовать различные алгоритмы энтропийного кодирования, наподобие ANS.
Вы можете создать два потока, один с CABAC and другой с CAVLC and сравнить время занятое для их создание, а так же конечный размер файла.
После того, как мы выполнили все эти шаги, нам нужно упаковать сжатые кадры и контекст к этим шагам. Нам необходимо сообщить декодеру о решениях, принятых кодером, например битовая глубина, цветовое пространство, разрешение, информация о предсказаниях (векторы движения, направление внутреннего предсказания), профиль, уровень, частота кадров, тип кадра, номер кадра и многое другое.
Мы поверхностно изучим поток битов H.264. Наш первый шаг - создать минимальный битовый поток H.264 *, что мы можем сделать это с помощью нашего собственного репозитория и ffmpeg.
./s/ffmpeg -i /files/i/minimal.png -pix_fmt yuv420p /files/v/minimal_yuv420.h264
* ffmpeg по умолчанию добавляет все параметры кодирования в виде SEI NAL - вскоре мы определим, что такое NAL.
Эта команда сгенерирует необработанный поток битов h264 с одиночным кадром, 64x64, с цветовым пространством yuv420 и с использованием следующего изображения в качестве кадра.
Стандарт AVC (H.264) определяет, что информация будет отправляться в макро кадрах (в смысле сети), называемых NAL (Сетевой Уровень Aбстракции). Основной целью NAL является обеспечение "дружественного к сети" представления видео, этот стандарт должен работать на телевизорах (на основе потоков), в Интернете (на основе пакетов) и т.д.
Существует маркер синхронизации для определения границ единиц NAL. Каждый маркер синхронизации содержит значение 0x00 0x00 0x01
, за исключением самого первого, который является 0x00 0x00 0x00 0x01
. Если мы запустим hexdump в сгенерированном потоке битов h264, мы сможем идентифицировать как минимум три NAL в начале файла.
Как мы уже говорили, декодеру надо знать не только данные изображения, но также детали видео, фрейма, цвета, используемые параметры и другие. Первый байт каждого NAL определяет его категорию и тип.
NAL type id | Description |
---|---|
0 | Undefined |
1 | Coded slice of a non-IDR picture |
2 | Coded slice data partition A |
3 | Coded slice data partition B |
4 | Coded slice data partition C |
5 | IDR Coded slice of an IDR picture |
6 | SEI Supplemental enhancement information |
7 | SPS Sequence parameter set |
8 | PPS Picture parameter set |
9 | Access unit delimiter |
10 | End of sequence |
11 | End of stream |
... | ... |
Обычно первый NAL битового потока представляет собой SPS, этот тип NAL отвечает за информирование общих переменных кодирования, таких как профиль, уровень, разрешение и другие.
Если мы пропустим первый маркер синхронизации, мы можем декодировать первый байт, чтобы узнать, какой тип NAL является первым.
Например, первый байт после маркера синхронизации равен 01100111
, где первый бит (0
) находится в поле forbidden_zero_bit, следующие 2 бита (11
) сообщают нам поле nal_ref_idc который указывает если этот является NAL опорным полем или нет, а остальные 5 битов (00111
) информируют нас о поле nal_unit_type, в данном случае это SPS (7) единица NAL.
Второй байт (binary = 01100100, hex = 0x64, dec = 100
) SPS NAL - это поле profile_idc, которое показывает профиль, который использовал кодировщик, в этом случае мы использовали ограниченный высокий профиль, это высокий профиль без поддержки B (двунаправленных) срезов.
Когда мы читаем спецификацию потока битов H.264 для SPS NAL, мы найдем много значений, например, parameter name, category и description, давайте посмотрим на pic_width_in_mbs_minus_1
и поля pic_height_in_map_units_minus_1
.
Parameter name | Category | Description |
---|---|---|
pic_width_in_mbs_minus_1 | 0 | ue(v) |
pic_height_in_map_units_minus_1 | 0 | ue(v) |
ue(v): целое число без знака Exp-Golomb-кодированный
Если мы немного посчитаем значения этих полей, мы получим разрешение. Мы можем представить 1920 x 1080
, используя pic_width_in_mbs_minus_1
со значением 119 ((119 + 1) * macroblock_size = 120 * 16 = 1920)
, опять же экономя место, вместо того, чтобы кодировать 1920
, как мы это сделали с 119
.
Если мы продолжим проверять наше созданное видео в двоичном виде (например: xxd -b -c 11 v/minimal_yuv420.h264
), мы можем перейти к последнему NAL, который является самим кадром.
Мы можем видеть его первые 6 байтовых значений: 01100101 10001000 10000100 00000000 00100001 11111111
. Поскольку мы уже знаем, что первый байт говорит нам о том, что это за тип NAL, в данном случае (00101
) это IDR Slice (5), и мы можем проверить его:
Используя информацию спецификации, мы можем декодировать, какой тип слайса (slice_type), номер кадра (frame_num) среди других важных полей.
Чтобы получить значения некоторых полей (ue (v), me (v), se (v) или te (v)
)), нам нужно декодировать его, используя специальный декодер под названием Exponential-Golomb, этот метод очень эффективен для кодирования значений переменных, главным образом, когда существует много значений по умолчанию.
Значения slice_type и frame_num этого видео равны 7 (I срез) и 0 (первый кадр).
Мы можем видеть поток битов как протокол, и если вы хотите или вам надо узнать больше об этом потоке битов, обратитесь к спецификации МСЭ H.264 Вот макросхема, которая показывает, где находятся данные изображения (сжатые YUV).
Мы можем исследовать другие битовые потоки, такие как битовый поток VP9, H.265 (HEVC) или даже наш новый лучший друг AV1 поток битов, они все похожи? Нет, но как только вы выучите один, вы легко сможете понять другие.
Мы можем создать однокадровое видео и использовать mediainfo для проверки потока битов H.264. Вы даже можете увидеть исходный код, который анализирует битовый поток h264 (AVC).
Мы также можем использовать Intel Video Pro Analyzer, который платный, хотя существует бесплатная пробная версия, которая ограничивает вас только первые 10 кадров (которых для учебных целей должно быть достаточно).
Мы заметим, что многие из современных кодеков используют ту же модель, которую мы изучили. Можно посмотреть на блок-схему видеокодека Thor и увидеть что она содержит все шаги, которые мы изучали. Идея состоит в том, что теперь вы в состоянии лучше понять инновации и документы в этой области.
Ранее мы рассчитывали, что нам потребуется 139 ГБ дискового пространства для хранения видеофайла одного часа в длинне при разрешении 720p и 30 к/с. С помощю методов которые описаны здесь, такие как меж и внутреннее предсказание, трансформации, квантование, энтропийное кодирование и другие, то же видео воспринимаемого качества можно сжать до только 367.82 МБ.
Мы решили использовать 0.031 бит на пиксель на основе примера видео, представленного здесь.
Зная больше о том, как работают кодеки, легко понять как новые кодеки способны обеспечивать более высокое разрешение с меньшим количеством битов.
Мы сравним AVC и HEVC, помня что это почти всегда компромисс между большим количеством циклов ЦП (сложность) и степенью сжатия.
HEVC имеет больше количество разделов (и подразделов), которые так же и больше в размере чем AVC, больше направлений внутреннего предсказания, улучшенное энтропийное кодирование и более, все эти улучшения дали H.265 способность сжимать на 50% больше, чем H.264.
[TODO]
[TODO]
Мы можем использовать простую систему токенов для защиты контента. Запрос видео без токена будет запрещен CDN-ом, в то время как пользователь с действительным токеном может воспроизводить контент. Он работает почти так же, как и большинство систем веб-аутентификации.
Использую эту систему токенов позволяет пользователю загружать видео и распространять его. Затем можно использовать систему DRM (управление цифровыми правами), чтобы избежать этого.
В реальных производственных системах люди часто используют оба метода для обеспечения авторизации и аутентификации.
- FPS - FairPlay Streaming
- PR - PlayReady
- WV - Widevine
DRM зто система цифровых прав, это способ обеспечить защиту авторских прав на цифровых материалов - например, цифровое видео и аудио. Хотя он используется во многих местах он не является общепринятым.
Создатель контента (в основном, студии) хотят защитить свою интеллектуальную собственность от копирования, чтобы предотвратить несанкционированное распространение цифрового контента.
Мы собираемся описать абстрактную и общую форму DRM в очень упрощенном виде.
Учитывая контент C1 (т.е. потоковое видео hls или dash), с проигрывателем P1 (т.е. shaka-clappr, exo-player или ios) в устройстве D1 (т.е. смартфоне , Телевизор, планшет или настольный компьютер / ноутбук) с использованием DRM системы DRM1 (widevine, playready или FairPlay).
Контент C1 зашифрован с помощью симметричного ключа K1 от системы DRM1, генерируя зашифрованный контент C'1.
Проигрыватель P1 устройства D1 имеет два ключа (асимметричные): закрытый ключ PRK1 (этот ключ защищен 1 и известен только D1) и открытый ключ PUK1.
** 1 </ sup> защищен **: эта защита может быть ** с помощью аппаратного обеспечения **, например, этот ключ может храниться в специальном (только для чтения) чипе, который работает как [черный box] (https://en.wikipedia.org/wiki/Black_box), чтобы обеспечить расшифровку, или ** с помощью программного обеспечения ** (менее безопасно), система DRM предоставляет средства, чтобы узнать, какой тип защиты имеет данное устройство.
Когда ** игрок P1 хочет воспроизвести ** контент ** C'1 **, он должен иметь дело с ** DRM-системой DRM1 **, предоставив свой открытый ключ ** PUK1 **. DRM-система DRM1 возвращает ** ключ K1 в зашифрованном виде ** с открытым ключом клиента ** PUK1 **. Теоретически, этот ответ - это то, что ** только D1 способен расшифровать **.
K1P1D1 = enc (K1, PUK1)
P1 использует свою локальную систему DRM (это может быть SOC, специализированное аппаратное или программное обеспечение), эта система может дешифровать контент, и используя свой закрытый ключ PRK1, может расшифровать симметричный ключ K1 от K1P1D1 и воспроизвести C'1. В лучшем случае ключи не выставляются через ОЗУ.
``, K1 = dec (K1P1D1, PRK1)
P1.play (dec (C'1, K1)) ``,
Убедитесь, что у вас установлен docker и просто запустите ./s/ start_jupyter.sh
и следуйте инструкциям на терминале.
- DEMUXED - вы можете проверить последние 2 презентации..
Здесь самый богатый контент, вся информация которую мы видели в этом тексте, была извлечена, основана или вдохновлена. Вы можете углубить свои знания с помощью этих удивительных ссылок, книг, видео и т. д.
Онлайн курсы и учебные пособия:
- https://www.coursera.org/learn/digital/
- https://people.xiph.org/~tterribe/pubs/lca2012/auckland/intro_to_video1.pdf
- https://xiph.org/video/vid1.shtml
- https://xiph.org/video/vid2.shtml
- http://slhck.info/ffmpeg-encoding-course
- http://www.cambridgeincolour.com/tutorials/camera-sensors.htm
- http://www.slideshare.net/vcodex/a-short-history-of-video-coding
- http://www.slideshare.net/vcodex/introduction-to-video-compression-13394338
- https://developer.android.com/guide/topics/media/media-formats.html
- http://www.slideshare.net/MadhawaKasun/audio-compression-23398426
- http://inst.eecs.berkeley.edu/~ee290t/sp04/lectures/02-Motion_Compensation_girod.pdf
Books:
- https://www.amazon.com/Understanding-Compression-Data-Modern-Developers/dp/1491961538/ref=sr_1_1?s=books&ie=UTF8&qid=1486395327&sr=1-1
- https://www.amazon.com/H-264-Advanced-Video-Compression-Standard/dp/0470516925
- https://www.amazon.com/Practical-Guide-Video-Audio-Compression/dp/0240806301/ref=sr_1_3?s=books&ie=UTF8&qid=1486396914&sr=1-3&keywords=A+PRACTICAL+GUIDE+TO+VIDEO+AUDIO
- https://www.amazon.com/Video-Encoding-Numbers-Eliminate-Guesswork/dp/0998453005/ref=sr_1_1?s=books&ie=UTF8&qid=1486396940&sr=1-1&keywords=jan+ozer
Onboarding material:
- https://github.com/Eyevinn/streaming-onboarding
- https://howvideo.works/
- https://www.aws.training/Details/eLearning?id=17775
- https://www.aws.training/Details/eLearning?id=17887
- https://www.aws.training/Details/Video?id=24750
Bitstream Specifications:
- http://www.itu.int/rec/T-REC-H.264-201610-I
- http://www.itu.int/ITU-T/recommendations/rec.aspx?rec=12904&lang=en
- https://storage.googleapis.com/downloads.webmproject.org/docs/vp9/vp9-bitstream-specification-v0.6-20160331-draft.pdf
- http://iphome.hhi.de/wiegand/assets/pdfs/2012_12_IEEE-HEVC-Overview.pdf
- http://phenix.int-evry.fr/jct/doc_end_user/current_document.php?id=7243
- http://gentlelogic.blogspot.com.br/2011/11/