Содержание статьи +
- TL;DR
- Зачем это нужно
- Что значит «in-loop»
- Deblocking – сглаживание сетки
- Sample-Adaptive Offset (SAO) – мелкие правки повсюду
- Adaptive Loop Filter (ALF) – Wiener-фильтр внутри кодека
- CDEF – направленный «sharpener» от AV1
- Сквозной пример
- Сравнительная таблица
- Типичная ловушка – отключённый deblocking при транскоде
- Где в этом Фора Софт
- Главное
- Что почитать дальше
TL;DR
In-loop фильтрация – этап работы видеокодека, устраняющий артефакты блочного сжатия: видимую сетку 8×8 или 16×16 на границах блоков, «ringing»-ореол вокруг резких переходов и слабый шум на однородных участках. Она выполняется внутри цикла кодирования: и кодер, и декодер обязаны применять одни и те же фильтры в строгой последовательности – иначе опорные кадры перестанут совпадать, и изображение быстро начнёт «рассыпаться». Четыре фильтра охватывают почти всё, что используется в индустрии в 2026 году: deblocking, унаследованный от H.264 и улучшенный в HEVC; Sample-Adaptive Offset (SAO) и Adaptive Loop Filter (ALF), появившиеся в HEVC и развитые в VVC; а также Constrained Directional Enhancement Filter (CDEF), которым AV1 заменил SAO. Вместе они обеспечивают экономию битрейта на 5–12% при неизменном визуальном качестве – и именно благодаря им современный кодек при 2 Мбит/с выглядит не так, как H.264 2003 года.
Зачем это нужно
Если вы когда-нибудь видели низкобитрейтный стрим, на котором по лицу человека вдруг проступает сетка из квадратов 8×8 – вы видели именно тот failure mode, ради подавления которого существуют in-loop фильтры. Продакт-менеджер, знающий, что современный декодер применяет четыре пост-квантовых фильтра внутри цикла кодирования, перестанет считать «более мягкую» картинку худшей: это может быть нормальная работа deblocking-фильтра. Стриминг-инженер, различающий SAO и ALF, читает лог энкодера без догадок. Основатель, понимающий, почему AV1 отказался от SAO в пользу CDEF, увидит, почему у AV1-декодера в железе иной on-chip пайплайн фильтров, чем у HEVC. В этой статье мы разберём каждый фильтр, покажем арифметику на конкретном примере и завершим сравнением: что отдают разные кодеки и какой вклад это оказывает в битрейт.
Что значит «in-loop»
Любой современный кодек использует гибридную архитектуру: он предсказывает следующий блок по соседним блокам или по предыдущему кадру, преобразует остаток, квантует коэффициенты и энтропийно кодирует результат. Декодер выполняет эти шаги в обратном порядке, чтобы восстановить блок. Восстановление является приближённым, поскольку квантование намеренно отбрасывает часть информации. Эта ошибка приближения проявляется в виде видимых разрывов на границах блоков, слабых отголосков вокруг резких переходов и низкоамплитудного шума на однородных участках.
Очистить это можно двумя способами. Пост-фильтрация применяется после декодера и не влияет на предсказание следующего кадра. Она может быть агрессивной – от её результата ничто не зависит. In-loop фильтрация, напротив, работает внутри цикла предсказания. В качестве опорного кадра, на который кодер опирается при предсказании следующего P или B кадра, используется именно отфильтрованный кадр, а не исходный восстановленный. Поэтому каждый декодер в мире обязан применять один и тот же фильтр в строго определённом порядке: даже расхождение в один пиксель с любой стороны приводит к накоплению ошибки – drift, который нарастает с каждым кадром при компенсации движения.
In-loop фильтрация окупается, потому что более чистый опорный кадр улучшает motion estimation на следующем P-кадре. Остатки в последующих кадрах уменьшаются, на них требуется меньше бит, и эта экономия с лихвой покрывает затраты на сами фильтры. Вендорские бенчмарки, начиная с H.264, показывают 5–10% экономии битрейта при неизменном PSNR только за счёт deblocking, и ещё 1–4% дополнительно от каждого из SAO, ALF и CDEF там, где они поддерживаются.
Deblocking – сглаживание сетки
Первый фильтр, который применяет любой современный кодек, – это deblocking. Он устраняет артефакты блокирования: видимые скачки значений пикселей на границе двух закодированных блоков, возникающие из-за независимого квантования каждого блока. При низком битрейте скачок достигает 8–20 уровней яркости и прорисовывает сетку блоков по всему кадру.
Deblocking-фильтр анализирует каждую горизонтальную и вертикальную границу между блоками и определяет, насколько сильно сглаживать изображение через эту границу. При принятии решения учитываются три параметра: boundary strength (был ли один из соседних блоков закодирован как intra, отличаются ли векторы движения или опорные кадры с двух сторон?), активность на каждой стороне границы (текстурированные участки допускают более резкие переходы, чем однородные) и quantisation parameter (чем агрессивнее квантование, тем больше артефактов и тем сильнее усиливается фильтр с ростом QP). Само ядро фильтра короткое и симметричное: в H.264 использовался 4-таповый фильтр, затрагивающий до 2 пикселей с каждой стороны; в HEVC его расширили до 3 пикселей с каждой стороны на границах с высокой интенсивностью; в VVC – до 7 пикселей с каждой стороны на самых протяжённых границах блоков.
Пример с числами. Два соседних 4×4 luma-блока на плоской поверхности граничат по вертикальной линии. Четыре пикселя слева в одной строке – 148, 150, 151, 152; справа – 162, 161, 160, 159. На границе наблюдается скачок на 11 уровней яркости – он хорошо заметен на качественном мониторе. Фильтр deblocking применяет нормализованное симметричное ядро, которое сглаживает два пикселя на каждой стороне границы, приближая их к среднему значению:
- новый левый пограничный пиксель = round((152 × 1 + 162 × 3) / 4) = round(159,5) = 160
- новый правый пограничный пиксель = round((152 × 3 + 162 × 1) / 4) = round(154,5) = 155
11-уровневый скачок превращается в плавный 5-уровневый переход, а соседние пиксели с обеих сторон получают меньший импульс в том же направлении. На выходе получается визуально непрерывная граница, а не ступенька. Важно: фильтр консервативен – он отступает, если на любой стороне наблюдается высокая активность, и поэтому никогда не превращает реальную текстуру в кашу.
Deblocking – самый дешёвый из четырёх фильтров. Он затрагивает только пиксели у границы блока, использует короткое ядро и принимает локальные решения. По публикациям HEVC и AV1 типичная нагрузка на декодер при deblocking составляет 1–2% от общего числа циклов декодирования, а экономия битрейта – 5–10%. Это классический пример «дешёвой сделки» в современном видеокодировании.
Sample-Adaptive Offset (SAO) – мелкие правки повсюду
После удаления блоковых артефактов в HEVC и VVC применяется Sample-Adaptive Offset (SAO). Цель SAO – устранить остаточную ошибку квантования, сохраняющуюся после deblocking: небольшой сдвиг по компоненте DC в однородных областях и «ringing»-эффекты вокруг резких границ, вызванные чрезмерным квантованием высокочастотных базисных функций преобразования.
SAO обрабатывает по одной CTU за раз. Для каждой CTU энкодер выбирает один из двух режимов – Edge Offset (EO) или Band Offset (BO) – и передаёт в битстриме четыре небольших смещения. Edge Offset классифицирует каждый пиксель в одну из пяти категорий на основе значений двух соседних пикселей вдоль выбранного направления (горизонталь, вертикаль, 45°, 135°): локальный минимум, локальный максимум, начало края, конец края или часть плоского участка. Затем энкодер передаёт по одному смещению для каждой неплоской категории – обычно ±1 или ±2 уровня яркости – и декодер прибавляет это смещение ко всем пикселям данной категории. Band Offset делит диапазон яркости на 32 равные полосы и передаёт смещения для четырёх соседних полос.
Пример с числами. CTU содержит плоский участок со средним значением luma 132, и после квантования преобразование дало DC-сдвиг −2: восстановленное среднее стало 130 вместо 132. Энкодер замечает это в процессе rate-distortion поиска, устанавливает для этой CTU режим SAO типа Band Offset, выбирает четыре полосы, покрывающие диапазон luma от 128 до 143, и сигнализирует оффсеты +2 для каждой из них. Декодер прибавляет +2 ко всем пикселям в этих полосах, восстанавливая среднее значение до 132, при этом не затрагивая соседние полосы. Стоимость в битах битстрима составляет около 30–60 на одну CTU.
SAO дешёв в кодировании и декодировании. Энкодер выполняет небольшой поиск по соотношению «скорость – искажение» на CTU – обычно 5–8 альтернатив, – а декодеру требуется лишь таблица поиска и одно целочисленное сложение на пиксель. Экономия битрейта по сравнению с deblocking в HEVC составляет 1–3% при одинаковом PSNR, а на контенте с плавными градиентами и резкими краями (анимация, motion graphics) – ещё выше.
Adaptive Loop Filter (ALF) – Wiener-фильтр внутри кодека
VVC добавляет третий фильтр поверх deblocking и SAO – Adaptive Loop Filter (ALF). Цель ALF – устранить всё, что осталось после SAO: малоамплитудные высокочастотные ошибки, равномерно распределённые по восстановленному кадру. Эти артефакты невозможно компенсировать с помощью per-CTU-оффсетов, поскольку их среднее значение равно нулю.
ALF – это вейнеровский фильтр, классический инструмент обработки сигналов, который находит линейный фильтр, минимизирующий среднеквадратичную ошибку между отфильтрованной реконструкцией и оригиналом. Коэффициенты фильтра энкодер оценивает по разнице между реконструкцией и оригиналом; эти коэффициенты квантуются и передаются в битстриме; декодер применяет те же коэффициенты к своей реконструкции.
В VVC ALF используется 7-точечный ромбовидный фильтр для яркости и 5-точечный ромбовидный фильтр для цветности; коэффициенты выбираются для каждого CTU из пула до 25 вариантов. «Адаптивная» часть – классификация на уровне CTU: энкодер анализирует каждый 4×4 субблок по локальной градиентной активности и направлению, а декодер переключается между формами фильтров. Плоский субблок получает более сглаженный фильтр; субблок с преобладающим вертикальным краем – фильтр, сохраняющий край и сглаживающий вдоль него; субблок с краем под углом 45° – фильтр, повернутый на 45°. Стоимость сигнализации невелика – несколько бит на CTU плюс глобальные коэффициенты фильтрации на кадр.
VVC также вводит Cross-Component ALF (CC-ALF) – технологию, использующую канал luma в качестве дополнительного входа при фильтрации chroma-каналов. Идея заключается в том, что текстура в luma-канале обычно соответствует активности в chroma-каналах, и фильтр, управляемый luma, может восстановить детали chroma, утраченные из-за chroma sub-sampling и квантования. CC-ALF обеспечивает дополнительную экономию битрейта на уровне 0,5–1% для chroma-каналов в VVC при типичных значениях QP, используемых в стриминге.
Совместный эффект ALF и CC-ALF в VVC – экономия битрейта на 3–6% по сравнению с deblocking и SAO при неизменном PSNR, но при более высокой вычислительной нагрузке на декодирование: Karczewicz et al. (2021) отмечают, что ALF занимает около 5–8% времени работы VVC-декодера и является самым затратным из всех одиночных фильтров в цепочке. AVS3 реализует аналогичный Wiener-основанный ALF, в то время как AV1 его не поддерживает.
CDEF – направленный «sharpener» от AV1
AV1 пошёл другим путём и отказался от SAO. После деблокинга AV1 применяет Constrained Directional Enhancement Filter (CDEF), разработанный Steinar Midtskogen и Jean-Marc Valin в Cisco и Mozilla и доработанный в рамках AOMedia. CDEF направлен на устранение ringing-ореола вокруг резких краёв и направленного размытия, которое деблокинг иногда оставляет на наклонных текстурах.
CDEF работает на каждом 8×8 блоке. На блоке энкодер оценивает доминирующее направление границы из восьми возможных (по 22,5°) и выбирает основную силу фильтра вдоль этого направления и вторичную силу поперёк. Основной фильтр сглаживает вдоль границы, а вторичный – заостряет поперёк. Вторая пара сил обрабатывает хромину. Совместный эффект – сохранение резкости на настоящих краях и подавление точечного паттерна ringing, возникающего из-за разреженных квантованных высокочастотных коэффициентов.
Дизайн CDEF намеренно прост: восемь направлений, четыре основные силы, две дополнительные, никаких коэффициентов, обученных по методу Винера – фильтр представляет собой фиксированное ядро, применяемое с заданными силами, а не полноценный адаптивный Wiener-фильтр. В этой простоте и заключается его преимущество: CDEF обходится примерно в ту же стоимость для декодера, что и SAO в HEVC, и обеспечивает экономию битрейта на натуральных видео на уровне 2–4%. Согласно статье Midtskogen/Valin 2017 года, CDEF превосходит SAO по PSNR-каналу Y в среднем на 0,85% на тестовом наборе AOMedia и ещё сильнее – по перцептивной метрике VMAF, что и стало решающим аргументом для AOMedia в пользу выбора CDEF вместо SAO.
AV1 также применяет Loop Restoration после CDEF, который включает два режима: фильтр в стиле Wiener и self-guided фильтр. По сути Loop Restoration ближе к VVC ALF, но проще – максимум 7-таповый Wiener-фильтр или guided-изображение фильтр с двумя параметрами. Вклад составляет около 1–2% экономии битрейта поверх CDEF. От AV2 ожидают, что все три in-loop фильтра AV1 будут дополнены нейросетевыми альтернативами, которые сейчас находятся в экспериментальных треках.
Сквозной пример
1080p HEVC-стрим кодирует медленную футбольную сцену на 4 Мбит/с с QP 28. Внутри одной CTU на зелёном газоне восстановленные значения luma составляют ровно 137; в оригинале было 140. Deblocking не применяет коррекции: на границах блоков нет скачков яркости. Энкодер SAO проводит поиск по каждой CTU, выбирает режим Band Offset, обнаруживает, что полосы 128–143 на 3 уровня ниже требуемого, и передаёт четыре оффсета +3, потратив 36 бит на сигнализацию в битстриме. Декодер прибавляет +3 ко всем пикселям этих полос, возвращая значение к 140. Если бы был включён ALF (в VVC он есть, в HEVC – нет), он добавил бы небольшую высокочастотную коррекцию, потратив около 60–100 бит на кадр на передачу глобальных коэффициентов фильтра. Вся цепочка фильтров восстанавливает участок с заметно потускневшего 137 до исходного 140, и следующее P-кадровое предсказание энкодера начинается уже от исправленной опорной картинки. Без фильтров каждый последующий P-кадр предсказывал бы от значения 137 и либо сохранял бы 3-уровневую ошибку (и распространял её дальше), либо тратил дополнительные биты на её исправление. Фильтры окупаются уже на третьем кадре и продолжают приносить выгоду далее.
Сравнительная таблица
История пяти доминирующих кодеков в 2026 году – это всё больше фильтров и всё более высокая степень сжатия при медленно растущих затратах на декодирование.
| Кодек (год) | Deblocking | SAO | ALF | CDEF | Loop Restoration | Экономия цепочки (типично) | Доля в декоде |
|---|---|---|---|---|---|---|---|
| H.264 / AVC (2003) | да | нет | нет | нет | нет | ~5–8% | ~3% |
| HEVC (2013) | да | да | нет | нет | нет | ~7–11% | ~5% |
| AV1 (2018) | да | нет | нет | да | да | ~9–13% | ~6% |
| VVC (2020) | да | да | да (+CC-ALF) | нет | нет | ~10–14% | ~8–10% |
| AVS3 (2019) | да | да | да | нет | нет | ~9–12% | ~7% |
Два наблюдения. Во-первых, каждый кодек после H.264 сохранил деблокинг – это самая простая и дешёвая опция в цепочке обработки, и никто не нашёл оснований её отбрасывать. Во-вторых, выбор того, что ставить после деблокинга, – один из самых явных архитектурных «отпечатков» кодека: HEVC использует коррекцию на основе смещения (SAO), AV1 – направленный остряк (CDEF), VVC поверх SAO добавил обучаемый фильтр Винера (ALF). Каждый из этих подходов уходит корнями в приоритеты той организации по стандартизации, которая разрабатывала кодек.
Типичная ловушка – отключённый deblocking при транскоде
Самый частый баг in-loop фильтрации в транскодинговом пайплайне – это отключённый deblocking, который забыли включить обратно. FFmpeg, x264, x265 и SVT-AV1 поддерживают опцию для отключения deblocking – обычно --no-deblock или -deblock 0:0. Инженеры используют её при отладке, чтобы посмотреть «сырой» вывод сетки блоков, но забывают убрать перед выкатыванием конфигурации энкодера в продакшн.
Видимый эффект незначителен. Энкодер работает чуть быстрее, выход проходит базовые проверки воспроизведения, а первый VMAF на тестовом высокобитрейтном клипе примерно соответствует включённому deblocking. Однако на низкобитрейтном контенте, как только в кадр попадает движение, по плоским участкам начинают «маршировать» блоки. На клиентских дашбордах появляются жалобы «видео пикселит», а баг трудно воспроизвести: энкодер не фиксирует отключённый фильтр как ошибку в логах.
Лечится contract-тестом в CI: закодировать референсный клип с прод-конфигом, декодировать и убедиться, что deblocking_filter_disabled_flag (H.264 / HEVC) или эквивалент (loop_filter_level > 0 в AV1) в битстриме имеет ожидаемое значение. Мы добавили однострочный ffprobe-проверку в каждый клиентский пайплайн, который сопровождаем – она занимает миллисекунду на кодирование и за два года дважды поймала тот же баг у трёх клиентов.
Где в этом Фора Софт
Мы поставляем энкодерские конфигурации и инструменты анализа битстримов для пайплайнов видеоконференций, OTT, видеонаблюдения, e-learning, телемедицины и AR/VR. В каждом из наших пайплайнов реализован in-loop-фильтр в CI-сьюте: deblocking включён, SAO активирован там, где это разрешено спецификацией, ALF-коэффициенты присутствуют в VVC-стриме, а AV1-стримы имеют ненулевые значения CDEF. Когда клиент сообщает о видимых блоках на 720p мобильном видео, первым делом мы проверяем состояние deblocking-фильтра в свежем энкоде. Двадцать лет отладки битстримов через H.263, MPEG-2, MPEG-4 Part 2, H.264, HEVC, VP8, VP9 и AV1 убедили нас: цепочка in-loop-фильтров – это как раз то место, где мелкие ошибки в конфигурации вызывают серьёзные проблемы у клиентов. Поэтому аудит занимает у нас доли секунды и позволяет экономить один тикет поддержки каждые две недели.
Главное
- In-loop фильтры работают внутри петли предсказания, поэтому энкодер и декодер используют одни и те же опорные кадры.
- Deblocking сглаживает резкие переходы на границах блоков, работает быстро и экономит 5–10% битрейта – присутствует во всех современных кодеках.
- SAO корректирует мелкие per-CTU смещения после deblocking, поддерживается в HEVC, VVC и AVS3, даёт прирост эффективности на 1–3%.
- ALF – это Wiener-фильтр, реализованный в VVC и AVS3; обеспечивает прирост на 3–6%, но требует 5–8% времени работы декодера.
- AV1 заменил SAO на CDEF (направленный фильтр) и Loop Restoration (аналог Wiener-фильтра), что изменило пайплайн декодера и дало экономию 3–5%.
- Отключённый deblocking – наиболее частая ошибка in-loop фильтров; однострочный тест ffprobe надёжно её выявляет.
Что почитать дальше
- Квантование: где теряется качество – этап обработки, на котором возникают артефакты, устраняемые in-loop фильтрами.
- H.265 / HEVC – кодек, представивший SAO в паре с deblocking-фильтром.
- AV1: где он находится в 2026 – кодек, заменивший SAO на CDEF.