TOC Prev Next
JMF provides a platform-neutral framework for displaying time-based media. The
Java Media Player APIs are designed to support most standard media content
types, including MPEG-1, MPEG-2, QuickTime, AVI, WAV, AU, and MIDI.
Using JMF, you can synchronize and present time-based media from diverse
sources.
Existing media players for desktop computers are heavily dependent on native
code for computationally intensive tasks like decompression and rendering. The
JMF API provides an abstraction that hides these implementation details from the
developer. For example, a particular JMF Player implementation might choose to
leverage an operating system's capabilities by using native methods. However, by
coding to the JMF API, the application or applet developer doesn't need to know
whether or not that implementation uses native methods.
The JMF Player API:
- Scales across different protocols and delivery mechanisms
- Scales across different types of media data
- Provides an event model for asynchronous communication between JMF
Players and applications or applets
1.1 Data Sources
A DataSource encapsulates the location of media and the protocol and software
used to deliver the media. A Java Media Player contains a DataSource. Once
obtained, the source cannot be reused to deliver other media. A Player's data
source is identified by either a JMF MediaLocator or a URL (universal resource
locator).
MediaLocator is a JMF class that describes the media that a Player displays. A
MediaLocator is similar to a URL and can be constructed from a URL. In Java, a
URL can only be constructed if the corresponding protocol handler is installed on
the system. MediaLocator doesn't have this restriction.
Java Media Players can present media data obtained from a variety of sources,
such as local or network files and live broadcasts. JMF supports two different
types of media sources:
- 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.
- 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.
The degree of control that a client program can extend to the user depends on the
type of media 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.
1.2 Players
A Java Media Player is an object that processes a stream of data as time passes,
reading data from a DataSource and rendering it at a precise time. A Java Media
Player implements the Player interface.
Clock defines the basic timing and synchronization operations that a Player
uses to control the presentation of media data.
Controller extends Clock to provide methods for managing system
resources and preloading data and a listening mechanism that allows you to
receive notification of media events.
Duration provides a way to determine the duration of the media being
played.
Player supports standardized user control and relaxes some of the
operational restrictions imposed by Clock.
Players share a common model for timekeeping and synchronization. A
Player's media time represents the current position in the media stream. Each
Player has a TimeBase that defines the flow of time for that Player. When a
Player is started, its media time is mapped to its time-base time. To be synchronized,
Players must use the same TimeBase.
A Player's user interface can include both a visual component and a control-
panel component. You can implement a custom user-interface for a Player or use
the Player's default control-panel component.
A Player must perform a number of operations before it is capable of presenting
media. Because some of these operations can be time consuming, JMF allows you
to control when they occur by defining the operational states of a Player and
providing a control mechanism for moving the Player between those states.
1.3 Media Events
The JMF event reporting mechanism allows your program to respond to media-
driven error conditions, such as out-of-data or resource unavailable conditions.
The event system also provides an essential notification protocol; when your
program calls an asynchronous method on a Player, it can only be sure that the
operation is complete by receiving the appropriate event.
Two types of JMF objects post events: GainControl objects and Controller
objects. Controller and GainControl follow the established Java Beans patterns
for events.
A GainControl object posts only one type of event, GainChangeEvent. To
respond to gain changes, you implement the GainChangeListener interface.
A Controller can post a variety of events that are derived from ControllerEvent.
To receive events from a Controller such as a Player, you implement
the ControllerListener interface. The following figure shows the events that
can be posted by a Controller.
ControllerEvents fall into three categories: change notifications, closed events,
and transition events:
- Change notification events such as
RateChangeEvent and
DurationUpdateEvent indicate that some attribute of the Player has
changed, often in response to a method call. For example, the Player posts a
RateChangeEvent when its rate is changed by a call to setRate.
TransitionEvents allow your program to respond to changes in a Player's
state. A Player posts transition events whenever it moves from one state to
another. (See Section 1.4 for more information about Player states.)
ControllerClosedEvents are posted by a Player when the Player shuts
down. When a Player posts a ControllerClosedEvent, it is no longer
usable. A ControllerErrorEvent is a special case of
ControllerClosedEvent. You can listen for ControllerErrorEvents so
that your program can respond to Player malfunctions, minimizing the
impact on the user.
1.4 Player States
A Java Media Player can be in one of six states. The Clock interface defines the
two primary states: Stopped and Started. To facilitate resource management, Controller
breaks the Stopped state down into five standby states: Unrealized, Realizing
, Realized, Prefetching, and Prefetched.
In normal operation, a Player steps through each state until it reaches the Started
state:
- A
Player in the Unrealized state has been instantiated, but does not yet know
anything about its media. When a media Player is first created, it is
Unrealized.
- When
realize is called, a Player moves from the Unrealized state into the
Realizing state. A Realizing Player is in the process of determining its
resource requirements. During realization, a Player acquires 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 one
Player at a time; such resources are acquired during Prefetching.) A
Realizing Player often downloads assets over the net.
- When a
Player finishes Realizing, it moves into the Realized state. A
Realized Player knows what resources it needs and information about the
type of media it is to present. Because a Realized Player knows 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 another Player from starting.
- When
prefetch is called, a Player moves from the Realized state into the
Prefetching state. A Prefetching Player is preparing to present its media.
During this phase, the Player preloads its media data, obtains exclusive-use
resources, and anything else it needs to do to prepare itself to play.
Prefetching might have to recur if a Player's media presentation is
repositioned, or if a change in the Player's rate requires that additional
buffers be acquired or alternate processing take place.
- When a
Player finishes Prefetching, it moves into the Prefetched state. A
Prefetched Player is ready to be started; it is as ready to play as it can be
without actually being Started.
- Calling
start puts a Player into the Started state. A Started Player's time-
base time and media time are mapped and its clock is running, though the
Player might be waiting for a particular time to begin presenting its media
data.
A Player posts TransitionEvents as it moves from one state to another. The
ControllerListener interface provides a way for your program to determine
what state a Player is in and to respond appropriately.
Using this event reporting mechanism, you can manage Player latency by controlling
when a Player begins Realizing and Prefetching. It also enables you to
ensure that the Player is in an appropriate state before calling methods on the
Player.
1.4.1 Methods Available in Each Player State
To prevent race conditions, not all methods can be called on a Player in every
state. Table 1, "Restrictions on Player Methods" identifies the restrictions
imposed by JMF. If you call a method that is illegal in a Player's current state,
the Player throws an error or exception.
Table 1:
|
Method
|
Unrealized
Player
|
Realized
Player
|
Prefetched Player
|
Started
Player
|
|---|
getStartLatency
|
NotRealizedError
|
legal
|
legal
|
legal
|
getTimeBase
|
NotRealizedError
|
legal
|
legal
|
legal
|
setMediaTime
|
NotRealizedError
|
legal
|
legal
|
legal
|
setRate
|
NotRealizedError
|
legal
|
legal
|
legal
|
getVisualComponent
|
NotRealizedError
|
legal
|
legal
|
legal
|
getControlPanelComponent
|
NotRealizedError
|
legal
|
legal
|
legal
|
getGainControl
|
NotRealizedError
|
legal
|
legal
|
legal
|
setStopTime
|
NotRealizedError
|
legal
|
legal
|
StopTimeSetError
if previously set
|
syncStart
|
NotPrefetchedError
|
NotPrefetchedError
|
legal
|
ClockStartedError
|
setTimeBase
|
NotRealizedError
|
legal
|
legal
|
ClockStartedError
|
deallocate
|
legal
|
legal
|
legal
|
ClockStartedError
| |
addController
|
NotRealizedError
|
legal
|
legal
|
ClockStartedError
| |
removeController
|
NotRealizedError
|
legal
|
legal
|
ClockStartedError
|
mapToTimeBase
|
ClockStoppedException
|
ClockStoppedException
|
ClockStoppedException
|
legal
|
Restrictions on Player Methods
1.5 Calling JMF Methods
JMF uses the following convention for errors and exceptions:
- Java Media Errors are thrown when a program calls a method that is illegal in
the object's current state. Errors are thrown in situations where you have
control over the state and the requested operation could result in a race
condition. For example, it is an error to call certain methods on a Started
Player. It is your responsibility to ensure that a Player is stopped before
using these methods. Applications should not catch JMF errors; well-written
applications will never encounter these errors.
- Java Media Exceptions are thrown when a program calls a method that cannot
be completed or is not applicable in the object's current state. Exceptions are
thrown in situations where you do not necessarily have control over the state.
For example, an exception is thrown if you attempt to synchronize two
Players with incompatible time bases. This is not an error because you could
not determine ahead of time that the time bases were incompatible. Similarly,
if you call a method that is only applicable for a Started Player and the
Player is Stopped, an exception is thrown. Even if you just started the
Player, it might have already stopped in response to other conditions, such
as end of media.
Some JMF methods return values that indicate the results of the method call. In
some instances, these results might not be what you anticipated when you called
the method; by checking the return value, you can determine what actually happened.
For example, the return value might indicate:
- The value that was actually set. For example, not all
Players can present
media data at five times the normal rate. If you call setRate(5.0), the
Player will set its rate as close as it can to 5.0 and return the rate it actually
set. That rate might be 5.0, or it might be 1.0; you need to check the return
value to find out.
- That the information you requested is not currently available. For example, a
Player might not know its duration until it has played its media stream once.
If you call getDuration on such a Player before it has played, getDuration
returns DURATION_UNKNOWN. If you call getDuration again after the Player
has played, it might be able to return the actual duration of the media stream.
TOC Prev Next
|