Processing Time-Based Media with JMF

A Processor can be used as a programmable Player that enables you to control the decoding and rendering process. A Processor can also be used as a capture processor that enables you to control the encoding and multiplexing of the captured media data.

You can control what processing is performed by a Processor several different ways:

Note: Some high-performance or light-weight Processor implementations might choose not to support the selection of processing options so that they can provide a highly-optimized JMF presentation solution. The reference implementation of JMF 2.0 provided by Sun Microsystems, Inc. and IBM Corporation fully supports the selection of processing options through TrackControl objects and setOutputContentDescriptor.

Configuring a Processor

In addition to the Realizing and Prefetching phases that any Player moves through as it prepares to start, a Processor also goes through a Configuring phase. You call configure to move an Unrealized Processor into the Configuring state.

While in the Configuring state, a Processor gathers the information it needs to construct TrackControl objects for each track. When it's finished, it moves into the Configured state and posts a ConfigureCompleteEvent. Once a Processor is Configured, you can set its output format and TrackControl options. When you're finished specifying the processing options, you call realize to move the Processor into the Realizing state and begin the realization process.

Once a Processor is Realized, further attempts to modify its processing options are not guaranteed to work. In most cases, a FormatChangeException will be thrown.

Selecting Track Processing Options

To select which plug-ins are used to process each track in the media stream, you:

  1. Call the PlugInManager.getPlugInList method to determine what plug-ins are available. The PlugInManager returns a list of plug-ins that match the specified input and output formats and plug-in type.
  2. Call getTrackControls on the Processor to get a TrackControl for each track in the media stream. The Processor must in the Configured state before you call getTrackControls.
  3. Call the TrackControl setCodecChain or setRenderer methods to specify the plug-ins that you want to use for each track.

When you use setCodecChain to specify the codec and effect plug-ins for a Processor, the order in which the plug-ins actually appear in the processing chain is determined by the input and output formats each plug-in supports.

To control the transcoding that's performed on a track by a particular Codec, you can use the codec controls associated with the track. To get the codec controls, you call the TrackControl getControls method. This returns all of the Controls associated with the track, including codec controls such as H263Control, QualityControl, and MPEGAudioControl. (For a list of the codec controls defined by JMF, see Standard Controls.)

Converting Media Data from One Format to Another

You can select the format for a particular track through the TrackControl for that track:

  1. Call getTrackControls on the Processor to get a TrackControl for each track in the media stream. The Processor must be in the Configured state before you call getTrackControls.
  2. Use the TrackControl setFormat method to specify the format to which you want to convert the selected track.

Specifying the Output Data Format

You can use the Processor setContentDescriptor method to specify the format of the data output by the Processor. You can get a list of supported data formats by calling getSupportedContentDescriptors.

You can also select the output format that you want by using a ProcessorModel to create the Processor. (See Using a ProcessorModel to Create a Processor for more information.)

Specifying an output data format automatically selects the default processing options for this format, overriding the previous processing options selected through the TrackControls. Setting the output data format to null causes the media data to be rendered instead of output to the Processor object's output DataSource.

Specifying the Media Destination

You can specify a destination for the media stream by selecting a particular Renderer for a track through its TrackControl, or by using the output from a Processor as the input to a particular DataSink. You can also use the Processor output as the input to another Player or Processor that has a different destination.

Selecting a Renderer

To select the Renderer that you want to use, you:

  1. Call getTrackControls on the Processor to get a TrackControl for each track in the media stream. The Processor must in the Configured state before you call getTrackControls.
  2. Call the TrackControl setRenderer method to specify the Renderer plug-in.

Writing Media Data to a File

You can use a DataSink to read media data from Processor object's output DataSource and render the data to a file.

  1. Get the output DataSource from the Processor by calling getDataOutput.
  2. Construct a file writer DataSink by calling Manager.createDataSink. Pass in the output DataSource and a MediaLocator that specifies the location of the file to which you want to write.
  3. Call open on the DataSink to open the file.
  4. Call start on the DataSink to begin writing data.

The format of the data written to the specified file is controlled through the Processor. By default, a Processor outputs raw data. To change the content type of a Processor object's output DataSource, you use the setContentDescriptor method.

Example 4-1: Using a DataSink to write media data to a file.
 DataSink sink;
 MediaLocator dest = new MediaLocator(file://newfile.wav);
 	 sink = Manager.createDataSink(p.getDataOutput(), dest);;
 } catch (Exception) {} 

A Processor can enable user control over the maximum number of bytes that it can write to its destination by implementing the StreamWriterControl. You find out if a Processor provides a StreamWriterControl by calling getControl("") on the Processor.

Connecting a Processor to another Player

The output from a Processor can be used as the input to another Player. To get the output from a Processor, you call getDataOutput, which returns a DataSource. This DataSource can in turn be used to construct a Player or Processor through the Manager.

Using JMF Plug-Ins as Stand-alone Processing Modules

JMF Plug-ins can also be used outside of the JMF framework. You can instantiate the plug-in directly and call its processing method to perform the processing operation.

You might want to do this to encode or decode a media stream, or convert a stream from one format to another.


Copyright © 1998-1999 Sun Microsystems, Inc. All Rights Reserved.