Содержание статьи +
- TL;DR
- Зачем это нужно
- Что значит «inter» и одна большая идея
- Чем inter-frame отличается от intra-frame
- Типы кадров: I, P и B
- Оценка движения: поиск, который делает всю работу
- Пошаговый пример: от поиска к вектору движения и стоимости в байтах
- Как современные кодеки расширяют базовый рецепт
- Что стоит на энкодере и на декодере
- Типичная ошибка: считать «motion-estimation accuracy» перцептивной точностью
- Где находится Фора Софт
- Ключевые выводы
- Что почитать дальше
TL;DR
Межкадровое кодирование (inter-frame coding) сжимает видеокадр, описывая, как он изменился по сравнению с уже декодированными кадрами. Энкодер для каждого блока нового кадра ищет наиболее похожий участок в опорном кадре, сохраняя лишь небольшой указатель – motion vector – и небольшой residual там, где совпадение неполное. Эта одна идея обеспечивает около 90% всей экономии битов в типичном потоковом видео: P-кадр занимает примерно 50% от размера I-кадра, B-кадр – около 25%, а современные кодеки достигают ещё большей эффективности благодаря affine warps, optical flow и compound prediction. Поймёте межкадровое кодирование – поймёте, почему часовая серия Netflix умещается в гигабайт, а не в сто.
Зачем это нужно
Настройки GOP, количество B-кадров, число reference frames и пресет motion search напрямую влияют на битрейт, задержку, нагрузку на CPU и визуальное качество ваших стримов. Продакт-менеджер, понимающий, что «preset slower» удваивает время кодирования в основном за счёт более сложного motion search, принимает более обоснованные решения о стоимости. Основатель, осознающий, что низколатентный стриминг исключает использование B-кадров, не удивится, обнаружив, что WebRTC-архитектура расходует больше битов, чем HLS, при одинаковом качестве. Операционный лидер, знающий, что панорамная съёмка снижает эффективность сжатия, сможет честно провести демо и бенчмарки. Тридцать минут, потраченных на освоение этой ментальной модели, окупаются каждой беседой с инженерами и каждой строкой в datasheet поставщика.
Что значит «inter» и одна большая идея
Латинское inter означает «между». Inter-Frame Coding – это часть видеокодека, сжимающая один кадр с опорой на другие кадры, уже декодированные приёмником. Противоположный подход – intra-frame coding, при котором кадр сжимается исключительно на основе пикселей, содержащихся в нём самом.
Главная идея межкадрового кодирования – в том, что соседние кадры реального видео почти идентичны. Два кадра, снятые с интервалом в 1/30 секунды, обычно отличаются лишь несколькими движущимися объектами на практически неизменном фоне. Описывать второй кадр полностью, если первый уже передал декодеру 95% информации, – это расточительство.
Inter-frame coding избавляется от этого расточительства. Вместо того чтобы описывать кадр 2 с нуля, энкодер говорит декодеру: «Возьми участок в координатах (320, 480) из кадра 1, сдвинь его на (+3, −1) пикселя и вставь по тем же координатам в кадре 2. Теперь исправь его небольшим блоком ошибки». Сдвиг (+3, −1) – это motion vector. Небольшой блок ошибки – это residual. Вместе они занимают несколько байт, тогда как полное описание кадра потребовало бы килобайты.
Умножьте экономию на каждый блок в каждом неключевом кадре каждого видео – и получите двигатель, построивший весь стриминговый интернет.
Чем inter-frame отличается от intra-frame
У обоих пайплайнов одинаковый бэкенд – трансформация, квантование, энтропийное кодирование – но фронтенды различаются. Intra-кадр предсказывает блок на основе соседей в том же кадре. Inter-кадр предсказывает блок на основе патча из другого кадра. Та же машина, разные опорные данные.
Они сосуществуют внутри каждого видеокодека, потому что эффективны на разных типах контента. Intra-кодирование выигрывает на первом кадре, при резких сменах сцены и там, где предыдущий кадр ненадёжен – например, при occlusion, появлении новых объектов или резких перепадах освещения. Inter-кодирование эффективнее на длительных участках без таких изменений – а таких в видео большинство. Типичный 2-секундный HLS-сегмент H.264 при 24 кадрах в секунду содержит примерно 1 ключевой кадр и 47 межкадровых; на межкадровое кодирование приходится основная часть сэкономленных байт.
Типы кадров: I, P и B
Реальный видеопоток содержит три типа кадров. Их названия пришли из стандарта MPEG-1 (1993) и прижились.
I-кадр (intra-кодированный) – полноценное статическое изображение, аналогичное JPEG. Может декодироваться независимо. Любой видеопоток требует I-кадров как точек старта и восстановления. I-кадры занимают много места.
P-кадр (predicted) кодируется с использованием предсказания на основе одного или нескольких предыдущих опорных кадров. Энкодер копирует фрагменты из прошлого, применяет векторы движения и добавляет остаточные данные. Обычно P-кадр занимает около 50% объёма I-кадра при том же содержании. Точное значение сильно зависит от сложности сцены, но 50% – это правильный порядок величины.
B-кадр (bi-predicted) кодируется с использованием предсказания как из прошлых, так и из будущих опорных кадров. Энкодер может брать данные из любого направления и даже усреднять два блока. B-кадры – самые эффективные с точки зрения сжатия: обычно их размер составляет около 25% от размера I-кадра. Платой за это становятся буфер декодера и задержка: чтобы воспроизвести B-кадр, зависящий от будущего кадра, декодеру нужно дождаться его получения.
Закрепим цифрами. Возьмём 2-секундный HLS-сегмент 1080p24, закодированный с помощью x264 на пресете «veryslow», с закрытой группой кадров (GOP) длиной 48 кадров и B-паттерном IBBPBBPBBPBB…. Такой сегмент содержит 1 I-кадр, 15 P-кадров и 32 B-кадра.
Допустим, I-кадр занимает 200 кбит, P-кадр в среднем – 100 кбит, B-кадр в среднем – 50 кбит. Тогда:
total = 1 × 200 + 15 × 100 + 32 × 50
total = 200 + 1500 + 1600
total = 3300 кбит за 2 секунды
битрейт = 1650 кбит/с ≈ 1.65 MbpsПовторим тот же сегмент с отключёнными B-кадрами – обычное дело в low-latency live-стримах – и энкодеру придётся заменять их P-кадрами. Каждый старый B-слот превращается в P-кадр объёмом 100 кбит.
total = 1 × 200 + 47 × 100
total = 200 + 4700
total = 4900 кбит за 2 секунды
битрейт = 2450 кбит/с ≈ 2.45 MbpsОтказ от B-кадров обходился примерно в 48% дополнительного битрейта при неизменном качестве. Это и есть цена, которую приходится платить за снижение задержки в пайплайнах WebRTC или LL-HLS.
Оценка движения: поиск, который делает всю работу
Задача энкодера – для каждого блока текущего кадра найти в опорном кадре участок, наиболее ему соответствующий. Этот процесс называют motion estimation, часто сокращают до ME. Результатом motion estimation является motion vector для каждого блока.
Motion vector – это просто два числа: горизонтальный и вертикальный сдвиг, измеренные в пикселях (или sub-pixel единицах). Вектор (+3, −1) означает: «возьми патч из тех же координат опорного кадра, сдвинь его на 3 пикселя вправо и на 1 вверх – и используй как предсказание для текущего блока».
Motion estimation – самый затратный этап в видеокодере. Множество исследований показывают, что он занимает 60–80% от общего времени кодирования. Каждая сэкономленная минута работы CPU даёт более быстрые транскоды, снижает облачные расходы и позволяет запускать больше стримов на одном сервере. Каждый сэкономленный байт в motion vector и residual – это байт, который не придётся скачивать пользователю.
Шаг 1 – выбрать область поиска
Энкодер не может позволить себе сравнивать текущий блок со всеми возможными патчами во всём опорном кадре. В кадре 1080p насчитывается около 2 миллионов патчей размером 16×16; умножив это на 8000 блоков в кадре, получаем 16 миллиардов сравнений на кадр. При частоте 30 кадров в секунду это составляет полтриллиона сравнений в секунду – что невозможно для CPU.
Поэтому энкодер ограничивает поиск небольшим окном вокруг исходных координат блока в опорном кадре – это search range, или merange в терминах x264/x265. Типичные значения: 16, 24 или 32 пикселя. Внутри этого окна энкодер рассматривает кандидатные патчи и оценивает каждый из них.
Шаг 2 – оценка кандидатов с помощью функции стоимости
Каждый кандидатный патч оценивается по степени соответствия текущему блоку. Две метрики здесь играют ключевую роль.
Sum of Absolute Differences (SAD) вычисляет абсолютные разницы между каждой парой пикселей и суммирует их. Быстрый, целочисленный метод – дефолтный выбор для большинства кодировщиков в реальном времени.
Sum of Squared Differences (SSD) возводит каждую разницу в квадрат перед суммированием. Лучше коррелирует с восприятием качества, но требует больше вычислительных ресурсов. Пресеты повышенного качества используют SSD или гибридную метрику SATD, которая обрабатывает блок разностей с помощью небольшого преобразования Адамара, чтобы учесть перцептивные частоты.
Шаг 3 – паттерны поиска, не проверяющие каждого кандидата
Даже в окне размером 32 пикселя полный перебор – так называемый full search или exhaustive search – оказывается слишком медленным для работы в реальном времени. В таком окне насчитывается около 4225 возможных позиций. Современные кодеки используют умные стратегии, проверяющие лишь небольшое подмножество вариантов и быстро сходящиеся к хорошему решению.
Паттерны, которые встречаются в документации энкодеров:
Diamond search основан на предсказании и проверяет четыре кардинальных соседа плюс центр, затем переходит к победителю и повторяет процесс. Дешёвый и быстрый метод; используется по умолчанию в пресете me=dia в x264 и является нижней планкой для real-time кодирования.
Hexagon search использует кольцо из шести точек вместо креста из четырёх. Шестиугольный паттерн покрывает больше направлений за один шаг и сходится к более качественным минимумам, чем diamond. Это значение по умолчанию в x264 и x265 (me=hex) и является разумным компромиссом между скоростью и качеством.
Uneven Multi-Hexagon (UMH) сначала выполняет кросс-поиск, чтобы обнаружить крупное трансляционное движение, затем применяет серию шестиугольников с уменьшающимся радиусом и завершает процесс diamond refinement. UMH обнаруживает более быстрое движение, чем простой hexagon, и обеспечивает прирост около +0.1 dB PSNR на типичном эталонном наборе – при увеличении времени кодирования на 30–40%.
Enhanced Predictive Zonal Search (EPZS) формирует начальное предсказание на основе векторов движения пространственных и временных соседей – того же блока в предыдущем кадре, блока слева и блока сверху – и осуществляет поиск только в их окрестностях. Отлично справляется с плавными движениями, например, при панорамировании; широко используется в облачных транскодерах.
Полный перебор (также называемый исчерпывающим поиском, me=esa и me=tesa в x264) проверяет каждую возможную позицию. Применяется исключительно для placebo-архивных кодировок; на практике UMH уступает ему на доли децибела при значительно меньших затратах.
Практическое правило в x264: me=hex – для live-трансляций и быстрых пресетов, me=umh – для VOD, me=esa/tesa – для пресетов «placebo», а в продакшене их использовать не стоит.
Шаг 4 – уточнение на уровне субпикселей
Лучшее совпадение по целым пикселям редко оказывается истинным минимумом. Реальное движение непрерывно и не привязано к пиксельной сетке – небольшой дополнительный сдвиг почти всегда уменьшает остаточную ошибку.
Поэтому после оценки движения с точностью до целого пикселя энкодер выполняет уточнение с субпиксельной точностью. Он интерполирует опорный кадр на более мелкую сетку – с шагом в полпикселя, четверть пикселя или одну восьмую пикселя – и в небольшой окрестности найденного на целой сетке кандидата ищет лучшее совпадение. Для интерполяции используется небольшой фильтр (обычно 6- или 8-таповый сепарабельный), а для поиска – крошечный ромб.
Выигрыш заметный. Half-pixel motion vectors дали MPEG-2 около 1 дБ по сравнению с integer-only. Quarter-pixel – ещё +0,5–0,8 дБ. AV1 и VVC поддерживают eighth-pixel accuracy для некоторых типов блоков. Биты на более точный вектор почти бесплатны; биты, сэкономленные в residual, – нет.
Пошаговый пример: от поиска к вектору движения и стоимости в байтах
Конкретный разбор поможет закрепить модель. Представьте блок размером 16×16 пикселей в текущем кадре, который попадает на часть пиджака мужчины. В опорном кадре, сделанном 1/30 секунды назад, тот же пиджак сместился на три пикселя вправо и на один пиксель вниз – камера панорамировала влево и вверх.
Энкодер выбирает диапазон поиска 16 пикселей, центрированный на исходных координатах блока в опорном кадре. Выполняет hexagon search и находит кандидата с целочисленной точностью (+3, −1) с SAD = 320. Уточняет до полупиксельной точности – SAD снижается до 210 в точке (+3.0, −1.0), так как целочисленный кандидат уже находился на сетке. Дальнейшее уточнение до четвертьпиксельной точности даёт SAD = 198 в точке (+3.0, −1.25) – истинное движение оказалось чуть ниже целочисленной сетки.
Энкодер сохраняет для блока три порции информации. Во-первых – вектор движения (+3.00, −1.25) в единицах quarter-pixel, закодированный как разность с предсказанным вектором (медианой векторов трёх соседних блоков). Во-вторых – один бит, указывающий, что блок использует интер-предсказание с предыдущим кадром в качестве опорного. В-третьих – residual: блок 16×16 разностей между текущим блоком и сдвинутым опорным патчем. Residual мал: SAD = 198 соответствует средней ошибке около 0,8 уровня на пиксель – после трансформации и квантования почти все коэффициенты обнуляются. В итоге блок занимает порядка 20 бит в bitstream.
Сравните с intra-кодированием того же блока – около 600–800 бит. Inter-кодирование обходится примерно в 30 раз дешевле.
Как современные кодеки расширяют базовый рецепт
Описанный однонаправленный трансляционный поиск – это базовая технология H.261 / MPEG-2. Каждое последующее поколение кодеков добавляло инструменты, способные улавливать то, что базовая технология не может описать. Шесть таких инструментов обеспечивают основную часть выигрыша в эффективности.
Переменные размеры блоков
Целый блок 16×16 с одним motion vector – слишком грубый, если он охватывает два объекта, движущихся по-разному. H.264 ввёл разбиения до 4×4. H.265 добавил квадродерево от 64×64 до 4×4. AV1 начинает с суперблока 128×128. VVC использует 128×128 CTU с бинарными, тернарными и квадро-сплитами до 4×4. Меньшие блоки требуют больше битов на векторы, но точнее отслеживают границы движения.
Несколько систем отсчёта
Зачем заставлять энкодер предсказывать по непосредственно предыдущему кадру? Возможно, блок лучше всего соответствует патчу из кадра, который был три кадра назад – например, потому что движущийся передний план временно его закрыл. H.264 ввёл многокадровое предсказание с опорой на до 16 кадров. AV1 поддерживает семь опорных кадров, разделённых на две категории: прошлые (LAST, LAST2, LAST3, GOLDEN) и будущие (BWDREF, ALTREF, ALTREF2). VVC позволяет использовать до 15 опорных кадров. Выбор опорного кадра осуществляется на уровне блока; наибольший выигрыш достигается при периодическом движении и коротких скрытиях (occlusions).
B-кадры и составное предсказание
B-кадр может использовать для предсказания каждого блока один или оба референса – прошлый и будущий – и усреднять их. Двунаправленное усреднение сглаживает шум и уменьшает остаточную ошибку. AV1 расширяет этот подход до compound prediction: wedge-основанной, модулированной разностью и взвешенной по расстоянию комбинации двух предикторов – что позволяет описывать более сложные границы движения внутри одного блока.
Аффинное движение: вращение, масштабирование, зум
Одиночный motion vector описывает только перемещение. Он не учитывает вращение, масштабирование или перспективные искажения. В стандартах VVC и AV1 реализованы аффинные модели движения: вместо одного вектора на блок энкодер передаёт два или три вектора контрольных точек, а декодер вычисляет отдельный вектор для каждого 4×4-подблока с помощью интерполяции. В результате – эффективная обработка камерных зумов, dolly-съёмок, поворотов автомобилей и вращающихся логотипов с использованием лишь небольшой доли битов по сравнению с передачей независимого вектора для каждого подблока.
Warped и global motion (визитная карточка AV1)
AV1 находится между простой трансляционной ME и полной аффинной моделью. Глобальное движение задаёт одну аффинную модель на уровне кадра – это полезно, когда весь кадр подвергается единому преобразованию, например, при панорамировании или зуме камеры. Локальное искажённое движение вычисляет параметры warp на уровне блока, используя векторы движения соседних блоков, почти без дополнительных затрат на сигнализацию. Вместе эти инструменты эффективно кодируют длинные участки панорамирования и зума, на которых трансляционная ME тратит биты впустую.
Уточнение оптического потока (BDOF и DMVR в VVC)
VVC добавляет два инструмента уточнения на стороне декодера, которые улучшают грубый вектор движения без передачи дополнительных битов. Bi-Directional Optical Flow (BDOF) применяет коррекцию на основе оптического потока на уровне блоков 4×4, используя градиенты двух опорных фрагментов. Decoder-Side Motion Vector Refinement (DMVR) позволяет декодеру выполнить небольшое сопоставление блоков вокруг полученного вектора и использовать уточнённую позицию. Оба метода снижают стоимость передачи вектора движения: энкодер передаёт более грубый вектор, а дополнительную работу выполняет декодер.
Что стоит на энкодере и на декодере
Асимметрия межкадрового кодирования – одна из его недооценённых особенностей. Энкодер проделывает колоссальную работу, чтобы найти векторы движения; декодер лишь читает эти векторы и копирует фрагменты. Кодирование часового фильма в 4K HEVC занимает 15–60 минут на быстром сервере; декодирование того же фильма легко работает на пятилетнем смартфоне.
Эта асимметрия – то, что делает стриминговую экономику эффективной. Студия может потратить десять часов работы GPU на кодирование одной минуты мастер-ролика для Netflix и распределить эти затраты на сотни миллионов просмотров. А вот live-энкодер на спортивном мероприятии имеет лишь один шанс закодировать каждый кадр в реальном времени – поэтому в live-пресетах отключают B-кадры, уменьшают диапазон поиска и переходят на diamond/hexagon search.
Компромиссы каждого пресета:
| Параметр | Что контролирует | Влияние на битрейт | Влияние на время кодирования |
|---|---|---|---|
| Search range | Ширина окна поиска | Шире – ниже битрейт на быстром движении | Шире – квадратично медленнее |
| Search pattern | Какие позиции проверяются | Лучше паттерн – ниже битрейт | Лучше паттерн – в 2–10 раз медленнее |
| Sub-pixel depth | Half, quarter, eighth pixel | Тоньше – ниже битрейт | Каждый уровень ≈ ×1.5 |
| Reference frames | Сколько прошлых/будущих кадров | Больше – ниже битрейт, отдача падает | Больше – линейно медленнее |
| B-frame count | Сколько B между P | Больше B – ниже битрейт | Больше B – небольшой хит времени, большой декодер-буфер |
| Affine / warped motion | Включены ли неподвижные модели | Ниже битрейт на ротации/zoom | +5–15% времени |
Практический шпаргалка для x264 и x265 – в скачиваемом PDF.
Типичная ошибка: считать «motion-estimation accuracy» перцептивной точностью
Частое недопонимание между продактом и инженерами возникает вокруг слова «точность». Motion vector считается «точным», если он минимизирует функцию стоимости – обычно SAD, иногда SSD или SATD. Ни одна из этих функций не измеряет перцептивное качество так же, как это делают VMAF или SSIM.
В результате два вектора движения с одинаковым SAD могут давать заметно разное визуальное качество после квантования остатка на низких битрейтах. Энкодеры пытаются устранить этот разрыв с помощью rate-distortion optimisation (RDO): каждый кандидат оценивается по полной стоимости (motion vector + residual), а не только по остатку; при этом SATD-ориентированные поиски лучше учитывают перцептивные частоты. Более медленные пресеты выполняют больше RDO-циклов, быстрые – пропускают их. Если вы транслируете стрим с низким битрейтом и качество «блочит при движении», ответ редко в том, чтобы «увеличить битрейт». Чаще всего – «выберите более медленный пресет, чтобы энкодер тратил больше времени на RDO-циклы для каждого блока».
Где находится Фора Софт
Настройки межкадровой кодировки применяются ко всем продуктам, которые Фора Софт поставляла с 2005 года. В наших решениях для видеоконференций и WebRTC жёсткие требования к задержкам вынуждают использовать пайплайн без B-кадров и ограниченные диапазоны поиска, что мы компенсируем продуманными битрейт-лестницами и селективной коррекцией ошибок вперёд. В сборках для OTT и интернет-ТВ мы настраиваем индивидуальные битрейт-лестницы под каждый контент, используя полный набор инструментов компенсации движения в HEVC и AV1, что позволяет экономить 25–40% трафика CDN при неизменном VMAF. В проектах видеонаблюдения длинные статичные сцены дают возможность использовать очень длинные GOP и вставлять ключевые кадры адаптивно по обнаружению смены сцены. Наши разработки для e-learning, телемедицины и AR/VR используют тот же инструментарий, но с других сторон – данная статья обобщает десятилетие таких решений в продакшене.
Ключевые выводы
- Межкадровое кодирование заменяет полное описание кадра вектором движения плюс небольшим остатком, экономя основную часть байтов современного видео.
- P-кадры занимают около 50% объёма I-кадра, B-кадры – около 25%; отключение B-кадров обычно требует увеличения битрейта на 30–50%.
- Оценка движения занимает 60–80% времени работы энкодера и является главным фактором компромисса между скоростью и качеством.
- Выбор шаблона поиска (diamond, hexagon, UMH, full) и диапазона поиска определяют основную часть этих затрат.
- Современные кодеки расширяют набор инструментов за счёт multi-reference, affine, warped, global, optical-flow и compound prediction.
- Энкодер выполняет основную работу, а декодер просто копирует данные – именно эта асимметрия и лежит в основе экономики стриминга.