Programmieren Sie Multimedia mit JMF, Teil 1

Das Java Media Framework (JMF) ist eine große und vielseitige API zur Verarbeitung zeitbasierter Medien. Es kann jedoch Wochen dauern, bis die Komplexität von JMF verstanden ist. In Anbetracht dieser Komplexität wird in diesem Artikel JMF auf einfache Weise vorgestellt. Wir zeichnen zunächst eine Analogie mit einer Stereoanlage und diskutieren dann die häufigsten Schnittstellen und Klassen von JMF. Schließlich sehen wir Arbeitscode, der einen Teil der Funktionen der API demonstriert.

Dieser Artikel, der erste einer zweiteiligen Reihe, konzentriert sich auf die JMF-Architektur. Teil 2 konzentriert sich hauptsächlich auf den Code, der zeigt, wie die Erfassungsgeräte registriert und Audio- und Videodaten abgespielt und erfasst werden.

JMF, derzeit in Version 2.1, ist die Initiative von Sun, die zeitbasierte Medienverarbeitung auf Java zu bringen. Zeitbasierte Medien sind Daten, die sich in Bezug auf die Zeit erheblich ändern, z. B. Audio- und Videoclips, MIDI-Sequenzen und Animationen. Beachten Sie, dass Sun kürzlich angekündigt hat, den JMF 2.1-Quellcode im Rahmen des Sun Community Source Licensing Program (SCSL) freizugeben. JMF 2.1 ist auch eine vollständige Referenzimplementierung und ermöglicht es Ihnen, mit Multimedia alles Mögliche zu tun. JMF kann unter anderem:

  • Spielen Sie verschiedene Multimediadateien in einem Java-Applet oder einer Java-Anwendung ab. Die unterstützten Formate umfassen AU, AVI, MIDI, MPEG, QuickTime und WAV.
  • Spielen Sie Streaming-Medien aus dem Internet ab.
  • Nehmen Sie Audio und Video mit Ihrem Mikrofon und Ihrer Videokamera auf und speichern Sie die Daten in einem unterstützten Format.
  • Verarbeiten Sie zeitbasierte Medien und ändern Sie das Inhaltstypformat.
  • Übertragen Sie Audio und Video in Echtzeit im Internet.
  • Übertragung von Live-Radio- oder Fernsehprogrammen.

Bevor Sie jedoch eine JMF-Anwendung schreiben, müssen Sie die JMF-Architektur, ihre Schnittstellen und ihre Klassen vollständig verstehen.

Die JMF-Architektur

Um die JMF-Architektur leicht zu verstehen, nehmen Sie Ihre Stereoanlage als Vergleich. Wenn Sie eine Sarah Vaughan-CD mit Ihrem CD-Player abspielen, liefert die CD die Musikdaten an das System. Diese Daten wurden zuvor mit Mikrofonen und anderen Geräten im Aufnahmestudio erfasst. Das Mikrofon dient als Audioaufnahmegerät. Die CD selbst ist eine Datenquelle für die Stereoanlage.

Der CD-Player gibt das Musiksignal an den Lautsprecher aus - das Ausgabegerät. Über den CD-Player können wir jedoch auch einen Kopfhörer anschließen. In diesem Fall fungiert der Kopfhörer als Ausgabegerät.

JMF verwendet dasselbe Modell. Während Sie weiterlesen, werden Sie auf Begriffe wie: stoßen.

  • Datenquelle
  • Aufnahme Gerät
  • Spieler
  • Prozessor
  • DataSink
  • Format
  • Manager

Schauen wir uns diese Begriffe genauer an.

Datenquelle

Eine Datenquelle kapselt den Medienstrom ähnlich wie eine Musik-CD. In JMF DataSourcerepräsentiert ein Objekt das Audiomedium, das Videomedium oder eine Kombination aus beiden. A DataSourcekann eine Datei oder ein eingehender Stream aus dem Internet sein. Das Gute an dieser Klasse ist, dass, sobald Sie ihren Speicherort oder ihr Protokoll festgelegt haben, DataSourcesowohl der Medienspeicherort als auch das Protokoll und die Software, die zur Bereitstellung der Medien verwendet werden, gekapselt sind. Einmal erstellt, DataSourcekann a in ein Playerzu renderndes PlayerElement eingespeist werden, wobei es nicht darum geht, woher das DataSourcestammt oder was seine ursprüngliche Form war.

Mediendaten können aus verschiedenen Quellen abgerufen werden, z. B. aus lokalen oder Netzwerkdateien oder aus Live-Internetübertragungen. Als solches kann DataSources danach klassifiziert werden, wie eine Datenübertragung initiiert wird:

  • Datenquelle ziehen: Der Client initiiert die Datenübertragung und steuert den Datenfluss von der Quelle. HTTP und FILE dienen als Beispiele für etablierte Protokolle für diesen Datentyp.
  • Push-Datenquelle: Der Server initiiert die Datenübertragung und steuert den Datenfluss von einer Push-Datenquelle. Beispiele für Push-Datenquellen sind Broadcast-Medien und Video-on-Demand.

Wie wir in Teil 2 dieser Reihe diskutieren werden, können mehrere Datenquellen zu einer zusammengefasst werden. Wenn Sie beispielsweise eine Live-Szene aufnehmen, haben Sie wahrscheinlich zwei Datenquellen: Audio und Video. In dieser Situation möchten Sie diese beiden möglicherweise kombinieren, um die Steuerung zu vereinfachen.

Aufnahme Gerät

Ein Aufnahmegerät stellt die Hardware dar, mit der Sie Daten erfassen, z. B. ein Mikrofon, eine Standbildkamera oder eine Videokamera. Erfasste Mediendaten können in ein PlayerRendering eingespeist , verarbeitet, um die Daten in ein anderes Format zu konvertieren, oder für die zukünftige Verwendung gespeichert werden.

Erfassungsgeräte können entweder als Push- oder Pull- Quellen kategorisiert werden . Mit einer Pull-Quelle steuert der Benutzer, wann ein Bild aufgenommen werden soll. Stellen Sie sich als Beispiel eine Standbildkamera vor, bei der ein Benutzer auf eine Schaltfläche klickt, um die Aufnahme zu machen. Im Gegensatz dazu fungiert ein Mikrofon als Push-Quelle, da es kontinuierlich einen Strom von Audiodaten liefert.

Spieler

A Playernimmt einen Stream von Audio- oder Videodaten als Eingabe und rendert ihn in einen Lautsprecher oder einen Bildschirm, ähnlich wie ein CD-Player eine CD liest und Musik an den Lautsprecher ausgibt. A Playerkann Zustände haben, die natürlich existieren, weil a Playersich und seine Datenquelle vorbereiten muss, bevor es mit dem Abspielen der Medien beginnen kann. Um dies zu verstehen, legen Sie eine CD in Ihre Stereoanlage ein und spielen Sie den vierten Titel auf der CD ab. Was würde passieren? Der CD-Player spielt das Lied nicht sofort ab. Es muss zuerst den Track durchsuchen, in dem das vierte Lied beginnt, und einige andere Vorbereitungen treffen. Nach ungefähr einer halben Sekunde (abhängig von Ihrem CD-Player) hören Sie die Musik. Ebenso muss der JMF Playereinige Vorbereitungen treffen, bevor Sie den Ton hören oder das Video sehen können. Im normalen Betrieb aPlayerdurchläuft jeden Zustand, bis er den Endzustand erreicht. JMF definiert sechs Zustände in a Player:

  • Nicht realisiert: In diesem Zustand wurde das PlayerObjekt instanziiert. Wie ein Neugeborenes, das seine Umgebung noch nicht erkennt, Playerweiß ein neu instanziiertes noch nichts über seine Medien.
  • Realisieren: A wechselt Playervom nicht realisierten Zustand in den realisierenden Zustand, wenn Sie die Methode von Player' aufrufen realize(). Im realisierenden Zustand Playerist der dabei, seinen Ressourcenbedarf zu bestimmen. Bei einer Realisierung werden Playerhäufig Assets über das Netzwerk heruntergeladen.
  • Realisiert: Beim Übergang vom realisierenden Zustand Playerkommt der in den realisierten Zustand. In diesem Zustand Playerweiß der , welche Ressourcen er benötigt, und verfügt über Informationen über die Art der Medien, die präsentiert werden sollen. Es kann auch visuelle Komponenten und Steuerelemente bereitstellen, und die Verbindungen zu anderen Objekten im System sind vorhanden.
  • Prefetching: Wenn die prefetch()Methode aufgerufen wird, wechselt a Playervom realisierten Zustand in den Prefetching-Zustand. Ein Prefetching Playerbereitet die Präsentation seiner Medien vor. Während dieser Phase Playerlädt der Benutzer seine Mediendaten vor, erhält Ressourcen zur ausschließlichen Verwendung und unternimmt alles, was zum Abspielen der Mediendaten erforderlich ist.
  • Prefetched: Der Status, in dem Playerdas Vorabrufen von Mediendaten abgeschlossen ist - es kann gestartet werden.
  • Gestartet: Dieser Status wird beim Aufrufen der start()Methode eingegeben . Das Playerist nun bereit, die Mediendaten zu präsentieren.

Prozessor

A Processorist eine Art von Player. In der JMF-API wird eine ProcessorSchnittstelle erweitert Player. Als solches Processorunterstützt a dieselben Präsentationssteuerelemente wie a Player. Im Gegensatz zu a Playerhat a Processorjedoch die Kontrolle darüber, welche Verarbeitung auf dem Eingabemedienstrom ausgeführt wird.

Zusätzlich zum Rendern einer Datenquelle Processorkann a auch Mediendaten über a ausgeben, DataSourcesodass sie von einem anderen präsentiert Playeroder Processorvon einem anderen weiter verarbeitet Processoroder in ein anderes Format konvertiert werden können.

Neben den sechs oben genannten PlayerZuständen Processorenthält a zwei zusätzliche Zustände, die vor dem ProcessorEintritt in den Realisierungszustand, aber nach dem nicht realisierten Zustand auftreten:

  • Konfigurieren: A wechselt Processorbeim Aufrufen der configure()Methode aus dem nicht realisierten Status in den Konfigurationsstatus . A Processorist im Konfigurationsstatus vorhanden, wenn es eine Verbindung zum herstellt DataSource, den Eingabestream demultiplext und auf Informationen über das Format der Eingabedaten zugreift.
  • Konfiguriert: Aus dem Konfigurationsstatus wechselt a Processorin den konfigurierten Status, wenn es mit dem verbunden ist DataSourceund das Datenformat ermittelt wurde.

Wie bei a Playergeht a Processorbeim realize()Aufruf der Methode in den realisierten Zustand über .

DataSink

Dies DataSinkist eine Basisschnittstelle für Objekte, die von a gelieferte Medieninhalte lesen DataSourceund die Medien an einem bestimmten Ziel rendern. DataSinkBetrachten Sie als Beispiel ein File-Writer-Objekt, das die Medien in einer Datei speichert.

Format

Ein FormatObjekt repräsentiert das genaue Medienformat eines Objekts. Das Format selbst enthält keine codierungsspezifischen Parameter oder Informationen zum globalen Timing. Es beschreibt den Codierungsnamen des Formats und den Datentyp, den das Format benötigt. FormatUnterklassen umfassen AudioFormatund VideoFormat. VideoFormatEnthält wiederum sechs direkte Unterklassen:

  • H261Format
  • H263Format
  • IndexedColorFormat
  • JPEGFormat
  • RGBFormat
  • YUVFormat

Manager

Ein Manager, ein Zwischenobjekt, integriert Implementierungen von Schlüsselschnittstellen, die nahtlos mit vorhandenen Klassen verwendet werden können. In der Stereoanlage gibt es kein reales Äquivalent, aber Sie können sich einen Manager als ein vielseitiges Objekt vorstellen, das zwei verschiedene Objekte miteinander verbinden kann. Mit können Sie beispielsweise Managerein Playeraus einem erstellen DataSource. JMF bietet vier Manager an:

  • Manager: Verwenden Sie Managererstellen Players, Processors, DataSources, und DataSinks. Wenn Sie beispielsweise ein rendern möchten DataSource, können Sie Managerein Playerdafür erstellen .
  • PackageManager: Dieser Manager unterhält eine Registrierung von Paketen , die JMF - Klassen enthalten, wie benutzerdefinierte Players, Processors, DataSources, und DataSinks.
  • CaptureDeviceManager: Dieser Manager verwaltet eine Registrierung der verfügbaren Erfassungsgeräte.
  • PlugInManager: Dieser Manager verwaltet eine Registrierung der verfügbaren JMF-Plug-In-Verarbeitungskomponenten.

Erstelle einen Spieler

Bei der JMF-Multimedia-Programmierung besteht eine Ihrer wichtigsten Aufgaben darin, eine zu erstellen Player. Sie erstellen eine Playerdurch den anruf Managers‘ createPlayer()Methode. Der Managerverwendet die URL des Mediums oder MediaLocatordie von Ihnen angegebene, um ein geeignetes zu erstellen Player. Sobald Sie eine haben Player, können Sie Playerdie visuellen Komponenten des Objekts erhalten - wobei a Playerdie visuelle Darstellung seiner Medien darstellt. Sie können diese visuellen Komponenten dann Ihrem Anwendungsfenster oder Applet hinzufügen.

Um Playerdie visuelle Komponente eines Objekts anzuzeigen , müssen Sie:

  1. Erhalten Sie die visuelle Komponente, indem Sie die getVisualComponent()Methode aufrufen
  2. Fügen Sie die visuelle Komponente zum Anwendungsfenster oder Applet hinzu

A Playerkann auch ein Bedienfeld mit Tasten zum Starten, Stoppen und Anhalten des Medienstroms sowie zum Steuern der Lautstärke enthalten, genau wie die ähnlichen Tasten Ihres CD-Players.

Viele der PlayerMethoden von können nur aufgerufen werden, wenn sich das Playerim realisierten Zustand befindet. Um sicherzustellen, dass es sich in diesem Zustand befindet, können Sie die Methode von Manager' createRealizedPlayer()verwenden, um das zu erstellen Player. Diese Methode bietet eine bequeme Möglichkeit, eine Playerin einem einzigen Schritt zu erstellen und zu realisieren . Wenn es aufgerufen wird, blockiert es, bis das Playerrealisiert ist.

Ferner start()kann aufgerufen werden, nachdem a Playererstellt wurde, aber bevor es den vorabgerufenen Zustand erreicht. start()Es wird versucht, den PlayerStatus von dem Status, in dem er sich gerade befindet, in den Startzustand zu versetzen. Beispielsweise können Sie die start()Methode sofort aufrufen , nachdem a Playerinstanziiert wurde. Die start()Methode ruft dann implizit alle erforderlichen Methoden auf, um den Playerin den gestarteten Zustand zu versetzen .

Mediendaten erfassen

Die Medienerfassung ist eine weitere wichtige Aufgabe bei der JMF-Programmierung. Sie können Mediendaten mit einem Aufnahmegerät wie einem Mikrofon oder einer Videokamera erfassen. Es kann dann verarbeitet und gerendert oder in einem Medienformat gespeichert werden. Um Mediendaten zu erfassen, müssen Sie:

  1. Suchen Sie das Erfassungsgerät, das Sie verwenden möchten, indem Sie das abfragen CaptureDeviceManager
  2. Besorgen Sie sich ein CaptureDeviceInfoObjekt für das Gerät
  3. Holen Sie sich ein MediaLocatoraus dem CaptureDeviceInfoObjekt und verwenden Sie es, um ein zu erstellenDataSource
  4. Erstellen Sie entweder ein Playeroder ein Processormit demDataSource
  5. Starten Sie den Playeroder Processor, um den Erfassungsprozess zu starten

Sie verwenden die CaptureDeviceManager, um auf im System verfügbare Erfassungsgeräte zuzugreifen. Dieser Manager fungiert als zentrale Registrierung für alle für JMF verfügbaren Erfassungsgeräte. Sie können eine verfügbare Geräteliste erhalten, indem Sie die getDeviceList()Methode aufrufen . Ein Erfassungsgerät wird durch ein CaptureDeviceInfoObjekt dargestellt. Sie verwenden die Methode von CaptureDeviceManager's getDevice(), um die CaptureDeviceInfofür ein bestimmtes Aufnahmegerät abzurufen.

Um das Erfassungsgerät zum Erfassen von Mediendaten zu verwenden, müssen Sie die Geräte MediaLocatorvon ihrem CaptureDeviceInfoObjekt abrufen. Sie können dies entweder verwenden MediaLocator, um ein Playeroder ein Processordirekt zu erstellen, oder das verwenden MediaLocator, um ein zu erstellen DataSource, das Sie als Eingabe für ein Playeroder verwenden können Processor. Verwenden Sie die Methode Player's oder Processor' s start(), um den Erfassungsprozess zu starten.

Multimedia-Verarbeitung in Echtzeit

Mit JMF können Sie auch eine Live-Mediensendung senden oder empfangen, z. B. Live-Radio- und Fernsehsendungen oder Echtzeit-Telefonkonferenzen über das Internet oder ein Intranet.

Ein Merkmal des Echtzeit-Medientransports, das sich vom Zugriff auf statische Daten unterscheidet: Das Echtzeitprotokoll garantiert nicht, dass alle Pakete sicher ankommen. Was noch wichtiger ist: Wie können Sie die verlorenen Daten ausgleichen und keine große Verzögerung beim Empfang der Daten sicherstellen? Wenn Sie mit Echtzeit-Medienstreams arbeiten, spielen Sie die Mediendaten ab, ohne auf den Download der vollständigen Stream-Daten zu warten. Ebenso erfordert die Übertragung über das Internet in Echtzeit ein Netzwerk mit hoher Bandbreite, damit der Empfänger die Mediendaten kontinuierlich abspielen kann.