Einleitung

Multimediale Anwendungen gewinnen in der heutigen Zeit mehr und mehr an Bedeutung. Nicht nur mit einem herkömmlichen PC sondern seit der Einhführung von UMTS auch auf mobilen Stationen wie zum Beislpiel auf Handys, können multimediale Datenstöme empfangen und dargestellt werden. Die Anwendungsmöglichkeiten reichen dabei von Video on Demand bis zu Telefon- oder Videokonferenzen.

Die Übertragung multimedialer Daten muß allerdings unter Beräcksichtigung der zeitkritische Anforderungen geschehen, die an Sender Empfänger und Übertragungsmedium gestellt werden. Dies wird durch die Verwendung einer Gruppe von Protokollen erreicht, die im Internet für diesen Zweck weit verbreitet ist: dem Real-Time Streaming Protokol (RTSP) umd dem Real-Time Transport Protokol (RTP). Besonders problematisch wird es, wenn sich die zu berücksichtigenden Gegebenheiten während der laufenden Übertragung drastisch ändern. Dies kann zum Beispiel bei der Funkübertragung zum Handy geschehen. Die tatsächlich für die Übertragung zur Verfügung stehende Bandbreite kann sich zum Beispiel durch Wettereinflüsse verringern.

Damit ist die Entwicklung eines Proxys motiviert, der in der Lage ist, auf solcherart veränderliche Anforderungen zu reagieren. Dieser Proxy wird zwischen dem Server und dem Client dazwischengeschaltet. Er sollte in der Lage sein, mit geeigneten Mitteln die zu versendende Datenmenge an die Gegebenheiten des Senders, des Empfängers und des Übertragungsmediums anzupassen. Dieser Proxy soll in Java implementiert werden, under Benutzung des Java Media Framework (JMF). Der Proxy soll eine Möglichkeit bieten, Videodatenströme mittels Transcoding umzukodieren, mit dem Ziel, die Datenrate anzupassen.

Vorüberlegungen

Der Proxy muss also, um seine Aufgaben erfüllen zu können, zumindest drei Schnittstellen zur Verfügung stellen.

  1. Eine RTP/RTSP Schnittstelle zum Server, die faktisch wir ein Client funktioniert und die Aufgabe hat, Videodaten von einem Videoserver anzufordern, zu empfangen und in einem Puffer abzulegen.
  2. Eine RTP/RTSP Schnittstelle zum Client, die faktisch wie ein Server funktioniert und die Aufgabe hat, die möglciherweise angepaßten Videodaten an den eigentlichen Client zu senden.
  3. Und schließlich eine Schnittstelle, die es erlaubt, verschiedene Transcodingmodule zur Laufzeit auszuwählen, zu laden und auszuführen.
Diese drei Schnittstellen stellen einige besondere Anforderungen an das JMF, insbesondere die, in das JMF eigene Verarbeitungsroutinen in den Übertragungsprozess von Videodaten einzufügen. Es erscheint ebenfalls wünschenswert eine möglichst umfassende Kontrolle über die Protokolle zu haben, um auch hier ein gewisses Finetuning betreiben zu können oder sogar, um sie zu erweitern, etwa um den Entscheidungsprozeß, welches Transcodingmodul verwendet werden soll, zu unterstützen.

Das Java Media Framework

Das JMF dient dazu, auf möglichst einfache Art und Weise und mit möglichst wenig Aufwand Multimediadatenströme zu verarbeiten. Jede Mögliche Verarbeitung, egal ob Kodierung, Dekodierung oder das Rendern, kann mit einfachen mitteln realisiert werden. Dazu werden vom JMF bestimmte Interfaces definiert. Die wichtigsten Interfaces sind:

DataSource beschreibt einen Datenstrom von rohen Multimediadaten, die von Processor verarbeitet oder von einem Player dargestellt werden kann. Es ist dabei nicht wichtig, woher ein DataSource Objekt seine Daten tatsächlich bezieht, ob aus einer Datei oder aus einer RTP Verbindung. Wichtig ist nur,m dass er einem Processor sie auf immer die gleiche Weise zur Verfügung stellt, d.h. dass die eigentliche Datenquelle darin gekapselt ist.

Ein Processor ist dabei als verarbeitende Instanz zu verstehen, ein Processor hat üblicherweise einn DataSource als Eingbe und einen DataSource als Ausgabe, während ein Player nur einen DataSource als Eingabe benötigt, denn die Daten werden ja gerendert dargestellt. Der Processor dagegen prodziert wieder ein DataSource Objekt, das wierderum als Eingang für einen anderen Processor oder Player dienen kann. Somit können Processor Objekte hintereinander gehängt werden, was einer sequenziellen Abarbeitung verschiedener Aufgaben entspricht. Processor Objekte selbst können aus mehreren Plugins zusammengesetzt sein. Ein Plugin kann somit als minimaler oder auch atomarer Processor verstanden werden. Die nachfolgende Abbildung stammt aus dem JMF User Guide und zeigt einen typischen Processor.

Processor (Schema)

Dem Benutzer wird durch das JMF die Möglichkeit gegeben, entweder einen Processor aus vorhandenen Plugins zusammenzusetzen, ihn mit eigenen Plugins zu ergänzen oder aber komplett einen eigenen Processor in das JMF zu integrieren. Ebenso können andere Teile wie DataSources Player, Plugins und Codecs integriert werden. Um dies zu ermöglichen gibt es den Manager. Der Manager hat die Aufgabe anhand der Vorgaben des Entwicklers Instanzen der gesuchten Interfaces anzulegen. Dazu durchsucht er eine interne Liste, die Package Prefixe enthält. Wenn das JMF erweitert werden soll, kann man seine eigenen Klassen als ein eigenes Package in das System integrieren. Möchte man zum Beispiel eine eigene Implementation des RTPDataSource integrieren, erstellt man eine Klasse des entsprechenden Namens und speichert sie als eigenes Packet, also etwa java.meineigenes.RTPDataSource. Dann fügt man das Packet "java.meineigenes" in die Liste der Packet-Prefixe ein. Der Manager würde nun stets eine Instanz von java.meineigenes.RTPDataSource erzeugen, wenn ein RTP DataSource Objekt benötigt wird. Auf die gleiche Art funktioniert es mit Plugins.

Lösungsansatz

Zunächst wird eine eigene flexible RTP/RTSP implementierung in das JMF eingebettet. Danach wird ein Processor Objekt implementiert, das eine Transcodierung realisiert, und auf der Basis der Manager Funktionalität kann eine API geschaffen werden, die Anhand gewisser Parameter in einem vordefinierten Package-Path nach entsprechenden Transcoder-Implementationen sucht. Beispielsweise könnte für jede Session eine Property-Liste angelegt werden, die angibt, welche Parameter des Vidiostromes bei geändert werden können. Wenn klar ist, welche Transcodingmodule für eine solche Änderung zuständig sind, kann eine Manager instanz diese nach und nach in einem Package Path zu laden versuchen. Dabei wird solange probiert, bis eine passende implementierung gefunden wurde. Gibt es für einen Property Eintrag keine entsprechnung oder wird keine Implementation gefunden so würde dies gemeldet.

Letztlich wäre noch ein Session Manager zu implementieren, der alle zu einer einzelnen Übertragung gehörenden Informationen und Verbindungen verwaltet.

Beispiel

Die Property Liste gibt an: es soll erst die Auflösung dann die Qualität des Videostroms verändert werden, dann würde zunächst im Package-Pfad nach einer implementation für die Auflösungsänderung gesucht, danach nach einer Qualitätsänderung. Hieße nun der Package-Pfad: ["java.eigenes", "java.sonstiges"] und die entsprechenden Transcoding Module "ResolutionTranscoder" und "QualityTranscoder" würde nacheinander versucht werden folgende Klassen zu laden: "java.eigenes.ResulutionTranscoder", "java.eigenes.QualityTranscoder", "java.sonstiges.ResulutionTranscoder" und schliesslich "java.sonstiges.QualityTranscoder".