Програмний декодинг: що це, принцип роботи та сценарії застосування

Автор: IT Sectr Опубліковано: 2026-05-25 Час читання: 9 хв

Software decoding — процес декомпресії медіаданих силами центрального процесора (CPU) за допомогою програмних бібліотек, без використання апаратних блоків SoC. Програмні декодери реалізовані як кроссплатформенні бібліотеки: FFmpeg з libavcodec та dav1d для AV1. Згідно з документацією FFmpeg (2026), libavcodec підтримує понад 200 кодеків, що робить software decoding єдиним способом відтворення рідкісних форматів.

Головне

  • Software decoding — декомпресія медіа на CPU за допомогою бібліотек на кшталт FFmpeg та libavcodec
  • Сумісність — програмні декодери підтримують сотні форматів, недоступних для апаратних блоків
  • Енергоспоживання в 5–10 разів вище апаратного, що скорочує час автономної роботи
  • Dav1d — оптимізований програмний декодер AV1, що забезпечує до 50% приросту швидкості
  • Застосування — рідкісні формати, кастомні pipeline, fallback за відсутності апаратної підтримки

Що таке програмне декодування?

Software decoding — спосіб декомпресії медіаданих, при якому всі обчислювальні операції виконуються на універсальних ядрах CPU. На відміну від апаратного декодингу, де кожен кодек має виділений фізичний блок, програмний декодер — це звичайний код, що виконує ті самі алгоритми інструкціями процесора.

Програмні декодери пишуться на C/C++ з використанням оптимізацій під конкретні архітектури CPU: SIMD-інструкції ARM NEON для мобільних пристроїв, Intel SSE/AVX для десктопів. Бібліотека libavcodec зі складу FFmpeg містить десятки тисяч рядків оптимізованого асемблерного коду для різних платформ, дозволяючи програмному декодингу досягати пристойної продуктивності навіть для важких форматів на кшталт AV1 на потужних CPU.

Головна перевага програмного декодингу — універсальність. Якщо апаратний декодер підтримує лише 4–5 основних форматів (H.264, H.265, VP9, AV1), то FFmpeg може декодувати понад 200 кодеків: від сучасних AV1 та H.265 до архівних Sorenson Spark, RealVideo та Motion JPEG. Це робить програмний декодинг незамінним інструментом для додатків, що працюють з нестандартними медіаданими — наприклад, професійних відеоредакторів, систем відеоспостереження та спеціалізованих плеєрів.

Як працює програмний декодинг?

Програмний декодинг повторює ті самі етапи, що й апаратний, але на універсальному CPU. Кожен етап реалізується у вигляді функцій, які послідовно викликаються для кожного макроблоку або кадру. Ключова відмінність — гнучкість: розробник може змінювати pipeline, додавати фільтри та постобробку між етапами декодингу.

Архітектура програмного декодера

Типовий програмний декодер складається з модулів, що реалізують окремі етапи алгоритму. Модуль ентропійного декодингу читає бітовий потік та відновлює квантовані DCT-коефіцієнти. Для H.264 цей модуль реалізує CABAC (Context-Adaptive Binary Arithmetic Coding) — складний алгоритм з умовними переходами, який погано піддається апаратному прискоренню, але на CPU з хорошим branch predictor виконується ефективно.

Модуль зворотного квантування множить коефіцієнти на крок квантування, а модуль зворотного DCT застосовує дискретно-косинусне перетворення. Програмна реалізація зворотного DCT використовує швидкий алгоритм Чена або алгоритм Льоффлера, які скорочують кількість операцій множення-накопичення з 4096 до 256 для 8x8 блоку. SIMD-інструкції NEON (ARM) або SSE (x86) дозволяють обробляти 4–8 коефіцієнтів за одну інструкцію, що дає 4–8-кратне прискорення порівняно зі скалярним кодом.

Модуль компенсації руху — найбільш вимогливий до пам'яті. Він витягує області з опорних кадрів відповідно до векторів руху та застосовує субпіксельну інтерполяцію. Для H.265 точність інтерполяції досягає 1/8 пікселя, що вимагає фільтрації з 8-таповим FIR-фільтром для луми та 4-таповим для хроми. Програмна реалізація змушена завантажувати з кешу великі обсяги даних опорних кадрів, що робить компенсацію руху вузьким місцем при декодингу високих роздільних здатностей на CPU.

Особливості декодування на мобільних CPU

Сучасні мобільні процесори, такі як Apple A17 або Qualcomm Snapdragon 8 Gen 2, мають 6–8 ядер з продуктивністю, достатньою для програмного декодингу 1080p H.264 без пропуску кадрів. Однак для 4K-контенту, особливо у форматах H.265 та AV1, програмний декодинг на CPU може не справлятися: типове завантаження всіх ядер досягає 70–90%, що критично для багатозадачності. Великі ядра (Apple Performance, Qualcomm Kryo Prime) забезпечують ~4–5x продуктивність порівняно з малими енергоефективними ядрами, але споживають пропорційно більше енергії.

Ринок програмних декодерів представлений кількома ключовими бібліотеками, кожна з яких оптимізована під свою нішу. Вибір декодера залежить від необхідних форматів, платформи та ліцензійних обмежень.

FFmpeg / libavcodec

FFmpeg — де-факто стандарт програмного декодингу в індустрії. Бібліотека libavcodec включає декодери для всіх основних та більшості рідкісних кодеків, підтримує всі контейнери (MP4, MKV, AVI, MOV, WebM) та працює на всіх платформах. FFmpeg ліцензований під LGPL/GPL, що вимагає врахування ліцензійних умов при комерційному використанні. На мобільних пристроях FFmpeg використовується через обгортки: ffmpeg-kit для iOS та Android, mobile-ffmpeg для React Native.

Dav1d — оптимізований декодер AV1

Dav1d — програмний декодер AV1 від VideoLAN (розробників VLC), написаний на C з оптимізаціями під SIMD. Його головне завдання — максимально швидкий програмний декодинг AV1 на CPU без апаратної підтримки. Dav1d на 30–50% швидше еталонного декодера libaom від Alliance for Open Media завдяки агресивним оптимізаціям: ручне керування кешем, використання JIT-компіляції для фільтрів постобробки та векторизація критичних функцій.

На мобільних пристроях dav1d може декодувати 1080p AV1 в реальному часі на флагманських SoC (Apple A16+, Snapdragon 8 Gen 2+), але для 4K потрібен потужний CPU. Наприклад, на Apple M1 програмний dav1d досягає ~60 FPS для 4K AV1, а на Snapdragon 8 Gen 2 — ~35 FPS. Для стабільного 4K-відтворення AV1 на мобільних пристроях все ж рекомендується апаратна підтримка.

ДекодерФорматиПлатформиЛіцензія
libavcodec200+ кодеківВсіLGPL/GPL
dav1dAV1ВсіBSD 2-Clause
libaomAV1ВсіBSD 2-Clause
MediaFoundationH.264, H.265WindowsПропрієтарна

Порівняння програмного та апаратного декодингу

Вибір між програмним та апаратним декодингом — це компроміс між сумісністю та ефективністю. У таблиці нижче представлено детальне порівняння ключових характеристик.

ПараметрSoftware DecodingHardware Decoding
Підтримувані формати200+ кодеків4–6 кодеків
Енергоспоживання1,5–5 Вт0,2–0,8 Вт
КастомізаціяПовний контроль над pipelineТільки через API
Затримка30–80 мс5–15 мс
ТепловиділенняВисоке (45–50 C)Низьке (35–40 C)
Оновлення кодеківЧерез оновлення бібліотекиТільки з новим SoC

Програмний декодинг забезпечує максимальну гнучкість: розробник може модифікувати алгоритми, додавати кастомні фільтри, реалізовувати власні конвеєри обробки. Наприклад, в додатках відеомонтажу кожен етап декодингу може бути перенаправлений на GPU для кольорокорекції або накладання ефектів — це можливо лише при програмному контролі над декодингом.

Однак плата за гнучкість — енергоспоживання. Для мобільних пристроїв з акумулятором 3000–5000 мА·год безперервний програмний декодинг скорочує час перегляду з 10–15 годин (апаратний) до 2–4 годин. Розігрів CPU до 45–50 градусів також може викликати троттлінг — зниження частоти процесора для захисту від перегріву, що призводить до пропуску кадрів та погіршення користувацького досвіду.

Приклади коду програмного декодингу

Розглянемо практичну реалізацію програмного декодингу на обох мобільних платформах. На iOS програмний декодинг використовується через FFmpeg, на Android — через ту саму бібліотеку з Java/Kotlin обгорткою.

Програмний декодинг з FFmpeg на C

cpp
extern "C" {
    #include <libavcodec/avcodec.h>
    #include <libavformat/avformat.h>
    #include <libswscale/swscale.h>
}

class SoftwareDecoder {
    AVCodecContext* codecCtx;
    
public:
    bool init(const char* filename) {
        AVFormatContext* fmtCtx = nullptr;
        avformat_open_input(&fmtCtx, filename, nullptr, nullptr);
        avformat_find_stream_info(fmtCtx, nullptr);
        
        int videoStream = av_find_best_stream(
            fmtCtx, AVMEDIA_TYPE_VIDEO, -1, -1, nullptr, 0
        );
        
        AVCodec* decoder = avcodec_find_decoder(
            fmtCtx->streams[videoStream]->codecpar->codec_id
        );
        
        codecCtx = avcodec_alloc_context3(decoder);
        avcodec_parameters_to_context(codecCtx,
            fmtCtx->streams[videoStream]->codecpar);
        avcodec_open2(codecCtx, decoder, nullptr);
        return true;
    }
    
    AVFrame* decodePacket(AVPacket* packet) {
        avcodec_send_packet(codecCtx, packet);
        AVFrame* frame = av_frame_alloc();
        int ret = avcodec_receive_frame(codecCtx, frame);
        return (ret >= 0) ? frame : nullptr;
    }
};

Код демонструє мінімальний pipeline FFmpeg для програмного декодингу. avformat_open_input відкриває файл та визначає формат контейнера, avcodec_find_decoder автоматично знаходить відповідний декодер для будь-якого кодека. Метод decodePacket використовує нове API (avcodec_send_packet / avcodec_receive_frame), яке підтримує багатопотокове декодування при увімкненому прапорці AV_CODEC_FLAG_LOW_DELAY для realtime-додатків.

Програмний декодинг на Kotlin з mobile-ffmpeg

kotlin
class SoftwareDecoder(private val context: Context) {
    fun decodeVideo(inputPath: String, outputFolder: String) {
        val cmd = "-i $inputPath -vf fps=1 $outputFolder/frame_%04d.jpg"
        FFmpegExecutor(context).executeCommand(cmd) { rc ->
            Log.d("Decoder", "Finished with rc: $rc")
        }
    }
    
    fun getFrameCount(filePath: String): Int {
        val probe = MediaMetadataRetriever()
        probe.setDataSource(filePath)
        val duration = probe.extractMetadata(
            MediaMetadataRetriever.METADATA_KEY_DURATION
        )?.toIntOrNull() ?: 0
        val fps = probe.extractMetadata(
            MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT
        )?.toIntOrNull() ?: 0
        probe.release()
        return fps
    }
}

Приклад на Kotlin використовує FFmpegExecutor для вилучення одного кадру в секунду з відео. Параметр -vf fps=1 створює фільтр, який пропускає 59 кадрів з 60, скорочуючи навантаження на CPU. Такий підхід корисний для створення прев'ю та плейсхолдерів у мобільних додатках. Для програмного декодингу в реальному часі рекомендується використовувати низькорівневе API libavcodec безпосередньо через JNI.

Програмний декодинг AV1 з dav1d

c
#include <dav1d/dav1d.h>

int decode_av1_frame(const uint8_t* data, size_t size) {
    Dav1dContext* ctx = nullptr;
    Dav1dSettings settings = { 0 };
    dav1d_default_settings(&settings);
    settings.n_threads = 4;
    dav1d_open(&ctx, &settings);
    
    Dav1dData dav1d_data = { 0 };
    dav1d_data_wrap(&dav1d_data, data, size, nullptr, nullptr);
    
    Dav1dPicture pic = { 0 };
    if (dav1d_send_data(ctx, &dav1d_data) == 0) {
        dav1d_get_picture(ctx, &pic);
    }
    
    dav1d_close(&ctx);
    return pic.p.w;
}

Dav1d надає мінімалістичне API: dav1d_open створює контекст декодера із заданою кількістю потоків, dav1d_send_data приймає стиснений бітовий потік, dav1d_get_picture повертає декодований кадр у форматі YUV420. Для мобільних пристроїв оптимальна кількість потоків (n_threads) — кількість продуктивних ядер CPU мінус один, щоб залишити ресурс для UI-потоку. Dav1d також підтримує Dav1dPicAllocator для керування пам'яттю та уникнення зайвих копіювань при передачі кадру в GPU.

Сценарії застосування програмного декодингу

Незважаючи на більш високе енергоспоживання, програмний декодинг незамінний у ряді сценаріїв, де апаратний декодинг не може забезпечити потрібну функціональність. Розуміння цих сценаріїв допомагає розробнику приймати архітектурні рішення.

Рідкісні та застарілі формати

Апаратні декодери підтримують лише сучасні формати. Якщо додаток працює з архівними записами, відеоспостереженням (MJPEG, H.263), професійними кодеками (ProRes, DNxHD, CineForm) або контентом від сторонніх джерел — програмний декодинг через FFmpeg буде єдиним варіантом. ProRes декодується програмно на всіх пристроях, крім чипів Apple A13+ з апаратною підтримкою. Для H.263 апаратної підтримки немає на жодній сучасній SoC — лише програмний декодинг.

Кастомна постобробка

Програмний декодинг дає повний доступ до кожного етапу обробки кадру. Це критично важливо для додатків, де потрібно застосувати фільтри (розмиття, шумозаглушення, підвищення різкості) безпосередньо на декодованих даних перед виведенням. Фільтри FFmpeg дозволяють вибудовувати складні ланцюжки: декодинг -> кольорокорекція -> масштабування -> накладання субтитрів -> кодування — все в рамках однієї бібліотеки без передачі даних між різними API.

Fallback при відсутності апаратної підтримки

Рекомендована архітектура медіаплеєра — гібридна: апаратний декодинг як основний, програмний як fallback. Перед відтворенням додаток перевіряє доступність апаратного декодера для даного кодека. Якщо декодер не знайдено — запускається програмний через FFmpeg. Така стратегія забезпечує максимальну сумісність без втрати продуктивності для основних форматів. Перевірку доступності слід виконувати при кожному запуску, оскільки апаратна підтримка може відрізнятися навіть на пристроях однієї моделі через різні ревізії SoC.

Часті запитання

Чому програмний декодинг споживає більше енергії?

CPU — універсальний процесор, що виконує безліч різних завдань. Для декодингу він використовує загальні обчислювальні блоки та кеш-пам'ять, які споживають енергію навіть при виконанні одного завдання. Апаратний декодер — вузькоспеціалізована схема з фіксованим конвеєром, де кожен транзистор задіяний лише в декодингу, що радикально знижує енергоспоживання.

Який програмний декодер найшвидший?

Для H.264/H.265 — libavcodec з FFmpeg з увімкненими SIMD-оптимізаціями. Для AV1 — dav1d, який на 30–50% швидше еталонного libaom. На мобільних пристроях продуктивність dav1d дозволяє декодувати 1080p AV1 в реальному часі на флагманських SoC (A16+, Dimensity 9200+).

Чи можна використовувати FFmpeg на iOS та Android?

Так, FFmpeg портований на обидві платформи. Для iOS використовуйте ffmpeg-kit — готову збірку з підтримкою всіх кодеків та форматів. Для Android — mobile-ffmpeg або зберіть FFmpeg через NDK. Врахуйте ліцензійні обмеження GPL/LGPL при комерційному розповсюдженні.

Що таке декодинг H.264 в realtime на CPU?

Realtime-декодинг означає, що CPU встигає декодувати кадри швидше, ніж вони виводяться на екран (зазвичай 30 або 60 FPS). Для 1080p H.264 сучасний мобільний CPU справляється із запасом, використовуючи близько 30–50% одного продуктивного ядра. Для 4K H.265 realtime на CPU можливий лише на флагманських SoC з 70–90% завантаженням всіх ядер.

Як зменшити навантаження на CPU при програмному декодингу?

Використовуйте багатопотокове декодування (frame-level parallelism) через FFmpeg з прапорцем thread_count, встановіть skip_frame на B-кадри (якщо допустимо для сценарію), зменшіть роздільну здатність через фільтр scale перед декодингом. Для AV1 з dav1d використовуйте n_threads = кількість ядер CPU мінус один.

Підсумки

  • Software decoding — декомпресія на CPU через універсальні бібліотеки (FFmpeg, dav1d, libavcodec)
  • FFmpeg підтримує понад 200 кодеків, забезпечуючи максимальну сумісність з будь-якими форматами
  • Dav1d — найшвидший програмний декодер AV1 з оптимізаціями під ARM NEON та Intel AVX
  • Енергоспоживання в 5–10 разів вище апаратного: 1,5–5 Вт проти 0,2–0,8 Вт
  • Програмний декодинг забезпечує повний контроль над pipeline для кастомної постобробки та фільтрації
  • Основні сценарії — рідкісні формати, професійні кодеки, fallback при відсутності апаратної підтримки
  • Використовуйте гібридну стратегію: апаратний декодинг за замовчуванням з програмним fallback для непідтримуваних кодеків

Ми розробимо мобільний застосунок під ключ

IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.

Обговорити проект

Читайте також