Ogg-Vorbis

Hintergrund

Das Programm ffmpeg zum Verarbeiten von verschiedenen Audio- und Videodaten hatte leider eine Zeit lang einen Fehler, so daß die erzeugten Ogg-Dateien von ogg-info als problematisch angezeigt wurden:

Die Dateien konnten zwar noch alle abgespielt werden, jedoch war das nicht-spulen-können eine zu große Einschränkung, weshalb die Dateien korrigiert werden sollten.

Grundwissen

Vorbis ist ein Audio-Codec und ein Datenformat zur komprimierten Speicherung von Audiodaten. Das Format ist verlustbehaftet und erzielt ähnliche Komprimierungsraten wie MP3.

Ogg ist ein Container-Format für Multimediadaten. Neben Audio-Daten können auch Video-Daten und Untertitelinformationen darin gespeichert werden. Dazu werden die einzelnen Pakete der Codecs den Zeitstempeln nach geordnet ineinander verwoben und auf sog. Seiten verteilt. Die Pakete werden dazu in einzelne Segmente zu maximal 255 Byte zerhackt und normalerweise zu Seiten von ca. 4 KiB zusammengestellt.

Seite
Größe richtet sich nach der Übertragung, z.B. beim Streaming per TCP und UPD. Kleine Seiten erhöhen den Anteil der Verwaltungsinformation, große Seiten brauchen ggf. zu viel Speicherplatz beim Empfänger zum Zwischenspeichern und Abspielen.
Paket
Größe richtet sich nach dem Codec, z.B. bei Audio wenige Millisekunden oder bei Video die Daten eines einzelnen Bildes. Gerade bei Video kann die Größe stark variieren.
Segment
Fragment eines Pakets für die Platzierung innerhalb einer Seite.
Granule-Position
Lineare Position innerhalb der OGG-Datei. Der genaue Wert ist Codec-abhängig: Für Vorbis ist dies z.B. die Anzahl der Samples nach der Kodierung, für den Theora-Video-Codec eine Kombination aus Sekunden und Frame-Position. Erst das Skeleton-Format stellt eine Möglichkeit zur Verfügung, diese Umrechnungsinformationen allgemeingültig anzugeben, so daß sich die Informationen selbst dann berechnen lassen, wenn nicht alle Codecs bekannt sind.

Ansatz 1

oggdec ALT.ogg | oggenc NEU.ogg verschlechtert nicht nur die Qualität, sondern hat eine hohe Laufzeit, da die Datei nicht nur dekomprimiert, sondern auch wieder effizient komprimiert werden müsste. Die Lösung schied aus diesen beiden Gründen aus.

Ansatz 2

Nach Möglichkeit sollen die Änderungen in-place erfolgen: Sowohl die Seriennummer als auch die Granule-Position stehen im Ogg-Header. Die Seriennummer kann direkt geändert werden und erfordert zusätzlich die Neuberechnung der crc32-Prüfsumme.

Zur Berechnung der Granule-Position müssen die Daten allerdings dekodiert werden, was aber wesentlich effizienter als die Enkodierung ist. Danach kann die Granule-Position sowie die Prüfsumme aktualisiert werden.

Der Overhead läßt sich so aber nicht in-place verringern, denn dazu müssen mehrere Pakete auf eine Seite umgepackt werden.

Implementierung

Die Programm sind in C geschrieben und lassen sich mit gcc übersetzen. Neben einem selbstgebauten Parser für Ogg-Dateien wird aber auch libogg für das Re-Multiplexing und libvorbis für die Neuberechnung der Granule-Position benötigt. Ein Makefile ist vorhanden.

Die Quelltexte sind über git clone http://pmhahn.de/git/ogg/ verfügbar.

ogg-fix-eos.c
Setzt in-place die end-of-stream-Markierung auf der letzten Seite
ogg-remux.c
Liest eine Datei ein und schreibt sie direkt wider zurück. Dadurch wird die Datei neu auf eine Seitengröße von ca. 4 KiB gemultiplext und eine ggf. vorhandene Seriennummer 0 durch 0x00031415 ersetzt.
ogg-vorbis-header-dump.c
Liest eine Datei und gibt alle Felder und deren Belegung aus.
ogg-vorbis-recalc-granule.c
Korrigiert in-place die Granule-Position, Seriennummer und eos-Markierung.
ogg-vorbis-redo.c
Korrigiert die Granule-Position, Seriennummer und eos-Markierung und führt dabei ein Remultiplexing durch.
ogg-stat.c
Sammelt statistische Daten der OGG-Dateien.
ogg-vorbis-index.c
Gibt die Header-Informationen der OGG-Vorbis-Dateien tabellarisch aus.
bit.h, bit.c
Bit-Friemelei
crc32.h, crc32.c
crc32 Prüfsummenberechnung
ogg.h, Makefile
Gemeinsame Dateien