Software decoding — der Prozess der Dekompression von Mediendaten durch die CPU mithilfe von Softwarebibliotheken, ohne Verwendung von Hardwareblöcken des SoC. Software-Decoder werden als plattformübergreifende Bibliotheken implementiert: FFmpeg mit libavcodec und dav1d für AV1. Laut FFmpeg-Dokumentation (2026) unterstützt libavcodec mehr als 200 Codecs, was software decoding zur einzigen Möglichkeit macht, seltene Formate wiederzugeben.
Wichtige Erkenntnisse
Software decoding ist eine Methode zur Dekompression von Mediendaten, bei der alle Berechnungsvorgänge auf den Allzweck-CPU-Kernen ausgeführt werden. Im Gegensatz zur Hardware-Decodierung, bei der jeder Codec einen dedizierten physischen Block hat, ist ein Software-Decoder gewöhnlicher Code, der dieselben Algorithmen mit Prozessorbefehlen ausführt.
Software-Decoder werden in C/C++ mit Optimierungen für bestimmte CPU-Architekturen geschrieben: ARM NEON SIMD-Befehle für mobile Geräte, Intel SSE/AVX für Desktops. Die libavcodec-Bibliothek von FFmpeg enthält Zehntausende von Zeilen optimierten Assembler-Codes für verschiedene Plattformen, sodass Software-Decodierung auch für schwere Formate wie AV1 auf leistungsstarken CPUs eine anständige Leistung erzielen kann.
Der Hauptvorteil der Software-Decodierung ist die Vielseitigkeit. Wenn ein Hardware-Decoder nur 4–5 Hauptformate (H.264, H.265, VP9, AV1) unterstützt, kann FFmpeg mehr als 200 Codecs decodieren: von modernem AV1 und H.265 bis hin zu archivierten Sorenson Spark, RealVideo und Motion JPEG. Dies macht Software-Decodierung zu einem unverzichtbaren Werkzeug für Anwendungen, die mit nicht standardmäßigen Mediendaten arbeiten — wie professionelle Videobearbeitungsprogramme, Videoüberwachungssysteme und spezialisierte Player.
Software-Decodierung durchläuft dieselben Phasen wie Hardware-Decodierung, jedoch auf einer Allzweck-CPU. Jede Phase wird als Funktionen implementiert, die nacheinander für jeden Makroblock oder Frame aufgerufen werden. Der Hauptunterschied ist die Flexibilität: Der Entwickler kann die Pipeline ändern, Filter und Nachbearbeitung zwischen den Decodierungsphasen hinzufügen.
Ein typischer Software-Decoder besteht aus Modulen, die einzelne Algorithmusphasen implementieren. Das Entropiedecodierungsmodul liest den Bitstrom und rekonstruiert quantisierte DCT-Koeffizienten. Für H.264 implementiert dieses Modul CABAC (Context-Adaptive Binary Arithmetic Coding) — einen komplexen Algorithmus mit bedingten Verzweigungen, der hardwaremäßig schwer zu beschleunigen ist, aber auf einer CPU mit gutem Branch-Predictor effizient läuft.
Das inverse Quantisierungsmodul multipliziert die Koeffizienten mit der Quantisierungsstufe, und das inverse DCT-Modul wendet die diskrete Kosinustransformation an. Die Software-Implementierung der inversen DCT verwendet den schnellen Chen-Algorithmus oder den Loeffler-Algorithmus, die die Anzahl der Multiplikations-Akkumulations-Operationen für einen 8x8-Block von 4096 auf 256 reduzieren. NEON-SIMD-Befehle (ARM) oder SSE (x86) ermöglichen die Verarbeitung von 4–8 Koeffizienten pro Befehl, was eine 4–8-fache Beschleunigung im Vergleich zu skalarem Code bietet.
Das Bewegungskompensationsmodul ist das speicherintensivste. Es extrahiert Bereiche aus Referenzframes gemäß Bewegungsvektoren und wendet Subpixel-Interpolation an. Für H.265 erreicht die Interpolationsgenauigkeit 1/8 Pixel, was einen 8-Tap-FIR-Filter für Luma und 4-Tap für Chroma erfordert. Die Software-Implementierung muss große Mengen an Referenzframedaten aus dem Cache laden, was die Bewegungskompensation bei der Decodierung hoher Auflösungen auf der CPU zum Engpass macht.
Moderne mobile Prozessoren wie der Apple A17 oder Qualcomm Snapdragon 8 Gen 2 haben 6–8 Kerne mit ausreichender Leistung für die Software-Decodierung von 1080p H.264 ohne Frame-Ausfälle. Bei 4K-Inhalten, insbesondere in den Formaten H.265 und AV1, kann die Software-Decodierung auf der CPU jedoch Schwierigkeiten bereiten: Die typische Auslastung aller Kerne erreicht 70–90%, was für Multitasking kritisch ist. Die großen Kerne (Apple Performance, Qualcomm Kryo Prime) bieten eine etwa 4–5-fache Leistung im Vergleich zu kleinen energieeffizienten Kernen, verbrauchen aber proportional mehr Energie.
Der Markt für Software-Decoder umfasst mehrere wichtige Bibliotheken, die jeweils für ihre Nische optimiert sind. Die Wahl des Decoders hängt von den erforderlichen Formaten, der Plattform und den Lizenzbeschränkungen ab.
FFmpeg ist der De-facto-Standard für Software-Decodierung in der Branche. Die Bibliothek libavcodec enthält Decoder für alle wichtigen und die meisten seltenen Codecs, unterstützt alle Container (MP4, MKV, AVI, MOV, WebM) und läuft auf allen Plattformen. FFmpeg ist unter LGPL/GPL lizenziert, was die Einhaltung der Lizenzbedingungen für die kommerzielle Nutzung erfordert. Auf mobilen Geräten wird FFmpeg über Wrapper verwendet: ffmpeg-kit für iOS und Android, mobile-ffmpeg für React Native.
Dav1d ist ein Software-AV1-Decoder von VideoLAN (Entwickler von VLC), geschrieben in C mit SIMD-Optimierungen. Sein Hauptziel ist die schnellstmögliche Software-Decodierung von AV1 auf CPUs ohne Hardwareunterstützung. Dav1d ist 30–50% schneller als der Referenzdecoder libaom der Alliance for Open Media dank aggressiver Optimierungen: manuelles Cache-Management, JIT-Kompilierung für Nachbearbeitungsfilter und Vektorisierung kritischer Funktionen.
Auf mobilen Geräten kann dav1d 1080p AV1 in Echtzeit auf Flaggschiff-SoCs (Apple A16+, Snapdragon 8 Gen 2+) decodieren, aber für 4K ist eine leistungsstarke CPU erforderlich. Beispielsweise erreicht Software-dav1d auf Apple M1 etwa 60 FPS für 4K AV1, während es auf Snapdragon 8 Gen 2 etwa 35 FPS erreicht. Für eine stabile 4K-AV1-Wiedergabe auf mobilen Geräten wird weiterhin Hardwareunterstützung empfohlen.
| Decoder | Formate | Plattformen | Lizenz |
|---|---|---|---|
| libavcodec | 200+ Codecs | Alle | LGPL/GPL |
| dav1d | AV1 | Alle | BSD 2-Clause |
| libaom | AV1 | Alle | BSD 2-Clause |
| MediaFoundation | H.264, H.265 | Windows | Proprietär |
Die Wahl zwischen Software- und Hardware-Decodierung ist ein Kompromiss zwischen Kompatibilität und Effizienz. Die folgende Tabelle bietet einen detaillierten Vergleich der wichtigsten Merkmale.
| Parameter | Software Decoding | Hardware Decoding |
|---|---|---|
| Unterstützte Formate | 200+ Codecs | 4–6 Codecs |
| Energieverbrauch | 1,5–5 W | 0,2–0,8 W |
| Anpassung | Vollständige Kontrolle über Pipeline | Nur über API |
| Latenz | 30–80 ms | 5–15 ms |
| Wärmeentwicklung | Hoch (45–50 C) | Niedrig (35–40 C) |
| Codec-Updates | Durch Bibliotheksupdate | Nur mit neuem SoC |
Software-Decodierung bietet maximale Flexibilität: Der Entwickler kann Algorithmen ändern, benutzerdefinierte Filter hinzufügen und eigene Verarbeitungspipelines implementieren. Beispielsweise kann in Videobearbeitungsanwendungen jede Decodierungsphase zur Farbkorrektur oder Effektüberlagerung an die GPU weitergeleitet werden — dies ist nur mit Softwarekontrolle über die Decodierung möglich.
Der Preis für die Flexibilität ist jedoch der Energieverbrauch. Bei mobilen Geräten mit einem 3000–5000-mAh-Akku verkürzt kontinuierliche Software-Decodierung die Betrachtungszeit von 10–15 Stunden (Hardware) auf 2–4 Stunden. Die CPU-Erwärmung auf 45–50 Grad kann auch zu Throttling führen — einer Reduzierung der Prozessorfrequenz zum Schutz vor Überhitzung, was zu Frame-Ausfällen und einer Verschlechterung der Benutzererfahrung führt.
Betrachten wir eine praktische Implementierung der Software-Decodierung auf beiden mobilen Plattformen. Auf iOS wird Software-Decodierung über FFmpeg verwendet, auf Android über dieselbe Bibliothek mit einem 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;
}
};
Der Code demonstriert eine minimale FFmpeg-Pipeline für Software-Decodierung. avformat_open_input öffnet die Datei und bestimmt das Containerformat, avcodec_find_decoder findet automatisch einen geeigneten Decoder für jeden Codec. Die Methode decodePacket verwendet die neue API (avcodec_send_packet / avcodec_receive_frame), die Multithread-Decodierung mit aktiviertem Flag AV_CODEC_FLAG_LOW_DELAY für Echtzeitanwendungen unterstützt.
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
}
}
Das Kotlin-Beispiel verwendet FFmpegExecutor, um ein Bild pro Sekunde aus einem Video zu extrahieren. Der Parameter -vf fps=1 erstellt einen Filter, der 59 von 60 Bildern überspringt und so die CPU-Last reduziert. Dieser Ansatz ist nützlich für die Erstellung von Vorschauen und Platzhaltern in mobilen Anwendungen. Für Echtzeit-Software-Decodierung wird empfohlen, die Low-Level-libavcodec-API direkt über JNI zu verwenden.
#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 bietet eine minimalistische API: dav1d_open erstellt einen Decoder-Kontext mit einer bestimmten Anzahl von Threads, dav1d_send_data akzeptiert den komprimierten Bitstrom, dav1d_get_picture gibt den decodierten Frame im YUV420-Format zurück. Für mobile Geräte ist die optimale Thread-Anzahl (n_threads) die Anzahl der Performance-CPU-Kerne minus eins, um Ressourcen für den UI-Thread freizulassen. Dav1d unterstützt auch Dav1dPicAllocator für die Speicherverwaltung und zur Vermeidung unnötiger Kopien bei der Übertragung von Frames an die GPU.
Trotz des höheren Energieverbrauchs ist Software-Decodierung in mehreren Szenarien unverzichtbar, in denen Hardware-Decodierung die erforderliche Funktionalität nicht bieten kann. Das Verständnis dieser Szenarien hilft Entwicklern, architektonische Entscheidungen zu treffen.
Hardware-Decoder unterstützen nur moderne Formate. Wenn die Anwendung mit Archivaufnahmen, Videoüberwachung (MJPEG, H.263), professionellen Codecs (ProRes, DNxHD, CineForm) oder Inhalten von Drittanbietern arbeitet — ist Software-Decodierung über FFmpeg die einzige Option. ProRes wird auf allen Geräten außer Apple A13+-Chips mit Hardwareunterstützung nur softwaremäßig decodiert. Für H.263 gibt es auf keinem modernen SoC Hardwareunterstützung — nur Software-Decodierung.
Software-Decodierung bietet vollen Zugriff auf jede Frame-Verarbeitungsstufe. Dies ist entscheidend für Anwendungen, die Filter (Unschärfe, Rauschunterdrückung, Schärfung) direkt auf decodierte Daten vor der Ausgabe anwenden müssen. FFmpeg-Filter ermöglichen den Aufbau komplexer Ketten: Decodierung -> Farbkorrektur -> Skalierung -> Untertiteleinblendung -> Codierung — alles innerhalb einer einzigen Bibliothek ohne Datenübertragung zwischen verschiedenen APIs.
Die empfohlene Mediaplayer-Architektur ist hybrid: Hardware-Decodierung als primäre, Software-Decodierung als Fallback. Vor der Wiedergabe prüft die Anwendung die Verfügbarkeit eines Hardware-Decoders für den angegebenen Codec. Wird kein Decoder gefunden, wird die Software-Decodierung über FFmpeg gestartet. Diese Strategie gewährleistet maximale Kompatibilität, ohne die Leistung für Hauptformate zu opfern. Verfügbarkeitsprüfungen sollten bei jedem Start durchgeführt werden, da die Hardwareunterstützung selbst bei Geräten desselben Modells aufgrund unterschiedlicher SoC-Revisionen variieren kann.
Häufig gestellte Fragen
Die CPU ist ein Allzweckprozessor, der viele verschiedene Aufgaben ausführt. Für die Decodierung verwendet sie gemeinsam genutzte Recheneinheiten und Cache-Speicher, die auch bei der Ausführung einer einzelnen Aufgabe Energie verbrauchen. Ein Hardware-Decoder ist eine hochspezialisierte Schaltung mit einer festen Pipeline, bei der jeder Transistor nur der Decodierung gewidmet ist, was den Energieverbrauch radikal senkt.
Für H.264/H.265 — libavcodec von FFmpeg mit aktivierten SIMD-Optimierungen. Für AV1 — dav1d, das 30–50% schneller ist als das Referenz-libaom. Auf mobilen Geräten ermöglicht die Leistung von dav1d die Echtzeit-Decodierung von 1080p AV1 auf Flaggschiff-SoCs (A16+, Dimensity 9200+).
Ja, FFmpeg wurde auf beide Plattformen portiert. Für iOS verwenden Sie ffmpeg-kit — einen fertigen Build mit Unterstützung aller Codecs und Formate. Für Android — mobile-ffmpeg oder bauen Sie FFmpeg über das NDK. Beachten Sie die GPL/LGPL-Lizenzbeschränkungen für den kommerziellen Vertrieb.
Echtzeit-Decodierung bedeutet, dass die CPU Bilder schneller decodieren kann, als sie auf dem Bildschirm angezeigt werden (normalerweise 30 oder 60 FPS). Für 1080p H.264 kommt eine moderne mobile CPU locker zurecht und verwendet etwa 30–50% eines Performance-Kerns. Für 4K H.265 ist Echtzeit auf der CPU nur auf Flaggschiff-SoCs mit 70–90% Auslastung aller Kerne möglich.
Verwenden Sie Multithread-Decodierung (Frame-Level-Parallelität) über FFmpeg mit dem Flag thread_count, setzen Sie skip_frame auf B-Frames (wenn für das Szenario akzeptabel), reduzieren Sie die Auflösung über den Scale-Filter vor der Decodierung. Für AV1 mit dav1d verwenden Sie n_threads = Anzahl der CPU-Kerne minus eins.
Zusammenfassung
Wir entwickeln eine mobile Applikation schlüsselfertig
IT Sectr entwickelt seit 2017 iOS- und Android-Apps für Startups und Unternehmen. Wir beraten Sie und schlagen die beste Lösung vor.
Lesen Sie auch