Software decoding — het proces van decomprimeren van mediagegevens door de centrale verwerkingseenheid (CPU) met behulp van softwarebibliotheken, zonder gebruik van hardwareblokken van de SoC. Softwarematige decoders zijn geïmplementeerd als cross-platform bibliotheken: FFmpeg met libavcodec en dav1d voor AV1. Volgens FFmpeg-documentatie (2026) ondersteunt libavcodec meer dan 200 codecs, waardoor software decoding de enige manier is om zeldzame formaten af te spelen.
Belangrijkste punten
Software decoding — een manier van decomprimeren van mediagegevens waarbij alle rekenkundige bewerkingen worden uitgevoerd op universele CPU-kernen. In tegenstelling tot hardwarematig decoderen, waarbij elke codec een toegewezen fysiek blok heeft, is een softwarematige decoder gewone code die dezelfde algoritmen uitvoert met processorinstructies.
Softwarematige decoders worden geschreven in C/C++ met optimalisaties voor specifieke CPU-architecturen: SIMD-instructies ARM NEON voor mobiele apparaten, Intel SSE/AVX voor desktops. De bibliotheek libavcodec uit FFmpeg bevat tienduizenden regels geoptimaliseerde assembleertaal voor verschillende platformen, waardoor softwarematig decoderen behoorlijke prestaties kan leveren, zelfs voor zware formaten zoals AV1 op krachtige CPU's.
Het belangrijkste voordeel van softwarematig decoderen is universaliteit. Als een hardwarematige decoder slechts 4–5 basisformaten (H.264, H.265, VP9, AV1) ondersteunt, kan FFmpeg meer dan 200 codecs decoderen: van moderne AV1 en H.265 tot archaïsche Sorenson Spark, RealVideo en Motion JPEG. Dit maakt softwarematig decoderen een onmisbaar hulpmiddel voor applicaties die met niet-standaard mediagegevens werken — bijvoorbeeld professionele videobewerkers, beveiligingscamerasystemen en gespecialiseerde spelers.
Softwarematig decoderen doorloopt dezelfde fasen als hardwarematig, maar op een universele CPU. Elke fase wordt geïmplementeerd als functies die opeenvolgend worden aangeroepen voor elk macroblok of frame. Het belangrijkste verschil is flexibiliteit: de ontwikkelaar kan de pipeline aanpassen, filters en nabewerking toevoegen tussen de decodeerfasen.
Een typische softwarematige decoder bestaat uit modules die afzonderlijke fasen van het algoritme implementeren. De entropie-decodermodule leest de bitstroom en reconstrueert de gekwantiseerde DCT-coëfficiënten. Voor H.264 implementeert deze module CABAC (Context-Adaptive Binary Arithmetic Coding) — een complex algoritme met conditionele vertakkingen dat slecht geschikt is voor hardwareversnelling, maar efficiënt werkt op een CPU met een goede branch predictor.
De inverse kwantiseringsmodule vermenigvuldigt de coëfficiënten met de kwantiseringsstap, en de inverse DCT-module past de discrete cosinustransformatie toe. De softwarematige implementatie van inverse DCT gebruikt het snelle Chen-algoritme of het Loeffler-algoritme, die het aantal vermenigvuldigings-accumulatiebewerkingen verminderen van 4096 naar 256 voor een 8x8 blok. SIMD-instructies NEON (ARM) of SSE (x86) maken het mogelijk 4–8 coëfficiënten in één instructie te verwerken, wat een 4–8-voudige versnelling geeft vergeleken met scalaire code.
De bewegingscompensatiemodule — de meest geheugenintensieve. Deze haalt gebieden uit referentieframes op basis van bewegingsvectoren en past subpixelinterpolatie toe. Voor H.265 bereikt de interpolatienauwkeurigheid 1/8 pixel, wat filtering met een 8-taps FIR-filter vereist voor luminantie en een 4-taps voor chrominantie. De softwarematige implementatie moet grote hoeveelheden referentieframegegevens uit de cache laden, wat bewegingscompensatie tot een knelpunt maakt bij het decoderen van hoge resoluties op de CPU.
Moderne mobiele processors, zoals de Apple A17 of Qualcomm Snapdragon 8 Gen 2, hebben 6–8 kernen met voldoende prestaties voor softwarematig decoderen van 1080p H.264 zonder frames over te slaan. Voor 4K-inhoud, vooral in formaten H.265 en AV1, kan softwarematig decoderen op de CPU echter tekortschieten: de typische belasting van alle kernen bereikt 70–90%, wat kritisch is voor multitasking. Grote kernen (Apple Performance, Qualcomm Kryo Prime) bieden ~4–5x prestatie vergeleken met kleine energiezuinige kernen, maar verbruiken evenredig meer energie.
De markt voor softwarematige decoders wordt vertegenwoordigd door enkele belangrijke bibliotheken, elk geoptimaliseerd voor hun niche. De keuze van de decoder hangt af van de vereiste formaten, het platform en licentiebeperkingen.
FFmpeg — de de facto standaard voor softwarematig decoderen in de industrie. De bibliotheek libavcodec bevat decoders voor alle belangrijke en de meeste zeldzame codecs, ondersteunt alle containers (MP4, MKV, AVI, MOV, WebM) en werkt op alle platformen. FFmpeg is gelicentieerd onder LGPL/GPL, wat vereist dat licentievereisten in acht worden genomen bij commercieel gebruik. Op mobiele apparaten wordt FFmpeg gebruikt via wrappers: ffmpeg-kit voor iOS en Android, mobile-ffmpeg voor React Native.
Dav1d — een softwarematige AV1-decoder van VideoLAN (de makers van VLC), geschreven in C met SIMD-optimalisaties. De belangrijkste taak is het zo snel mogelijk softwarematig decoderen van AV1 op een CPU zonder hardwareondersteuning. Dav1d is 30–50% sneller dan de referentiedecoder libaom van Alliance for Open Media dankzij agressieve optimalisaties: handmatig cachebeheer, gebruik van JIT-compilatie voor nabewerkingsfilters en vectorisatie van kritieke functies.
Op mobiele apparaten kan dav1d 1080p AV1 in realtime decoderen op vlaggenschip SoC's (Apple A16+, Snapdragon 8 Gen 2+), maar voor 4K is een krachtige CPU nodig. Op de Apple M1 bereikt softwarematige dav1d bijvoorbeeld ~60 FPS voor 4K AV1, en op Snapdragon 8 Gen 2 — ~35 FPS. Voor stabiele 4K AV1-weergave op mobiele apparaten wordt nog steeds hardwareondersteuning aanbevolen.
| Decoder | Formaten | Platformen | Licentie |
|---|---|---|---|
| libavcodec | 200+ codecs | Alle | LGPL/GPL |
| dav1d | AV1 | Alle | BSD 2-Clause |
| libaom | AV1 | Alle | BSD 2-Clause |
| MediaFoundation | H.264, H.265 | Windows | Propriëtair |
De keuze tussen softwarematig en hardwarematig decoderen is een compromis tussen compatibiliteit en efficiëntie. De onderstaande tabel geeft een gedetailleerde vergelijking van de belangrijkste kenmerken.
| Parameter | Software Decoding | Hardware Decoding |
|---|---|---|
| Ondersteunde formaten | 200+ codecs | 4–6 codecs |
| Energieverbruik | 1,5–5 W | 0,2–0,8 W |
| Aanpassing | Volledige controle over pipeline | Alleen via API |
| Latency | 30–80 ms | 5–15 ms |
| Warmteafgifte | Hoog (45–50 °C) | Laag (35–40 °C) |
| Codec-updates | Via bibliotheekupdate | Alleen met nieuwe SoC |
Softwarematig decoderen biedt maximale flexibiliteit: de ontwikkelaar kan algoritmen wijzigen, aangepaste filters toevoegen, eigen verwerkingspijplijnen implementeren. In videobewerkingstoepassingen kan bijvoorbeeld elke decodeerfase worden omgeleid naar de GPU voor kleurcorrectie of het toepassen van effecten — dit is alleen mogelijk bij softwarematige controle over het decoderen.
De prijs voor flexibiliteit is echter het energieverbruik. Voor mobiele apparaten met een batterij van 3000–5000 mAh verkort continu softwarematig decoderen de kijktijd van 10–15 uur (hardware) tot 2–4 uur. Opwarming van de CPU tot 45–50 graden kan ook throttling veroorzaken — verlaging van de processorfrequentie ter bescherming tegen oververhitting, wat leidt tot het overslaan van frames en verslechtering van de gebruikerservaring.
Laten we de praktische implementatie van softwarematig decoderen op beide mobiele platformen bekijken. Op iOS wordt softwarematig decoderen gebruikt via FFmpeg, op Android — via dezelfde bibliotheek met een Java/Kotlin-wrapper.
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;
}
};
De code toont een minimale FFmpeg-pipeline voor softwarematig decoderen. avformat_open_input opent het bestand en bepaalt het containerformaat, avcodec_find_decoder vindt automatisch de juiste decoder voor elke codec. De methode decodePacket gebruikt de nieuwe API (avcodec_send_packet / avcodec_receive_frame), die multithreaded decoderen ondersteunt wanneer de vlag AV_CODEC_FLAG_LOW_DELAY is ingeschakeld voor realtime-toepassingen.
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", "Voltooid met 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
}
}
Het voorbeeld in Kotlin gebruikt FFmpegExecutor om één frame per seconde uit video te extraheren. De parameter -vf fps=1 maakt een filter dat 59 van de 60 frames overslaat, waardoor de CPU-belasting afneemt. Deze aanpak is nuttig voor het maken van voorbeelden en placeholders in mobiele applicaties. Voor realtime softwarematig decoderen wordt aanbevolen de low-level API van libavcodec rechtstreeks via JNI te gebruiken.
#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 biedt een minimalistische API: dav1d_open maakt een decodercontext met een opgegeven aantal threads, dav1d_send_data accepteert de gecomprimeerde bitstroom, dav1d_get_picture retourneert het gedecodeerde frame in YUV420-formaat. Voor mobiele apparaten is het optimale aantal threads (n_threads) het aantal productieve CPU-kernen minus één, om resources over te laten voor de UI-thread. Dav1d ondersteunt ook Dav1dPicAllocator voor geheugenbeheer en het vermijden van onnodige kopieën bij het doorgeven van het frame aan de GPU.
Ondanks het hogere energieverbruik is softwarematig decoderen onmisbaar in scenario's waar hardwarematig decoderen de vereiste functionaliteit niet kan bieden. Inzicht in deze scenario's helpt de ontwikkelaar bij het nemen van architectuurbeslissingen.
Hardwarematige decoders ondersteunen alleen moderne formaten. Als een applicatie werkt met archiefopnamen, videobewaking (MJPEG, H.263), professionele codecs (ProRes, DNxHD, CineForm) of inhoud van derden — is softwarematig decoderen via FFmpeg de enige optie. ProRes wordt softwarematig gedecodeerd op alle apparaten behalve Apple A13+ chips met hardwareondersteuning. Voor H.263 is er op geen enkele moderne SoC hardwareondersteuning — alleen softwarematig decoderen.
Softwarematig decoderen geeft volledige toegang tot elke fase van framebewerking. Dit is van cruciaal belang voor applicaties waar filters (vervaging, ruisonderdrukking, verscherping) direct op de gedecodeerde gegevens moeten worden toegepast voordat ze worden weergegeven. FFmpeg-filters maken het mogelijk complexe ketens te bouwen: decoderen -> kleurcorrectie -> schalen -> ondertiteling toevoegen -> coderen — alles binnen één bibliotheek zonder gegevensoverdracht tussen verschillende API's.
De aanbevolen architectuur voor een mediaspeler is hybride: hardwarematig decoderen als primair, softwarematig als fallback. Vóór het afspelen controleert de applicatie de beschikbaarheid van de hardwarematige decoder voor de betreffende codec. Als de decoder niet wordt gevonden — wordt softwarematig decoderen via FFmpeg gestart. Deze strategie zorgt voor maximale compatibiliteit zonder prestatieverlies voor basisformaten. De beschikbaarheidscontrole moet bij elke start worden uitgevoerd, omdat hardwareondersteuning zelfs op apparaten van hetzelfde model kan verschillen door verschillende SoC-revisies.
Veelgestelde vragen
De CPU is een universele processor die vele verschillende taken uitvoert. Voor het decoderen gebruikt hij gedeelde rekenblokken en cachegeheugen die energie verbruiken, zelfs bij het uitvoeren van één taak. De hardwarematige decoder is een gespecialiseerde schakeling met een vaste pijplijn, waarbij elke transistor alleen betrokken is bij het decoderen, wat het energieverbruik drastisch vermindert.
Voor H.264/H.265 — libavcodec uit FFmpeg met ingeschakelde SIMD-optimalisaties. Voor AV1 — dav1d, die 30–50% sneller is dan de referentie libaom. Op mobiele apparaten maakt de prestaties van dav1d realtime decoderen van 1080p AV1 mogelijk op vlaggenschip SoC's (A16+, Dimensity 9200+).
Ja, FFmpeg is naar beide platformen overgezet. Gebruik voor iOS ffmpeg-kit — een kant-en-klare build met ondersteuning voor alle codecs en formaten. Voor Android — mobile-ffmpeg of bouw FFmpeg via NDK. Houd rekening met GPL/LGPL-licentiebeperkingen bij commerciële distributie.
Realtime decoderen betekent dat de CPU frames sneller kan decoderen dan ze worden weergegeven (meestal 30 of 60 FPS). Voor 1080p H.264 kan een moderne mobiele CPU dit met gemak aan, waarbij ongeveer 30–50% van één productieve kern wordt gebruikt. Voor 4K H.265 in realtime op de CPU is dit alleen mogelijk op vlaggenschip SoC's met 70–90% belasting van alle kernen.
Gebruik multithreaded decoderen (frame-level parallelism) via FFmpeg met de vlag thread_count, stel skip_frame in op B-frames (indien acceptabel voor het scenario), verlaag de resolutie via het scale-filter vóór het decoderen. Gebruik voor AV1 met dav1d n_threads = aantal CPU-kernen minus één.
Samenvatting
We ontwikkelen een mobiele applicatie turnkey
IT Sectr creëert sinds 2017 iOS- en Android-applicaties voor startups en bedrijven. We adviseren u en stellen de beste oplossing voor.
Lees ook