Videos verarbeiten stellt Benutzer meist vor eine harte Geduldsprobe, selbst wenn der eingesetzte Rechner über eine schnelle CPU und viel Arbeitsspeicher verfügt. Mit dem nötigen Wissen und der passenden Hardware macht er dem Prozess jedoch über die Hardwarebeschleunigung der Grafikkarte Beine.
Ffmpeg [1] ist wohl eines der am weitesten verbreiteten Werkzeuge, um Videodateien zu manipulieren. Die Bibliotheken des Projekts kommen in diversen grafischen Frontends zum Einsatz. Hardware-seitig helfen meist Grafikkarten bei der Videoverarbeitung – zumindest beim Dekodieren. Mit den richtigen Optionen und der passenden Hardware erzielen sie in bestimmen Fällen dramatische Leistungssteigerungen. Der Artikel demonstriert, wie Anwender Ffmpeg mit der Hardwarebeschleunigung verheiraten und wann das überhaupt Sinn ergibt.
Der Klassiker mit CPU
Videokameras oder digitale Videorecorder wie TV-Headend [2] nehmen Videos in einem Format wie Mpeg 2 entgegen, um sie dann in ein Containerformat wie MP4 oder MKV zu verpacken. Videocodecs wie H.264 oder das neuere H.265 erlauben es, Dateien wesentlich effizienter zu speichern. Der Nachteil: Abhängig von der Einstellung funktioniert die Kompression nicht mehr verlustfrei und wird unter Umständen beim Anschauen sichtbar.
Kommen keine Transformationen wie Größenumwandlungen oder Filter zum Einsatz, wandelt Ffmpeg Videos um, indem es Video- und Audioströme liest, dekodiert und dann wieder enkodiert. Ffmpeg ist dabei schlau genug, sich gleich auf mehrere CPUs zu stützen, wenn diese vorhanden sind. Der Parameter »-threads X« erlaubt es dem Benutzer dabei, die Anzahl der parallel arbeitenden Threads (und damit der genutzten CPUs) selbst festzulegen.
Im einfachsten Fall konvertiert der Anwender ein Video mit dem Befehl:
ffmpeg -i Quelldatei Zieldatei.format
Ffmpeg erkennt das richtige Format in der Regel automatisch. Die Codecs für das Ziel wählt die Software dabei anhand des Containertyps. Für Matroska-Container (».mkv«) greift sie etwa zu x264 als Standardcodec für den Videostream.
Turbogang einlegen
Um dem Prozess Beine zu machen, setzt Ffmpeg auf die Option »-hwaccel«, die als Argument die Art der Beschleunigung mitnimmt. Wer allein »-hwaccels« eingibt (mit einem “s” am Ende), dem präsentiert Ffmpeg eine Liste der einkompilierten Methoden (Listing 1).
Listing 1
Hardwarebeschleunigung in Ffmpeg
01 #> ffmpeg -hwaccels 02 ffmpeg version 2.8.11-0ubuntu0.16.04.1 Copyright (c) 2000-2017 the FFmpeg developers 03 built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 20160609 04 configuration: --prefix=/usr --extra-version=0ubuntu0.16.04.1 --build-suffix=-ffmpeg --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --cc=cc --cxx=g++ --enable-gpl --enable-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-libx264 --enable-libopencv 05 libavutil 54. 31.100 / 54. 31.100 06 libavcodec 56. 60.100 / 56. 60.100 07 libavformat 56. 40.101 / 56. 40.101 08 libavdevice 56. 4.100 / 56. 4.100 09 libavfilter 5. 40.101 / 5. 40.101 10 libavresample 2. 1. 0 / 2. 1. 0 11 libswscale 3. 1.101 / 3. 1.101 12 libswresample 1. 2.101 / 1. 2.101 13 libpostproc 53. 3.100 / 53. 3.100 14 Hardware acceleration methods: 15 vdpau
Die Webseite unter [3] erklärt die Methoden, die sich jeweils als Schlüsselwörter für die »-hwaccel«-Option eignen. Listing 1 zeigt die Ausgabe des unter Ubuntu 16.04 gelieferten Ffmpeg, das nur Vdpau unterstützt. Das steht für “Video Decode and Presentation API for Unix” [4] und stammt von Nvidia. Es soll in erster Linie komprimierte Videoformate auf der Grafikkarte dekodieren und diese für das Abspielen von Videos einspannen.
Vdpau
Logisch funktioniert Vdpau so, dass die Libav die komprimierten Videoframes an die GPU schickt, die diese dekodiert. Mit Hilfe des Vdpau-API holt nicht Ffmpeg selbst, sondern die darüberliegende Video-Anwendung (etwa VLC) die ausgepackten Daten ab.
Ähnlich wie bei X11 gibt es auch für Vdpau Treiber, die das API auf die konkrete Hardware abbilden. Unter Ubuntu finden sich etwa im Paket »mesa-vdpau-drivers« Treiber für den freien Nouveau-, aber auch für den freien »radeon«-Treiber (AMD). Vdpau unterstützt dabei die Codecs H.264, Mpeg 1, 2, 4 sowie VC 1, wobei auch eine Rolle spielt, welche Codecs die verbaute Grafikkarte unterstützt. Ein Aufruf für Ffmpeg sieht dann wie folgt aus:
ffmpeg -hwaccel vdpau -i Testvideo.MPG Testvideo.mkv
Auf dem Rechner des Autors mit einer sehr alten Radeon-Karte (Radeon HD 4250) lieferte der Befehl nur ein Viertel der Performance, den eine reine CPU-Kodierung bringt. Um zu funktionieren, benötigt Vdpau zugleich einen laufenden X-Server, da das System über diesen auf die Grafikkarte zugreift.
VA-API
Die zweite Option zur Grafikbeschleunigung liefert VA-API (Video Acceleration API, [5]). Intel hat es für seine GMA-GPUs entwickelt. Es funktioniert ähnlich wie Vdpau, auch hier kommen wieder Treiber zum Zug. Die Bibliothek unterstützt AMD-GPUs über die Schnittstellen UVD (Unified Video Decoder) und VCE (Video Coding Engine). Das Dekodieren gelingt mit GPUs mit Graphics Core Next (GCN) und deren Nachfolgern. Dabei beherrschen die Karten dieselben Algorithmen wie Vdpau.
Karten ab GCN 3 unterstützen dann auch den recht Ressourcen-intensiven Codec H.265, der zum Beispiel in Deutschland bei DVB-T2 zum Einsatz kommt. Das Einpacken der Daten beherrschen GPUs von AMD nur für H.264 (abhängig vom Modell der Grafikkarte).
Für die Grafikchips von Intel spielt die Generation des Chips eine ausschlaggebende Rolle für den VA-API-Support. Sie bestimmt darüber, welche Funktionen und Codecs der Chip unterstützt. Der Marketingname, unter dem diese Funktionen bei Intel laufen, lautet “Intel Quick Sync Video”.
Auch hier reden bestimmte Treiber mit der Hardware. Der i965-Treiber ist quelloffen, ihn gibt es als fertiges Paket, das bei Ubuntu und Debian »i965-va-driver« heißt. Alternativ existiert noch der auf der proprietären MFX-Bibliothek von Intel basierende iHD-Treiber, der in bestimmten Fällen etwas bessere Ergebnisse beim Enkodieren erzielen soll.
Auf dem zweiten Testlaptop war neben einer durchschnittlichen Nvidia-Karte (Geforce GTX 950M) auch ein Intel-Grafikchip (in der CPU) integriert. Der Ffmpeg-Aufruf mit VA-API-Support muss in diesem Fall gezielt die richtige Grafikkarte ansprechen:
ffmpeg -hwaccel vaapi -hwaccel_output_ format vaapi -hwaccel_device /dev/dri/renderD129 -i Testvideo.MPG -c:v h264_vaapi Testvideo-Intel.mkv
Im Gegensatz zur Umwandlung mit der CPU dauerte der Lauf hier nur 13 Sekunden (Vergleich in Abbildung 1). Auch die Option »-preset slow« beeinflusste die Laufzeit nur minimal. Sie sorgt dafür, dass Ffmpeg Videos sorgfältiger, aber auch langsamer kodiert. Das führt zu deutlich besseren Ergebnissen und weniger Fragmenten im Bild.

Abbildung 1: Die verschiedenen Tests zeigen: Mit Cuvid und Nvenc klappt das Transkodieren am schnellsten, mit Software-Enconding (CPU) dauert es am längsten.
Ffmpeg mit Cuda
Mit dem Cuda-SDK öffnete Nvidia Entwicklern schon sehr früh eine Tür, um die Rechenpower ihrer Grafikkarten für andere Zwecke zu nutzen. Selbst das Knacken von WLAN-Passwörtern gelingt mit Hilfe der richtigen GPU und dem Cuda-SDK deutlich schneller.
Entsprechend unterstützt auch Ffmpeg Cuda, kompiliert es in der Regel aber nicht mit ein. Ein Grund könnte sein, dass Cuda, wie alle Applikationen, die es verwenden, den proprietären Nvidia-Treiber voraussetzt.
Laut Recherche für den Artikel braucht das aktuelle Ffmpeg aus dem Git-Repository den Nvidia-Treiber, momentan ab Version 3.82. Wer ihn installieren möchte, findet auf Nvidias Webseite eine Anleitung zum Thema [6]. Unter Ubuntu genügt das Hinzufügen des PPA »graphics-drivers/ppa« über folgenden Eintrag:
add-apt-repository ppa:graphics-drivers/ppa`
Danach installiert der Admin die Pakete »nvidia-384«, »nvidia-384-dev«, »libcuda1-284« und »nvidia-cuda-dev«.
Da es kein einzelnes Nvidia-Paket gibt, das der Admin einfach per »apt-get update« auf den neuesten Stand bringt, sondern neue Nvidia-Treiber stets neue Paketnamen tragen (mit der Versionsnummer), muss er diese manuell aktualisieren [7]. Im nächsten Schritt klont er die aktuelle Version von Ffmpeg aus dem Git-Repository:
git clone https://github.com/ffmpeg/FFMPeg
Beim Aufruf von »./configure« gehören »nvenc« und »cuvid« in die Liste der aktivierten Abhängigkeiten, womit auch sie in der erzeugten Binärdatei landen.
Um auch alle anderen wichtige Algorithmen einzubinden, verwendete der Autor die »./configure«-Zeile aus Listing 2. Die letzten Algorithmen sind nur der Vollständigkeit halber mit von der Partie, damit das selbst kompilierte Ffmpeg mit dem von Ubuntu vorgebauten vergleichbar ist. Ein schlichtes »make« löst die Übersetzung aus, die Ergebnisdatei landet direkt im Source-Verzeichnis.
Listing 2
Nvidia-Support für Ffmpeg
01 ./configure --enable-cuda \ 02 --enable-cuvid \ 03 --enable-nvenc \ 04 --enable-nonfree \ 05 --enable-libnpp \ 06 --enable-opengl \ 07 --enable-vaapi \ 08 --enable-vdpau \ 09 --enable-libvorbis \ 10 --enable-libmp3lame \ 11 --enable-libx264 \ 12 --enable-libx265 \ 13 --enable-gpl
Um sie zu testen, kam eine fünfminütige Aufnahme aus einer Videokamera im Mpeg-2-Format zum Einsatz. Auf dem Testlaptop, der eine i5-Quadcore-CPU mit 2,8 GHz nutzt, dauerte das Transkodieren der Testdatei mit dem Aufruf
./ffmpeg -i Testvideo.mpg Testvideo.mkv
1 Minute und 8 Sekunden. Das heißt, dass das Umwandeln mit Ffmpeg auf diesem Wege rund 4,5-mal schneller (laut Ffmpeg 4,36-mal) ablief, als das ganze 5-minütige Video zum Abspielen in Echtzeit gebraucht hätte. Mit »-preset slow« dauerte das Umwandeln zwar 1,42 Minuten, gelang aber immer noch dreimal schneller.
Übernimmt die Grafikkarte das Enkodieren, ist der folgende Aufruf notwendig:
./ffmpeg -c:v h264_nvenc nvenc-plain.mkv
Danach wandelt Ffmpeg das Video in nur 14 Sekunden um – was etwa einem 21stel der Laufzeit des Videos entspricht. Mit dem Parameter »-preset slow« dauert es ebenfalls nur 14 Sekunden.
Die optimale Leistung erzielt Ffmpeg aber, wenn die Grafikkarte auch das Dekodieren übernimmt:
./ffmpeg -hwaccel cuvid -c:v mpeg2_cuvid -i ../Testvideo.MPG -c:v h264_nvenc cuvid-nvenc-plain.mkv
Den Parameter nach dem ersten »-c:v« wählt der Benutzer abhängig vom Videocodec der Quelldatei, der Befehl »ffprobe Testvideo.MPG« gibt diese Informationen aus. Tippt der Admin dann »ffmpeg -decoders | grep cuvid« ein, zeigt das die unterstützten Hardware-Dekoder. Am Ende dauerte das Konvertieren des Testfilms 8 Sekunden (37-mal schneller) sowie 11 Sekunden (27-mal schneller) beim »-preset slow«. Und das, obwohl die in der Testmaschine verbaute Grafikkarte nicht gerade als Highend-Modell gilt.
Neuere Karten liefern auch Support für das De- und Enkodieren von H.265/HEVC. Der Versuch mit dem alten Modell führte zum Ergebnis in Abbildung 2.
Raspberry Pi
Auch der Raspberry Pi bringt auf seinem SoC Hardware-Unterstützung für einige Algorithmen mit. Fehlen die, wird das Abspielen von Videos schwierig. Auch hier muss der User Ffmpeg selber übersetzen und die Optionen (»–enable-omx«, »–enable-omx-rpi«) aktivieren. Der Pi dekodiert auch einige Codecs in Hardware, braucht dafür bei Mpeg 2 aber eine Lizenz, die extra zu beschaffen ist. Für den Test konfigurierte der Autor Ffmpeg mit den Optionen aus Listing 3. Raspbian verlangte noch nach den Paketen »libmp3lame-dev« und »libx264-dev«.
Listing 3
Konfiguration für den Raspberry Pi
01 ./configure --arch=armel \ 02 --target-os=linux \ 03 --enable-gpl \ 04 --enable-omx \ 05 --enable-omx-rpi \ 06 --enable-mmal \ 07 --enable-nonfree \ 08 --enable-libmp3lame \ 09 --enable-libx264
Der Aufruf zum Transkodieren des Testvideos mit Hardwaresupport lautet dann:
./ffmpeg -i ~/Testvideo.MPG -c:v h264_omx Testvideo.MKV
Will der Admin (bei vorhandener Lizenz) auch die Hardwaredekodierung verwenden, nutzt er den folgenden Aufruf:
./ffmpeg -c:v mpeg2_mmal -i ~/Testvideo.MPG-c:v h264_omx Testvideo.MKV
Wie schon bei den Nvidia-Treibern muss der Admin hier manuell den richtigen Hardwaredekodierer passend zur vorliegenden Datei auswählen, wobei »h264_mmal« auch ohne Lizenz funktioniert.
Der relative Performance-Unterschied auf dem Raspberry Pi 1 des Autors war gewaltig: Brauchte die Software-Enkodierung 40-mal mehr Zeit, als der Film lang war (Faktor 0,025), lag der Faktor mit Beschleunigung nur noch bei 0,65 und arbeitete Ffmpeg 26-mal schneller.
Auf dem Raspberry Pi 3 fiel der Sprung nicht ganz so gewaltig aus, da hier vier Kerne an der Datei arbeiten. Die Softwarevariante brachte es hier auf den Faktor 0,2, während die beschleunigte Variante auf den Faktor 1,4 kam, also knapp 7-mal schneller arbeitete als mit dem Software-Enkoder.
Beim Raspberry Pi sollte der Admin noch beachten, den GPU-Speicher über die Option »gpu_mem« in der Datei »/boot/config.txt« nicht zu niedrig einzustellen (ein Forumseintrag sprach von mindestens 128 MByte), damit der Encoder arbeiten kann. Zudem kann die GPU nur im H.264-Format kodieren.
Fazit
Wer häufiger Videodateien von einem in einen anderen Codec umwandeln möchte, kann mit der passenden Grafikkarte und den richtigen Treibern viel Zeit sparen. Die Karten unterstützen auch Video-Effekte und Hardware-basiertes Umskalieren von Videos, die HW-Accel-Webseiten von Ffmpeg [3] zeigen einige Beispiele hierfür.
Die Feineinstellungen sollten Admins aber auf Herz und Nieren prüfen, da die Hardwarekodierer Videos in schlechterer Qualität erzeugen. Hier gilt es, zunächst etwas Videomaterial umzuwandeln und anzuschauen. Bei Videos in niedriger Auflösung fällt es womöglich nicht so schnell auf, aber Videos mit hoher Auflösung (Full HD) und viel Bewegung (etwa bei Sportveranstaltungen) zeigen unter Umständen Fragmente.
Infos
- Ffmpeg: http://www.ffmpeg.org
- TV-Headend: http://tvheadend.org
- Ffmpeg und Hardwarebeschleunigung: https://trac.ffmpeg.org/wiki/HWAccelIntro
- Vdpau: https://www.freedesktop.org/wiki/Software/VDPAU/
- VA-API: https://01.org/linuxmedia/vaapi
- Nvidias Ffmpeg-Seiten: https://developer.nvidia.com/ffmpeg
- Allgemeines zu Nvidia und Videoverarbeitung: https://developer.nvidia.com/nvidia-video-codec-sdk






