| CONTENTS | PREV | NEXT | INDEX | JMF 2.0 API Guide |
You can extend JMF by implementing one of the plug-in interfaces to perform custom processing on a
Track, or by implementing completely newDataSourcesandMediaHandlers.Note: JMF Players and Processors are not required to support plug-ins--plug-ins won't work with JMF 1.0-based Players and some 2.0-based implementations might choose not to support plug-ins. The reference implementation of JMF 2.0 provided by Sun Microsystems, Inc. and IBM Corporation fully supports the plug-in API.
Implementing JMF Plug-Ins
Custom JMF plug-ins can be used seamlessly with
Processorsthat support the plug-in API. After you implement your plug-in, you need to install it and register it with thePlugInManagerto make it available to plug-in compatibleProcessors.Implementing a Demultiplexer Plug-In
A
Demultiplexerparses media streams such as WAV, MPEG or QuickTime. If the stream is multiplexed, the separate tracks are extracted. You might want to implement aDemultiplexerplug-in to support a new file format or provide a higher-performance demultiplexer. If you implement a customDataSource, you can implement aDemultiplexerplug-in that works with your customDataSourceto enable playback through an existingProcessor.A
Demultiplexeris a single-input, multi-output processing component. It reads data from a push or pullDataSource, extracts the individual tracks, and outputs each track separately.A
Demultiplexeris a type ofMediaHandler, it must implement theMediaHandlersetSourcemethod. This method is used by theProcessorto locate aDemultiplexerthat can handle itsDataSource. TheProcessorgoes through the list of registeredDemultiplexersuntil it finds one that does not return an exception whensetSourceit called.The main work performed by a
Demultiplexeris done in the implementation of thegetTracksmethod, which returns an array of the tracks extracted from the inputDataSource.A complete example of a GSM demultiplexer is provided in Demultiplexer Plug-In. When you implement a
Demultiplexer, you need to:
- Implement
getSupportedInputContentDescriptorsto advertise what input formats the demulitplexer supports. For example, the GSM demultiplexer needs to advertise that it supports GSM files.
- Implement the
MediaHandlersetSourcemethod to check theDataSourceand determine whether or not theDemultiplexercan handle that type of source. For example, the GSM demultiplexer supportsPullDataSources:
- Implement
getTracksto parse the header and extract the individual tracks from the stream if it is multiplexed. In the GSM demultiplexer areadHeadermethod is implemented to parse the header. ThegetTracksmethod returns an array ofGsmTracks. (See Demultiplexer Plug-In for the implementation ofGsmTracks.)
Implementing a Codec or Effect Plug-In
Codecplug-ins are used to decode compressed media data, convert media data from one format to another, or encode raw media data into a compressed format. You might want to implement aCodecto provide performance enhancements over existing solutions, support new compressed or uncompressed data formats, or convert data from a custom format to a standard format that can be easily processed and rendered.A
Codecis a single-input, single-output processing component. It reads data for an individual track, processes the data, and outputs the results.A
Codecplug-in can enable the user to control the processing it performs throughEncodingControlorDecodingControlobjects. These controls provide a way to adjust attributes such as the frame rate, bit rate, and compression ratio. Codec controls are accessed through thegetControlsmethod. If a particularCodecControlprovides a user-interface component, its accessed by callinggetControlComponent.When you implement a
Codec, you need to:
- Implement
getSupportedInputFormatsandgetSupportedOutputFormatsto advertise what input and output formats the codec supports.- Enable the selection of those formats by implementing
setInputFormatandsetOutputFormat.- Implement
processto actually perform the compression or decompression of the inputTrack.Effect Plug-ins
An
Effectplug-in is actually a specialized type ofCodecthat performs some processing on the inputTrackother than compression or decompression. For example, you might implement a gain effect that adjusts the volume of an audio track. Like aCodec, anEffectis a single-input, single-output processing component and the data manipulation that theEffectperforms is implemented in theprocessmethod.An
Effectplug-in can be used as either a pre-processing effect or a post-processing effect. For example, if aProcessoris being used to render a compressed media stream, theEffectwould typically be used as a post-processing effect and applied after the stream has been decoded. Conversely, if theProcessorwas being used to output a compressed media stream, theEffectwould typically be applied as a pre-processing effect before the stream is encoded.When you implement an
Effect, you need to:
- Implement
getSupportedInputFormatsandgetSupportedOutputFormatsto advertise what input and output formats the effect supports.- Enable the selection of those formats by implementing
setInputFormatandsetOutputFormat.- Implement
processto actually perform the effect processing.Note that there's no mechanism for specifying what a particular
Effectdoes--the name of anEffectplug-in class should provide some indication of its intended use.Example: GainEffect Plug-In
In this example, the
Effectinterface is implemented to create an effect that adjusts the gain on the incoming audio data and outputs the modified data. By default, theGainEffectprocessmethod increases the gain by a factor of 2.
Implementing a Multiplexer Plug-In
A
Multiplexeris essentially the opposite of aDemultiplexer: it takes individual tracks of media data and merges them into a single multiplexed media-stream such as an MPEG or QuickTime file. You might want to implement aMultiplexerplug-in to support a customDataSourceor provide a higher-performance. However, it's not always necessary to implement a separateMultiplexerplug-in--multiplexing can also be performed by aDataSink.A
Multiplexeris a multi-input, single-output processing component. It reads data from a set of tracks and outputs aDataSource.The main work performed by a
Multiplexeris done in the implementation of theprocessmethod. ThegetDataSourcemethod returns theDataSourcegenerated by theMultiplexer.When you implement a
Multiplexer, you need to:
- Implement
getSupportedOutputContentDescriptorsto advertise what output formats theMultiplexersupports.- Enable the selection of the output format by implementing
setOutputContentDescriptor.- Implement
processto actually merge the individual tracks into an output stream of the selected format.Unlike a
Codec, there is no specific query mechanism. TheinitializeTracksmethod should returnfalseif any of the specified track formats are not supported.Implementing a Renderer Plug-In
A
Rendererdelivers media data in its final processed state. It is a single-input processing component with no output.Rendererplug-ins read data from aDataSourceand typically present the media data to the user, but can also be used to provide access to the processed media data for use by another application or device. For example, you might implement aRendererplug-in if you want to render a video to a location other than the screen.If you're implementing a video renderer, you should implement the
VideoRendererinterface, which extendsRendererto define video-specific attributes such as theComponentwhere the video will be rendered.The main work performed by a
Rendereris done in the implementation of theprocessmethod. When you implement aRenderer, you need to:
- Implement
getSupportedInputFormatsto advertise what input formats theRenderersupports.- Enable the selection of the input format by implementing
setInputFormat.- Implement
processto actually process the data and render it to the output device that thisRendererrepresents.Example: AWTRenderer
This example implements the
Rendererplug-in to create aRendererfor RGB images that usesAWTImage.
Registering a Custom Plug-In With the Plug-In Manager
To make a custom plug-in available to a
Processorthrough theTrackControlinterface, you need to register it with thePlugInManager.(The default plug-ins are registered automatically.)To register a new plug-in, you
use thePlugInManager addPlugInmethod. You must callcommitto make the addition permanent. For example, to register theGainEffectplug-in from the example on page 89:
If you want to make your plug-in available to other users, you should create an Java applet or application that performs this registration process and distribute it with your plug-in.
You can remove a plug-in either temporarily or permanently with the
removePlugInmethod. To make the change permanent, you callcommit.Note: The reference implementation of JMF 2.0 provided by Sun Microsystems, Inc. and IBM Corporation provides a utility application,
JMFRegistry, that you can use to register plug-ins interactively.Implementing Custom Data Sources and Media Handlers
Custom
DataSourcesandMediaHandlerssuch asPlayersandProcessorscan be used seamlessly with JMF to support new formats and integrate existing media engines with JMF.Implementing a Protocol Data Source
A
DataSourceis an abstraction of a media protocol-handler. You can implement new types ofDataSourcesto support additional protocols by extendingPullDataSource,PullBufferDataSource,PushDataSource, orPushBufferDataSource. If you implement a customDataSource, you can implementDemultiplexerandMultiplexerplug-ins that work with your customDataSourceto enable playback through an existingProcessor, or you can implement a completely customMediaHandlerfor yourDataSource.A
DataSourcemanages a collection ofSourceStreamsof the corresponding type. For example, aPullDataSourceonly supports pull data-streams; it manages a collection ofPullSourceStreams. Similarly, aPushDataSourceonly supports push data-streams; it manages a collection ofPushSourceStreams. When you implement a newDataSource, you also need to implement the corresponding source stream:PullSourceStream,PullBufferStream,PushSourceStream, orPushBufferStream.If your
DataSourcesupports changing the media position within the stream to a specified time, it should implement thePositionableinterface. If theDataSourcesupports seeking to a particular point in the stream, the correspondingSourceStreamshould implement theSeekableinterface.So that the
Managercan construct your customDataSource, the name and package hierarchy for theDataSourcemust follow certain conventions. The fully qualified name of your customDataSourceshould be:<protocol package-prefix>.media.protocol.<protocol>.DataSourceThe protocol package-prefix is a unique identifier for your code that you register with the JMF
PackageManager(for example,COM.mybiz) as a protocol package-prefix. The protocol identifies the protocol for your newDataSource. For more information, see Integrating a Custom Data Source with JMF.Example: Creating an FTP DataSource
The example in Sample Data Source Implementation demonstrates how to support an additional protocol by implementing a custom
DataSourceandSourceStream. ThisDataSource,FTPDataSource, implementsPullDataSource.Integrating a Custom Data Source with JMF
To integrate a custom
DataSourceimplementation with JMF you need to:
- Install the package containing the new
DataSourceclass,<protocol-prefix>.media.protocol.<protocol>.DataSource.- Add your package prefix to the protocol package-prefix list controlled by the
PackageManager. TheManagerqueries thePackageManagerfor the list of protocol package-prefixes it uses to search for aDataSource.For example, to integrate a new
DataSourcefor the protocol type xxx, you would create and install a package called:<protocol package-prefix>.media.protocol.xxx.DataSourcethat contains the new
DataSourceclass. You also need to add your package prefix (an identifier for your code, such asCOM.mybiz) to the protocol package-prefix list managed by thePackageManager.
If you want to make your new
DataSourceavailable to other users, you should create an Java applet or application that performs this registration process and distribute it with yourDataSource.Implementing a Basic Controller
Controllerscan be implemented to present time-based media other than audio or video data. For example, you might want to create aControllerthat manages a slide-show presentation of still images.Example: Creating a Timeline Controller
The sample in Sample Controller Implementation illustrates how a simple time-line
Controllercan be implemented in JMF. ThisController,TimeLineController, takes array of time values (representing a time line) and it keeps track of which segment in the time line you are in.
TimeLineControlleruses a custom media event,TimeLineEvent, to indicate when the segment in the time line changes.Implementing a DataSink
JMF provides a default
DataSinkthat can be used to write data to a file. Other types ofDataSinkclasses can be implemented to facilitate writing data to the network or to other destinations.To create a custom
DataSink, you implement theDataSinkinterface. ADataSinkis a type ofMediaHandler, so you must also implement theMediaHandlersetSourcemethod.To use your
DataSinkwith JMF, you need to add your package-prefix to the content package-prefix list maintained by thePackageManager. For more information, see "Integrating a Custom Media Handler with JMF".Integrating a Custom Media Handler with JMF
To integrate a new
MediaHandlerwith JMF, you need to:
- Implement the
MediaHandler setSourcemethod to check theDataSourceand determine whether or not thehandlercan handle that type of source. When the client programmer calls the appropriateManager createmethod,setSourceis called as theManagersearches for an appropriateMediaHandler.- Install the package containing the new class.
- Add your package prefix to the content package-prefix list controlled by the
PackageManager. TheManagerqueries thePackageManagerfor the list of content package-prefixes it uses to search for aMediaHandler.For example, to integrate a new
Playerfor the content type mpeg.sys, you would create and install a package called:<content package-prefix>.media.content.mpeg.sys.Handlerthat contains the new
Playerclass. The package prefix is an identifier for your code, such asCOM.mybiz. You also need to add your package prefix to the content package-prefix list managed by thePackageManager.
If you want to make your new
MediaHandleravailable to other users, you should create an Java applet or application that performs this registration process and distribute it with yourMediaHandler.Registering a Capture Device with JMF
The implementor of a device is responsible for defining a
CaptureDeviceInfoobject for the device. When the device is installed, it must be registered with theCaptureDeviceManagerby callingaddDevice.