| CONTENTS | PREV | NEXT | INDEX | JMF 2.0 API Guide |
JavaTM Media Framework (JMF) provides a unified architecture and messaging protocol for managing the acquisition, processing, and delivery of time-based media data. JMF is designed to support most standard media content types, such as AIFF, AU, AVI, GSM, MIDI, MPEG, QuickTime, RMF, and WAV.
By exploiting the advantages of the Java platform, JMF delivers the promise of "Write Once, Run AnywhereTM" to developers who want to use media such as audio and video in their Java programs. JMF provides a common cross-platform Java API for accessing underlying media frameworks. JMF implementations can leverage the capabilities of the underlying operating system, while developers can easily create portable Java programs that feature time-based media by writing to the JMF API.
With JMF, you can easily create applets and applications that present, capture, manipulate, and store time-based media. The framework enables advanced developers and technology providers to perform custom processing of raw media data and seamlessly extend JMF to support additional content types and formats, optimize handling of supported formats, and create new presentation mechanisms.
High-Level Architecture
Devices such as tape decks and VCRs provide a familiar model for recording, processing, and presenting time-based media. When you play a movie using a VCR, you provide the media stream to the VCR by inserting a video tape. The VCR reads and interprets the data on the tape and sends appropriate signals to your television and speakers.
![]()
Figure 2-1: Recording, processing, and presenting time-based media.
JMF uses this same basic model. A data source encapsulates the media stream much like a video tape and a player provides processing and control mechanisms similar to a VCR. Playing and capturing audio and video with JMF requires the appropriate input and output devices such as microphones, cameras, speakers, and monitors.
Data sources and players are integral parts of JMF's high-level API for managing the capture, presentation, and processing of time-based media. JMF also provides a lower-level API that supports the seamless integration of custom processing components and extensions. This layering provides Java developers with an easy-to-use API for incorporating time-based media into Java programs while maintaining the flexibility and extensibility required to support advanced media applications and future media technologies.
![]()
Figure 2-2: High-level JMF achitecture.
Time Model
JMF keeps time to nanosecond precision. A particular point in time is typically represented by a
Timeobject, though some classes also support the specification of time in nanoseconds.Classes that support the JMF time model implement
Clockto keep track of time for a particular media stream. TheClockinterface defines the basic timing and synchronization operations that are needed to control the presentation of media data.![]()
Figure 2-3: JMF time model.
A
Clockuses aTimeBaseto keep track of the passage of time while a media stream is being presented. ATimeBaseprovides a constantly ticking time source, much like a crystal oscillator in a watch. The only information that aTimeBaseprovides is its current time, which is referred to as the time-base time. The time-base time cannot be stopped or reset. Time-base time is often based on the system clock.A
Clockobject's media time represents the current position within a media stream--the beginning of the stream is media time zero, the end of the stream is the maximum media time for the stream. The duration of the media stream is the elapsed time from start to finish--the length of time that it takes to present the media stream. (Media objects implement theDurationinterface if they can report a media stream's duration.)To keep track of the current media time, a
Clockuses:
- The time-base start-time--the time that its
TimeBasereports when the presentation begins.- The media start-time--the position in the media stream where presentation begins.
- The playback rate--how fast the
Clockis running in relation to itsTimeBase. The rate is a scale factor that is applied to theTimeBase. For example, a rate of 1.0 represents the normal playback rate for the media stream, while a rate of 2.0 indicates that the presentationwill run at twice the normal rate. A negative rate indicates that theClockis running in the opposite direction from itsTimeBase--for example, a negative rate might be used to play a media stream backward.When presentation begins, the media time is mapped to the time-base time and the advancement of the time-base time is used to measure the passage of time. During presentation, the current media time is calculated using the following formula:
MediaTime = MediaStartTime + Rate(TimeBaseTime - TimeBaseStartTime)When the presentation stops, the media time stops, but the time-base time continues to advance. If the presentation is restarted, the media time is remapped to the current time-base time.
Managers
The JMF API consists mainly of interfaces that define the behavior and interaction of objects used to capture, process, and present time-based media. Implementations of these interfaces operate within the structure of the framework. By using intermediary objects called managers, JMF makes it easy to integrate new implementations of key interfaces that can be used seamlessly with existing classes.
Manager--handles the construction ofPlayers,Processors,DataSources, andDataSinks. This level of indirection allows new implementations to be integrated seamlessly with JMF. From the client perspective, these objects are always created the same way whether the requested object is constructed from a default implementation or a custom one.PackageManager--maintains a registry of packages that contain JMF classes, such as customPlayers,Processors,DataSources, andDataSinks.CaptureDeviceManager--maintains a registry of available capture devices.PlugInManager--maintains a registry of available JMF plug-in processing components, such asMultiplexers,Demultiplexers,Codecs,Effects, andRenderers.To write programs based on JMF, you'll need to use the
Managercreatemethods to construct thePlayers,Processors,DataSources, andDataSinksfor your application. If you're capturing media data from an input device, you'll use theCaptureDeviceManagerto find out what devices are available and access information about them. If you're interested in controlling what processing is performed on the data, you might also query thePlugInManagerto determine what plug-ins have been registered.If you extend JMF functionality by implementing a new plug-in, you can register it with the
PlugInManagerto make it available toProcessorsthat support the plug-in API. To use a customPlayer,Processor,DataSource, orDataSinkwithJMF, you register your unique package prefix with thePackageManager.Event Model
JMF uses a structured event reporting mechanism to keep JMF-based programs informed of the current state of the media system and enable JMF-based programs to respond to media-driven error conditions, such as out-of data and resource unavailable conditions. Whenever a JMF object needs to report on the current conditions, it posts a
MediaEvent.MediaEventis subclassed to identify many particular types of events. These objects follow the established Java Beans patterns for events.For each type of JMF object that can post
MediaEvents, JMF defines a corresponding listener interface. To receive notification when aMediaEventis posted, you implement the appropriate listener interface and register your listener class with the object that posts the event by calling itsaddListener method.
Controllerobjects (such asPlayersandProcessors) and certainControlobjects such asGainControlpost media events.![]()
Figure 2-4: JMF event model.
RTPSessionManagerobjects also post events. For more information, see RTP Events.Data Model
JMF media players
usually useDataSourcesto manage the transfer of media-content. ADataSourceencapsulates both the location of media and the protocol and software used to deliver the media. Once obtained, the source cannot be reused to deliver other media.A
DataSourceis identified by either a JMFMediaLocatoror aURL(universal resource locator).AMediaLocatoris similar to aURLand can be constructed from aURL, but can be constructed even if the corresponding protocol handler is not installed on the system. (In Java, aURLcan only be constructed if the corresponding protocol handler is installed on the system.)A
DataSourcemanages a set ofSourceStreamobjects. A standard data source uses a byte array as the unit of transfer. A buffer data source uses aBufferobject as its unit of transfer. JMF defines several types ofDataSourceobjects:![]()
Figure 2-5: JMF data model.
Push and Pull Data Sources
Media data can be obtained from a variety of sources, such as local or network files and live broadcasts. JMF data sources can be categorized according to how data transfer is initiated:
- Pull Data-Source--the client initiates the data transfer and controls the flow of data from pull data-sources. Established protocols for this type of data include Hypertext Transfer Protocol (HTTP) and FILE. JMF defines two types of pull data sources:
PullDataSourceandPullBufferDataSource, which uses aBufferobject as its unit of transfer.- Push Data-Source--the server initiates the data transfer and controls the flow of data from a push data-source. Push data-sources include broadcast media, multicast media, and video-on-demand (VOD). For broadcast data, one protocol is the Real-time Transport Protocol (RTP), under development by the Internet Engineering Task Force (IETF). The MediaBase protocol developed by SGI is one protocol used for VOD. JMF defines two types of push data sources:
PushDataSourceandPushBufferDataSource, which uses aBufferobject as its unit of transfer.The degree of control that a client program can extend to the user depends on the type of data source being presented. For example, an MPEG file can be repositioned and a client program could allow the user to replay the video clip or seek to a new position in the video. In contrast, broadcast media is under server control and cannot be repositioned. Some VOD protocols might support limited user control--for example, a client program might be able to allow the user to seek to a new position, but not fast forward or rewind.
Specialty DataSources
JMF defines two types of specialty data sources, cloneable data sources and merging data sources.
A cloneable data source can be used to create clones of either a pull or push
DataSource. To create a cloneableDataSource, you call theManagercreateCloneableDataSourcemethod and pass in theDataSourceyou want to clone. Once aDataSourcehas been passed tocreateCloneableDataSource, you should only interact with the cloneableDataSourceand its clones; the originalDataSourceshould no longer be used directly.Cloneable data sources implement the
SourceCloneableinterface, which defines one method,createClone. By callingcreateClone, you can create any number of clones of theDataSource that wasused to construct thecloneableDataSource. The clones can be controlled through the cloneableDataSourceused to create them-- whenconnect,disconnect,start, orstopis called on the cloneableDataSource, the method calls are propagated to the clones.The clones don't necessarily have the same properties as the cloneable data source used to create them or the original
DataSource. For example, a cloneable data source created for a capture device might function as a master data source for its clones--in this case, unless the cloneable data source is used, the clones won't produce any data. If you hook up both the cloneable data source and one or more clones, the clones will produce data at the same rate as the master.A
MergingDataSourcecan be used to combine theSourceStreamsfrom severalDataSourcesinto a singleDataSource. This enables a set ofDataSourcesto be managed from a single point of control--whenconnect,disconnect,start, orstopis called on theMergingDataSource, the method calls are propagated to the mergedDataSources.To construct a
MergingDataSource, you call theManagercreateMergingDataSourcemethod and pass in an array that contains the data sources you want to merge. To be merged, all of theDataSourcesmust be of the same type; for example, you cannot merge aPullDataSourceand aPushDataSource. The duration of the mergedDataSourceis the maximum of the mergedDataSourceobjects' durations. TheContentTypeisapplication/mixed-media.Data Formats
The exact media format of an object is represented by a
Formatobject. The format itself carries no encoding-specific parameters or global timing information, it describes the format's encoding name and the type of data the format requires.JMF extends
Formatto define audio- and video-specific formats.![]()
Figure 2-6: JMF media formats.
An
AudioFormatdescribes the attributes specific to an audio format, such as sample rate, bits per sample, and number of channels. AVideoFormatencapsulates information relevant to video data.Several formats are derived fromVideoFormatto describe the attributes of common video formats, including:To receive notification of format changes from a
Controller, you implement theControllerListenerinterface and listen forFormatChangeEvents. (For more information, see Responding to Media Events.)Controls
JMF
Controlprovides a mechanism for setting and querying attributes of an object. AControloften provides access to a corresponding user interface component that enables user control over an object's attributes. Many JMF objects exposeControls, includingControllerobjects,DataSourceobjects,DataSinkobjects, and JMF plug-ins.Any JMF object that wants to provide access to its corresponding
Controlobjects can implement theControlsinterface.Controlsdefines methods for retrieving associatedControlobjects.DataSourceandPlugInuse theControlsinterface to provide access to theirControlobjects.Standard Controls
JMF defines the standard
Controlinterfaces shown in Figure 2-8:, "JMF controls."
CachingControlenables download progress to be monitored and displayed. If aPlayerorProcessorcan report its download progress, it implements this interface so that a progress bar can be displayed to the user.
GainControlenables audio volume adjustments such as setting the level and muting the output of aPlayerorProcessor. It also supports a listener mechanism for volume changes.![]()
Figure 2-7: Gain control.
![]()
Figure 2-8: JMF controls.
DataSink or Multiplexerobjects that read media from aDataSourceand write it out to a destination such as a file can implement theStreamWriterControlinterface. ThisControlenables the user to limit the size of the stream that is created.
FramePositioningControlandFrameGrabbingControlexport frame-based capabilities forPlayersandProcessors.FramePositioningControlenables precise frame positioning within aPlayer or Processorobject's media stream.FrameGrabbingControlprovides a mechanism for grabbing a still video frame from the video stream. TheFrameGrabbingControlcan also be supported at theRendererlevel.Objects that have a
Format can implement theFormatControlinterface to provide access to theFormat.FormatControlalso provides methods for querying and setting the format.
A TrackControlis a type ofFormatControlthat provides the mechanism for controlling what processing aProcessorobject performs on a particular track of media data. With theTrackControlmethods, you can specify what format conversions are performed on individual tracks and select theEffect,Codec, orRendererplug-ins that are used by theProcessor. (For more information about processing media data, see Processing Time-Based Media with JMF.)Two controls,
PortControlandMonitorControlenable user control over the capture process.PortControldefines methods for controlling the output of a capture device.MonitorControlenables media data to be previewed as it is captured or encoded.
BufferControlenables user-level control over the buffering done by a particular object.JMF also defines several codec controls to enable control over hardware or software encoders and decoders:
BitRateControl--used to export the bit rate information for an incoming stream or to control the encoding bit rate. Enables specification of the bit rate in bits per second.FrameProcessingControl--enables the specification of frame processing parameters that allow the codec to perform minimal processing when it is falling behind on processing the incoming data.FrameRateControl--enables modification of the frame rate.H261Control--enables control over the H.261 video codec still-image transmission mode.H263Control--enables control over the H.263 video-codec parameters, including support for the unrestricted vector, arithmetic coding, advanced prediction, PB Frames, and error compensation extensions.KeyFrameControl--enables the specification of the desired interval between key frames. (The encoder can override the specified key-frame interval if necessary.)MpegAudioControl--exports an MPEG audio codec's capabilities and enables the specification of selected MPEG encoding parameters.QualityControl--enables specification of a preference in the trade-off between quality and CPU usage in the processing performed by a codec. This quality hint can have different effects depending on the type of compression. A higher quality setting will result in better quality of the resulting bits, for example better image quality for video.SilenceSuppressionControl--enables specification of silence suppression parameters for audio codecs. When silence suppression mode is on, an audio encoder does not output any data if it detects silence at its input.User Interface Components
A
Controlcan provide access to a user interfaceComponentthat exposes its control behavior to the end user. To get the default user interface component for a particularControl, you callgetControlComponent. This method returns an AWTComponentthat you can add to your applet's presentation space or application window.A
Controllermight also provide access to user interfaceComponents. For example, aPlayerprovides access to both a visual component and a control panel component--to retrieve these components, you call thePlayermethodsgetVisualComponentandgetControlPanelComponent.If you don't want to use the default control components provided by a particular implementation, you can implement your own and use the event listener mechanism to determine when they need to be updated. For example, you might implement your own GUI components that support user interaction with a
Player. Actions on your GUI components would trigger calls to the appropriatePlayermethods, such asstartandstop. By registering your custom GUI components asControllerListenersfor thePlayer, you can also update your GUI in response to changes in thePlayerobject's state.Extensibility
Advanced developers and technology providers can extend JMF functionality in two ways:
- By implementing custom processing components (plug-ins) that can be interchanged with the standard processing components used by a JMF
Processor- By directly implementing the
Controller,Player,Processor,DataSource, orDataSinkinterfacesImplementing a JMF plug-in enables you to customize or extend the capabilities of a
Processorwithout having to implement one from scratch. Once a plug-in is registered with JMF, it can be selected as a processing option for anyProcessorthat supports the plug-in API. JMF plug-ins can be used to:
- Extend or replace a
Processorobject's processing capability piecewise by selecting the individual plug-ins to be used.- Access the media data at specific points in the data flow. For example, different
Effectplug-ins can be used for pre- and post-processing of the media data associated with aProcessor.- Process media data outside of a
PlayerorProcessor. For example, you might use aDemultiplexerplug-in to get individual audio tracks from a multiplexed media-stream so you could play the tracks through Java Sound.In situations where an even greater degree of flexibility and control is required, custom implementations of the JMF
Controller,Player,Processor,DataSource, orDataSinkinterfaces can be developed and used seamlessly with existing implementations. For example, if you have a hardware MPEG decoder, you might want to implement aPlayerthat takes input from aDataSourceand uses the decoder to perform the parsing, decoding, and rendering all in one step. CustomPlayersandProcessorscan also be implemented to integrate media engines such as Microsoft's Media Player, Real Network's RealPlayer, and IBM's HotMedia with JMF.Note: JMF Players and Processors are not required to support plug-ins. Plug-ins won't work with JMF 1.0-based
Playersand someProcessorimplementations might choose not to support them. The reference implementation of JMF 2.0 provided by Sun Microsystems, Inc. and IBM Corporation fully supports the plug-in API.Presentation
In JMF, the presentation process is modeled by the
Controllerinterface.Controllerdefines the basic state and control mechanism for an object that controls, presents, or captures time-based media. It defines the phases that a media controller goes through and provides a mechanism for controlling the transitions between those phases. A number of the operations that must be performed before media data can be presented can be time consuming, so JMF allows programmatic control over when they occur.A
Controllerposts a variety of controller-specificMediaEventsto provide notification of changes in its status. To receive events from aControllersuch as aPlayer, you implement theControllerListenerinterface. For more information about the events posted by aController, see Controller Events.The JMF API defines two types of
Controllers:PlayersandProcessors.A PlayerorProcessoris constructed for a particular data source and is normally not re-used to present other media data.![]()
Figure 2-9: JMF controllers.
Players
A
Playerprocesses an input stream of media data and renders it at a precise time. ADataSourceis used to deliver the input media-stream to thePlayer.The rendering destination depends on the type of media being presented.![]()
Figure 2-10: JMF player model.
A
Playerdoes not provide any control over the processing that it performs or how it renders the media data.
Playersupports standardized user control and relaxes some of the operational restrictions imposed byClockandController.![]()
Figure 2-11: JMF players.
Player States
A
Playercan be in one of six states. TheClockinterface defines the two primary states: Stopped and Started. To facilitate resource management,Controllerbreaks the Stopped state down into five standby states: Unrealized, Realizing, Realized, Prefetching, and Prefetched.![]()
Figure 2-12: Player states.
In normal operation, a
Playersteps through each state until it reaches the Started state:
- A
Playerin the Unrealized state has been instantiated, but does not yet know anything about its media. When a mediaPlayeris first created, it is Unrealized.- When
realizeis called, aPlayermoves from the Unrealized state into the Realizing state. A RealizingPlayeris in the process of determining its resource requirements. During realization, aPlayeracquires the resources that it only needs to acquire once. These might include rendering resources other than exclusive-use resources. (Exclusive-use resources are limited resources such as particular hardware devices that can only be used by onePlayerat a time; such resources are acquired during Prefetching.) A RealizingPlayeroften downloads assets over the network.- When a
Playerfinishes Realizing, it moves into the Realized state. A RealizedPlayerknows what resources it needs and information about the type of media it is to present. Because a RealizedPlayerknows how to render its data, it can provide visual components and controls. Its connections to other objects in the system are in place, but it does not own any resources that would prevent anotherPlayerfrom starting.- When
prefetchis called, aPlayermoves from the Realized state into the Prefetching state. A PrefetchingPlayeris preparing to present its media. During this phase, thePlayerpreloads its media data, obtains exclusive-use resources, and does whatever else it needs to do to prepare itself to play. Prefetching might have to recur if aPlayerobject's media presentation is repositioned, or if a change in thePlayerobject's rate requires that additional buffers be acquired or alternate processing take place.- When a
Playerfinishes Prefetching, it moves into the Prefetched state. A PrefetchedPlayeris ready to be started.- Calling
startputs aPlayerinto the Started state. A StartedPlayerobject's time-base time and media time are mapped and its clock is running, though thePlayermight be waiting for a particular time to begin presenting its media data.A
PlayerpostsTransitionEventsas it moves from one state to another. TheControllerListenerinterface provides a way for your program to determine what state aPlayeris in and to respond appropriately. For example, when your program calls an asynchronous method on aPlayerorProcessor, it needs to listen for the appropriate event to determine when the operation is complete.Using this event reporting mechanism, you can manage a
Playerobject'sstart latency by controlling when it begins Realizing and Prefetching. It also enables you to determine whether or not thePlayeris in an appropriate state before calling methods on thePlayer.Methods Available in Each Player State
To prevent race conditions, not all methods can be called on a
Playerin every state. The following table identifies the restrictions imposed by JMF. If you call a method that is illegal in aPlayerobject's current state, thePlayerthrows an error or exception.
Table 2-1: Method restrictions for players.
Processors
Processorscan also be used to present media data. AProcessoris just a specialized type ofPlayerthat provides control over what processing is performed on the input media stream. AProcessorsupports all of the same presentation controls as aPlayer.![]()
Figure 2-13: JMF processor model.
In addition to rendering media data to presentation devices, a
Processorcan output media data through aDataSourceso that it can be presented by anotherPlayerorProcessor, further manipulated by anotherProcessor, or delivered to some other destination, such as a file.For more information about
Processors, see Processing.Presentation Controls
In addition to the standard presentation controls defined by
Controller, aPlayerorProcessormight also provide a way to adjust the playback volume. If so, you can retrieve itsGainControlby callinggetGainControl. AGainControlobject posts aGainChangeEventwhenever the gain is modified. By implementing theGainChangeListenerinterface, you can respond to gain changes. For example, you might want to update a custom gain controlComponent.Additional custom
Controltypes might be supported by a particularPlayerorProcessorimplementation to provide other control behaviors and expose custom user interface components. You access these controls through thegetControlsmethod.For example, the
CachingControlinterface extendsControlto provide a mechanism for displaying a download progress bar. If aPlayercan report its download progress, it implements this interface. To find out if aPlayersupportsCachingControl, you can callgetControl(CachingControl) orusegetControlsto get a list of all the supportedControls.Standard User Interface Components
A
PlayerorProcessorgenerally provides two standard user interface components, a visual component and a control-panel component.You can access theseComponentsdirectly through thegetVisualComponentandgetControlPanelComponentmethods.You can also implement custom user interface components, and use the event listener mechanism to determine when they need to be updated.
Controller Events
The
ControllerEventsposted by aControllersuch as aPlayerorProcessorfall into three categories: change notifications, closed events, and transition events:
- Change notification events such as
RateChangeEvent,DurationUpdateEvent, andFormatChangeEventindicate that some attribute of theControllerhas changed, often in response to a method call. For example, aPlayerposts aRateChangeEventwhen its rate is changed by a call tosetRate.TransitionEventsallow your program to respond to changes in aControllerobject'sstate. APlayerposts transition events whenever it moves from one state to another. (See Player States for more information about the states and transitions.)ControllerClosedEventsare posted by aControllerwhen it shuts down. When aControllerposts aControllerClosedEvent, it is no longer usable. AControllerErrorEventis a special case ofControllerClosedEvent. You can listen forControllerErrorEventsso that your program can respond toControllermalfunctions to minimize the impact on the user.![]()
Figure 2-14: JMF events.
Processing
A
Processoris aPlayerthat takes aDataSourceas input, performs some user-defined processing on the media data, and then outputs the processed media data.![]()
Figure 2-15: JMF processors.
A
Processorcan send the output data to a presentation device or to aDataSource. If the data is sent to aDataSource, thatDataSourcecan be used as the input to anotherPlayerorProcessor, or as the input to aDataSink.While the processing performed by a
Playeris predefined by the implementor, aProcessorallows the application developer to define the type of processing that is applied to the media data. This enables the application of effects, mixing, and compositing in real-time.The processing of the media data is split into several stages:
![]()
Figure 2-16: Processor stages.
- Demultiplexing is the process of parsing the input stream. If the stream contains multiple tracks, they are extracted and output separately. For example, a QuickTime file might be demultiplexed into separate audio and video tracks. Demultiplexing is performed automatically whenever the input stream contains multiplexed data.
- Pre-Processing is the process of applying effect algorithms to the tracks extracted from the input stream.
- Transcoding is the process of converting each track of media data from one input format to another. When a data stream is converted from a compressed type to an uncompressed type, it is generally referred to as decoding. Conversely, converting from an uncompressed type to a compressed type is referred to as encoding.
- Post-Processing is the process of applying effect algorithms to decoded tracks.
- Multiplexing is the process of interleaving the transcoded media tracks into a single output stream. For example, separate audio and video tracks might be multiplexed into a single MPEG-1 data stream. You can specify the data type of the output stream with the
ProcessorsetOutputContentDescriptormethod.- Rendering is the process of presenting the media to the user.
The processing at each stage is performed by a separate processing component. These processing components are JMF plug-ins. If the
ProcessorsupportsTrackControls, you can select which plug-ins you want to use to process a particular track. There are five types of JMF plug-ins:
Demultiplexer--parses media streams such as WAV, MPEG or QuickTime. If the stream is multiplexed, the separate tracks are extracted.Effect--performs special effects processing on a track of media data.Codec--performs data encoding and decoding.Multiplexer--combines multiple tracks of input data into a single interleaved output stream and delivers the resulting stream as an outputDataSource.Renderer--processes the media data in a track and delivers it to a destination such as a screen or speaker.Processor States
A
Processorhas two additional standby states, Configuring and Configured, which occur before theProcessorenters the Realizing state..![]()
Figure 2-17: Processor states.
- A
Processorenters the Configuring state whenconfigureis called. While theProcessoris in the Configuring state, it connects to theDataSource, demultiplexes the input stream, and accesses information about the format of the input data.- The
Processormoves into the Configured state when it is connected to theDataSourceand data format has been determined. When theProcessorreaches the Configured state, aConfigureCompleteEventis posted.- When
Realizeis called, theProcessoris transitioned to theRealizedstate. Once theProcessoris Realized it is fully constructed.While a
Processoris in the Configured state,getTrackControlscan be called to get theTrackControlobjects for the individual tracks in the media stream. TheseTrackControlobjects enable you specify the media processing operations that you want theProcessorto perform.Calling
realizedirectly on an UnrealizedProcessorautomatically transitions it through the Configuring and Configured states to the Realized state. When you do this, you cannot configure the processing options through theTrackControls--the defaultProcessorsettings are used.Calls to the
TrackControlmethods once theProcessoris in the Realized state will typically fail, though someProcessorimplementations might support them.Methods Available in Each Processor State
Since a
Processoris a type ofPlayer, the restrictions on when methods can be called on aPlayeralso apply toProcessors. Some of theProcessor-specific methods also are restricted to particular states. The following table shows the restrictions that apply to aProcessor. If you call a method that is illegal in the current state, theProcessorthrows an error or exception.
Table 2-2: Method restrictions for processors.
Processing Controls
You can control what processing operations the
Processorperforms on a track through theTrackControlfor that track. You callProcessor getTrackControlsto get theTrackControlobjectsfor all of the tracks in the media stream.Through a
TrackControl, you can explicitly select theEffect,Codec, andRendererplug-ins you want to use for the track. To find out what options are available, you can query thePlugInManagerto find out what plug-ins are installed.To control the transcoding that's performed on a track by a particular
Codec, you can get theControlsassociated with the track by calling theTrackControlgetControlsmethod. This method returns the codec controls available for the track, such asBitRateControlandQualityControl. (For more information about the codec controls defined by JMF, see Controls.)If you know the output data format that you want, you can use the
setFormatmethod to specify theFormatand let theProcessorchoose an appropriate codec and renderer. Alternatively, you can specify the output format when theProcessoris created by using aProcessorModel. AProcessorModeldefines the input and output requirements for aProcessor. When aProcessorModelis passed to the appropriateManagercreatemethod, theManagerdoes its best to create aProcessorthat meets the specified requirements.Data Output
The
getDataOutputmethod returns aProcessorobject's output as aDataSource. ThisDataSourcecan be used as the input to anotherPlayerorProcessoror as the input to a data sink. (For more information about data sinks, see Media Data Storage and Transmission.)A
Processorobject's outputDataSourcecan be of any type:PushDataSource,PushBufferDataSource,PullDataSource, orPullBufferDataSource.Not all
Processorobjects output data--aProcessorcan render the processed data instead of outputting the data to aDataSource. AProcessorthat renders the media data is essentially a configurablePlayer.Capture
A multimedia capturing device can act as a source for multimedia data delivery. For example, a microphone can capture raw audio input or a digital video capture board might deliver digital video from a camera. Such capture devices are abstracted as
DataSources. For example, a device that provides timely delivery of data can be represented as aPushDataSource. Any type ofDataSourcecan be used as a captureDataSource:PushDataSource,PushBufferDataSource,PullDataSource, orPullBufferDataSource.Some devices deliver multiple data streams--for example, an audio/video conferencing board might deliver both an audio and a video stream. The corresponding
DataSourcecan contain multipleSourceStreamsthat map to the data streams provided by the device.Media Data Storage and Transmission
A
DataSinkis used to read media data from aDataSourceand render the media to some destination--generally a destination other than a presentation device. A particularDataSinkmight write data to a file, write data across the network, or function as an RTP broadcaster. (For more information about using aDataSinkas an RTP broadcaster, see Transmitting RTP Data With a Data Sink.)Like
Players,DataSinkobjects are constructed through theManagerusing aDataSource. ADataSinkcan use aStreamWriterControlto provide additional control over how data is written to a file. See Writing Media Data to a File for more information about howDataSinkobjects are used.Storage Controls
A
DataSinkposts aDataSinkEventto report on its status. ADataSinkEventcan be posted with a reason code, or theDataSinkcan post one of the followingDataSinkEventsubtypes:
DataSinkErrorEvent, which indicates that an error occurred while theDataSinkwas writing data.EndOfStreamEvent, which indicates that the entire stream has successfully been written.To respond to events posted by a
DataSink, you implement theDataSinkListenerinterface.Extensibility
You can extend JMF by implementing custom plug-ins, media handlers, and data sources.
Implementing Plug-Ins
By implementing one of the JMF plug-in interfaces, you can directly access and manipulate the media data associated with a
Processor:
- Implementing the
Demultiplexerinterface enables you to control how individual tracks are extracted from a multiplexed media stream.- Implementing the
Codecinterface enables you to perform the processing required to decode compressed media data, convert media data from one format to another, and encode raw media data into a compressed format.- Implementing the
Effectinterface enables you to perform custom processing on the media data.- Implementing the
Multiplexerinterface enables you to specify how individual tracks are combined to form a single interleaved output stream for aProcessor.- Implementing the
Rendererinterface enables you to control how data is processed and rendered to an output device.Note: The JMF Plug-In API is part of the official JMF API, but JMF
PlayersandProcessorsare not required to support plug-ins. Plug-ins won't work with JMF 1.0-basedPlayersand someProcessorimplementations might choose not to support them. The reference implementation of JMF 2.0 provided by Sun Microsystems, Inc. and IBM Corporation fully supports the plug-in API.Custom
Codec,Effect, andRendererplug-ins are available to aProcessorthrough theTrackControlinterface. To make a plug-in available toadefaultProcessoror aProcessorcreated with aProcessorModel, you need to register it with thePlugInManager. Once you've registered your plug-in, it is included in the list of plug-ins returned by thePlugInManagergetPlugInListmethod and can be accessed by theManagerwhen it constructs aProcessorobject.Implementing MediaHandlers and DataSources
If the JMF Plug-In API doesn't provide the degree of flexibility that you need, you can directly implement several of the key JMF interfaces:
Controller,Player,Processor,DataSource, andDataSink. For example, you might want to implement a high-performancePlayerthat is optimized to present a single media format or aControllerthat manages a completely different type of time-based media.The
Managermechanism used to constructPlayer,Processor,DataSource, andDataSinkobjects enables custom implementations of these JMF interfaces to be used seamlessly with JMF. When one of thecreatemethods is called, theManageruses a well-defined mechanism to locate and construct the requested object. Your custom class can be selected and constructed through this mechanism once you register a unique package prefix with thePackageManagerand put your class in the appropriate place in the predefined package hierarchy.MediaHandler Construction
Players,Processors, andDataSinksare all types ofMediaHandlers--they all read data from aDataSource. AMediaHandleris always constructed for a particularDataSource, which can be either identified explicitly or with aMediaLocator. When one of thecreateMediaHandler methods is called,Manageruses the content-type name obtained from theDataSourceto find and create an appropriateMediaHandlerobject.![]()
Figure 2-18: JMF media handlers.
JMF also supports another type of
MediaHandler,MediaProxy. AMediaProxyprocesses content from oneDataSourceto create another. Typically, aMediaProxyreads a text configuration file that contains all of the information needed to make a connection to a server and obtain media data. To create aPlayerfrom aMediaProxy,Manager:
- Constructs a
DataSourcefor the protocol described by theMediaLocator- Uses the content-type of the
DataSourceto construct aMediaProxyto read the configuration file.- Gets a new
DataSourcefrom theMediaProxy.- Uses the content-type of the new
DataSourceto construct aPlayer.The mechanism that
Manageruses to locate and instantiate an appropriateMediaHandlerfor a particularDataSourceis basically the same for all types ofMediaHandlers:
- Using the list of installed content package-prefixes retrieved from
PackageManager, Managergenerates a search list of availableMediaHandlerclasses.Managersteps through each class in the search list until it finds a class namedHandlerthat can be constructed and to which it can attach theDataSource.When constructing
PlayersandProcessors,Managergenerates the search list of available handler classes from the list of installed content package-prefixes and the content-type name of theDataSource. To search forPlayers,Managerlooks for classes of the form:<content package-prefix>.media.content.<content-type>.HandlerTo search for
Processors,Managerlooks for classes of the form:<content package-prefix>.media.processor.<content-type>.HandlerIf the located
MediaHandleris aMediaProxy,Managergets a newDataSourcefrom theMediaProxyand repeats the search process.If no appropriate
MediaHandlercan be found, the search process is repeated, substitutingunknownfor the content-type name. Theunknowncontent type is supported by genericPlayersthat are capable of handling a large variety of media types, often in a platform-dependent way.Because a
DataSinkrenders the data it reads from itsDataSourceto an output destination, when aDataSinkis created the destination must also be taken into account. When constructingDataSinks,Manageruses the list of content package-prefixes and the protocol from theMediaLocatorthat identifies the destination. For each content package-prefix,Manageradds to the search list a class name of the form:<content package-prefix>.media.datasink.protocol.HandlerIf the located
MediaHandleris aDataSink,Managerinstantiates it, sets itsDataSourceandMediaLocator, and returns the resultingDataSinkobject. If the handler is aDataSinkProxy,Managerretrieves the content type of the proxy and generates a list ofDataSinkclasses that support the protocol of the destinationMedialocatorand the content type returned by the proxy:<content package-prefix>.media.datasink.protocol.<content-type>.HandlerThe process continues until an appropriate
DataSinkis located or theManagerhas iterated through all of the content package-prefixes.DataSource Construction
Manageruses the same mechanism to constructDataSourcesthat it uses to constructMediaHandlers, except that it generates the search list ofDataSourceclass names from the list of installed protocol package-prefixes.For each protocol package-prefix,
Manageradds to the search list a class name of the form:<protocol package-prefix>.media.protocol.<protocol>.DataSource
Managersteps through each class in the list until it finds aDataSourcethat it can instantiate and to which it can attach theMediaLocator.