Декодування — процес перетворення стисненого медіапотоку в нестиснений формат, придатний для виведення на екран і динаміки. У мобільних пристроях декодування виконується або програмно через CPU, або апаратно через спеціалізовані блоки GPU та DSP. За даними MDN Web Docs (2026), сучасні кодеки стискають потік у 100–500 разів, і декодування відновлює вихідну якість без втрат при правильному виборі профілю стиснення.
Головне
Декодування — це процес перетворення стиснених цифрових даних назад у вихідний нестиснений формат. У контексті медіа декодування відновлює відеокадри зі стисненого бітового потоку, створеного енкодером. Без декодування користувач не може побачити відео або почути аудіо, оскільки всі сучасні медіаформати використовують стиснення для економії пропускної здатності та місця на диску.
Типовий відеопотік у форматі H.264 при бітрейті 5 Мбіт/с займає в 100 разів менше місця, ніж нестиснений потік RGB з аналогічною роздільною здатністю. Алгоритм декодування повинен відновити кожен кадр назад у вихідну роздільну здатність і колірний простір, дотримуючись специфікації кодека у зворотному порядку відносно кодування. Для цього декодер обробляє внутрішньокадрові (I-frame) та міжкадрові (P-frame, B-frame) дані.
На мобільних пристроях декодування може відбуватися як на CPU, так і на виділених апаратних блоках. Сучасні SoC від Apple (серія A), Qualcomm (Snapdragon) та MediaTek (Dimensity) містять вбудовані декодери для всіх популярних форматів. Відеопроцесор бере на себе важку роботу зі зворотного дискретного косинусного перетворення та компенсації руху, звільняючи CPU для інших завдань.
Процес декодування складається з кількох послідовних етапів, що інвертують кроки кодування. Спочатку з бітового потоку витягуються заголовки та параметри стиснення — профіль, рівень, роздільна здатність, колірний простір. Потім декодер послідовно обробляє стиснені макроблоки, застосовуючи до них зворотні перетворення.
Перший етап — витяг ентропійного коду. Ентропійне декодування використовує алгоритми CABAC або CAVLC для відновлення коефіцієнтів дискретного косинусного перетворення. Цей етап не залежить від роздільної здатності відео — він обробляє потік бітів, а не пікселів, і його складність визначається бітрейтом, а не розмірами кадру.
Другий етап — зворотне квантування та зворотне DCT. Декодер множить квантовані коефіцієнти на крок квантування, відновлюючи наближені значення DCT-коефіцієнтів, після чого застосовує зворотне DCT-перетворення. Зворотне DCT відновлює просторові дані з частотної області, формуючи макроблок пікселів. Для хроми та люми перетворення виконується незалежно.
Третій етап — компенсація руху. Для P- та B-кадрів декодер використовує вектори руху, витягнуті з бітового потоку, і посилається на раніше декодовані опорні кадри. Компенсація руху створює предиктор поточного макроблока, до якого додається залишковий сигнал після зворотного DCT. Результат — повністю відновлений кадр, готовий до виведення.
// Псевдокод базового декодування відеокадру
struct DecodedFrame {
uint8_t* y_plane;
uint8_t* u_plane;
uint8_t* v_plane;
int width, height;
};
class Decoder {
public:
bool decodeNALUnit(const uint8_t* nalUnit, size_t size) {
if (!parseNALUHeader(nalUnit, size))
return false;
int sliceType = parseSliceType(nalUnit);
entropyDecode(nalUnit);
inverseQuantize();
inverseDCT();
if (sliceType != I_SLICE)
motionCompensation();
return true;
}
};
У наведеному прикладі показано базову структуру декодера H.264. Функція decodeNALUnit приймає NAL-одиницю — базовий блок стисненого потоку H.264. Декодер послідовно парсить заголовок, витягує тип слайса, застосовує ентропійне декодування, зворотне квантування та зворотне DCT. Для P- та B-слайсів додатково виконується компенсація руху з використанням опорних кадрів з буфера DPB.
Сучасні відеокодеки відрізняються алгоритмами стиснення, ефективністю та вимогами до обчислювальних ресурсів. Вибір формату безпосередньо впливає на розмір файлу, якість зображення та енергоспоживання при декодуванні на мобільному пристрої.
| Кодек | Рік | Стиснення | Апаратна підтримка |
|---|---|---|---|
| H.264 | 2003 | 1:100 | Всі сучасні SoC |
| H.265 | 2013 | 1:200 | Apple A8+, Snapdragon 805+ |
| VP9 | 2013 | 1:180 | Snapdragon 820+, Exynos |
| AV1 | 2018 | 1:300 | Apple A17+, Snapdragon 8 Gen 2+ |
H.264 — найпоширеніший відеокодек, що підтримується всіма мобільними пристроями. Його головна перевага — універсальність: будь-який Android-смартфон та iPhone можуть декодувати H.264 апаратно. Однак при однаковому бітрейті H.264 програє в якості більш сучасним кодекам H.265 та AV1, вимагаючи на 30–50% більше бітрейту для аналогічної візуальної якості.
H.265 забезпечує вдвічі краще стиснення порівняно з H.264 при тій же якості. Декодування H.265 потребує потужнішого апаратного блоку: VideoToolbox на iOS підтримує H.265 починаючи з iPhone 6 (A8), а Android-пристрої — з Snapdragon 805 та вище. При виборі H.265 для мобільного додатку варто враховувати, що старі пристрої можуть не мати апаратної підтримки та будуть декодувати цей формат програмно, що різко збільшує енергоспоживання.
AV1 — відкритий кодек від Alliance for Open Media, що забезпечує найкраще стиснення серед усіх сучасних форматів. AV1 на 30% ефективніший за H.265 та на 50% ефективніший за H.264 при однаковій візуальній якості. Апаратне декодування AV1 з'явилося лише в SoC 2023+ років: Apple A17 Pro, Qualcomm Snapdragon 8 Gen 2 та новіші. Для старіших пристроїв декодування AV1 можливе лише програмно через бібліотеку dav1d, що створює значне навантаження на CPU.
Вибір між програмним та апаратним декодуванням — ключове архітектурне рішення при розробці мобільного медіаплеєра. Кожен підхід має свої переваги та обмеження, які необхідно враховувати при проектуванні додатку.
Апаратне декодування виконується на спеціалізованих блоках відеообробки, які споживають значно менше енергії, ніж CPU при виконанні того ж завдання. За даними Qualcomm, апаратний декодер H.265 споживає в 5–10 разів менше енергії, ніж програмне декодування на CPU Snapdragon 8 Gen 1 при відтворенні 4K-відео. Це критично для мобільних пристроїв, де кожен міліват впливає на час автономної роботи.
Програмне декодування, навпаки, дає максимальну гнучкість. FFmpeg з бібліотекою libavcodec підтримує десятки кодеків та контейнерів, включаючи рідкісні та застарілі формати, які не мають апаратної підтримки. Розробник може модифікувати pipeline декодування, додавати постобробку та фільтри на льоту, що неможливо при використанні закритих апаратних блоків.
Програмне декодування виправдане в кількох сценаріях: при відтворенні рідкісних форматів (ProRes, DNxHD, Motion JPEG), при необхідності точного контролю над кожним етапом обробки кадру, а також при декодуванні AV1 на пристроях без апаратної підтримки. libavcodec зі складу FFmpeg дозволяє декодувати практично будь-який відомий формат, що робить його стандартом де-факто для універсальних медіаплеєрів.
Обмеження програмного декодування — тепловиділення. Безперервне декодування 4K-відео на CPU може нагріти пристрій до 45–50 градусів за 10–15 хвилин, що призводить до троттлінгу та зниження частоти кадрів. На пристроях без активного охолодження (планшети, телефони) це особливо помітно. Енергоспоживання CPU при програмному декодуванні може досягати 3–5 Вт проти 0,3–0,5 Вт при апаратному декодуванні того ж потоку.
Апаратне декодування — вибір за замовчуванням для будь-якого production-медіаплеєра. Воно забезпечує стабільні 60 кадрів/с для 4K-відео при мінімальному енергоспоживанні. VideoToolbox на iOS та MediaCodec на Android надають нативні API для апаратного декодування, які автоматично вибирають оптимальний блок обробки залежно від кодека та роздільної здатності.
Платформенні API беруть на себе керування буферами кадрів (surface pool на Android, CVPixelBufferPool на iOS), синхронізацію з дисплеєм та оптимізацію пам'яті. Розробнику достатньо відкрити декодер з потрібними параметрами та отримувати готові кадри. Апаратне декодування підтримує наскрізний pipeline з мінімальною затримкою: від прийому бітового потоку до виведення на екран проходить 5–15 мс проти 30–80 мс при програмному декодуванні.
Розглянемо практичну реалізацію декодування на обох мобільних платформах. На iOS апаратне декодування виконується через VideoToolbox, а програмне — через FFmpeg. На Android використовується MediaCodec для апаратного декодування.
@interface VideoDecoder ()
@property (nonatomic) VTDecompressionSessionRef session;
@end
@implementation VideoDecoder
- (void)setupDecoder {
CMVideoFormatDescriptionRef formatDesc;
CMVideoCodecType codecType = kCMVideoCodecType_H264;
OSStatus status = CMVideoFormatDescriptionCreate(
NULL, codecType, 1920, 1080, NULL, &formatDesc
);
VTDecompressionOutputCallbackRecord callback;
callback.decompressionOutputCallback = &decodingCallback;
VTDecompressionSessionCreate(NULL, formatDesc, NULL,
NULL, &callback, &_session);
}
- (void)decodeFrame: (uint8_t*)nalData length:(size_t)size {
CMBlockBufferRef blockBuffer;
CMBlockBufferCreateWithMemoryBlock(NULL, nalData,
size, NULL, NULL, 0, size, 0, &blockBuffer);
CMSampleBufferRef sampleBuffer;
CMSampleBufferCreate(NULL, blockBuffer, true, NULL,
NULL, NULL, 1, 0, NULL, 0, NULL, &sampleBuffer);
VTDecompressionSessionDecodeFrame(_session,
sampleBuffer, 0, NULL, 0);
}
@end
Код демонструє ініціалізацію апаратного декодера H.264 на iOS. VTDecompressionSessionCreate створює сесію декодування, а VTCreate викликає колбек при появі готового кадру. Сесія автоматично використовує апаратний блок, якщо він доступний для вказаного кодека. Для отримання декодованих кадрів у форматі CVPixelBuffer використовується callback, який передає кожен готовий кадр з мінімальною затримкою.
MediaCodec decoder = MediaCodec.createDecoderByType("video/avc");
MediaFormat format = MediaFormat.createVideoFormat(
"video/avc", 1920, 1080
);
format.setInteger(MediaFormat.KEY_FRAME_RATE, 30);
decoder.configure(format, surface, null, 0);
decoder.start();
ByteBuffer[] inputBuffers = decoder.getInputBuffers();
int inputIndex = decoder.dequeueInputBuffer(10000);
if (inputIndex >= 0) {
ByteBuffer buffer = inputBuffers[inputIndex];
buffer.clear();
buffer.put(nalData);
decoder.queueInputBuffer(inputIndex, 0, nalData.length, pts, 0);
}
На Android MediaCodec використовує для виведення Surface, а не піксельний буфер, що мінімізує копіювання даних між GPU та CPU. Декодер автоматично вибирає апаратний блок (OMX-компонент) на основі типу кодека. Для H.264 використовується OMX.google.h264.decoder, який може бути як апаратним, так і програмним залежно від реалізації виробника.
Вибір стратегії декодування залежить від цільової аудиторії додатку, підтримуваних форматів та вимог до продуктивності. Оптимальне рішення часто включає гібридний підхід: апаратне декодування для основних форматів (H.264, H.265) з програмним fallback для рідкісних кодеків.
Якщо додаток орієнтований на максимальну сумісність — використовуйте H.264, який гарантовано декодується апаратно на будь-якому пристрої. Для відеострімінгових сервісів виправданий H.265 з апаратною підтримкою на пристроях після 2016 року. AV1 — вибір для сервісів, де важлива економія пропускної здатності: YouTube, Netflix та інші великі платформи активно впроваджують AV1 для зниження витрат на CDN при збереженні якості.
Критичний параметр — buffer size декодера. Апаратні декодери мають фіксований пул буферів (зазвичай 4–16 кадрів). При відтворенні високобітрейтного потоку буфери можуть переповнитися, що призведе до пропуску кадрів. MediaCodec надає метод getOutputFrameRate для визначення реальної продуктивності декодера на конкретному пристрої, а VideoToolbox дозволяє контролювати realtime-пріоритет через kVTDecodeFrame_EnableAsynchronousDecompression.
Тепловий троттлінг — ще один фактор. Навіть апаратне декодування може нагрівати пристрій при тривалому відтворенні 4K HDR-відео. Рекомендується відстежувати температуру через ProcessInfo на iOS та BatteryManager на Android, знижуючи якість або роздільну здатність потоку при перегріві. Це особливо критично для ігор та стрімінгових додатків з тривалими сесіями перегляду.
Часті запитання
Кодування (encoding) перетворює нестиснені дані в стиснений формат, а декодування (decoding) відновлює вихідні дані зі стисненого потоку. Ці процеси обернені один одному та використовують однакові алгоритми: DCT, квантування, компенсацію руху. Енкодер виконує пряме перетворення, декодер — зворотне.
Для максимальної сумісності — H.264, оскільки він апаратно декодується на 100% сучасних пристроїв. Для кращого стиснення — H.265 або AV1. Вибір залежить від аудиторії: якщо 80% користувачів мають пристрої 2021+ років, H.265 забезпечить кращу якість при меншому бітрейті. AV1 виправданий для флагманських пристроїв з апаратною підтримкою 2023+ років.
Апаратний декодер — це спеціалізована мікросхема (ASIC), спроектована виключно для декодування. На відміну від CPU, який виконує декодування послідовними інструкціями, апаратний блок обробляє макроблоки паралельно. Енергоспоживання апаратного декодера в 5–10 разів нижче, оскільки чіп працює на меншій частоті та не має зайвих етапів конвеєра.
Профіль (profile) визначає набір алгоритмів стиснення, що використовуються енкодером: Baseline, Main, High. Рівень (level) задає максимальні параметри потоку: роздільну здатність, бітрейт, розмір буфера. Для мобільних пристроїв рекомендується профіль High та рівень 4.1–5.2 — цього достатньо для 1080p–4K відео з апаратним декодуванням.
На Android використовуйте MediaCodecList для отримання списку доступних кодеків та перевірки того, який з них є апаратним. На iOS перевірте підтримку через CMVideoFormatDescription з вказаним кодеком — якщо VTDecompressionSessionCreate успішна, кодек підтримується. Для AV1 на Android перевірте наявність кодека OMX.google.aomc.decoder або його апаратної версії.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також