Der H264-Codec unter Linux (x264)

(2008-09-15)

Zum Enkodieren meiner aufgenommenen DVB-Streams benutze ich in der Regel den MPEG4-Codec (XviD) mit mencoder. Letztens habe ich aber etwas vom H264-Codec gelesen, der angeblich bei geringerer Bitrate ein sehr viel besseres Ergebnis produzieren würde. Hier möchte ich einen kurzen Qualitätsvergleich anhand eines praktischen Beispiels geben und ein Script vorstellen, welches das Encoding einer MPEG TS-Datei in x264/ogg in einen Matroska-Container vornimmt.

Unterstützung

…für’s Enkodieren

Die mitgelieferte mencoder-Version von XUbuntu unterstützt (momentan) kein x264, daher muss man sich seine eigene aus dem Subversion-Repository bauen (somit hat man dann auch garantiert die aktuelle x264-Version). Außerdem kann man dabei viel genauer angeben, welche Codecs man (nicht) braucht und erhält am Ende eine optimierte Version :-).

Dafür richten wir uns zunächst ein eigenes Verzeichnis an und gehen hinein:

$ mkdir mplayerSVN && cd mplayerSVN

Wir brauchen auch den Sourcecode der libx264, damit sie mit der aktuellen mplayer-Version zusammenarbeitet:

$ svn co svn://svn.videolan.org/x264/trunk x264

Zum Kompilieren muss nasm installiert sein (ein Assembler-Compiler):

$ sudo apt-get install nasm

Anschließend konfigurieren wir den Sourcecode, bauen ihn und installieren ihn:

$ cd x264 && ./configure --enable-shared && make && make install

Nun wieder ein Verzeichnis zurück. Wir laden uns den aktuellen Entwicklungsstand aus dem Subversion-Repository und gehen in das dann erstellte Verzeichnis:

$ cd .. && svn co svn://svn.mplayerhq.hu/mplayer mplayer && cd mplayer

Wir konfigurieren den Sourcecode nun folgendermaßen:

./configure --enable-gui \
    --enable-largefiles \
    --disable-lirc \
    --disable-lircc \
    --disable-joystick \
    --disable-tv \
    --disable-tv-v4l1 \
    --disable-tv-v4l2 \
    --disable-tv-bsdbt848 \
    --disable-radio-v4l2 \
    --disable-radio-bsdbt848 \
    --enable-menu \
    --disable-macosx \
    --disable-inet6 \
    --enable-png \
    --enable-x264 \
    --disable-real \
    --enable-qtx \
    --enable-theora \
    --disable-sdl \
    --disable-dvb \
    --disable-dvbhead \
    --disable-ivtv \
    --disable-directx \
    --disable-mga \
    --disable-xmga \
    --disable-vidix-internal \
    --disable-vidix-external

Alle Optionen gibt’s mit ./configure --help | less. Die Optionen im Einzelnen bedeuten:

  • enable-gui: Grafische Oberfläche (gmplayer) aktivieren
  • disable-lirc und disable-lircc: Unterstützung für LIRC-Fernbedienungen deaktivieren
  • disable-joystick: Ich hab nur Tastatur und Maus :-)
  • disable-tv*, disable-radio* und disable-dvb*: Jeglichen TV/DVB-Support deaktivieren, das läuft in einer anderen Kiste
  • enable-menu: On-Screen-Menus aktivieren
  • disable-macosx: Wir kompilieren für Linux momentan
  • disable-inet6: Zumindest ich benutze es noch nicht im lokalen Netz, im Internet hat man als DSL-Endkunde wohl noch keine Chance, echtes IPv6 geroutet zu bekommen :-(
  • enable-png: Grafikausgabe von PNG-Dateien aktivieren
  • enable-x264: Die wichtigste Option und Sinn und Zweck des Kompilierens ;-)
  • disable-real: RealMedia? Nein, Danke
  • enable-qtx: QuickTime-Support aktivieren. Könnte höchstens für die Get-a-Mac-Werbespots nützlich sein… ;-)
  • enable-theora: Theora-Unterstützung (ebenfalls ein freier Codec) aktivieren
  • disable-{sdl, ivtv, directx, mga, xmga, vidix-internal, vidix-external}: Alle Displaytreiber deaktivieren, die wir nicht brauchen (nur XV eigentlich)

Und nun kompilieren wir mplayer und mencoder:

$ make

Nun kann man via ./mplayer <Datei> ausprobieren, ob mplayer funktioniert und ihn anschließend Systemweit installieren:

$ sudo make install

…für’s Abspielen

Um h264-Dateien abzuspielen, benötigt man relativ aktuelle Versionen der jeweiligen Player.

Dauer des Enkodierens

Auf meinem Athlon 64 3000+ dauert das Enkodieren von 20 MB MPEG-TS mit den höchsten Qualitätseinstellungen in H264 ca. 2,55 Minuten. Auf einem Dual Xeon 3,2 GHz dauert das Enkodieren der selben Datei (jedoch mit 4 Threads, damit die CPUs optimal belastet werden) nur 1 Minute. Mein Athlon XP 2400+ reiht sich mit 2,49 Minuten dazwischen ein.

Grafik: Performance meiner Systeme
Grafik: Performance meiner Systeme

Qualitätsvergleich

Man muss die einzelnen Bilder natürlich vergrößern (durch Anklicken), sonst werden die Unterschiede nicht deutlich. Die Bilder sind jeweils 1024x576 Pixel groß.

XviD

Frame 5 als XviD
Frame 5
Frame 40 als XviD
Frame 40
Frame 100 als XviD
Frame 100

H264

Frame 5 als H264
Frame 5
Frame 40 als H264
Frame 40
Frame 100 als H264
Frame 100

H264 Two-Pass

Frame 5 als H264 Two-Pass
Frame 5
Frame 40 als H264 Two-Pass
Frame 40
Frame 100 als H264 Two-Pass
Frame 100

H264 High-Quality

Frame 5 als H264 High-Quality
Frame 5
Frame 40 als H264 High-Quality
Frame 40
Frame 100 als H264 High-Quality
Frame 100

Die Bilder stammen übrigens aus der auf arte ausgestrahlten Dokumentation „Wer hat Angst vor Google?”.

Pro/Contra h264/XviD

Beide Formate sind Open-Source (DivX allerdings nicht). Bei h264 ist die Qualität bei geringerere Dateigröße deutlich besser, andererseits können sehr viele PCs und vor allem Standalone-Player (wie DVD-Player) mittlerweile XviD abspielen – bis diese auch h264 können, wird noch etwas Zeit vergehen. Der Rechenaufwand beim Abspielen von h264-Dateien ist in der Regel höher, sodass Geräte mit schwachen Prozessoren eventuell Probleme haben.

Weiterhin zu beachten ist, dass x264 momentan noch nicht fertig entwickelt ist, sodass es eventuell passieren kann, dass enkodierte Dateien nicht mehr fehlerfrei abgespielt werden können. Um das zu vermeiden, kann man sich den mplayer-Sourcecode zum Zeitpunkt des Enkodierens aufheben (oder zu späterem Zeitpunkt aus dem Subversion-Repository auschecken).

Für das reine Verteilen von Videos über das Internet, die hauptsächlich auf PC oder Laptop angeschaut werden sollen (und idealerweise als Zielgruppe die Open-Source-Gemeinde haben, da zum Beispiel mplayer super mit h264 umgehen kann), ist daher h264 meiner Meinung nach die bessere Wahl.

Geht es allerdings darum, Filme auch für’s Ansehen im Wohnzimmer zu archivieren, sollte man momentan noch XviD verwenden. Man kann natürlich auch eine XviD-Version aus einem h264-Video erstellen, dies bringt aber Qualitätsverluste mit sich…

Encoding

Das Script könnt ihr euch auch direkt herunterladen.

#!/bin/sh

(c) 2007 Michael Stapelberg

http://michael.stapelberg.de/Artikel/x264

#

Return codes:

0 Everything was OK

1 Not all necessary programs have been installed

2 Encoding failed

#

Syntax is:

encodeMKV.sh <source-file> <title> [output-file]

------------------------------------------------------------------------

Configuration

------------------------------------------------------------------------

Ogg-Quality (from 0 to 10)

OGG_QUALITY=5

Bitrate for x264-video

X264_BITRATE=1000

If you do not want to install the programs in $PATH, you can

specify their path here hard-coded...

MENCODER=which mencoder MPLAYER=which mplayer OGGENC=which oggenc MKVMERGE=which mkvmerge

------------------------------------------------------------------------

Don't touch the script below if you do not know what you're doing :)

------------------------------------------------------------------------

Check if all programs are here before starting the work

if [ -z "${MENCODER}" -o -z "${MPLAYER}" ]; then echo "Error: mencoder or mplayer was not found. Please install it" exit 1 fi

if [ -z "${OGGENC}" ]; then echo "Error: oggenc was not found. Please install it" exit 1 fi

if [ -z "${MKVMERGE}" ]; then echo "Error: mkvmerge was not found. Please install it" exit 1 fi

Check if the necessary parameters were given

if [ -z "${2}" ]; then echo "Syntax: ${0} <source-file> <title> [output-file]" exit 1 fi

Define filenames

SRC_VID=${1} TMP_VID=${1}.tmpv TMP_AUD=${1}.tmpa

TITLE=${2} if [ -z "${3}" ]; then MKV=${1}.mkv else MKV=${3} fi

if [ ! -f "${SRC_VID}" ]; then echo "Error: Sourcefile does not exist" exit 2 fi

echo -e "\nx264/matroska-encode-script\n" echo "------------------------------------------------------------------------" echo "Encoding \"${SRC_VID}\" to \"${MKV}\"..." echo -e "\tTitle: ${TITLE}" echo -e "\t(Temporary video file: ${TMP_VID})" echo -e "\t(Temporary audio file: ${TMP_AUD})" echo -e "------------------------------------------------------------------------\n"

Delete the tempfiles

rm -f "${TMP_VID}" "${TMP_AUD}" "${TMP_AUD}.ogg"

Encode video

${MENCODER} -really-quiet -ovc x264 -x264encopts
bitrate=${X264_BITRATE}:subq=6:partitions=all:8x8dct:me=umh:frameref=5:bframes=3:b_pyramid:weight_b:pass=1
-oac copy -of rawvideo -o "${TMP_VID}" "${SRC_VID}" 1>&- || { echo -e "\nError: mencoder could not encode the file. Check the printed errors" exit 2 } ${MENCODER} -really-quiet -ovc x264 -x264encopts
bitrate=${X264_BITRATE}:subq=6:partitions=all:8x8dct:me=umh:frameref=5:bframes=3:b_pyramid:weight_b:pass=2
-oac copy -of rawvideo -o "${TMP_VID}" "${SRC_VID}" 1>&- || { echo -e "\nError: mencoder could not encode the file. Check the printed errors" exit 2 }

Extract audio

${MPLAYER} -really-quiet -vo null -ao pcm:fast:file="${TMP_AUD}" "${SRC_VID}" || { echo -e "\nError: Audio-track could not be extracted via mplayer. Check the printed errors" exit 2 }

Encode audio

${OGGENC} -Q -q${OGG_QUALITY} "${TMP_AUD}" -o "${TMP_AUD}.ogg" || { echo -e "\nError: Audio-track could not be converted to ogg. Check the printed errors" exit 2 }

Mux files to MKV

${MKVMERGE} -q -o "${MKV}" --title "${TITLE}" --default-language ger "${TMP_VID}" "${TMP_AUD}.ogg" || { echo -e "\nError: Files could not be muxed to mkv. Check the printed erorrs" exit 2 }

Delete tempfiles

rm "${TMP_VID}" "${TMP_AUD}" "${TMP_AUD}.ogg"

echo -e "\n------------------------------------------------------------------------" echo "Created videofile \"${MKV}\"!" echo "------------------------------------------------------------------------"