mpeg2cleaner

In der Spezifikation für MPEG-2 Video (ITU-T Recommendation H.262 bzw. ISO/IEC 13818-2) werden bei einem Videostream verschiedene Datenblöcke benutzt, die alle mit dem Startcode-Präfix 0x00 0x00 0x01 beginnen. Wenn ein Datenblock zuende ist, können vor dem nächsten Datenblock noch beliebige Mengen an Nullbytes eingefügt werden. In der Spezifikation wird das als zero byte stuffing bezeichnet. Im Hex-Editor sieht das dann so aus:
Videostream im Hex-Editor
Der grau markierte Bereich ist ein solcher Bereich mit zero byte stuffing und würde dann vom mpeg2cleaner entfernt werden; die Startcode-Präfixe sind rot markiert.

Durch solche Bereiche kann die Datenrate eines Videostream erhöht werden, was vor allem bei DVB-S gemacht wird. Laut einer ARD-Anstalt wird das eingesetzt, weil bestimmte Receiver-Chipsätze Probleme mit zu geringen Datenraten haben. Der graue Bereich sieht hier klein aus (und ist je nach Fernsehsender auch wesentlich größer), aber in der Summe macht sich die Menge dann schon bemerkbar. Zum Beispiel bei ARD-alpha (früher: BR-alpha) über Satellit fielen konstant ca. 270 MB/h bzw. ca. 17% an diesen Fülldaten an - relativ viel, wenn man dort eine längere Sendung aufnimmt. Seitdem Anfang 2015 der für die Programmverbreitung zuständige WDR den Encoder erneuerte, wird ARD-alpha ohne nennenswerte Fülldaten ausgestrahlt.

Durch den mpeg2cleaner können solche Bereiche aus einem MPEG-2-Elementarstrom (*.m2v) entfernt werden. Wenn man also eine TV-Aufnahme gemacht hat, kann man nach der Behandlung mit ProjectX und MPEG2Schnitt den mpeg2cleaner darüberlaufen lassen, um die nutzlosen Fülldaten zu entfernen. Am Bildinhalt selbst ändert sich dabei natürlich gar nichts.

 Funktionsweise

Im Programm werden dabei die eigentlichen Videodaten nicht interpretiert - es werden nur Bereiche behandelt, die hinter einem Slice kommen (warum, kommt noch). Laut der MPEG-2-Spezifikation darf im Stream keine startcode emulation stattfinden - das o.g. Startcode-Präfix darf also tatsächlich nur am Anfang von Datenblöcken auftreten. Das bedeutet: Lange Blöcke mit Nullbytes können im Videostream nur vor einem neuen Datenblock, also hinter dem vorherigen Datenblock (bzw. seinen Nutzdaten) vorkommen. Wenn das nicht so wäre, würde irgendwann im Stream ein 1-Bit kommen und durch die 0-Bits davor würde dann verbotenerweise startcode emulation stattfinden. Die eindeutige Lage von langen Nullbyte-Blöcken ist damit klar.

Beim Anfang eines solchen Blocks weiß man nun aber erstmal nicht, ob nicht ein Teil der Nullbytes noch zu den Nutzdaten des vorherigen Blocks gehört - prinzipiell wäre das möglich. Zumindest bei Slices kann man dieses Problem eingrenzen (deswegen werden hier nur sie beachtet): Slices bestehen aus Macroblöcken, die im Normalfall wiederum aus einzelnen Blöcken für Luminanz und Farbanteile bestehen. Hinter den DCT-Koeffizienten dieser Blöcke muss dabei immer ein EOB-Symbol (end of block) stehen. Dieses ist mehrere Bits lang und enthält dabei mindestens ein 1-bit - kann also für die Erkennung des Endes der Nutzdaten genutzt werden (nachher kommen ja nur noch 0-Bits). Falls ein Macroblock einmal nicht intracodiert sein sollte und im Endeffekt kein EOB-Symbol besitzt, übernimmt ein Markerbit (Wert 1) diese Aufgabe.

Das ungefähre Ende der Nutzdaten ist jetzt bekannt und man könnte jetzt theoretisch ab dem letzten Byte vor dem Beginn eines großen Nullbyte-Blocks alle Nullbytes verwerfen bis auf zwei, die zum nächsten Startcode-Präfix gehören. Allerdings könnte das letzte Bit des EOB-Codeworts - in beiden möglichen Fällen mit Wert 0 - im ersten Byte des Nullbyte-Blocks enthalten sein. In dem Fall würde dann das folgende Startcode-Präfix nicht erkannt werden und der Videostream wäre fehlerhaft. Deswegen muss hier auf die Entfernung eines zusätzlichen Bytes verzichtet werden, damit die Nutzdaten im Videostream auf keinen Fall beschädigt werden. Theoretisch könnte man die Nutzdaten auch parsen, um eventuell dieses Byte doch zu entfernen - der Aufwand wäre hier aber nicht gerechtfertigt.

Diesen Erläuterungen nach werden insgesamt nun also Nullbyte-Blöcke, die mehr als drei Byte lang sind und sich hinter einem Slice befinden, auf drei Byte zusammengeschrumpft.

Ausgabe auf der Konsole
mpeg2cleaner-Ausgabe bei Anwendung auf den Abspann (siehe Beispiel unten)

Bei Fragen, Vorschlägen, Kritik etc. bitte an die Kontaktadresse im Homepage-Impressum wenden.


 Beispiel

Vor allem Sender über Satellit sind davon betroffen. Ein extremes Beispiel ist die Ausstrahlung von dem Film "Control (2004)" (ruhige Bilder) im rbb am 02.01.2011 per DVB-S. Auf den folgenden Screenshots sieht man den Verlauf der Video-Bitrate im Laufe der Zeit - einmal vor und nach Behandlung:

Ganzer Film vorher Ganzer Film vorher
Der gesamte Film ist vorher 5.660 MB und nachher 5.040 MB groß - damit wurden ganze 620 MB (11,0 %) Fülldaten entfernt.

Abspann vorher Abspann vorher
Beim Abspann (am Anfang mit Standbildern) wird es noch deutlicher: Vorher 142 MB, nachher 58 MB; es wurden 84 MB (59,3 %) Fülldaten entfernt.

 Alternative Programme

Mittlerweile gibt es auch ein paar andere Programme, die MPEG2-Füllbytes entfernen. Das Entfernen kann dabei entweder auf Elementarstrom (ES)-Ebene geschehen (wie hier) oder auf Transportstrom (TS)-Ebene. Im letzteren Fall werden bei relativ kleinen Nullbyte-Blöcken die Füllbytes nur zu einem gewissen Anteil entfernt - im Fall ARD-alpha über DVB-S wurden sogar gar keine entfernt. In so einem Fall sollte man nachher nochmal ein Programm über den Videostream laufen lassen, was auf ES-Ebene arbeitet.
Falls jemand eine ähnliche Funktion in seinem Programm benutzt, würde ich mich über einen Hinweis freuen, damit ich das Programm hier auflisten kann.

 Download

EXE mpeg2cleaner v1.4 - Windows-Version

ZIP mpeg2cleaner v1.4 - C++ Quellcode

 Versionsgeschichte

v1.4 (04.02.2015)

v1.3 (19.12.2013)

v1.2 (05.10.2013)

v1.1 (13.04.2012)

v1.0 (20.01.2012)

Impressum