Multimediaschnittstelle Microsoft DirectShow Fach: Fachrichtung: Semester: Name: Matrikel: Vertiefung (Seminar) MNC 3 Robin Lüdtke 41621 Inhaltsverzeichnis 1. Grundlagen .................................................................... 3 1.1 VFW ........................................................................................................................... 3 1.2 WDM (KS) / WMF .................................................................................................... 4 1.3 DirectShow – DirectX ................................................................................................ 5 1.4 Aufgaben von DirectShow ......................................................................................... 6 1.5 COM - kurze Einführung ........................................................................................... 7 2. Architektur .................................................................... 9 2.1 3. Filter-Graph-Manager .............................................................................................. 11 Filter-Graphen ............................................................ 12 3.1 Erstellung von Filter-Graphen .................................................................................. 12 3.2 Filter-Verbindungsprotokolle ................................................................................... 14 3.2.1 3.2.2 3.2.3 3.3 Datenfluss-Protokolle ............................................................................................... 17 3.3.1 3.3.2 3.4 MediaType-Vermittlung ................................................................................................................ 14 Transport-Vermittlung .................................................................................................................. 15 Speicherverwaltung-Vermittlung .................................................................................................. 16 Streaming-Protokoll ...................................................................................................................... 17 Control-Protokoll .......................................................................................................................... 18 Synchronisation ........................................................................................................ 20 4. Beispiel ......................................................................... 22 5. Zusammenfassung ...................................................... 23 6. Quellen ......................................................................... 23 2 1. Grundlagen In der folgenden Ausarbeitung werden die Grundlagen von DirectShow beschrieben. Jeder, der mittels Microsoft-Betriebssystem (ab Win98) versucht hat, eine DVD, ein Video, einen Song im MP3-Format wiederzugeben oder beispielsweise eine Webcam über USB oder eine Videokamera über Firewire benutzt hat, hat unbewusst die DirectShow-Schnittstelle benutzt. Denn der größte Teil der Multimediasoftware (z.B.: Windows Media Player, Pinnacle Studio, Winamp, Intro-Videos bei PC-Spielen, …) unter Windows nutzt DirectShow für die Multimediadatenverarbeitung. 1.1 VFW 1992 wurde die VFW-Multimediaschnittstelle als frei erhältliches AddOn für das MicrosoftBetriebssystem Windows 3.11 zur Verfügung gestellt. Anfangs waren die Aufgaben und Leistung sehr beschränkt. Durch Weiterentwicklung ist folgender Aufgaben/Funktionsumfang entstanden: • Aufgaben: Abspielen / Aufnahme / Kompression / Dekompression von Video• • • /Audiodaten Anfangs: nur 16-Bit Architektur; Heute: teilweise 32-Bit. AVI (Audio Video Interleaved) Container-Dateiformat Spezielle Treiber für Kommunikation mit Hardware Die Weiterentwicklung von VFW ist seit einigen Jahren eingestellt. Wesentliche Gründe (Nachteile) dafür sind: • VFW-Treiber: separate Treiber für WinNT/Win9x notwendig (nicht Sourcecode- • • • • /Binärkompatibel), keine standardisierten gerätespezifischen Kommunikationsschnittstellen (z.B.: fehlende TVTuner-Unterstützung), Treibermodell inkonsistent Unterstützung weniger Dateiformate (z.B.: AVI Container-Dateiformat) nur teilweise 32 Bit Architektur keine Synchronisationsmechanismen AVI Container-Dateiformat: begrenzt auf 2 GB, nicht streamingfähig, Synchronisation schwierig Aufgrund der genannten Nachteile ist eine neue Multimediaschnittstelle unabdingbar. Zusätzlich sind das VFW-Treibermodell sowie das AVI Container-Dateiform, aufgrund enormer Einschränkungen und Nachteile für heutige Anforderungen nicht mehr akzeptabel. Aufgrund von Kompatibilitätszwecken ist es weiterhin Bestandteil der WindowsBetriebssysteme. Beispiel: Will man eine Videodatei über das Internet empfangen (streamen), so muss die Multimediaschnittstelle sowie das Dateiformat über Synchronisationsmechanismen verfügen. Weder die VFW-Multimediaschnittstelle noch das AVI Dateiformat können somit für einen derartigen Einsatzbereich verwendet werden. Neuentwicklung: Multimediaschnittstelle (DirectShow) / Treiberarchitektur (siehe Abschnitt 1.2 (WDM)) / Dateiformat (siehe Abschnitt 1.2 (WMF)) 3 1.2 WDM (KS) / WMF WDM (Windows Driver Model) (KS (Kernel-Streaming)): Dieses Treibermodell basiert auf dem WinNT-Treibermodell mit wesentlichen Erweiterungen (z.B.: Plug&Play). WDM wird für Multimediageräte und neuere USB oder Firewire-Geräte verwendet. Vorteile gegenüber VFW-Treiber: Treiber sind innerhalb der Windows-Betriebssysteme kompatibel. Entwickler müssen somit nicht für jedes Betriebssystem einen eigenen Treiber programmieren, wie es bei VFW der Fall ist. es besteht volle 32-Bit Unterstützung standardisierte Kommunikationsschnittstellen sind vorhanden (z.B.: TVTunerUnterstützung, Captureformate auslesen, Videoparametereinstellung,…) Die erste Implementierung von WDM sah noch vor, alle Signale in einem auf Kernel-Ebene laufenden Mixer zusammenzumischen und erst dann auszugeben. Dabei entstand eine nicht zu verhindernde Latenz von 30ms, die im Video-/Audiobereich unakzeptabel ist. Auf Vorschlag der Firma Cakewalk wurde eine Variante von WDM entworfen, die es ermöglichte, auch an diesem Mixer vorbei auf die Hardware zuzugreifen. Inzwischen wurde dieser Vorschlag von Microsoft offiziell anerkannt und diese Variante wird als WDM(KS) (Kernel-Streaming) bezeichnet. Geräte auf WDM-Treibern basierend, unterstützen das Kernel-Streaming. Dabei werden die Daten ohne umschalten in den User-Mode, komplett im Kernel-Mode transportiert. Daraus ergeben sich folgende Vorteile: Die Umschaltung zwischen User- und Kernel-Mode ist sehr rechenintensiv und dadurch entstehen hohe Latenzzeiten Latenzzeit wird verringert Kernel-Streaming erlaubt hohen Datentransfer ohne CPU-Belastung Das Kernel-Streaming basiert auf einer Filterarchitektur, wie in der folgenden Abbildung 1 dargestellt. Jeder Filter entspricht einem WDM-Treiber mit KS-Unterstützung. Filter werden über Pins miteinander verbunden. Der Datentransfer geschieht über die verbundenen Pins im Kernel-Mode (Multimediadaten-Transport von Hardware zu Hardware). Abbildung 1: Kernel Streaming Filter-Architektur am Beispiel WMF (Windows Media Format): Innerhalb des WMF wird das Container-Dateiformat ASF (Advanced-Streaming-Format) beschrieben. Dies ist ein proprietäres Format und stellt Microsofts eigene MPEG4Implementierung dar. Entwickelt wurde es vor der Verabschiedung des endgültigen MPEG4 Standards, welcher das QuickTime Movie (MOV-Format) vorsieht. Auch bietet das WMF die 4 Möglichkeit der Kompression von Video-/Audiodaten mittels Microsofts entwickelten MPEG4-Codec’s, sowie die effiziente Multimedia-Datenübertragung per Netzwerk (geringe Netzwerkbandbreite). In neueren WMF-Versionen wird zusätzlich HDTV unterstützt. Mit Microsofts MPEG4-Codec komprimierte Videos erhalten die Dateiendung „.wmv“ (Windows Media Video) und Audiodaten „.wma“ (Windows Media Audio) Vorteile von ASF Container-Dateiformat gegenüber AVI Container-Dateiformat: 1.3 ASF enthält Synchronisationsmechanismen und ist somit Streamingfähig Dateigröße nicht begrenzt DirectShow – DirectX DirectX ist eine Sammlung von Komponenten für verschiedene multimediale Bereiche (Grafik, Audio,…) und bietet dafür Schnittstellen für die effiziente Kommunikation von Software mit Hardware. Dem Programmierer steht eine hardwareunabhängige Funktionsbibliothek bereit. Wird eine DirectX-Funktion verwendet, die eine spezielle Hardware erfordert, so wird diese Funktion bei fehlender Hardwareunterstützung mittels Softwareemulation (optimierte Softwareroutinen mittels Assemblercode) bereitgestellt. DirectShow ist seit 1996 Bestandteil der DirectX-Komponentensammlung und benutzt andere DirectX-Komponenten wie in Abbildung 2 dargestellt. Im Abschnitt 2 folgt eine detaillierte Erklärung. Abbildung 2: DirectX Komponenten 5 1.4 Aufgaben von DirectShow Hauptaufgaben: In der Abbildung 3 wird das Hauptprinzip von DirectShow präsentiert. DirectShow wird vorerst zur Vereinfachung als Black-Box dargestellt. Im ersten Schritt wird immer eine Multimediadatenquelle benötigt (links dargestellt), welche Multimediadaten erzeugt und an die Black-Box weiterleitet. Als Quelle können verschiedene Multimedia-Peripheriegeräte dienen (z.B.: DVB-T-/TVKarten, Framegrabber, Firewire-/USB-Kameras, Audioquellen), welche über einen WDModer VFW-Treiber verfügen. Multimediadatenträger(z.B.: Video-CD, Video-DVD) sowie auf Datenträgern abgelegte Videos (z.B.: MPEG-Video, QuickTime-Video), Audiomaterial (z.B.: MP3, PCM-Audio) und Einzelbilder (z.B.: JPG, BMP, TIFF) oder Netzwerkstreams sind ebenfalls möglich. Im zweiten Schritt werden die erhaltenen Multimediadaten von der Multimediadatenquelle, innerhalb der Black-Box verarbeitet (z.B.: Kompression, Dekompression, Multiplexing, …). Die Applikation kann dabei die Datenverarbeitung in der Black-Box über verschiedene Funktionen steuern. Im letzten Schritt werden die Multimediadaten ausgegeben (rechts dargestellt). Die Ausgabe kann entsprechend des Multimediadatenformats an die Grafikkarte, Soundkarte oder auf einen Datenträger (z.B.: Videos, Einzelbilder) oder Netzwerkstream erfolgen. Abbildung 3: Hauptaufgaben von DirectShow DES (DirectShow Editing Service): Aufbauend auf der DirectShow-Architektur bietet DirectShow zusätzlich eine API für Videobearbeitung (Video-/Audioschnitt), die in dieser Dokumentation nicht erklärt wird. 6 1.5 COM - kurze Einführung DirectShow sowie alle DirectX-Komponenten und andere Software basieren auf der „COM“Technologie (Component Object Model). Um ein besseres Verständnis der folgenden Abschnitte und Beispiele zu erhalten, werden an dieser Stelle die Grundlagen dieser Technologie beschrieben. Komponentenbasierte Softwareentwicklung ist die Basis der Software heutzutage. Anstelle der Programmierung von komplexer Software werden Software-Teilstücke (Komponenten) programmiert, welche zusammen kommunizieren. Der größte Vorteil liegt darin, dass die meisten Komponenten so aufgebaut werden können, um sie in einem nächsten Projekt ohne größere Veränderungen wieder zu verwenden. Ein weiterer Vorteil ergibt sich in der Überarbeitung der Komponenten, wobei jede Komponente separat weiterentwickelt werden kann, ohne die anderen Komponenten zu beeinflussen. Die Basis der Komponentenentwicklung beruht dabei auf einem einheitlichen Kommunikationsprotokoll, damit die erstellten Komponenten untereinander überhaupt kommunizieren können. Microsoft hat dafür die Schnittstelle „COM“ (Component Object Model) ins Leben gerufen, welche die Art und Weise der Kommunikation zwischen Objekten sowie die Spezifikationen der Objekte selbst und ihre Funktionalitäten beschreiben. COM ist dabei Sprach- Plattform- und Maschinenunabhängig (COM kann ebenfalls über Netzwerk mit Objekten kommunizieren) entwickelt. Die Basis eines COM-Objekts ist ein Codeblock, welcher ein oder mehrere COMSchnittstellen (Interfaces) beinhaltet. Eine COM-Schnittstelle ist wiederum eine Kapselung von Funktionen und die Implementierung ist ähnlich der Implementierung von virtuellen Funktionstabellen der meisten C++ Compiler. In C++ bedeuten COM-Objekte eine oder mehrere abstrakte Klassen, welche COM-Schnittstellen genannt werden. Andere Klassen können lediglich die Funktionen der COM-Objekte durch die angebundenen Schnittstellen aufrufen aber haben keinen Zugang auf Membervariablen, sondern können diese nur über Set/Get Funktionen, welche die Schnittstelle bietet verändern. Abbildung 4: COM Objekt + Schnittstellen (Interfaces) Alle COM-Schnittstellen werden direkt oder indirekt von der so genannten „IUnknown“ abgeleitet. IUnknown ist folgendermaßen deklariert: Klasse typedef struct interface; interface IUnknown { virtual HRESULT QueryInterface( REFIID idd, void** ppvObject) = 0; virtual ULONG AddRef( void)= 0; virtual ULONG Release( void) = 0;}; 7 Die Funktionen AddRef und Release dienen dem Anlegen und Zerstören von COM-Objekten und sollen nicht weiter betrachtet werden. Hauptbestandteil damit COM überhaupt funktionieren kann, ist die Funktion QueryInterface(). Durch diese Funktionen können weitere Schnittstellen, die das COM-Objekt anbietet verwendet werden. Der Funktion wird eine Schnittstellen-ID (GUID) und ein Zeiger übergeben, welcher nach Abschluss mit dem Schnittstellenzeiger, durch die ID bestimmte Schnittstelle gefüllt ist. Als Beispiel könnte man sich ein Radio vorstellen. Zuerst legt man ein Radio-Objekt an und erhält einen Schnittstellen Zeiger auf pRadio. Will man nun den CD-Player bedienen so fragt man über die Radio-Schnittstelle, ob eine Schnittstelle ICDPlayer vorhanden ist: ICDPlayer* pCDPlayer = NULL; HRESULT hr = pRadio->QueryInterface(IID_ICDPlayer, (VOID**)&pCDPlayer ); // pCDPlayer kann nun genutzt werden Dies ist der Vorteil von COM. Das Objekt kann verbessert und erweitert werden ohne jegliche Neukompilierung. Wenn man sich beispielsweise für die Unterstützung eines Kassettenplayers entscheidet, so muss nur über QueryInterface() die Schnittstelle ICassettePlayer nachgefragt werden. Damit COM so arbeiten kann gibt es zwei Restriktionen für das System-Design. Alle Schnittstellen müssen public definiert sein. In den DirectX Header-Dateien kann man beispielsweise alle DirectX-Schnittstellen finden. Jedes COM-Programm kann jedes COMObjekt nutzen, solange es die Schnittstellendefinition sowie die IDs (GUIDs) für die COMSchnittstelle kennt. Eine weitere Restriktion ist, dass eine COM-Schnittstelle sich niemals ändern darf. Nachdem sie fertig gestellt ist und der Öffentlichkeit zugänglich ist, kann keine Modifikation mehr vorgenommen werden. Um weitere Funktionalitäten zu integrieren müssen neue COM-Schnittstellen erstellt werden. Will man also die vorhandene Schnittstelle ICDPlayer erweitern so muss man eine neue Schnittstelle ICDPlayer2 anlegen. Wird die erweiterte COM-Schnittstelle ICDPlayer2 nicht benötigt, so kann natürlich auch ICDPlayer weiterhin uneingeschränkt genutzt werden. Die „älteren“ COM-Schnittstellen verfallen also nicht. Nun bleibt noch die letzte Frage, wie COM-Objekte überhaupt angelegt werden. Ein COM Objekt wird generell durch eine COM-Objekt-ID und einer Schnittstellen-ID bestimmt. Intern ruft die COM-Erstellungsroutine die Windows-Registrierung auf und sucht die COM-Objekt-ID. Wenn das COM-Objekt im System installiert ist, so gibt es in der Registrierung eine Referenz von COM-Objekt-ID auf eine DLL. Die DLL wird dann von der nachfragenden Anwendung aus geladen. Das Objekt wird unter Benutzung einer DLL-Side Class-Factory konstruiert und gibt eine Iunknown-Schnittstelle zurück und danach wird diese Schnittstelle nach der angegebenen Schnittstellen-ID untersucht. Beispiel: Wenn man nach der COM-Objekt-ID für Direct3D in der Registrierung sucht, so findet man eine Referenz zu d3d9.dll. Um allen COM-Objekt Entwicklern eine eindeutige ID für Ihre COM-Objekte zu garantieren, gibt es die sogenannte GUID (globally unique identifiers), welche aus 16 Byte besteht und einmalig ist. Diese GUID setzt sich zusammen aus einem sehr langen TIMESTAMP und einer Hardware-ID (z.B. Netzwerkkarte des Rechners). 8 2. Architektur In den folgenden Abschnitten wird die in Abbildung 3 dargestellte Black-Box (DirectShow) detailliert beschrieben. Den ersten Einblick gewährt die Abbildung 5. Sie zeigt die zwei Hauptbestandteile von DirectShow (hellblau unterlegt). Der Filter-Graph-Manager dient zur Erstellung und Steuerung des Filter-Graphen und wird in Abschnitt 2.1 genauer erklärt. Der Filter-Graph stellt einen gerichteten Graphen mit Knoten (genannt Filter (implementiert als COM-Objekt)) dar, die über eine verschiedene Anzahl an Input- und Output-Pins verfügen. Die Filter werden über ihre Pins miteinander verbunden. Die Datenverarbeitung findet somit vollständig in den Filtern und der Daten-Transport über die Pins statt. Es stehen drei Filterarten zur Verfügung: Source-Filter leiten Daten in den Filter-Graph ein. Daten können beispielsweise aus einer Multimediadatei oder DVD, vom Netzwerk oder einer Firewire-/USB-Kamera stammen. Diese Filterart kann nur über Output-Pins verfügen, da sie am Anfang der Filterkette steht. Transform-Filter erhalten einen Eingangs-Datenstrom. Dieser wird im Filter verarbeitet und anschließend ein neuer Ausgangs-Datenstrom erzeugt. Video/Audiokompressoren, Dekompressoren und Effektfilter sind Beispiele für TransformFilter. Der Filter kann Input- sowie Output-Pins besitzen. Rendering-Filter befinden sich immer am Ende des Filter-Graphen. Der ankommende Eingangs-Datenstrom wird verarbeitet und dem Benutzer präsentiert. Ein Video-Rendering-Filter nutzt für die Präsentation von Videomaterial die Direct3D-Schnittstelle für optimale 2D-Grafikbeschleunigung. Beim AudioRendering-Filter erfolgt die Wiedergabe des Audiomaterials mittels der DirectSoundSchnittstelle. Bei der Wiedergabe einer Mididatei kommt die DirectMusicSchnittstelle zum Einsatz. Ein Rendering-Filter kann auch zum Schreiben von Daten auf verschiedene Datenträger oder für das Erzeugen von Netzwerkstreams verwendet werden. Diese Filterart kann nur Input-Pins besitzen, da sie am Ende der Filterkette steht. Abbildung 5: DirectShow-Architektur 9 Der genannte Sachverhalt soll am Beispiel noch einmal verdeutlicht werden. Es soll eine AVI-Datei mit integriertem Video und Audio wiedergegeben werden. An erster Stelle benötigt man einen Source-Filter, der einen Datenstrom von einem Datenträger lesen kann. In Abbildung 6 ist dieser Filter am Anfang des Filter-Graphen zu sehen mit einem Output-Pin. Dieser Datenstrom muss anschließend in eine Video- sowie Audiospur aufgeteilt werden. Diesen Vorgang übernimmt der „AVI-Splitter“-Transform-Filter. Da das Video- und Audiomaterial in der AVI-Datei im komprimierten Format vorliegt, müssen weitere Dekompressions-Filter (Transform-Filter) eingefügt werden. Im Beispiel übernimmt der „DivX Decoder Filter“ die Dekompression des Videomaterials und der „MPEG Layer-3 Decoder“ die Dekompression der Audiospur. Im nächsten Schritt können weitere TransformFilter in den Filter-Graph eingebaut werden (z.B.: „MV Rotate 90“-Filter (Video mit 90° Drehung) oder „Echo“-Filter). Abschließend stehen der „Video Renderer“-Filter sowie der „Default DirectSound Device“-Filter für die Präsentation von Video- sowie Audiomaterial zur Verfügung. Diese nutzen wie oben erwähnt die DirectX-Komponenten zur Präsentation der Multimediadaten. Abbildung 6: Filter-Graph für Wiedergabe einer „AVI“-Datei. Der Programmablauf jeder DirectShow-Anwendung ist immer gleich und in folgende drei Schritte unterteilt (siehe Abbildung 7): Abbildung 7: Programmablauf einer DirectShow-Anwendung 1) Applikation erstellt ein Objekt des Filter-Graph-Managers 2) Filter-Graph-Manager erstellt einen Filter-Graphen 3) Die Applikation gibt Steuerbefehle (z.B.: Start, Stop, Pause) an Filter-GraphManager. Der Filter-Graph-Manager steuert den Filter-Graphen und sendet Events des Filter-Graphen (z.B.: Videodateiende erreicht) an die Anwendung. Die Applikation kommuniziert nur mit dem Filter-Graph-Manager. Einzige Ausnahme ist die Konfiguration der einzelnen Filter im Filter-Graph durch die Anwendung selbst. 10 2.1 Filter-Graph-Manager Wie in Abschnitt 2 angedeutet, ist der Filter-Graph-Manager das zentrale Objekt von DirectShow mit folgenden Aufgaben: Erstellung, Steuerung, Synchronisation von Filter-Graphen Ereignisbehandlung (z.B.: Videodateiende erreicht) Er fungiert als Zwischenstück zwischen Applikation und Filter-Graph. Implementiert als COM-Objekt stellt er eine große Anzahl an COM-Schnittstellen für seinen Aufgabenbereich zur Verfügung. Beispiele (siehe Abbildung 8): IGraphBuilder COM-Schnittstelle: stellt Methoden für die Filter-Graph Erstellung bereit (siehe 3.1) IFilterMapper2 COM-Schnittstelle: enthält Methoden für die Registrierung, Unregistrierung und Suche von Filtern IMediaControl COM-Schnittstelle: dient der Datenfluss-Kontrolle des Filter-Graphen (Start, Stop, Pause – Methoden) Abbildung 8: Filter-Graph-Manager-Schnittstellen 11 3. Filter-Graphen Der Aufbau von Filter-Graphen kann im Abschnitt 2 nachgelesen werden. 3.1 Erstellung von Filter-Graphen Für die Erstellung von Filter-Graphen ist nur der Filter-Graph-Manager zuständig (siehe Abschnitt 2.1). Die Anwendung gibt lediglich Befehle zur Erstellung von Filter-Graphen über die Filter-Graph-Manager COM-Schnittstelle IGraphBuilder, mit den Hauptmethoden: IGraphBuilder::RenderFile(„Mediadateiname“) IGraphBuilder::Render(OutputPin) IGraphBuilder::Connect(OutputPin, InputPin) Intelligent Connect: Hinter diesen Methoden verbirgt sich das so genannte „Intelligent Connect“. Dies bedeutet: Es bestehen drei Möglichkeiten einen Filter-Graph zu erstellen, wie in Abbildung 9 dargestellt ist. Abbildung 9: „Intelligent Connect“ Vollautomatische Erstellung von Filter-Graphen: Die Anwendung ruft lediglich die Methode IGraphBuilder::RenderFile(…) des Filter-GraphManagers, unter Angabe einer Datei welche abgespielt werden soll auf. Daraufhin erstellt der Filter-Graph-Manager einen kompletten Filter-Graph, indem er folgende Schritte durchläuft: 1) Der Filter-Graph-Manager ruft die Methode IGraphBuilder::AddSourceFilter(...) auf, welche einen passenden Source-Filter in den Filter-Graph einfügt. 2) Der Filter-Graph-Manager ruft die Methode IGraphBuilder::Render(Output-Pin) auf, wobei das Output-Pin des eingefügten Source-Filters als Übergabeparameter dient. Dieser Methodenaufruf bewirkt das Einfügen eines Rendering-Filters in den Filter-Graph. Durch die Angabe des Output-Pins kann der passende RenderingFilter bestimmt werden. 3) Aufruf der Methode IGraphBuilder::Connect(Output-Pin, Input-Pin). Als OutputPin-Übergabeparameter dient das Source-Filter-Output-Pin und das RenderingFilter-Input-Pin wird als Input-Pin-Übergabeparameter verwendet. Somit wird eine Verbindung von Source-Filter und Rendering-Filter veranlasst. In den meisten Fällen kann man die beiden Pins nicht einfach verbinden, denn es werden noch weitere Zwischenfilter (Transform-Filter) benötigt. Wie diese Zwischenfilter gefunden werden, klärt der folgende Absatz 12 IGraphBuilder::Connect(OutputPin, InputPin): Diese Methode muss gesondert betrachtet werden, da für die Verbindung von Pins größtenteils verschiedene Zwischenfilter (Transform-Filter) benötigt werden. Als Beispiel stelle man sich einen Source-Filter, der nur unkomprimierte RGB-Bilder liefert und einen Video Rendering-Filter, der nur das YUV-Format versteht vor. Diese beiden Filter will man mittels IGraphBuilder::Connect(Output-Pin, Input-Pin) verbinden. Eine direkte Verbindung wäre nicht möglich. Es wird also ein Zwischenfilter (Transform-Filter) benötigt, der die Farbraumtransformation übernimmt. Folgender Algorithmus wird bei jedem Aufruf dieser Methode einmal oder mehrfach abgearbeitet: 1) Direkte Verbindung der Pins probieren; Kein Erfolg 2) 2) Filter aus dem Cache probieren; Kein Erfolg 3) Cache: Alle Filter die in einem bestehenden Filter-Graph vorhanden waren und wieder entfernt worden sind, werden im Cache abgelegt. Nach zerstören des Filter-Graphen wird auch der Cache geleert. 3) unverbundene Filter im Filter-Graph probieren; Kein Erfolg 4) 4) Filter über Windows-Registrierung suchen und probieren; Jeder Filter muss vor der Verwendung vom Anwender registriert werden und erhält einen Eintrag in der internen Windows-Betriebssystem-Registrierung. Die Filter sind in Kategorien unterteilt (Source-Filter, Transform-Filter, Rendering-Filter). Weiterhin erhält jeder Filter einen Major- und SubType, die angeben welche Media-Formate (z.B.: MajorType: RGB, SubType: RGB555) der Filter unterstützt. Um Deadlocks zu vermeiden, wird nach einer gewissen Anzahl von Versuchen dieser Algorithmus abgebrochen. Halbautomatische Erstellung von Filter-Graphen: Die gewünschten Filter werden manuell in den Filter-Graph eingefügt und die fehlenden Filter werden vollautomatisch ergänzt. Als Beispiel kann man sich folgendes Szenario vorstellen. Es soll eine Videodatei in Farbe wiedergegeben werden und das Bild soll aber in Graustufen dargestellt werden. An erster Stelle fügt man den vorhandenen Graustufen-DirectShow-Filter in den Filter-Graph ein. Im zweiten Schritt folgt der Aufruf von IGraphBuilder::RenderFile(„Videodateiname“). Aufgrund des oben genannten Algorithmus wird der Graustufen-Filter während der Erstellung des Filter-Graphen an eine passende Stelle vor den Video-Rendering-Filter eingebunden. Manuelle Erstellung von Filter-Graphen: Alle benötigten Filter werden manuell eingefügt und verbunden. Dynamic-Graph-Building: Der größte Teil der erhältlichen Filter unterstützt nur die Verbindung von Filtern bei gestopptem Filter-Graph. Abhilfe schafft das Dynamic-Graph-Building, was im Filter implementiert sein muss. Das Ziel ist während dem Filter-Graph-„Run“-Zustand den FilterGraph manipulieren zu können. Dieses Thema soll an dieser Stelle nicht weiter behandelt werden, da kaum Filter mit dieser Unterstützung zu finden sind. 13 3.2 Filter-Verbindungsprotokolle In den folgenden drei Abschnitten soll geklärt werden welche Schritte notwendig sind, um zwei Filter miteinander zu verbinden. Die Verbindung der Filter vollzieht sich nur über die Pins der Filter. Pins sind als COM-Objekte implementiert und stellen verschiedene COMSchnittstellen zur Verfügung. 3.2.1 MediaType-Vermittlung Der erste Schritt beim Verbindungsaufbau ist die MediaType-Vermittlung. Eine Verbindung zweier Filter ist nur dann möglich, wenn sie den gleichen Medien-Typ unterstützen. Medien-Typ: Der Medien-Typ wird durch die DirectShow AM_MEDIA_TYPE-Struktur beschrieben. Die Struktur enthält an erster Stelle einen Major- und SubType. Dabei legt der MajorType (siehe Abbildung 10 - orange dargestellt) fest, ob es sich um eine Video-, Audio-, oder beispielsweise Midispur handelt. Der SubType beschreibt den Medien-Typ genauer (siehe Abbildung 10 - blau dargestellt). Um den Medien-Typ noch detaillierter darzustellen, stehen für Video beispielsweise die VIDEOINFOHEADER- und BITMAPINFOHEADER-Struktur zur Verfügung, welche verschiedene Bildeigenschaften beinhalten. Für die detaillierte Beschreibung des Audiomaterials ist die WAVEFORMATEX-Struktur zuständig, die die Eigenschaften über das Audiomaterial speichert. Alle diese Strukturen werden in die AM_MEDIA_TYPE-Struktur eingebettet. Die Applikation ruft die Filter-Graph-Manager COM-Schnittstellen-Methode IGraphBuilder::Connect(…) auf. Daraufhin veranlasst der Filter-Graph-Manager den Austausch der AM_MEDIA_TYPE-Struktur der beiden Filter untereinander. Bei Übereinstimmung wird mit dem nächsten Verbindungsschritt in Abschnitt 3.2.2 fortgefahren. Abbildung 10: MediaType-Vermittlung 14 3.2.2 Transport-Vermittlung Für den Datenaustausch über die Pins stehen verschiedene Transportprotokolle zur Auswahl (siehe Abbildung 11). Im zweiten Schritt des Verbindungsaufbaus muss zwischen den zwei Filtern ein Transportprotkoll ausgehandelt werden. Abbildung 11: Transportprotkolle Local-memory Transportprotokolle (am häufigsten verwendet): Im Push-Verfahren werden die Daten vom Output-Pin des vorhergehenden Filters an das Input-Pin des nachfolgenden Filters transportiert. Als Beispiel kann man sich eine Webcam vorstellen, welche die Daten in den Filter-Graph einspeist. Im Pull-Verfahren werden die Daten des Input-Pins vom nachfolgenden Filter vom OutputPin des vorhergehenden Filters angefordert. Ein einfaches Beispiel ist die Wiedergabe einer AVI-Datei. Der benötigte AVI-Splitter-Filter (siehe Abbildung 6) arbeitet im Pull-Verfahren und fordert seine Daten vom vorhergehenden Filter (Dateilese-Filter) an. Kernel-Streaming Transportprotokoll: Informationen über die Kernel-Streaming Technologie können im Abschnitt 1.2 gefunden werden. Bei diesem Transportprotokoll werden lediglich Steuerinformationen über die Pins übertragen. Der Datenaustausch erfolgt direkt von Hardware zu Hardware im Kernel-Mode. Die verwendeten DirectShow-Filter stellen Abstraktionen der jeweiligen Hardware-Treiber dar. In Abbildung 11 ist ein Beispiel angegeben. 15 3.2.3 Speicherverwaltung-Vermittlung Der dritte und letzte Schritt beim Verbindungsaufbau besteht im Aushandeln eines MemoryAllocators (Speicherverwaltung) zwischen zwei Filtern. Die Übertragung der Daten von einem Filter zu einem anderen Filter basieret auf MediaSamples, die von einem Memory-Allocator verwaltet werden (siehe Abbildung 12 und Abschnitt 3.3.1). Der Memory-Allocator wird von den Pins der Filter zur Verfügung gestellt. Media-Sample: Ein Media-Sample ist ein COM-Objekt, welches einen Speicher (Memory-Buffer) verwaltet, in dem die Media-Daten (z.B.: Video-/Audiosamples) abgelegt werden. Für den Zugriff implementiert das Media-Sample die COM-Schnittstelle IMediaSample. Um feststellen zu können, welche Art von Media-Daten im Media-Sample enthalten sind, erhält jedes MediaSample eine gefüllte AM_MEDIA_TYPE-Struktur, die mit der Methode IMediaSample::GetMediaType(AM_MEDIA_TYPE) abgerufen und mit IMediaSample::SetMediaType(AM_MEDIA_TYPE) gesetzt wird. Abbildung 12: Speicherverwaltung-Vermittlung Auswahl des Memory-Allocators: Der Memory-Allocator verwaltet eine bestimmte Anzahl an Media-Samples und es befindet sich immer ein Memory-Allocator zwischen zwei Filtern. Der Algorithmus für die Auswahl des Memory-Allocators ist in Abbildung 12 (oberer Teil) zu finden. Wichtig ist, dass der Memory-Allocator immer vom Output-Pin gewählt wird und die Memory-Allocator-Anforderungen des Input-Pins berücksichtigt werden. 16 3.3 Datenfluss-Protokolle In einem Filter-Graph werden zwei verschiedene Arten von Daten transportiert: Media-Daten (z.B.: Video-/Audiosamples): in Downstream-Reihenfolge transportiert (Source-F. Rendering-F.) Kontroll-Daten: in Upstream-Reihenfolge transportiert (Rendering-F. Source-F.) Beispiele für Kontroll-Daten-Protokolle: End-of-stream-Protokoll: Definiert, wie die Filter die End-Of-Stream-Informationen erzeugen und verarbeiten und wie der Filter-Graph-Manager informiert wird. Flushing-Protokoll: Definiert, wie die Filter Daten durch den Filter-Graph flushen Error detection and reporting-Protokoll: Definiert, wie Fehler vom Filter gehandhabt und durch den Filter-Graph weitergereicht werden Quality management-Protokoll: dynamische Anpassung der Datenrate im FilterGraph entsprechend der Laufzeit-Performance. Erhält ein Rendering-Filter zu viele oder zu wenige Daten, so kann er dies durch senden von Quality-Messages an die einzelnen Filter regulieren. In den folgenden zwei Abschnitten werden das Media-Daten- und ein Kontroll-DatenProtokoll vorgestellt. 3.3.1 Streaming-Protokoll Die Abbildung 13 beschreibt das Media-Daten-Datenfluss-Protokoll innerhalb eines FilterGraphen anhand des Push-Models (siehe Abschnitt 3.2.2). In der Abbildung wird davon ausgegangen, dass die Filter erfolgreich verbunden sind und zwischen zwei Filtern ein Memory-Allocator gewählt ist. Weiterhin befindet sich der Filter-Graph im zweiten Durchlauf. Dies bedeutet, dass ein Media-Sample schon den Rendering-Filter erreicht hat und ein zweites Media-Sample vom Source-Filter gefüllt wird. Abbildung 13: Media-Daten-Datenfluss-Protokoll im Filter-Graph 17 Ablauf-Algorithmus: 1) 2) 3) 4) Der Source-Filter fordert ein Media-Sample vom Memory-Allocator an. Dieses Media-Sample wird im Source-Filter befüllt. Das Media-Sample wird an den Transform-Filter übermittelt. Im Transform-Filter wird ein neues Media-Sample vom Memory-Allocator angefordert. Zum gleichen Zeitpunkt geschieht Vorgang 1). 5) Die Media-Daten vom Media-Sample werden in das Media-Sample übertragen (kopiert) und entsprechend manipuliert. Zum gleichen Zeitpunkt geschieht Vorgang 2). 6) Das Media-Sample wird wieder freigegeben und das Media-Sample wird an den Rendering-Filter übergeben. Zum gleichen Zeitpunkt geschieht Vorgang 3). 7) Im Rendering-Filter wird das erhaltene Media-Sample präsentiert. Zum gleichen Zeitpunkt geschieht Vorgang 4). Der angegebene Algorithmus basiert auf der Verwendung eines Transform-Filters, in dem die Media-Daten kopiert werden müssen, aufgrund der verschiedenen verwendeten MemoryAllocator (siehe Punkt 5). Es gibt viele Anwendungsfälle, in denen die Media-Daten aber nicht kopiert werden sollen. Dafür steht der TransInPlace-Transform-Filter zur Verfügung (siehe Abbildung 13). Dieser Filter kann jedoch nur eingesetzt werden, wenn der MemoryAllocator am Input-Pin auch am Output-Pin verwendet wird. Dies bedeutet, dass der vorhergehende Filter und der nachfolgende Filter den gleichen Allocator verwenden müssen. In den meisten Fällen ist dies problemlos möglich. Jedoch gibt es Rendering-Filter, die nur ihren eigenen implementierten Allocator akzeptieren. In solchen Fällen besteht keine Chance der TransInPlace-Transform-Filter-Verwendung. 3.3.2 Control-Protokoll In diesem Kapitel wird das Kontroll-Daten-Control-Protokoll vorgestellt. Es beschreibt die Zustandsübergange (z.B.: Run to Stop) im Filter-Graph. Abbildung 14: Control-Protkoll Filter können drei verschiedene Zustände annehmen: Run, Pause und Stop. 18 Der Pause-Zustand dient der Datenpufferung im Filter-Graph, damit auf ein Run-Kommando sofort reagiert werden kann. Alle Zustandsübergange werden vom Filter-Graph-Manager kontrolliert. Ruft eine Anwendung die Methoden IMediaControl::Run, IMediaControl::Pause oder IMediaControl::Stop vom Filter-Graph-Manager auf (siehe Abbildung 14), so leitet der Filter-Graph-Manager diese Zustandübergange an alle Filter im Filter-Graph weiter. Der Übergang vom Stop- in den Run-Zustand erfolgt immer über den Pause-Zustand (siehe Abbildung 14). Für die meisten Filter ist der Run- und Pause-Zustand identisch. Folgender Filter-Graph soll betrachtet werden: Source->Transform->Rendering. Es wird angenommen, dass der Source-Filter keine Live-Capture-Quelle ist. Wird der Source-Filter in den Pause-Zustand versetzt, so erzeugt dieser einen Streaming-Thread, welcher neue Daten generiert und diese so schnell wie möglich in Media-Samples schreibt. Anschließend transportiert der Thread die Media-Samples im „Push“-Verfahren (siehe Abschnitt 3.2.2) zum Transform-Filter. Während sich der Rendering-Filter im Pause-Zustand befindet, wartet er auf ein Media-Sample. Sobald er das erste Media-Sample erhält, blockiert er bis er in einen anderen Zustand versetzt wird. Damit ist der Filter-Graph gepuffert und bereit gestartet zu werden. Der Source- und Transform-Filter ignorieren den Zustandsübergang von Pause zu Run, da der Rendering-Filter den Streaming-Thread sowieso nach Erhalt des ersten Media-Samples blockiert. Wird der Rendering-Filter vom Pause- in den Run-Zustand versetzt, so wird die Blockierung aufgehoben und im ersten Schritt erfolgt die Verarbeitung des Media-Samples, welches im Pause-Zustand gehalten wurde. Anschließend wird jedes Media-Sample entsprechend seiner Präsentationszeit verarbeitet (siehe Abschnitt 3.4). Live-Quellen (z.B.: Webcams,…) bilden eine Ausnahme, denn eine Live-Quelle produziert keine Samples im Pause-Zustand, sondern nur im Run-Zustand. Damit wird auch keine Datenpufferung im Pause-Zustand benötigt. Wird ein Filter in den Stop-Zustand versetzt, so werden alle folgenden Media-Samples, die der Filter erhält verworfen und die Pins der Filter geben die Media-Samples vom MemoryAllocator frei. Bei Source-Filtern würde zusätzlich der Streaming-Thread und weitere benötigte Threads freigegeben werden. Zustandsübergänge: Der Filter-Graph-Manager sendet die Zustandsübergänge in Upstream-Reihenfolge (siehe Abschnitt 3.3 / Abbildung 14). Die Reihenfolge ist dabei wichtig, um den Verlust von MediaSamples zu vermeiden und Deadlocks im Filter-Graph auszuschließen. Die entscheidensten Zustandsübergänge sind zwischen Pause und Stop: Stop- zu Pause-Zustand: Nachdem jeder Filter in den Pause-Zustand versetzt ist, ist er zum Empfang von neuen Media-Samples bereit. Der Source-Filter ist immer der Letzte, der die Pause-Zustandsmitteilung erhält. Er beginnt einen Streaming-Thread zu erzeugen und startet anschließend mit dem Transport neuer Media-Samples. Da sich alle anderen Filter im PauseZustand befinden, wird kein Media-Sample verworfen. Der Filter-Graph-Manager wartet solange, bis jeder Rendering-Filter ein Media-Sample erhalten hat (mit Ausnahme der LiveQuellen, wie oben beschrieben). Pause- zu Stop-Zustand: Wird ein Filter in den Stop-Zustand versetzt, gibt er alle MediaSamples frei, die er noch hält. Dadurch wird die Blockade in den Upstream-Filtern, die auf Media-Samples warten aufgehoben. Es könnte passieren, dass der Upstream-Filter noch einige zusätzliche Media-Sample sendet, bevor er das Stop-Kommando bekommt, aber der Downstream-Filter würde diese verwerfen, da er sich schon im Stop-Zustand befindet. 19 3.4 Synchronisation In diesem Abschnitt werden die Synchronisationsmechanismen von DirectShow näher beleuchtet. Abbildung 15: Synchronisation im Filter-Graph Die Funktionsweise der Synchronisation soll am Beispiel (Abbildung 15) näher verdeutlicht werden. Die Abbildung 15 zeigt die Wiedergabe einer AVI-Datei mit komprimiertem Video und Audio (siehe Abbildung 6) und die verwendeten Threads sind mit einem roten, blauen und grünen Pfeil markiert. Der Source- und Parser-Filter transportieren die Media-Daten im Pull-Verfahren (siehe Abschnitt 3.2.2) mit Hilfe eines Threads (roter Pfeil), wobei der Parser-Filter Media-Daten vom Source-Filter anfordert. Die angeforderten Media-Daten werden im Parser-Filter in eine Video- und Audiospur aufgesplittet und danach über zwei Output-Pins an die Dekoder-Filter mittels Push-Verfahren (siehe Abschnitt 3.2.2) gesendet. Für den Transport der Video- und Audiodaten werden jeweils ein Thread (blauer und grüner Pfeil) zur Verfügung gestellt, damit die Dekompression in den Dekompressions-Filtern und die Präsentation der Daten in den Rendering-Filtern parallel abgearbeitet werden kann. Würde man den Filter-Graph in Abbildung 15 ohne jegliche Synchronisationsmechanismen starten, so würde das System die Media-Daten so schnell wie möglich verarbeiten. Dieser Effekt ist in einigen Fällen sogar erwünscht, wenn man beispielsweise eine WAV-Datei, so schnell wie möglich in MP3 umkonvertieren möchte. Für die Wiedergabe einer Media-Datei müssen aber unbedingt Synchronisationsmechanismen verwendet werden, damit das Videound Audiomaterial synchron wiedergegeben werden kann und die Abspielgeschwindigkeit eingehalten wird. Timestamps: Für die Synchronisation werden Timestamps verwendet. Ein Timestamp besteht aus einem Startzeitpunkt (timeStart), an dem das Media-Sample im Rendering-Filter präsentiert werden soll und einem Endzeitpunkt (timeEnd), der angibt zu welchem Zeitpunkt das Media-Sample wieder freigegeben werden kann. timeEnd minus timeStart ergeben die Präsentationsdauer eines Media-Samples. timeStart und timeEnd werden jeweils in einer 64-Bit-Variablen (REFERENCE_TIME) in 100 Nanosekunden-Einheiten gespeichert. Der Timestamp wird mit der Methode IMediaSample::SetTime(…) an das Media-Sample (siehe Abschnitt 3.2.3: 20 Media Sample) übertragen und wird über die Methode IMediaSample::GetTime(…) abgerufen. Für die Generierung der Timestamps sind meist die Source-Filter zuständig. Am Beispiel (Abbildung 15) erledigt dies der Parser-Filter. Um einen Timestamp erzeugen zu können, wird eine Reference-Clock benötigt. Reference-Clock/Reference-Time/Stream-Time: Eine Reference-Clock stellt einen sehr genauen Zeitgeber zur Verfügung. Dieser Zeitgeber ist größtenteils in der Hardware implementiert (z.B.: Soundkarte). Soll ein Filter-Graph mit Hilfe von Synchronisationsmechanismen abgespielt werden, so muss der Filter-Graph vor der Wiedergabe eine zuverlässige Reference-Clock zur Verfügung stellen. Ein Filter-Graph kann nur über eine Reference-Clock verfügen. Abbildung 16: manuelle Reference-Clock-Auswahl Die Auswahl der Reference-Clock kann automatisch oder (wie in Abbildung 16 dargestellt) manuell geschehen. Für die manuelle Auswahl stehen drei Möglichkeiten zur Verfügung: Die Applikation implementiert die Reference-Clock und stellt sie dem Filter-Graph zur Verfügung. Die Reference-Clock ist in einem Filter des Filter-Graphen implementiert. Der Filter-Graph soll ohne Synchronisationsmechanismen arbeiten und die MediaDaten so schnell wie möglich verarbeiten. Ist beim Start des Filter-Graphen keine Reference-Clock angegeben, so sucht der Filter-Graph automatisch eine passende Reference-Clock nach folgendem Algorithmus: Filter-Graph-Manager sucht Reference-Clock-Implementationen in Filtern in Upstream-Reihenfolge (beginnend bei Rendering-Filter) erste gefundene Reference-Clock (in Filter) wird übernommen keine Reference-Clock gefunden Filter Graph Manager stellt interne ReferenceClock auf Basis der System-Uhrzeit zur Verfügung Die von der Reference-Clock zur Verfügung gestellte Zeit wird als Reference-Time bezeichnet, die immer aufsteigend und niemals rückwärts läuft. Innerhalb eines Filter-Graph wird jedoch nur die Stream-Time, welche relativ zum letzten Filter-Graph-Start definiert ist verwendet (siehe Abbildung 15). Beispiel: Wenn ein Media-Sample ein timeStart von t zugewiesen ist, so sollte das Sample zur Stream-Time t vom Rendering-Filter präsentiert werden. Nachdem der Parser-Filter im Beispiel (siehe Abbildung 15) anhand einer Reference-Clock den Timestamp erstellt hat, wird das Media-Sample über den Dekompressor-Filter zum Rendering-Filter transportiert. Der Rendering-Filter liest anschließend den Timestamp vom erhaltenen Media-Sample aus und arbeitet den angegebenen Algorithmus (Abbildung 15 rechts) ab. 21 4. Beispiel Sourcecode für Wiedergabe einer MPEG-Datei (vollautomatische Filter-Graph Erstellung): //Schnittstellenzeiger definieren 1: IGraphBuilder *pGraph; 2: IMediaControl *pMediaControl; 3: IMediaEvent *pEvent; 4: CoInitialize(NULL); //COM-Laufzeitumgebung initialisieren //Filter Graph Manager Objekt erstellen+IGraphBuilder Schnittstellenzeiger erzeugen 5: CoCreateInstance(CLSID_FilterGraph, …, …,IID_IGraphBuilder, (void **)&pGraph); 6: pGraph->RenderFile(„Beispiel.mpg“, NULL); //Graph vollautomatisch erstellen 7: pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl); 8: pMediaControl->Run(); //Graph starten //Warten auf Beendigung des Graphen 9: pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent); 10: long evCode; pEvent->WaitForCompletion(INFINITE, &evCode); 11: pMediaControl->Release(); pEvent->Release(); pGraph->Release(); //Schnittstellenzeiger freigeben 12: CoUninitialize(); //COM-Laufzeitumgebung freigeben In den Zeilen 1-3 werden einige COM-Schnittstellenzeiger definiert. Die folgende Methode CoInitialize(…) (Zeile 4) dient der Initialisierung der COM-Laufzeitumgebung und muss bei jeder COM-Anwendung, vor der Benutzung der COM-Technologie aufgerufen werden. In Zeile 5 erfolgt die Erstellung des Filter-Graph-Manager-Objekts. Zusätzlich wird der Standard-COM-Schnittstellenzeiger IGraphBuilder des Filter-Graph-Managers erzeugt. Durch Aufruf der Methode pGraph->RenderFile(„Beispiel.mpg“,NULL) (Zeile 6) der COMSchnittstelle IGraphBuilder, wird der Filter-Graph-Manager veranlasst, einen Filter-Graph entsprechend der wiederzugebenden Datei vollautomatisch zu erstellen. Um den Filter-Graph steuern zu können, wird die ImediaControl-COM-Schnittstelle benötigt. Diese wird über die IgraphBuilder-COM-Schnittstelle mittels pGraph>QueryInterface(IID_IMediaControl, (void **)&pMediaControl) (Zeile 7) erstellt. Der FilterGraph wird über die erzeugte IMediaControl-COM-Schnittstelle (Zeile 8) gestartet. Die MPEG-Datei soll anschließend bis zum Ende abgespielt werden. Um das DateiendeEreignis zu erhalten wird die COM-Schnittstelle IMediaEvent benötigt. Diese wird ebenfalls über die IgraphBuilder-COM-Schnittstelle mittels pGraph>QueryInterface(IID_IMediaEvent, (void **)&pEvent) (Zeile 9) erhalten. In der folgenden Zeile wird durch den Methodenaufruf pEvent->WaitForCompletion(INFINITE, &evCode) der Applikationsthread solange blockiert, bis die MPEG-Datei fertig wiedergegeben ist. In Zeile 11 werden die in Zeile 1-3 definierten COM-Schnittstellenzeiger wieder freigegeben. Die COM-Laufzeitumgebung muss ebenfalls freigegeben werden, was in Zeile 12 erledigt wird. 22 5. Zusammenfassung Im Rahmen der vorliegenden Arbeit wurden die wichtigsten Grundlagen der Multimediaschnittstelle DirectShow gegeben. Darunter fallen die Entstehung und die Hauptaufgaben von DirectShow sowie die Architektur und die Hauptbestandteile, den FilterGraph-Manager und damit verbunden die Erstellung, Kontrolle und Synchronisation von Filter-Graphen. Aufgrund des enormen Umfangs von DirectShow, konnten einige Themengebiete (z.B.: DES (DirectShow Editing Service)) nur grob umrissen werden. Die Entwicklung eigener DirectShow-Filter stellt ein sehr interessantes Thema dar und hilft DirectShow wesentlich besser zu verstehen. Leider konnte dieser Teil nicht behandelt werden, da es den Rahmen dieser Arbeit sprengen würde. DirectShow löst die alte VFW-Multimediaschnittstelle ab und bietet Multimediaschnittstelle von Microsoft viele Vor- und auch einige Nachteile: Vorteile 6. gut dokumentiert modulare Struktur wiederverwendbare Komponenten (Filter) als neue Nachteile abhängig von MicrosoftBetriebssystemen Kenntnisse in der WindowsProgrammierung notwendig Quellen Offline-Literatur: • • • • Programming Microsoft DirectShow for Digital Video and Television / Mark D. Pesce. Audio-,Video- und Grafikprogrammierung / Kai Bruns, Benjamin Neidhold DirectShow-SDK Dokumentation Microsoft MSDN-Bibliothek Online-Literatur: • • • http://www.gdcl.co.uk/ http://www.jmcgowan.com/avi.html Suchmaschinen (Google) / Internet 23