Medienverarbeitung mit Java in elementaren Einheiten Studienarbeit Name: Verena Henrich Dieburger Weg 9 64390 Erzhausen Studiengang: Informationstechnik Kurs: TIT03ANS Semester: WS 05 / SS 06 Betreuer: Patrick Wolf Firma: Fraunhofer IPSI Dolivostraße 15 64293 Darmstadt Universität: Berufsakademie Mannheim Coblitzweg 7 68163 Mannheim Abgabedatum: 1. Juni 2006 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Kurzfassung Eine einfache Möglichkeit kontinuierliche, digitale Medien (Audio, Video, etc.) aufzufassen, ist sie als Folge von elementaren, semantischen Einheiten zu verstehen. Solch eine Einheit stellt einen grundlegenden Bestandteil eines Mediums mit semantischer Bedeutung dar. Beispielsweise besteht ein Video aus einer Folge einzelner Bilder (Frames), die jeweils eine elementare, semantische Einheit repräsentieren. Eine solche Interpretation ermöglicht die Verarbeitung digitaler Medien auf einer höheren Abstraktionsebene als die herkömmliche Interpretation digitaler Medien als Byteströme. In Java steht für die Verarbeitung digitaler Medien das Java Media Framework (JMF) zur Verfügung. Darin kommunizieren die einzelnen Glieder der digitalen Verarbeitungskette über einfache Byte-Array-Ströme miteinander. Das JMF erlaubt auch eigene Glieder (Plug-Ins) zu entwickeln und dieser Verarbeitungskette hinzuzufügen. Ein Plug-In besteht aus einer oder mehreren Klassen und ist unabhängig vom eigentlichen Programm. Es kann dynamisch in ein Programm eingebunden und an einer bestimmten Stelle im Programmfluss verwendet werden. In dieser Arbeit wird vorgestellt, wie der Plug-In-Mechanismus des JMF genutzt werden kann, um das Verarbeiten digitaler Medien in elementaren, semantischen Einheiten zu ermöglichen. Es wird dabei ein DivideIntoUnits-Plug-In entwickelt, das Videos des MPEG-1-Standards in solche Einheiten zerlegen kann. Als mögliche, darauf aufsetzende Anwendung wird eine Watermarker-Klasse umgesetzt, mit der einzelne Frames mit digitalen Wasserzeichen markiert werden können. Dafür wird ein Konzept entwickelt, bei dem die elementaren, semantischen Einheiten durch individuelle Frame-Klassen repräsentiert werden und so die beispielhaft aufsetzende Anwendung des Verfahrens digitaler Wasserzeichen ermöglicht wird. Ehrenwörtliche Erklärung Ich versichere hiermit, dass ich die vorliegende Arbeit mit dem Titel Medienverarbeitung mit Java in elementaren Einheiten selbständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel verwendet habe. Ort, Datum Unterschrift ii Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Inhaltsverzeichnis Kurzfassung................................................................................................................. ii Ehrenwörtliche Erklärung............................................................................................. ii Inhaltsverzeichnis ....................................................................................................... iii Abbildungsverzeichnis ................................................................................................ iv 1 Einleitung............................................................................................................. 1 1.1 Begriffsbildung: Elementare Einheiten ......................................................... 2 2 MPEG.................................................................................................................. 3 2.1 Notwendigkeit der Komprimierung ............................................................... 3 2.2 Grundlagen .................................................................................................. 3 2.3 Aufbau.......................................................................................................... 5 2.4 Elementare Einheiten in MPEG.................................................................... 7 3 Java Media Framework (JMF)............................................................................. 9 3.1 Grundlagen .................................................................................................. 9 3.2 Medienverarbeitung im JMF....................................................................... 10 3.3 Plug-Ins im JMF ......................................................................................... 11 4 Umsetzung des Projektes.................................................................................. 13 4.1 DivideIntoUnits-Plug-In............................................................................... 13 4.1.1 MPEG-Verarbeitung im JMF ............................................................... 13 4.1.2 Abstraktionsebene elementare Einheiten............................................ 15 4.1.3 Problem von binärer und hexadezimaler Schreibweise in Java .......... 16 4.2 Weiterverarbeitung der elementaren Einheiten .......................................... 17 4.2.1 Digitale Wasserzeichen....................................................................... 18 4.2.1.1 Grundlagen .................................................................................. 18 4.2.1.2 Eigenschaften .............................................................................. 18 4.2.1.3 Anwendungsgebiete .................................................................... 19 4.2.1.4 LSB-Wasserzeichen .................................................................... 20 5 4.2.2 4.2.3 Konzept der detaillierten Frame-Analyse ............................................ 21 LSB-Wasserzeichen in MPEG ............................................................ 22 4.2.4 Watermarker Klasse............................................................................ 25 Zusammenfassung............................................................................................ 26 Anhang – Codebeispiel ...............................................................................................v Quellen ...................................................................................................................... vii iii Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Abbildungsverzeichnis Abbildung 1: Zwei aufeinander folgende Frames ....................................................... 4 Abbildung 2: I-, P- und B-Frames [M03] ..................................................................... 4 Abbildung 3: Makroblock ............................................................................................ 6 Abbildung 4: Aufbau einer Video Sequenz [L] ............................................................ 6 Abbildung 5: MPEG-Video-Strom-Schichten .............................................................. 7 Abbildung 6: Klassendiagramm zur Medienhandhabung [SM01] ............................. 10 Abbildung 7: Plus-Ins eines Processors [SM99] ....................................................... 11 Abbildung 8: Controls Klassendiagramm [SM01] ..................................................... 12 Abbildung 9: Diskrete Kosinus-Transformation [I93], [O04] ...................................... 23 iv Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich 1 Einleitung Digitale Medien lassen sich grob in zwei Kategorien einteilen: in zeitunabhängige und in zeitabhängige. Zeitunabhängige Medien, beispielsweise Bilder, können als eine einzige elementare, semantische Einheit betrachtet werden, die konstant unverändert bleibt. Anders ist dies bei zeitabhängigen Medien wie Audio und Video. Diese bestehen aus einer Folge von Teileinheiten, die sich mit der Zeit verändern – sie bestehen aus mehreren semantischen Einheiten, die es zu erfassen gilt. In dieser Arbeit werden nur zeitabhängige Medien behandelt, bei denen elementare, semantische Einheiten separiert betrachtet werden. Es stellt sich die Frage, wie solch eine elementare, semantische Einheit aussieht und wie sie aufgebaut ist. Eine solche Einheit in einem Medium ist ein kleiner wohl definierter Teil – bei einem Video beispielsweise ein Frame. Zur genauen Begriffsklärung dient der nächste Abschnitt 1.1, in dem eine elementare, semantische Einheit definiert und abgegrenzt wird. In dieser Arbeit wird am Beispiel eines Videos im MPEG-Format der Bytestrom analysiert und in elementare, semantische Einheiten unterteilt. Andere Medienformate werden nicht betrachtet. Eine elementare, semantische Einheit in einem MPEG-Video ist ein Teil des Bytestroms und muss anhand von eindeutigen Erkennungsmerkmalen aus dem gesamten Medienstrom herausgesucht werden. Auf den Aufbau von MPEG und die darin enthaltenen elementaren Einheiten wird in Kapitel 2 eingegangen. Als nächste Grundlage wird in Kapitel 3 das Java Media Framework (JMF) vorgestellt. Dieses erlaubt die generische Handhabung digitaler Medien mit Java. Es werden bereits Standardimplementierungen zur Verfügung gestellt, die eine Erweiterung durch selbst programmierte Schritte in Form von Plug-Ins ermöglichen. Im Java Media Framework sollen MPEG-Videos, die in diesem Framework byteweise eingelesen und verarbeitet werden, in elementare, semantische Einheiten geteilt werden. Liegen diese Einheiten separiert vor, so wird die individuelle Bearbeitung des Videos vereinfacht, indem die Bearbeitung auf einer höheren Abstraktionsebene, nämlich in semantischen Einheiten, ermöglicht wird, ohne dabei auf der BytestromEbene arbeiten zu müssen. Kapitel 4 beschreibt die Umsetzung des Projektes im JMF, wie dort mit Hilfe des DivideIntoUnits-Plug-Ins das Medium in elementare, semantische Einheiten geteilt und eine separate Weiterverarbeitung der Einheiten ermöglicht wird. Außerdem erfolgt eine Einführung in das Verfahren digitaler Wasserzeichen. Dieses Verfahren stellt eine mögliche Weiterverarbeitung der semantischen Einheiten dar – sie werden mit Hilfe der Watermarker-Klasse mit digitalen Wasserzeichen markiert. 1 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich 1.1 Begriffsbildung: Elementare Einheiten Als erstes wird die Frage nach den elementaren, semantischen Einheiten in einem Medium geklärt. Zur Begriffserklärung und als Denkanstoß zunächst die Wortklärungen von elementar und semantisch: Elementar bedeutet grundlegend notwendig und wesentlich; semantisch hingegen bezieht sich auf die Bedeutung von Zeichen bzw. die Bedeutung von Daten oder Informationen. Eine elementare, semantische Einheit ist für Medien nicht spezifiziert. Da ein zeitabhängiges Medium oft aus einem Video- sowie einem Audio-Teil besteht, kann beispielsweise ein Video-Teil als eine elementare, semantische Einheit betrachtet werden (in Abgrenzung zum Audio-Teil). Als Alternative dazu könnte auch die vermutlich kleinste visuelle Einheit, ein Bildpunkt eines Frames des Video-Teils, als elementare, semantische Einheit in Betracht gezogen werden. In der Umsetzung des Projekts wird nur mit dem Video-Teil gearbeitet, daher muss der Audio-Teil nicht näher betrachtet werden. Zur Bearbeitung und logischen Verwendung der elementaren, semantischen Einheiten ist es am sinnvollsten, einen Frame des Video-Teils als elementare, semantische Einheit zu betrachten. Ein Vorteil dieser Betrachtung ist, dass ein Video komplett in Einheiten aufgeteilt wird, also eine vollständige Komposition ergibt. Außerdem grenzt sich ein Frame zu anderen Frames ab und besitzt die Semantik eines Bildes – er stellt also eine semantische Einheit dar. Elementar ist ein Frame ebenfalls, denn ohne Frames als wesentliche Bestandteile wäre ein Video kein zeitabhängiges, visuelles Medium. Ein Video-Strom besteht aus einer Folge von Frames, die wiederum aus Bytes bestehen. Das Problem, das es zu lösen gilt, beruht auf der Interpretation dieser Bytes. Ein kompletter Video-Strom wird durch einen Bytestrom repräsentiert. In diesem Bytestrom sind die einzelnen Frames nicht ohne weiteres Wissen zu finden. Abschnitt 2.4 zeigt am Beispiel von MPEG, wie die Frames in einem Bytestrom gefunden werden können. 2 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich 2 MPEG In diesem Projekt werden nur die zeitabhängigen, visuellen Medien, also Videos, betrachtet. Am Beispiel von MPEG-1 [I93] soll gezeigt werden, wie der Aufbau eines Videos aussehen und wie der vorhandene Bytestrom interpretiert werden kann. Der Video-Strom stellt eine Folge aneinander gereihter Frames dar, die wiederum aus Bytes bestehen. Eine höhere Abstraktionsebene interpretiert die Bytes als zusammengehörige elementare, semantische Einheiten. Die Einheiten sollen in vorliegendem Kapitel gesucht und der Aufbau eines MPEG-Videos veranschaulicht dargestellt werden, um dann eine weitere Bearbeitung der Einheiten verstehen und vornehmen zu können. Dieses Kapitel gibt zunächst einen Überblick von MPEG und dann im Detail dessen Aufbau im Hinblick auf die elementaren, semantischen Einheiten. 2.1 Notwendigkeit der Komprimierung Unkomprimierte Videos weisen sehr hohe Bitraten auf – beim Format des digitalen Fernsehens beispielsweise liegen sie in unkomprimierter Form zwischen 290 und 370 MBit/s [H95]. Effizienzprobleme, bei denen technische Geräte mit zu großen Datenraten überfordert sind, treten meist nicht bei der Wiedergabe (Dekodierung), sondern bei der Übertragung von Videos auf. Die Datenrate (Übertragungsrate) beschreibt eine Menge von Daten, die in einer bestimmten Zeit übertragen werden. Notwendige Übertragungsraten können nur durch Komprimierung erreicht werden. Dabei werden die Datenraten reduziert. Eine Komprimierung ist notwendig; sie kann jedoch andere Probleme mit sich ziehen, wie beispielsweise einen meist bei starker Komprimierung auftretenden Qualitätsverlust. Es muss also ein Verfahren verwendet werden, das ein geeignetes Mittel zwischen zu starken Qualitätsverlusten und einer erwünschten oder vorgegebenen Kompressionsrate findet und so ein qualitativ gutes Video mit vorgegebener Kompressionsrate erstellt. Dabei beschreibt die Kompressionsrate, wie stark Daten komprimiert werden. Hier setzt die Moving Pictures Expert Group an [H95]. Diese hat Standards entwickelt, u. a. MPEG-1, bei dem eine Bitrate (Datenrate) von bis zu 1,5 MBit/s [I93], und MPEG-2, bei dem eine Bitrate von 4 bis 80 MBit/s [M96], erreicht wird. 2.2 Grundlagen Ein MPEG-Video [M95] besteht nicht aus einzelnen, aufeinander folgenden Bildern – dies wäre zu ineffizient im Hinblick auf die Kompressionsrate. Die Idee von MPEG besteht darin, redundante und überflüssige Informationen wegfallen zu lassen. So wird zum Beispiel bei zwei aufeinander folgenden Frames der erste Frame vollständig komprimiert gespeichert und von dem zweiten wird nur die Differenz zum ersten gespeichert. Diese Vorgehensweise ist möglich, weil es Informationen gibt, die annähernd gleich bleiben. In Abbildung 1 bleibt der Hintergrund gleich, nur das Fahrzeug bewegt sich. 3 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Abbildung 1: Zwei aufeinander folgende Frames In regelmäßigen Abständen, meist alle 12 bis 15 Frames, wird ein vollständiger, kodierter Frame, ein so genannter I-Frame (Intra-Coded-Frame), gespeichert. Dieser ist JPEG-komprimiert und stellt ein Referenzframe dar. Ein Referenzframe dient als Bezugspunkt für andere Frames und stellt seine Informationen anderen Frames zur Verfügung. Zwischen den vollständigen intra-kodierten Frames befinden sich interkodierte Differenzframes. Diese besitzen nicht die komplette Bildinformation, die notwendig ist, um den Frame wiederherstellen zu können, sondern beziehen sich auf einen Referenzframe, speichern nötige Differenzinformationen und die Berechnungsmethode, wie sie aus vorangegangenen und gegebenenfalls auch nachfolgenden Referenzframes wiederhergestellt (dekodiert) werden können. Sie weisen eine erheblich höhere Kompressionsrate als I-Frames auf ([S99], Kapitel 7.7.1). Interframe-Kodierung klassifiziert zwei Frame-Typen: P-Frames (Predictive-CodedFrame) und B-Frames (Bidirectional-Predictive-Coded-Frame). P-Frames enthalten Differenzinformationen zu ihrem vorhergegangenen Referenzframe und können selbst wieder einen Referenzframe für andere Frames darstellen. B-Frames werden ausgehend von einem vorhergehenden und einem nachfolgenden Referenzframe berechnet. Diese Abhängigkeiten sind in Abbildung 2 dargestellt. Es ist ebenfalls der unterschiedliche Informationsgehalt der einzelnen Frames zu erkennen: der I-Frame ist ein vollständiges Bild, P- und B-Frames bestehen nur aus Teilinformationen. Abbildung 2: I-, P- und B-Frames [M03] 4 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Zur Vollständigkeit wird noch der 4. Frame-Typ erwähnt, der D-Frame (DC-CodedFrame). Dieser ist intraframe-kodiert und beinhaltet nur ausgewählte Anteile eines Frames, die einem schnellen Vorlauf des Videos dienen. D-Frames sind keine notwendigen Bestandteile des MPEG-Videos, ihre Funktion kann gegebenenfalls durch I-Frames übernommen werden. Deshalb und weil sie keine Rolle bei der sequenziellen Betrachtung spielen, sind sie für diese Arbeit nicht von Interesse und werden nicht weiter behandelt. In P-Frames wird von einem sich bewegenden Frameteil der örtliche Unterschied zum Referenzframe gespeichert. Abbildung 1 zeigt dafür ein Beispiel: Die beiden Frames weisen einen örtlichen Unterschied zwischen dem Fahrzeug auf. Der rechte Frame zeigt einen Vektor, der die Bewegungsrichtung und -länge wiedergibt. Der PFrame würde also diesen Vektor, den Frameteil der sich bewegt (in diesem Beispiel das Fahrzeug) und, falls erforderlich, eine Veränderung des Fahrzeugs speichern. Dieses Verfahren, bei dem ein Bewegungsvektor gespeichert wird, nennt man auch Bewegungskompensation (engl.: motion compensation) und wird mit Hilfe von Makroblöcken umgesetzt, die im nächsten Absatz erklärt sind. 2.3 Aufbau Ein Video als zeitabhängiges Medium wird auch als System-Strom (system-stream) bezeichnet und setzt sich aus Elementar-Strömen (elementary-stream oder auch Track) zusammen. Elementar-Ströme können beispielsweise Audio- oder VideoStröme sein. Da andere Ströme hier nicht von Interesse sind, wird nur der reine Video-Strom des gesamten MPEG-System-Stroms betrachtet. Dieser besteht aus einzelnen Abschnitten, die als Sequenzen bezeichnet werden und in verschiedene Ebenen (Schichten) unterteilt sind. Eine Sequenz besteht aus Folgen von Frames, I-, P- und B-Frames, die jeweils zu Gruppen zusammengefasst sind, den Groups-OfPictures (GOP). Eine GOP besteht immer mindestens aus einem I-Frame. Eine typische GOP, die sich häufig als praktisch erwiesen hat, besteht aus folgender Framereihenfolge: I B B P B B P B B P B B P. Die einzelnen Frames eines MPEG-Videos bestehen aus Slices, in deren Header (Kopf mit Information) Informationen über ihre eigene räumliche Positionierung im Frame gespeichert sind. Slices bestehen wiederum aus untergeordneten Einheiten, den Makroblöcken. Ein Slice fasst nebeneinander liegende Makroblöcke zusammen. Die Anzahl der Makroblöcke in einem Slice ist im Slice-Header gespeichert. Da die Anzahl nicht vorgegeben ist und variieren kann, kann die Länge der Slices unterschiedlich sein. Es gibt in einem Slice mindestens einen Makroblock. Alle Slices eines Frames füllen insgesamt einen ganzen Frame aus. Ein Makroblock wird zur Speicherung der Bewegungsvektoren verwendet und besteht aus 6 Blöcken: 4 Luminanz- und 2 Chrominanzblöcke, mit je 8x8 Werten. Jeder der Luminanzblöcke Y0 – Y3 speichert von 8x8 Bildpunkten (Pixel) 8x8 Luminanzwerte (Helligkeit, Leuchtdichte, Lichtstärke), sie ergeben zusammen eine 16x165 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Anordnung. In Abbildung 3 sind sie in schwarz dargestellt, wobei hier nur in Y0 für jeden Bildpunkt ein Kästchen gezeichnet ist. Die Luminanzblöcke bilden 16x16 Werte mit einem Wert für jeden Bildpunkt. Die Chrominanzblöcke Cb und Cr, enthalten je einen Chrominanzwert (Farbe) für 4 Bildpunkte. Ein Chrominanzblock deckt mit 8x8 Chrominanzwerten 16x16 Bildpunkte ab. Beide Chrominanzblöcke liegen jeweils räumlich deckend mit den 4 Luminanzblöcken. In Abbildung 3 stellen die 2 Chrominanzblöcke jeweils eine in blau-rot angedeutete Anordnung dar – sie bilden jeweils 8x8 Werte mit einem Wert für 4 Bildpunkte. Abbildung 3: Makroblock Nicht jeder Makroblock beinhaltet 6 vollständige Blöcke, sondern es ist abhängig vom Frame-Typ, wie viel Information der jeweilige Makroblock beinhaltet. In I-Frames besitzt ein Makroblock meist 6 Blöcke, da diese Frames vollständige Bilder darstellen. [I93] Die Blöcke stellen die kleinste Einheit im MPEG-Standard dar, die für den Bewegungsalgorithmus relevant ist. Sie dienen als Eingabe für die diskrete KosinusTransformation (DCT). Bei der Bildkomprimierung werden Blöcke aus 8x8 BildpunktWerten in 8x8 DCT-Koeffizienten transformiert. Abschnitt 4.2.3 geht darauf genauer ein. Abbildung 4 zeigt die beschriebene Zusammensetzung eines MPEG-Videos: Abbildung 4: Aufbau einer Video Sequenz [L] 6 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich MPEG-Video kann als Schichtenmodell betrachtet werden, welches Abstraktionen zulässt. Es ergibt sich ein Schichtenmodell wie in Abbildung 5, bei dem jede Schicht einen Header enthält, in dem sich beispielsweise weitere Informationen zur Schicht mit spezifischen Parametern befinden. Die einzelnen Video-Strom-Schichten mit ihren Headern und zusätzlichen, hier nicht aufgeführten Ergänzungen, ergeben zusammen einen kodierten MPEG-Video-Strom [P06]. Abbildung 5: MPEG-Video-Strom-Schichten 2.4 Elementare Einheiten in MPEG Wie in Abschnitt 1.1 bereits angesprochen, ist es zur Bearbeitung und logischen Verwendung der Einheiten am sinnvollsten, einen Frame als elementare, semantische Einheit zu betrachten. In MPEG gibt es jedoch verschiedene Frame-Typen: I-, P- und B-Frames. D-Frames werden von vorne herein außen vor gelassen. Ein I-Frame kann separiert betrachtet werden und unabhängig davon, ob das Video kodiert oder dekodiert vorliegt, sogar dann angezeigt werden, wenn sonst keine Information vorhanden ist. Anders ist dies bei P- und B-Frames, bei denen in kodierter Form eine separierte Betrachtung und Bearbeitung schwer möglich ist, denn sie benötigen zur Wiederherstellung (Dekodierung) Teile eines Referenzframes, welche jedoch bereits einer anderen elementaren Einheit zugeteilt wären. 7 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Da in kodierter Form die separierte Betrachtung von P- und B-Frames als elementare, semantische Einheiten einen erheblichen Mehraufwand gegenüber der separierten Betrachtung von I-Frames erfordert, soll es für die Umsetzung des Projekts genügen, lediglich alle I-Frames zu separieren und weiter zu verarbeiten. Ein Frame muss aus dem gesamten Video-Bytestrom herausgesucht werden. Dafür gibt es in einem MPEG-Video-Strom Erkennungsmerkmale in Form von Bytecodes. Ein Beispiel eines solchen Bytecodes ist der Startcode, der eine 32 Bit (4 Byte) umfassende, genau definierte Folge von Bits umfasst. Ein Startcode beginnt immer mit den gleichen drei Bytes, nämlich 0000 0000 0000 0000 0000 0001 (in binärer Darstellung) bzw. 0x000001. Das vierte und letzte Byte des Startcodes gibt dessen spezifischen Typ an. Das letzte Byte eines Frame-Startcodes ist 0000 0000 (binäre Darstellung). Damit sieht der gesamte Startcode eines Frames wie folgt aus: 0000 0000 0000 0000 0000 0001 0000 0000 (in binärer Darstellung) bzw. 0x00000100. Die Identifikation eines Frames im Hinblick auf dessen Typ, also ob es sich um einen I-, P- oder B-Frames handelt, geschieht ebenfalls über genau spezifizierte Bytecodes bzw. Bitcodes. Weiter gibt es eindeutig definierte Startcodes für Sequenzen, GroupsOf-Pictures und Slices. Außerdem gibt es einen Sequenz-Endcode und andere Parameter-spezifische Byte- und Bitcodes, die beispielsweise für Header verwendet werden. Alle Startcodes sind byte-aligned. Das bedeutet, dass sie in Bezug auf das erste Bit des Bytestroms jeweils bei einem Vielfachen von 8 Bits beginnen. Außerdem müssen sie eindeutig zugeordnet werden können, um ihrer Aufgabe nachzukommen. Anderenfalls kann es zu Verwechslungen kommen, das MPEG-Video wäre fehlerbehaftet und könnte nicht eindeutig und standardisiert dekodiert werden. Im MPEG-1-Standard ISO/IEC 11172 [I93] sind unter anderem alle Byte- und Bitcodes eines MPEG-1-Bytestroms definiert. 8 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich 3 Java Media Framework (JMF) Das Java Media Framework [SM05] erlaubt die generische Handhabung von kontinuierlichen Medien mit Java. Es stellt bereits Standardimplementierungen für Verarbeitungsschritte zur Verfügung und erlaubt gleichzeitig, eigene Erweiterungen zu implementieren. So müssen Programmierer nicht ganze Verarbeitungsketten selbst implementieren, sondern können sich auf wesentliche Aufgaben konzentrieren. Dieses Kapitel stellt das JMF vor und geht speziell auf die Medienverarbeitung ein. 3.1 Grundlagen Mit dem Java Media Framework [SM05] können zeitabhängige, digitale Medien erfasst, abgespielt und bearbeitet werden. Die meisten gängigen Medienformate wie AIFF, AU, AVI, GSM, MIDI, MPEG, Quicktime, RMF und WAV werden unterstützt ([SM99], Kapitel 2). Von den vielfältigen Anwendungen des JMF interessiert in dieser Arbeit besonders das Bearbeiten von MPEG-Videos. Verschiedene Interfaces stellen umfangreiche Funktionalitäten für die Medienbearbeitung zur Verfügung. Im Folgenden werden Java Interfaces und Klassen mit einer geänderten Schriftart hervorgehoben. Eines der wichtigsten Interfaces des Java Media Frameworks ist Controller, das die Hauptaktivitäten wie Abspielen und Bearbeiten von Medien unterstützt. Controller realisiert eine Zeitbasis (Clock, Duration) und ein Ereignis-Verarbeitungsmodell (xListener). Die Zeitbasis wird durch die Interfaces Clock und Duration realisiert; das Ereignis-Verarbeitungsmodell wird später genauer beschrieben. Ein Beispiel für einen speziellen Controller ist Player (siehe Abbildung 6), dessen Hauptaufgabe darin besteht, Tracks abzuspielen. Player implementiert das Interface MediaHandler, durch das er Medien lesen und abspielen kann. Eine weitere Möglichkeit, um Medien abzuspielen, ist durch das Interface Processor gegeben, mit dessen Hilfe Tracks nicht nur abgespielt, sondern sogar auch bearbeitet oder verändert werden können. Ein Track stellt einen ElemantarStrom, also beispielsweise ein Video-Strom des MPEG-System-Stroms dar. Die meisten bisher genannten Interfaces sind im Klassendiagramm in Abbildung 6 zu sehen. 9 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Abbildung 6: Klassendiagramm zur Medienhandhabung [SM01] Zur Steuerung von Tracks, PlugIns und Controllern gibt es das Interface Controls (siehe Abschnitt 3.3 bzw. Abbildung 8 auf Seite 12). Mit Controls können Objektattribute kontrolliert und eingestellt werden. Controller, dessen Subinterfaces (Player und Processor) und die meisten Subinterfaces von Controls (siehe Abbildung 8) bieten die Möglichkeit ein Interface ControllerListenener bzw. allgemein xListener zu implementieren. Dadurch können Statusänderungen verarbeitet werden, indem die implementierende Klasse Events hervorruft (Ereignis-Verarbeitung). Diese Events werden ausgelöst, wenn ein bestimmter Status erreicht wird (beispielsweise ein Zustand) oder ein Ereignis eintritt (beispielsweise ein Zeitpunkt) und können für Status-, Ereignis- oder andere Bedingungsabfragen eingesetzt werden. Da von einem Interface nicht direkt ein Objekt erzeugt werden kann, steht im JMF die Klasse Manager zur Verfügung, mit deren Hilfe statisch Implementierungen von Controller oder Controls erzeugt werden können ([ED04], Kapitel 4). Ein Beispiel hierzu folgt bei der Umsetzung des DivideIntoUnits-PlugIns in Abschnitt 4.1.1. 3.2 Medienverarbeitung im JMF Für die Medienverarbeitung steht im Java Media Framework das Interface Processor zu Verfügung. Dies ist ein spezieller Controller und enthält also eine eigene Zeitbasis sowie ein Ereignis-Verarbeitungsmodell. Processor lässt sich als Verarbeitungskette mit Eingabe, Verarbeitung und Ausgabe, dem typischen Aufbau in der Computerverarbeitung, darstellen. Ein- und Ausgabe sind durch Datenquellen (DataSource) gekennzeichnet. Eine DataSource (entspricht einem MPEGSystem-Strom) ist eine Klasse des JMF, die als Eingabe eines Controllers 10 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich (Processor oder Player) dienen oder ein Medium abspeichern kann. Im zweiten Fall dient sie als Eingabe einer DataSink (Datensenke), die Mediendaten in Form einer Datei persistent machen oder ausgeben kann. Zwischen der Ein- und Ausgabe des Processors wird das Medium je nach Anwendung in individuellen Schritten nacheinander verarbeitet. Die einzelnen Schritte stellen meist PlugIns dar. PlugIn ist ein Subinterface von Controls (siehe nächster Abschnitt, Abbildung 8). Abbildung 7 zeigt mögliche PlugIns von Processor, wie (De-)Multiplexer, Codecs oder Effects ([ED04], Kapitel 4), die entweder mit vorgefertigter Funktionalität aus dem JMF übernommen werden können oder als implementierte Interfaces mit dem Superinterface PlugIn Funktionalitäten ersetzen oder ergänzen können. Ihre Funktionsweise wird im folgenden Abschnitt beschrieben. Abbildung 7: Plus-Ins eines Processors [SM99] 3.3 Plug-Ins im JMF Die Aufgaben von PlugIns können sehr unterschiedlich sein, und somit auch ihr Aussehen und ihre Verwendung. PlugIns sind Teilschritte der Verarbeitungskette eines Processors, die in einer festgelegten Reihenfolge abgearbeitet werden (siehe Abbildung 7). Sie bilden Bearbeitungsschritte, die entweder standardmäßig oder individuell selbst programmiert verwendet werden können. Sofern keine Standard-, sondern selbst programmierte Implementierungen verwendet werden, muss Processor mitgeteilt werden, dass zusätzliche PlugIns verwendet werden sollen. Dazu müssen die PlugIns im JMF registriert werden. Dies geschieht über eine Manager-Klasse, PlugInManager, mit deren Hilfe statisch (und bei Bedarf sogar permanent) PlugIns ergänzt werden können, die dann zur weiteren Verwendung zur Verfügung stehen [ED04]. Das Hinzufügen von PlugIns ermöglicht die Implementierung von zusätzlichen Funktionalitäten. Bereits vorhandene PlugIns sind (De-)Multiplexer, Codec oder Effect. Jedes dieser PlugIns stellt einen separaten Schritt dar und besitzt eine Ein- und eine Ausgabe. Ein Demultiplexer bekommt einen Mediendatenstrom (im JMF DataSource, in MPEG der System-Strom) als Eingabe, analysiert und zerlegt ihn, sofern er aus mehreren Elementar-Strömen besteht, also gemultiplext (zusammengesetzt) vorliegt, in seine einzelnen Tracks. Andernfalls, wenn der Mediendatenstrom nur aus einem Elementar-Strom besteht, wird dieser (zunächst noch gemultiplext als DataSource vorliegend) in einen Track umgewandelt. 11 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Die Ausgabe des Demultiplexers von Tracks geschieht in Form von Buffern. Solch ein Buffer stellt eine unstrukturierte Folge von bytes dar und dient dem Transport von Mediendaten innerhalb von Player oder Processor. Die Aufgabe eines Multiplexers hingegen ist genau das Gegenteil eines Demultiplexers. Dieser führt die einzelnen Tracks bzw. Buffer (bei MPEG die Elementar-Ströme), die er als Eingabe entgegennimmt, zusammen zu einem Datenstrom (im JMF DataSource; bei MPEG der System-Strom), den er als Ausgabe erzeugt. Ein Codec kodiert bzw. dekodiert die zu verarbeitenden Videodaten eines Tracks. Er bekommt einen einzelnen Track, bzw. Buffer als Eingabe und gibt auch einen solchen aus. Eine spezielle Form des Codecs in der Sprache des JMF ist ein Effect. Mit dessen Hilfe können Tracks mit gezielten Manipulationen verändert werden. Abbildung 8 zeigt als Klassendiagramm den hierarchischen Zusammenhang der zuvor genannten Controls. Abbildung 8: Controls Klassendiagramm [SM01] Die Lösung der vorgegebenen Aufgabe setzt bei den PlugIns an. Mit Hilfe eines Codecs, dem DivideIntoUnits-PlugIn, kann ein Video-Strom analysiert und in elementare, semantische Einheiten geteilt werden. Mit diesem Grundwissen über das Java Media Framework und insbesondere von PlugIns kann auf die eigentliche Aufgabe, die Medienverarbeitung mit Java in elementaren Einheiten eingegangen werden. Wie zuvor erwähnt, wird als mögliche Weiterverarbeitung in das Verfahren digitaler Wasserzeichen eingeführt. Das nächste Kapitel beschreibt zunächst die Umsetzung des DivideIntoUnits-PlugIns, bei dem ein MPEG-Video analysiert und in elementare Einheiten geteilt wird. Anschließend wird in das Verfahren digitaler Wasserzeichen eingeführt und die Umsetzung der Watermarker-Klasse beschrieben, mit deren Hilfe die elementaren Einheiten mit digitalen Wasserzeichen markiert werden können. 12 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich 4 Umsetzung des Projektes Die Hauptfunktionen des Projekts sind in einem PlugIn und einer Klasse gekapselt: dem DivideIntoUnits-PlugIn und der Watermarker-Klasse. Ersteres ist dafür zuständig, den gesamten MPEG-Bytestrom zu analysieren, die elementaren, semantischen Einheiten zu finden und deren separierte Weiterverarbeitung zu ermöglichen. Watermarker stellt eine mögliche Weiterverarbeitung dar und markiert die elementaren, semantischen Einheiten mit digitalen Wasserzeichen. Dieses Kapitel erklärt zuerst die Umsetzung des DivideIntoUnits-PlugIns, bei dem die Konzentration auf der Zerlegung des MPEG-Bytestroms in elementare, semantische Einheiten liegt. Als nächster Schritt wird in das Verfahren digitaler Wasserzeichen eingeführt, um schließlich die Umsetzung der Watermarker-Klasse zu verstehen. Insgesamt zeigt dieses Projekt eine Realisierung der Verarbeitung von MPEG-Byteströmen auf Basis von elementaren, semantischen Einheiten im Java Media Framework. 4.1 DivideIntoUnits-Plug-In Das DivideIntoUnits-PlugIn soll den gesamten MPEG-Video-Strom analysieren und auf Bytestrom-Ebene die elementaren, semantischen Einheiten finden. Diese Einheiten sind, wie in Abschnitt 1.1 erarbeitet, Frames und müssen in dem Video-Bytestrom unter anderem mit Hilfe von Startcodes gefunden werden. Es wird zuerst erklärt, wie im JMF die MPEG-Verarbeitung auf der Ebene des Bytestroms funktioniert. Ziel ist es schließlich, nicht auf der Bytestrom-Ebene arbeiten zu müssen, sondern eine Abstraktion der Verarbeitung auf elementaren, semantischen Einheiten zu erreichen. 4.1.1 MPEG-Verarbeitung im JMF Für die Medienverarbeitung im Java Media Framework wird das Interface Processor benötigt (siehe Kapitel 3). Da von einem Interface nicht direkt ein Objekt erzeugt werden kann, muss die Klasse Manager verwendet werden. Mit dem Aufruf Manager.createProcessor(inputFile) kann statisch ein Objekt von Processor erzeugt werden. Der Parameter inputFile kann entweder eine URL (Pfadangabe eines Mediums), ein MediaLocator (gekapselte Pfadangabe zu einem Medium) oder direkt eine DataSource (stellt ein Medium dar) sein. Die Klasse Manager weiß durch diesen Parameter, wie sie den Dateninhalt findet und auf welche Art und Weise sie eine Instanz von Processor erzeugen muss. Processor ist ein Subinterface von Controller und besitzt somit ein EreignisVerarbeitungsmodell. Das Ereignis-Verarbeitungsmodell vergibt Processor einige Status und erlaubt deren Abfrage. Außerdem kann durch processor.addControllerListener(controllerListener) das Interface ControllerListener eingebunden werden. Dieses Interface stellt die Methode 13 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich controllerUpdate(controllerEvent) zur Verfügung, welche beim Auftreten eines Ereignisses aufgerufen wird und Ereignisabfragen erlaubt. Mögliche Ereignisse (Event bzw. ControllerEvent) können erreichte Zeitpunkte des Datenstroms oder Status- bzw. Zustandsänderungen des Processors sein. Hat man ein Objekt von Processor erzeugt, kann man einen eingehenden Bytestrom bearbeiten. Zunächst findet eine Abfrage der einzelnen Tracks im gesamten MPEG-System-Strom statt. Der System-Strom setzt sich wie bereits erklärt aus ein oder mehreren Tracks zusammen. Die Tracks eines Processor bzw. SystemStroms können mit Hilfe des Interfaces TrackControl (ebenfalls ein Subinterface von Controls) kontrolliert und verändert werden. Die TrackControls, die jeweils einen Track repräsentieren, können durch processor.getTrackControls() abgefragt werden. In dieser Arbeit sind nur Video-Tracks von Interesse. Die Abfrage von processor.getTrackControls() gibt ein Array von TrackControls zurück. Aus diesem Array kann man den Video-Track bzw. den zuständigen TrackControl für den Video-Track heraussuchen, indem man das Format der einzelnen Tracks, das man durch TrackControl.getFormat() erhält, mit der Klasse VideoFormat vergleicht. Stimmt das Format des Tracks mit VideoFormat überein, handelt es sich um einen Video-Track. Die gesamte Verarbeitungskette des Processors teilt sich nach dem Demultiplexer in einzelne Verarbeitungsketten für jeden Track. Die Tracks werden später wieder mit einem Multiplexer zu einem System-Strom (DataSource) zusammengeführt. Zwischen Demultiplexer und Multiplexer können jedem Track individuell zusätzliche PlugIns als Verarbeitungsschritte hinzugefügt werden. In diesem Fall wird ein Array aus PlugIns oder noch spezieller ein Array aus Codecs angelegt. Da das DivideIntoUnits-PlugIn ein Codec ist, also ein spezielles PlugIn, kann es diesem Array hinzugefügt werden. Das Array beinhaltet alle zusätzlichen Schritte (PlugIns) und wird mit videoTrack.setCodecChain(codecsArray) dem jeweiligen Track, hier dem zuvor gesuchten Video-Track, hinzugefügt. Die bisher in diesem Abschnitt beschriebenen Funktionalitäten sind im Anhang in einem Codebeispiel zusammengeschrieben. Das Beispiel ist verkürzt und stellt nur die hier relevanten Zeilen dar. Die Hauptaufgaben des DivideIntoUnits-Codecs sind das Analysieren des Video-Tracks und das Suchen der I-Frames als elementare, semantische Einheiten, um schließlich deren separate Weiterverarbeitung zu ermöglichen. Ein Codec besitzt die Methode process(inputBuffer,outputBuffer). Hier stellt inputBuffer den eingehenden Buffer dar. Die darin enthaltenen Daten können mit inputBuffer.getData() ausgelesen werden. Diese Methode gibt die Daten als byte-Array zurück. Dieser Array kann analysiert, nach Startcodes durchsucht und gegebenenfalls verändert werden. Die Bearbeitung ist im nächsten Abschnitt erklärt. Schließlich werden die individuell bearbeiteten Daten mit 14 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich outputBuffer.setData(byteArray) an outputBuffer weitergegeben. Dieser Buffer stellt die Ausgabe des Codecs dar und dient gleichzeitig als Eingabe des nächsten PlugIns bzw. Verarbeitungsschrittes. Der folgende Codeausschnitt verdeutlicht die Funktionsweise eines Codecs. Es sind nur hier relevante Zeilen angegeben. import javax.media.*; public class DivideIntoUnits implements Codec { Object bufferPartData; byte[] byteData; byte[] outputBufferByte; /** * processor calls this method, inputBuffer is given, * outputBuffer need to be set */ public int process(Buffer inputBuffer, Buffer outputBuffer) { //each buffer is passed to accessFrame for further process accessFrame(inputBuffer); ... //set outputBuffer outputBuffer.setData(outputBufferByte); return BUFFER_PROCESSED_OK; } /** * analyse buffer and separate into units */ void accessFrame(Buffer bufferPart) { bufferPartData = bufferPart.getData(); byteData = (byte[]) bufferPartData; //set content of outputBuffer outputBufferByte = ...; //separation of units (is not specified in this example) ... } ... } 4.1.2 Abstraktionsebene elementare Einheiten Die elementaren, semantischen Einheiten sind, wie in Abschnitt 2.4 erarbeitet, IFrames und besitzen die Semantik eines Bildes. Um diese Einheiten separieren zu können, muss der eingehende Buffer analysiert und nach Startcodes durchsucht werden. Die Daten des Buffers können als byte-Array ausgelesen und dann byteweise verglichen werden. Da Startcodes byte-aligned sind, was bedeutet, dass sie in Bezug auf das erste Bit des Bytestroms jeweils bei einem Vielfachen von 8 Bits beginnen, reicht es aus, bei jedem neuen Byte nach dem Anfang eines Startcodes zu suchen und nicht auf die Ebene einzelner Bits herunter gehen zu müssen. Um einen Frame zu finden, muss man wissen, wie er charakterisiert ist. Wie in Abschnitt 2.4 beschrieben, sieht sein Startcode folgendermaßen aus: 0000 0000 0000 0000 0000 0001 0000 0000 (in binärer Darstellung) oder 0x00000100. Bei diesem Projekt sollen zunächst nur I-Frames gesucht werden. Dabei spielt die 3-Bit-große Frame-Typangabe eine Rolle, die in den auf einen Frame-Startcode folgenden Bytes 15 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich zu finden ist. Die I-Frame-Typangabe ist durch 001 (binäre Darstellung) charakterisiert. Die gesamte Suchabfrage für einen I-Frame ergibt sich also zu folgendem: 0000 0000 0000 0000 0000 0001 0000 0000 **** **** **00 1*** Startcode eines Frames Frame-Typangabe Hierbei stellen die * Platzhalter dar, die nicht zum Spezifizieren eines Frames benötigt werden, sondern andere Parameter beinhalten. Ein Frame beginnt mit solch einem Startcode und reicht bis zum Anfang des nächsten Frame-, GOP- oder Sequenz-Startcodes. Innerhalb eines Frames können Startcodes für Slices vorkommen. Hat man die Frames aus dem gesamten MPEG-Video-Bytestrom herausgesucht, so können diese gegebenenfalls weiter verarbeitet und verändert werden. Abschnitt 4.2 gibt ein Beispiel für eine mögliche Weiterverarbeitung. Die Bytecodes sind in dieser Arbeit wie im MPEG-1-Standard [I93] in binärer oder hexadezimaler Darstellung angegeben. In binärer Darstellung werden einzelne Bits und in hexadezimaler Darstellung je 4 Bits pro Ziffer bzw. Buchstabe dargestellt. Es tritt ein Problem bei der Verarbeitung auf, denn in Java gibt es als kleinsten Datentyp byte. Die auftretende Schwierigkeit liegt darin, dass mit byte auf die einzelnen Bits zugegriffen werden soll. Der nächste Abschnitt geht auf das Problem ein und gibt eine mögliche Lösung, die hier verwendet wird, an. 4.1.3 Problem von binärer und hexadezimaler Schreibweise in Java Zwischen den beiden Darstellungen binär und hexadezimal kann umgerechnet werden. In binärer Darstellung ist jedes Bit beschrieben, wogegen die hexadezimale Darstellung als Zusammenfassung von je 4 Bits aufgefasst werden kann – sie ist dementsprechend ¾ kürzer als die binäre. Trotzdem ist sie noch doppelt so lang wie der Datentyp byte, der kleinste, den es in Java gibt. Das Problem, das hierbei auftritt, ist nicht die Umrechnung von einem Java-byte in eine der anderen beiden Darstellungen, die hier wie im MPEG-1-Standard [I93] verwendet werden, sondern vielmehr die Verarbeitung einzelner Bits. Wenn auf weniger als 8 Bits oder 8 nicht bytealigned Bits zugegriffen werden soll, dann ist es nicht möglich einfach ein byte zu verändern. Es muss Bit-Shifting verwendet werden, bei dem einzelne (oder auch zusammenhängende) Bits separiert werden, damit auf diese einzeln zugegriffen werden kann und sie einzeln bearbeitet werden können. Die Funktionsweise des BitShiftings wird hier nicht erklärt; dies kann in [U06], Kapitel 2.8.4, nachgelesen werden. Bei der Bearbeitung und genauen Analyse von MPEG-Byteströmen (siehe Kapitel 4.2.2) muss nicht nur auf byte-aligned Bytes, sondern auch auf Bits, die nicht aus mindestens 8 aufeinander folgenden Bits bestehen und mitten in einem Byte anfangen, also nicht byte-aligned sind, zugegriffen werden. Dieser Problematik vorwegnehmend wird hier festgelegt, dass eine Bearbeitung auf Bitebene erfolgen und die 16 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich binäre Darstellung verwendet werden soll. So kann auf jedes Bit einzeln zugegriffen werden, was sich in Kapitel 4.2.2 als geeignet herausstellen wird. Die Bearbeitung von Bits kann nicht ohne weiteres in Java umgesetzt werden, denn dort ist byte der kleinste Datentyp. Zur Lösung dieses Problems wurde eine Variante gewählt, bei der mit byte je ein Bit repräsentiert wird. Ein byte soll nur die binären Werte 0 (als Byte repräsentiert durch 0000 0000) und 1 (als Byte repräsentiert durch 0000 0001) annehmen können. So kann ein byte als Bit interpretiert werden und das Problem ist gelöst, denn es kann auf einzelne Bits zugegriffen werden. Diese Variante ist nicht speicherfreundlich, denn dadurch steigen die jeweiligen byte-Arrays auf 8-fache Länge an. Trotzdem hat sich dieses Vorgehen bewährt, denn es ist notwendig an die Werte der einzelnen Bits zu gelangen. Eine Alternative wäre das Bit-Shifting, bei dem im Endeffekt auch nichts anderes gemacht wird, als ein Bit mit einem Byte dazustellen. Diese Alternative würde vielleicht weniger Speicher benötigen da jeweils nur ein oder wenige aktuelle Bits eines bytes, die gerade verglichen oder verändert werden, als separate zusätzliche bytes dargestellt werden. Das Problem, das bei dieser Alternative auftritt, besteht in einer längeren höheren Laufzeit, denn es ist rechenaufwändig jedes Bit einzeln umzuwandeln und gleich wieder zurück in Byte zu wandeln. Da Java eine verhältnismäßig langsame Programmiersprache ist, ist die Variante mehr Speicherplatz zu benötigen der Variante mehr Rechenaufwand zu haben vorzuziehen. 4.2 Weiterverarbeitung der elementaren Einheiten Eine mögliche Weiterverarbeitung der elementaren Einheiten stellt die Watermarker-Klasse dar. Sie kann als Verarbeitung auf der Abstraktionsebene der elementaren, semantischen Einheiten gesehen werden, dessen Grundlage im vorigen Abschnitt erarbeitet wurde. Es wird ein Konzept entwickelt, bei dem die elementaren, semantischen Einheiten durch Frame-Klassen repräsentiert werden. Diese Frame-Klassen ermöglichen eine detaillierte Analyse der Frames eines MPEG-Videos. Es soll sogar auch auf die kleinsten Einheiten, die DCT-Koeffizienten, zugegriffen werden können. Das vorgestellte Konzept dient als notwendige Grundlage für Watermarker. Vorliegendes Kapitel gibt zuerst einen grundlegenden Einblick in das Verfahren digitaler Wasserzeichen (Abschnitt 4.2.1), bevor die Umsetzung des Konzeptes der detaillierten Frame-Analyse erarbeitet wird (Abschnitt 4.2.2). Schließlich ist in den Abschnitten 4.2.3 und 4.2.4 die Umsetzung der weiteren Verarbeitung der elementaren Einheiten am Beispiel der Markierung von MPEG-Videos mit digitalen Wasserzeichen beschrieben. 17 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich 4.2.1 Digitale Wasserzeichen Das Haupteinsatzgebiet digitaler Wasserzeichen sind Integritäts- und Authentizitätsnachweise digitaler Medien. Die Anwendungsgebiete digitaler Wasserzeichen sind vielfältig und fordern unterschiedliche Eigenschaften und Parameter. Digitale Wasserzeichen sind nicht-wahrnehmbar und untrennbar mit einem Medium verbunden, so dass sie nicht unbefugt entfernt oder modifiziert werden können. Dieser Abschnitt gibt einen Überblick über Eigenschaften und Anwendungsgebiete digitaler Wasserzeichen. 4.2.1.1 Grundlagen Digitale Wasserzeichen stellen eine Sicherheitslösung für Angriffe gegen digitale Medien dar. Sie sind so konzipiert, dass sie nicht-wahrnehmbar, also transparent sind. Digitale Wasserzeichen beschreiben Verfahren, die es ermöglichen, versteckt Informationen in digitale Medien einzubetten ([CMB02], Kapitel 1). Die eingebetteten Informationen (Wasserzeichennachricht) können zum Beispiel einen Urhebernamen, eine Kunden- oder Seriennummer, Prüfsummen oder Produktwerbung beinhalten. Bei der Einbettung eines Wasserzeichens wird der Inhalt des digitalen Mediums insofern modifiziert, dass die Aussage des Mediums unverändert bleibt und die zusätzlichen Informationen nicht-wahrnehmbar hinzugefügt werden. Die zusätzliche Information wird untrennbar mit dem Medium verbunden. Wasserzeichenverfahren sind abhängig von den gewünschten Eigenschaften, die im nächsten Abschnitt erklärt sind. ([D00], Kapitel 3) 4.2.1.2 Eigenschaften Digitale Wasserzeichen besitzen verschiedene Eigenschaften. Die wichtigsten sind Transparenz, Kapazität, Robustheit, Sicherheit und Performanz. Es hängt jeweils von der Art der Anwendung ab, welcher dieser Faktoren wie stark gewichtet wird. Die Transparenz gibt an, wie stark ein Wasserzeichen wahrnehmbar ist. Sie ist also ein Maß für den Qualitätsverlust, der durch das Einbetten entsteht. Wasserzeichenverfahren mit hoher Transparenz zielen auf eine nicht-wahrnehmbare Manipulation, also einen geringen Qualitätsverlust des ursprünglichen Mediums. Im Gegensatz dazu, liegt auf diesem Verlust bei Verfahren mit geringer Transparenz ein nicht so großer Wert. Die Kapazität digitaler Wasserzeichen bezeichnet den Umfang (die Anzahl der Bits) der eingebetteten Information. Um eine große Kapazität zu erzielen, muss das Medium eine ausreichend hohe Datenrate für die Wasserzeichennachricht bereitstellen. ([CMB02], Kapitel 2.2.3) Robuste Wasserzeichen dürfen durch übliche Verarbeitungsschritte oder Manipulationen, wie Komprimierung und Skalierung der Medien nicht zerstört werden. Sie 18 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich müssen beispielsweise nach Digital/Analog- bzw. Analog/Digital-Wandlungen oder Konvertierungen in andere Datei- und Kompressionsformate noch eindeutig und unverändert auszulesen sein. ([D00], Kapitel 3.1.3.1) Die Skala der Robustheit reicht von robust bis fragil, wobei fragil bedeutet, dass das Wasserzeichen bei Veränderungen zerstört wird. Sicherheit bei digitalen Wasserzeichen bedeutet, wie hoch der Schutz des Wasserzeichens vor gezielten Angriffen ist. Ein Wasserzeichen gilt als sicher, wenn man es ohne einen geheimen Schlüssel weder auslesen noch verändern kann, ohne dabei das Medium selbst zu zerstören – sogar dann, wenn man ein markiertes Medium besitzt und Kenntnis über das Wasserzeichenverfahren hat ([D00], Kapitel 3.1.3.4). Wenn von der Performanz digitaler Wasserzeichen gesprochen wird, dann ist damit die Einbettungszeit gemeint. Im Praxiseinsatz müssen der Einbettungs- und der Auslesevorgang ausreichend schnell geschehen. Je nach Anwendung ist hierbei ein Vielfaches von Echtzeitgeschwindigkeit notwendig. All diesen Anforderungen zu entsprechen würde für ein einziges digitales Wasserzeichen keinen Sinn ergeben und wäre auch nicht möglich. Die Anforderungsschwerpunkte und Eigenschaften hängen daher von der jeweiligen Anwendung ab. ([D00], Kapitel 3.1.3.8) 4.2.1.3 Anwendungsgebiete Ein Hauptanwendungsgebiet digitaler Wasserzeichen ist die Urheberidentifizierung (Schutz des Urheberrechts, Authentifizierung des Senders). Hierfür ist es sinnvoll, die zusätzlichen Informationen, die einen Urheber eindeutig kennzeichnen, so komplex wie möglich mit dem Medium zu verbinden. Nach Veränderungen und Angriffen muss die Urheberschaft (Authentizität) noch eindeutig nachgewiesen werden können. Es werden nicht-wahrnehmbare, robuste Wasserzeichen eingesetzt, um den Urheber, in der Kommunikationstheorie auch als Sender bezeichnet, eindeutig identifizieren bzw. authentifizieren zu können. ([D00], Kapitel 4) Eine ähnliche Anwendung ist die Kundenidentifizierung (Authentifizierung des Empfängers), bei der eine eindeutige Kundeninformation, beispielsweise eine Kundennummer, individuell in jedem verkauften Medium robust eingebettet wird. Die Verkäufer digitaler Medien können jederzeit den Käufer identifizieren und auch bei unberechtigter Vervielfältigung oder Veröffentlichung kann ein eindeutiger Erzeuger (Kunde) der Kopie authentifiziert werden ([D00], Kapitel 5) Ein anderes Einsatzgebiet digitaler Wasserzeichen ist der Integritätsnachweis. Dabei muss jede kleinste Veränderung, die die Aussage des Mediums betrifft, erkannt werden. Das Medium darf nicht unbemerkt und unberechtigt verändert werden. Gleichzeitig sollte das Wasserzeichen gegenüber Manipulationen, die unabhängig von der Aussage sind, wie Kompression oder Skalierung, robust sein. Für solche Anforderungen werden inhaltsbasierte fragile Wasserzeichen verwendet. Eine Modifikation 19 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich der Aussage des Mediums zerstört diese einerseits fragilen Wasserzeichen. Andererseits sind diese robust, da sie durch Modifikationen ohne Änderung der Aussage nicht zerstört werden. Nutzt man die Eigenschaften inhaltsbasierter fragiler Wasserzeichen, kann Integritätsschutz gewährleistet werden ([D00], Kapitel 6). 4.2.1.4 LSB-Wasserzeichen In dieser Arbeit wird ein simples digitales Wasserzeichen verwendet, ein LSBWasserzeichen (Least Significant Bit). Es handelt sich dabei um ein Bildwasserzeichen, bei dem einzelne Werte eines Bildes nicht-wahrnehmbar manipuliert werden. In diesem Abschnitt wird ein LSB-Wasserzeichen am Beispiel eines Bildes im RGB-Format vorgestellt. Es gibt verschiedene Möglichkeiten ein LSB-Wasserzeichen zu realisieren. Ein grundlegendes Verständnis für ein LSB-Wasserzeichen wird in diesem Abschnitt geschaffen und später bei der Umsetzung im Projekt in Abschnitt 4.2.3 auf ein Frame des MPEG-Videos übertragen. In einem digitalen Bild, das im RGB-Format vorliegt, hat jeder Bildpunkt jeweils eine Farbwertangabe für Rot (R), Grün (G) und Blau (B). Diese Werte liegen normalerweise jeweils zwischen 0 und 255 und sind also je 8 Bit groß. Andere Werte des RGB-Formates werden an dieser Stelle vernachlässigt, da sie für das Verstehen des LSB-Wasserzeichens nicht von Interesse sind. Die Rot-, Grün- und Blauwerte werden vom menschlichen Auge unterschiedlich stark wahrgenommen. Da der Blauwert am geringsten wahrgenommen wird, fällt dort eine Wertänderung am wenigsten auf. Das hier erklärte LSB-Wasserzeichen verändert das niedrigste Bit des Blauwertes, das LSB, also das Bit mit der geringsten Bedeutung für den visuellen Gesamteindruck. Dies erfolgt, indem von jedem Bildpunkt, in das die Wasserzeichennachricht eingebettet werden soll, jeweils das LSB betrachtet wird. Die Wasserzeichennachricht, die letztendlich auch nur durch Bits repräsentiert wird, wird auf die ausgewählten LSBs übertragen. Dabei kann entweder einfach jedes LSB des Bildes an das Bit der Wasserzeichennachricht angepasst werden, unberücksichtigt welche Werte die LSBs zuvor hatten. Eine andere Möglichkeit wäre folgende: Wenn die Wasserzeichennachricht in dem jeweiligen Bit eine 0 bzw.1 enthält, so wird das LSB, das dieses Bit repräsentieren soll, ebenfalls auf 0 bzw. 1 gesetzt. Es wird zunächst verglichen, ob das LSB bereits identisch mit dem einzubettenden Bit ist, in diesem Fall wird keine Manipulation vorgenommen, andernfalls wird das LSB angepasst. Es wird also nicht unbedingt jedes LSB bzw. Bildpunkt, das einen Teil der Wasserzeichennachricht darstellt, manipuliert, sondern nur solche, die nicht von vorne herein die gewünschte Information tragen. Das Ergebnis ist mit beiden Vorgehensweisen gleich; also egal, ob man einfach jedes LSB mit dem Bit der Wasserzeichennachricht überschreibt unbeachtet der vorigen Werte der LSBs oder ob man zuerst jedes LSB mit dem Bit der Nachricht vergleicht und nur wenn notwendig eine Anpassung vornimmt. 20 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich In diesem Projekt soll ein LSB-Wasserzeichen in ein MPEG-Video eingebettet werden. Ähnlich dem beschriebenen LSB-Wasserzeichen in einem Bild im RGB-Format, kann auch in I-Frames eines MPEG-Videos ein LSB-Wasserzeichen eingebracht werden. Wie in Kapitel 2.2 beschrieben, basieren I-Frames auf JPEG-Komprimierung. Bei der Markierung von I-Frames bzw. JPEG-Bildern mit LSB-Wasserzeichen übernehmen DCT-Werte die Rolle der RGB-Werte. Dies ist in Abschnitt 4.2.3 beschrieben. Das LSB-Wasserzeichen ist fragil, denn die Wahrscheinlichkeit, selbst bei einer einfachen Manipulation des Bildes ein LSB, das einen Teil der Wasserzeichennachricht darstellt, zu verändern, ist sehr hoch. Das LSB-Wasserzeichen ist für viele Anwendungen von Interesse. Es kann beispielsweise als fragiles Wasserzeichen zur Authentifizierung von Bildinhalten verwendet werden. ([CMB02], Kapitel 5.3.3) 4.2.2 Konzept der detaillierten Frame-Analyse In Abschnitt 4.1 wurde bereits das DivideIntoUnits-PlugIn vorgestellt, mit dessen Hilfe Frames aus einem MPEG-Video-Strom herausgesucht werden können. Diese Frames sollen mit Hilfe der Watermarker-Klasse mit digitalen Wasserzeichen markiert werden. Dafür ist ein Zwischenschritt notwendig, der hier vorgestellt wird. Das Konzept sieht eine Frame-Klasse vor; diese ist nicht zu verwechseln mit java.awt.Frame. Das DivideIntoUnits-PlugIn soll der Klasse Frame die herausgesuchten Frame-Daten übergeben und somit separieren. Bei noch genauerer Betrachtung dieses Konzeptes gibt es für die spezifischen Frame-Typen individuelle Subklassen von Frame. So gibt es die Klasse IFrame, die alle I-Frames repräsentiert. Das DivideIntoUnits-PlugIn soll also alle I-Frame-Daten der Klasse IFrame übergeben. An dieser Stelle kommt einer der in Abschnitt 2.4 angedeuteten Gründe zum Tragen, warum in dieser Arbeit lediglich I-Frames und keine P- oder BFrames separiert und weiter verarbeitet werden: I-Frames besitzen insgesamt zwar mehr Informationen, da sie komplette Bilder darstellen, jedoch gibt es beim Analysieren eines MPEG-Bytestroms einige erhebliche Erleichterungen. All diese Erleichterungen zu erwähnen würde den Rahmen der Arbeit übersteigen, sie sind im MPEG1-Standard [I93] nachzulesen. Hier soll ein ausgewähltes Beispiel genügen: Makroblöcke besitzen Typangaben, die weitere Parameter nach sich ziehen. Werden nur IFrames untersucht, so können die Typen und Parameter-Werte für P- und B-Frames von vorneherein ausgeschlossen werden. Die Klasse IFrame analysiert die Daten, die sie von DivideIntoUnits übergeben bekommt. Da die DCT-Koeffizienten zur Markierung mit einem LSB-Wasserzeichen von Interesse sind, müssen die Frame-Daten danach durchsucht werden. Als erstes müssen jedoch die Slices herausgesucht werden. Dabei sieht das Konzept die Klasse Slice vor, an die IFrame die Slice-Daten übergibt. Dies stellt kaum eine Schwierigkeit dar, denn Slices haben Startcodes. Das bedeutet, sie beginnen mit den üblichen 3 Bytes aus Nullen. Das 4. Byte kann 0x01 bis 0xAF beinhalten und dient 21 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich neben der Erkennung als Slice-Startcode gleichzeitig als vertikale Positionierung des ersten Makroblocks eines Slices in einem Frame. Darauf folgen einige Angaben wie Quantisierung und Zusatzinformationen, bevor die Makroblöcke beginnen. Ein Makroblock eines I-Frames hat eine Adress- und eine Typangabe, gefolgt von den Blöcken. Da ein I-Frame ein vollständiges Bild darstellt, besitzen die Makroblöcke jeweils sechs Blöcke; vier für die Luminanz (Helligkeit) und zwei für die Chrominanz (Farbe). Diese Blöcke stellen eine Anordnung von 8x8 Bildpunkten dar und dienen als Eingabe für die diskrete Kosinus-Transformation. Bei der Bildkomprimierung werden Blöcke aus 8x8 Bildpunkten in 8x8 DCT-Koeffizienten transformiert, wie dies im nächsten Abschnitt beschrieben wird. Die Slice-Klasse sucht aus den Daten, die sie von IFrame übergeben bekommen hat, die DCT-Koeffizienten heraus, damit diese dann mit Wasserzeichen markieren werden können. An dieser Stelle kann die Klasse Watermarker eingebunden werden. Die DCTKoeffizienten liegen als Bits in byte-Arrays vor und können mit einem LSBWasserzeichen markiert werden, wie es in den nächsten Abschnitten beschrieben wird. 4.2.3 LSB-Wasserzeichen in MPEG Der Aufbau eines LSB-Wasserzeichen in einem Bild, das im RGB-Format vorliegt, wurde in Abschnitt 4.2.1.4 beschrieben. Es wurde darauf hingewiesen, dass es sich von einem LSB-Wasserzeichen in einem MPEG-Video unterscheidet. Die Frames eines MPEG-Videos basieren auf JPEG-Komprimierung. Sie beinhalten keine separaten Werte für Rot, Grün und Blau, sondern die Bildpunkte werden durch DCTKoeffizienten dargestellt. Um ein LSB-Wasserzeichen in einem MPEG-Frame nachvollziehen zu können, werden die DCT-Koeffizienten eines Frames genauer erklärt. Wie in Abschnitt 2.3 beschrieben, bestehen Makroblöcke in I-Frames aus 6 Blöcken, die zusammen 16x16 Bildpunkte darstellen (siehe Abbildung 3). Jeder Block beinhaltet 8x8 Werte des Bildpunktbereichs (Ortsbereich) und dient als Eingabe für die diskrete Kosinus-Transformation. Ein Block mit 8x8 Werten aus dem Ortsbereich, Abbildung 9 (a), wird mit Hilfe der zweidimensionalen diskreten Kosinus-Transformation in 8x8 Werte im Frequenzbereich, also in DCT-Koeffizienten siehe Abbildung 9 (b), transformiert. 22 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Abbildung 9: Diskrete Kosinus-Transformation [I93], [O04] Abbildung 9 stellt neben den DCT-Koeffizienten (b) die nach der Frequenz angeordnet sind die zugehörigen DCT-Basisfunktionen (c) dar. Der linke obere DCT-Koeffizient wird mit DC (Direct Current) bezeichnet und gibt die durchschnittliche Helligkeit aller Werte eines Blockes an. DC repräsentiert die einzige konstante Basisfunktion. Die anderen Koeffizienten heißen AC (Alternating Current) und geben die Abweichung zu dem DC-Wert an. Die AC-Werte rechts von DC repräsentieren horizontale, ansteigende Frequenzen und die AC-Werte unterhalb des DC-Wertes repräsentieren vertikale, ansteigende Frequenzen. Andere AC-Werte beinhalten sowohl horizontale, als auch vertikale Frequenzen. Alle DCT-Koeffizienten eines Blocks beinhalten alle Bildpunkt-Werte eines Blocks. Dabei können diese beiden Block-Repräsentationen trotz ähnlicher Darstellungsmöglichkeiten (Koordinaten-Anordnung) und gleichen Werte-Anzahlen (beide 8x8) nicht gleichgesetzt werden; in einem Frame wird nicht einfach jeder Bildpunkt durch einen DCT-Koeffizient repräsentiert. Die diskrete Kosinus-Transformation, die die beiden Repräsentationen voneinander trennt bzw. ineinander transformiert, ist komplexer als solch eine simple Annahme. Die zweidimensionale diskrete Kosinus-Transformation ist ein Produkt zweier eindimensionaler DCTs. x und y beschreiben die 64 Werte eines Blocks, die wie folgt in eine DCT-Darstellung transformiert werden: [I93] 23 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Mit Hilfe der Transformationsformel werden räumlich angeordnete Bildpunkte f(x,y) aus dem Ortsbereich in eine äquivalente Darstellung im Frequenzbereich, in DCTKoeffizienten F(u,v), transformiert. Dabei stellt f(x,y) die 64 Werte im Bild- bzw. Ortsbereich (Bildpunkte) dar. Die exakten Werte sind vom jeweiligen Farbmodell abhängig und können in MPEG-1 die in der Formel angegebenen Werte annehmen. F(u,v) repräsentiert die 64 DCT-Koeffizienten-Werte des Frequenzbereichs. Das Prinzip der Transformation ist für alle Blöcke (Luminanz- und Chrominanzblöcke) gleich; lediglich die exakten Werte hängen von dem jeweiligen Block, also von dem was sie repräsentieren (beispielsweise Helligkeit oder Farbe), ab. Um einen Frame in quadratischen Einheiten darstellen zu können und gleichzeitig den Rechenaufwand zu verringern, wird die DCT nicht auf einen ganzen Frame angewendet, sondern normalerweise auf 8x8 Bildpunkt-Werte. Würde man die Anzahl der Bildpunkte erhöhen, könnte zwar eine bessere Komprimierung erreicht werden, jedoch zum Nachteil der Laufzeit. ([KAA04], Kapitel 2) So kommt es zu einer Blockgröße von 8x8 Bildpunkten. Die berechneten DCT-Koeffizienten werden schließlich noch einer Quantisierung unterzogen, die hier nicht erklärt wird, da sie für diese Arbeit nicht relevant ist. Die DCT-Koeffizienten müssen im Bytestrom nacheinander gespeichert sein, sie werden im Zig-Zag-Modus von links oben bis rechts unten geordnet. Da sich die meisten Werte auf die linke obere Ecke der Matrix aus Abbildung 9 (b) konzentrieren, also meistens die hohen Frequenzen auftreten, ergibt sich der Vorteil, dass mögliche Nullen am Ende eines Blockes nicht unbedingt aufgeführt werden müssen, sondern durch einen End-Of-Block-Code verkürzt werden können. Ein Makroblock besteht aus 4 Luminanz- und 2 Chrominanzblöcken. Deren Werte werden nacheinander im Bytestrom angeordnet, zuerst die Luminanz- und dann die Chrominanz-Werte. Da Änderungen von Luminanzblöcken stärker auffallen, sollen für die Least-Significant-Bits in einem Frame die Chrominanzblöcke betrachtet werden. 24 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich In einem I-Frame bestehen Makroblöcke jeweils aus sechs Blöcken, die je 64 DCTWerte besitzen. Da der letzte Chrominanzblock weniger Relevanz als der vorletzte besitzt, beschränkt sich das hier verwendete LSB-Wasserzeichen auf diesen. Von den 64 DCT-Werten fallen Änderungen am niedrigsten (also letzten) Wert am geringsten auf. Genau diese Bits stellen die LSBs dar und können analog zu den LSBs eines Bildes im RGB-Format mit einem LSB-Wasserzeichen markiert werden. Die LSBs werden für die Markierung mit einem LSB-Wasserzeichen herausgesucht, um dann durch die Watermarker Klasse markiert werden zu können. Diese Funktionalität ist im folgenden Abschnitt beschrieben. 4.2.4 Watermarker Klasse Die Funktionalität der Markierung mit digitalen Wasserzeichen erfolgt durch die Watermarker-Klasse. Diese Klasse ist abstrakt und wird von der LSBWatermarker-Klasse implementiert. Watermarker besitzt die abstakte Methode process(inputByte), die von LSBWatermarker ebenfalls implementiert und definiert werden muss. Dieser Methode wird als Parameter ein byte übergeben, das ein Bit repräsentiert, und ein solches wird auch zurückgegeben – der Rückgabetyp dieser Methode ist byte. Die Funktionalität, die LSBWatermarker erfüllen soll, besteht in der Veränderung der übergebenen bytes, die Bits repräsentieren. Die Bits, die an LSBWatermarker übergeben werden, stellen bereits die LSBs dar. Das bedeutet, dass diese nun nach dem Prinzip aus Abschnitt 4.2.1.4 an die Bits der Wasserzeichennachricht angepasst werden müssen. Dabei wird nicht unbedingt jedes LSB, das an LSBWatermarker übergeben wird und einen Teil der Wasserzeicheninformation darstellt, verändert zurückgegeben. Es werden nur solche LSBs verändert zurückgegeben, die nicht von vorne herein die gewünschte Information tragen. Eine Schwierigkeit, die auftritt ist die, dass in Java lediglich byte als kleinste verwendbare Einheit existiert. Eine Lösung hierfür wurde bereits in Abschnitt 4.1.3 vorgestellt. Dort ist beschrieben, wie byte als Bit interpretiert werden kann und wie eine mögliche Problemlösung aussehen kann. 25 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich 5 Zusammenfassung Die Aufgabe dieser Studienarbeit ist die Medienverarbeitung mit Java in elementaren Einheiten. Das Ergebnis besteht aus einem PlugIn für das Java Media Framework: Mit Hilfe des DivideIntoUnits-PlugIns wird eine Weiterverarbeitung in elementaren, semantischen Einheiten ermöglicht. Es können die Klassen Frame, Slice und Watermarker ergänzt werden, durch die eine Markierung des Videos mit digitalen Wasserzeichen als Weiterverarbeitung der elementaren Einheiten ermöglicht wird. Zuerst wurde die Frage nach den elementaren, semantischen Einheiten geklärt. Diese Einheiten sollen die Eigenschaften von elementar, also grundlegend notwendig und wesentlich, sowie von semantisch, also einen Bezug zu der Bedeutung von Zeichen bzw. der Bedeutung von Daten oder von Informationen, besitzen. Da ein Video aus einer Folge von Frames besteht, kann eine elementare, semantische Einheit ein Frame sein. In dieser Arbeit wird mit dem Videoformat MPEG gearbeitet. Dieses besteht aus Sequenzen, die sich aus Groups-Of-Pictures zusammensetzen. GOPs sind Folgen von Frames. In einem Frame gibt es Slices, in denen wiederum Makroblöcke vorzufinden sind. Die kleinste Einheit stellen schließlich die Blöcke dar. In solch einem MPEG-Video wurde als nächstes eine elementare, semantische Einheit definiert. Der Aufbau eines MPEG-Videos zeigt, dass dieses Video durch die Art der Komprimierung nicht einfach nur aneinander gereihte Frames darstellt, sondern u. a. verschiedene Frame-Typen aufweist. In einer genauen Analyse wurde herausgearbeitet, dass für diese Arbeit die Separation von I-Frames ausreicht. Bei Separation aller möglichen Frame-Typen, also auch B-, P- und D-Frames, würde ein erheblicher Mehraufwand den Rahmen übersteigen. Kennt man den Aufbau eines MPEGVideos kann dessen Bearbeitung beginnen, bei der zunächst die elementaren, semantischen Einheiten herausgesucht werden sollen. Für die Medienverarbeitung in Java bietet sich das Java Media Framework an. Dieses Framework stellt umfangreiche Funktionalitäten für die Medienbearbeitung zur Verfügung. Um einen Video-Strom gezielt zu analysieren und zu bearbeiten eignet sich die Verwendung von Processor. Es wird ein zusätzliches PlugIn mit vorgegebener Funktionalität benötigt, denn ein PlugIn kann in die Verarbeitungskette von Processor integriert werden und auf die einzelnen Tracks eines Videos angewendet werden. Ein Teil des Ergebnisses ist ein DivideIntoUnits-PlugIn, oder besser gesagt ein DivideIntoUnits-Codec, also ein spezielles PlugIn, das auf den VideoTrack des MPEG-Videos angewendet wird. Es hat die Aufgabe, den Video-Strom, der im JMF als byte-Array vorliegt, zu analysieren, die elementaren, semantischen Einheiten zu finden und zu separieren. Es ist möglich, dass diese Einheiten einer weiteren Verarbeitung unterzogen werden; beispielsweise können sie mit Hilfe der 26 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Klassen Frame, Slice und Watermarker mit digitalen Wasserzeichen markiert werden. Digitale Wasserzeichen können unter anderem dem Nachweis der Integrität oder Authentizität eines Mediums dienen. Bei der Markierung eines Mediums mit einem digitalen Wasserzeichen wird das Medium verändert, indem ihm zusätzlich nichtwahrnehmbare Informationen hinzugefügt werden. Das Ergebnis besteht aus zwei Teilen, die kombiniert werden können. Zum einen dient das DivideIntoUnits-PlugIn der Analyse eines Videos und dessen Zerlegung in elementare, semantische Einheiten. Zum anderen stellen Frame, Slice und Watermarker eine mögliche Weiterverarbeitung der elementaren Einheiten dar, bei der ein Video mit digitalen Wasserzeichen markiert werden kann. 27 Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Anhang – Codebeispiel Im Folgenden wird als Ergänzung zu Kapitel 4.1.1 ein Java Codebeispiel vorgestellt. Es ist in gekürzter Form abgebildet und stellt keinen Anspruch auf Vollständigkeit, sondern verdeutlicht die Funktionsweise der Medienverarbeitung im Java Media Framework. Um ein solches Programm fehlerfrei auszuführen, fehlen noch einige weitere Zeilen. Das Codebeispiel zeigt, wie ein MPEG-System-Strom eingelesen und damit ein Processor erzeugt werden kann. Aus dem MPEG-System-Strom wird ein Video-Track herausgesucht, um schließlich das DivideIntoUnits-PlugIn darauf anwenden zu können. Durch das Interface ControllerListener mit der Methode controllerUpdate ist ein Ereignis-Verarbeitungsmodell mit eingebunden. import java.io.*; import javax.media.*; public class MpegAnalyser implements ControllerListener { Processor processor; MediaLocator inputMediaLocator; Object waitSync = new Object(); boolean stateTransitionOK = true; String inputFilePath = „pathToSomeVideo\\someVideo.mpg“; TrackControl[] trackControl; TrackControl videoTrack; public static void main(String[] args) { MpegAnalyser mpegAnalyser = new MpegAnalyser(); mpegAnalyser.startMpegAnalyser(); } public MpegAnalyser() { //create processor processor = null; inputMediaLocator = new MediaLocator("file:" + inputFilePath); try { processor = Manager.createProcessor(inputMediaLocator); } catch (Exception exception) { exception.printStackTrace(); } processor.addControllerListener(this); } /** * analyse MPEG stream and search video track, set plug-in to flow path */ public boolean startMpegAnalyser() { //put the processor into configured state processor.configure(); if (!waitForState(processor.Configured)) { System.err.println("Failed to configure the processor."); return false; } //obtain the track controls trackControls = processor.getTrackControls(); if (trackControls == null) { return false; } //search for the trackControl for the videoTrack videoTrack = null; for (int i = 0; i < trackControls.length; i++) { if (trackControls[i].getFormat() instanceof VideoFormat){ videoTrack = trackControls[i]; break; } v Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich } if (videoTrack == null) { System.err.println("Input media does not contain a video track."); return false; } //instantiate and set DivideIntoUnits codec to data flow path try { Codec codecs[] = {new DivideIntoUnits()}; videoTrack.setCodecChain(codecs); } catch (UnsupportedPlugInException e) { System.err.println("Process does not support effects."); } //realize the processor processor.prefetch(); if (!waitForState(processor.Prefetched)) { System.err.println("Failed to realize the processor."); return false; } //start the processor processor.start(); return true; } /** * block until processor has transitioned to the given state, * return false if transition failed */ boolean waitForState(int state) { synchronized (waitSync) { try { while (processor.getState() != state && stateTransitionOK) waitSync.wait(); } catch (Exception e) { System.err.println("Exception in method waitForState: " + e); } } return stateTransitionOK; } /** * method for event handling, is always called if event is caused */ public void controllerUpdate(ControllerEvent controllerEvent) { if (controllerEvent instanceof ConfigureCompleteEvent || controllerEvent instanceof RealizeCompleteEvent || controllerEvent instanceof PrefetchCompleteEvent) { synchronized (waitSync) { stateTransitionOK = true; waitSync.notifyAll(); } } else if (controllerEvent instanceof ResourceUnavailableEvent) { synchronized (waitSync) { stateTransitionOK = false; waitSync.notifyAll(); } } else if (controllerEvent instanceof EndOfMediaEvent) { processor.close(); System.exit(0); } } } vi Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich Quellen [CMB02] Cox, I. J., Miller, M. L., Bloom, J. A.: Digital Watermarking. Academic Press, San Diego, ISBN: 1-55860-714-5, 2002 [D00] Dittmann, J.: Digitale Wasserzeichen. Springer Verlag, Berlin, Heidelberg, ISBN: 3-540-66661-3, 2000 [ED04] Eidenberger, H. M., Divotkey, R.: Medienverarbeitung in Java™ – Audio und Video mit Java Media Framework & Mobile Media API, dpunkt Verlag, Heidelberg, ISBN: 3-89864-184-8, 1. Auflage, 2004 [H95] Heuler, M.: Bilddatenkompression mit MPEG-2. http://www.heuler.net/stud/seminar/node3.html#SECTION00021, 13.06.1995, zuletzt überprüft: 10.01.2006 [I93] ISO/IEC 11172: Information technology – Coding of moving pictures and associated audio for digital storage media at up to about 1,5 MBit/s. International Standart © ISO/IEC, Genf, 1. Ausgabe: 01.08.1993 [KAA04] Kachouri, R., Abid, M., Amar, C. B.: Design of DCT_2D toward FPGA. IEEE Conference Proceeding, 2004 [L] Lo, V.: A beginners guide for MPEG-2 Standard. http://www.fh-friedberg.de/fachbereiche/e2/telekomlabor/zinke/mk/mpeg2beg/beginnzi.htm, zuletzt überprüft: 22.03.2006 [M95] Moving Pictures Experts Group: The MPEG Home page. http://www.chiariglione.org/mpeg/, zuletzt überprüft: 10.01.2006 [M96] MPEG-2: Unix Open 05/96 Mai – Video-Codierung mit MPEG-2. http://www.mpeg2.de/doc/mpuo05/mpuo05.htm, 1996, zuletzt überprüft: 10.01.2006 [M03] Mandau, M.: Vergleichstest: MPEG4-Encoder & Alternativen – Wie MPEG-Standards Filme komprimieren. CHIP Online Archiv, http://archiv.chip.de/artikel/c1_archiv_artikelunterseite_17143436.html, 27.05.2003, zuletzt überprüft: 30.03.2006 [O04] Okumura, H.: DCT (Discrete Cosine Transform). http://oku.edu.mie-u.ac.jp/~okumura/compression/dct.html, 2004, zuletzt überprüft: 22.03.2006 vii Medienverarbeitung mit Java in elementaren Einheiten Verena Henrich [P06] PARADISO-design.net: Fernsehnormen – Standards und Technik. http://www.paradiso-design.net/videostandards.html, 2004 – 2006, zuletzt überprüft: 10.01.2006 [S99] Steinmetz, R.: Multimedia-Technologie – Grundlagen, Komponenten und Systeme. Springer Verlag, Berlin, Heidelberg, ISBN: 3-540-62060-5, 2. Auflage, 1999 [SM99] Sun Microsystems: Java™ Media Framework API Guide. Sun Microsystems, Inc., California, http://java.sun.com/products/java-media/jmf/2.1.1/specdownload.html, 19.11.1999 [SM01] Sun Microsystems: Java Media Framework API. Sun Microsystems, Inc., http://java.sun.com/products/java-media/jmf/2.1.1/apidocs/, 1999 – 2001, zuletzt überprüft: 25.01.2006 [SM05] Sun Microsystems: Java Media Framework Homepage. Sun Microsystems, Inc., http://java.sun.com/products/java-media/jmf/, 1994 – 2005, zuletzt überprüft: 10.01.2006 [U06] Ullenboom, C: Java ist auch eine Insel – Programmieren mit der Java Standard Edition Version 5. Galileo Computing, ISBN 3-89842-747-1, http://www.galileocomputing.de/openbook/javainsel5/, 5. Auflage, 2006 viii