| コンテンツ | 前 | 次 | 目次 | JMF 2.0 API ガイド |
To present time-based media such as audio or video with JMF, you use a
Player. Playback can be controlled programmatically, or you can display a control-panel component that enables the user to control playback interactively. If you have several media streams that you want to play, you need to use a separatePlayerfor each one. to play them in sync, you can use one of thePlayerobjects to control the operation of the others.A
Processoris a special type ofPlayerthat can provide control over how the media data is processed before it is presented. Whether you're using a basicPlayeror a more advancedProcessorto present media content, you use the same methods to manage playback. For information about how to control what processing is performed by aProcessor, see Processing Time-Based Media with JMF.The
MediaPlayerbean is a Java Bean that encapsulates a JMF player to provide an easy way to present media from an applet or application. TheMediaPlayerbean automatically constructs a newPlayerwhen a different media stream is selected, which makes it easier to play a series of media clips or allow the user to select which media clip to play. For information about using theMediaPlayerbean, see Presenting Media with the MediaPlayer BeanControlling a Player
To play a media stream, you need to construct a
Playerfor the stream, configure thePlayerand prepare it to run, and then start thePlayerto begin playback.Creating a Player
You create a
Playerindirectly through the mediaManager. To display thePlayer, you get thePlayerobject's components and add them to your applet's presentation space or application window.When you need to create a new
Player, you request it from theManagerby callingcreatePlayer or createProcessor. TheManageruses the mediaURLorMediaLocatorthat you specify to create an appropriatePlayer. AURLcan only be successfully constructed if the appropriate correspondingURLStreamHandleris installed.MediaLocatordoesn't have this restriction.Blocking Until a Player is Realized
Many of the methods that can be called on a
Playerrequire thePlayerto be in the Realized state. One way to guarantee that aPlayeris Realized when you call these methods is to use theManagercreateRealizedPlayermethod to construct thePlayer. This method provides a convenient way to create and realize aPlayerin a single step. When this method is called, it blocks until thePlayeris Realized.Managerprovides an equivalentcreateRealizeProcessormethod for constructing a RealizedProcessor.Note: Be aware that blocking until a
PlayerorProcessoris Realized can produce unsatisfactory results. For example, ifcreateRealizedPlayeris called in an applet,Applet.startandApplet.stopwill not be able to interrupt the construction process.Using a ProcessorModel to Create a Processor
A
Processorcan also be created using aProcessorModel. TheProcessorModeldefines the input and output requirements for theProcessorand theManagerdoes its best to create aProcessorthat meets these requirements. To create aProcessorusing aProcessorModel, you call theManager.createRealizedProcessormethod. Example 3-1 creates a RealizedProcessorthat can produce IMA4-encoded stereo audio tracks with a 44.1 kHz sample rate and a 16-bit sample size.
Since the
ProcessorModeldoes not specify a source URL in this example,Managerimplicitly finds a capture device that can capture audio and then creates aProcessorthat can encode that into IMA4.Note that when you create a Realized
Processorwith aProcessorModelyou will not be able to specify processing options through theProcessorobject'sTrackControls. For more information about specifying processing options for a Processor, see Processing Time-Based Media with JMF.Displaying Media Interface Components
A
Playergenerally has two types of user interface components, a visual component and a control-panel component. SomePlayerimplementations can display additional components, such as volume controls and download-progress bars.Displaying a Visual Component
A visual component is where a
Playerpresents the visual representation of its media, if it has one. Even an audioPlayermight have a visual component, such as a waveform display or animated character.To display a
Playerobject'svisual component, you:
- Get the component by calling
getVisualComponent.- Add it to the applet's presentation space or application window.
You can access the
Playerobject's display properties, such as its x and y coordinates, through its visual component. The layout of thePlayercomponents is controlled through the AWT layout manager.Displaying a Control Panel Component
A
Playeroften has a control panel that allows the user to control the media presentation. For example, aPlayermight be associated with a set of buttons to start, stop, and pause the media stream, and with a slider control to adjust the volume.Every
Playerprovides a default control panel. To display thedefault control panel:
- Call
getControlPanelComponentto get theComponent.- Add the returned
Componentto your applet's presentation space or application window.If you prefer to define a custom user-interface, you can implement custom GUI
Componentsand call the appropriatePlayermethods in response to user actions. If you register the custom components asControllerListeners, you can also update them when the state of thePlayerchanges.Displaying a Gain-Control Component
Playerimplementations that support audio gain adjustments implement theGainControlinterface.GainControlprovides methods for adjusting the audio volume, such assetLevelandsetMute. To display aGainControl Componentif thePlayerprovides one, you:
- Call
getGainControlto get theGainControlfrom thePlayer. If thePlayerreturns null, it does not support theGainControlinterface.- Call
getControlComponenton the returnedGainControl.- Add the returned
Componentto your applet's presentation space or application window.Note that
getControlsdoes not return aPlayerobject'sGainControl. You can only access theGainControlby callinggetGainControl.Displaying Custom Control Components
Many
Playershave other properties that can be managed by the user. For example, a videoPlayermight allow the user to adjust brightness and contrast, which are not managed through thePlayerinterface. You can find out what custom controls aPlayersupports by calling thegetControlsmethod.For example, you can call
getControlsto determine if aPlayersupports theCachingControlinterface.
Displaying a Download-Progress Component
The
CachingControlinterface is a special type ofControlimplemented byPlayersthat can report their download progress. ACachingControlprovides a default progress-bar component that is automatically updated as the download progresses. To use the default progress bar in an applet:
- Implement the
ControllerListenerinterface and listen forCachingControlEventsincontrollerUpdate.- The first time you receive a
CachingControlEvent:- Each time you receive a
CachingControlEvent, check to see if the download is complete. WhengetContentProgressreturns the same value asgetContentLength, remove the progress bar.The
Playerposts aCachingControlEventwhenever the progress bar needs to be updated. If you implement your own progress bar component, you can listen for this event and update the download progress wheneverCachingControlEventis posted.Setting the Playback Rate
The
Playerobject's rate determines how media time changes with respect to time-base time; it defines how many units aPlayerobject's media time advances for every unit of time-base time. ThePlayerobject's rate can be thought of as a temporal scale factor. For example, a rate of 2.0 indicates that media time passes twice as fast as the time-base time when thePlayeris started.In theory, a
Playerobject's rate could be set to any real number, with negative rates interpreted as playing the media in reverse. However, some media formats have dependencies between frames that make it impossible or impractical to play them in reverse or at non-standard rates.To set the rate, you call
setRateand pass in the temporal scale factor as a float value. WhensetRateis called, the method returns the rate that is actually set, even if it has not changed.Playersare only guaranteed to support a rate of 1.0.Setting the Start Position
Setting a
Playerobject's media time is equivalent to setting a read position within a media stream. For a media data source such as a file, the media time is bounded; the maximum media time is defined by the end of the media stream.To set the media time you call
setMediaTimeand pass in aTimeobject that represents the time you want to set.Frame Positioning
Some
Playersallow you to seek to a particular frame of a video. This enables you to easily set the start position to the beginning of particular frame without having to specify the exact media time that corresponds to that position.Playersthat support frame positioning implement theFramePositioningControl.To set the frame position, you call the
FramePositioningControlseekmethod. When you seek to a frame, thePlayerobject's media time is set to the value that corresponds to the beginning of that frame and aMediaTimeSetEventis posted.Some
Playerscan convert between media times and frame positions. You can use theFramePositioningControlmapFrameToTimeandmapTimeToFramemethods to access this information, if it's available. (Playersthat supportFramePositioningControlare not required to export this information.) Note that there is not a one-to-one correspondence between media times and frames --a frame has a duration, so several different media times might map to the same frame. (See Getting the Media Time for more information.) -Preparing to Start
Most media
Playerscannot be started instantly. Before thePlayercan start, certain hardware and software conditions must be met. For example, if thePlayerhas never been started, it might be necessary to allocate buffers in memory to store the media data. Or, if the media data resides on a network device, thePlayermight have to establish a network connection before it can download the data. Even if thePlayerhas been started before, the buffers might contain data that is not valid for the current media position.Realizing and Prefetching a Player
JMF breaks the process of preparing a
Playerto start into two phases, Realizing and Prefetching. Realizing and Prefetching aPlayerbefore you start it minimizes the time it takes thePlayerto begin presenting media whenstartis called and helps create a highly-responsive interactive experience for the user. Implementing theControllerListenerinterface allows you to control when these operations occur.Note:
Processorintroduces a third phase to the preparation process called Configuring. During this phase,Processoroptions can be selected to control how theProcessormanipulates the media data. For more information, see Selecting Track Processing Options.You call
realizeto move thePlayerinto the Realizing state and begin the realization process. You callprefetchto move thePlayerinto the Prefetching state and initiate the prefetching process. Therealizeandprefetchmethods are asynchronous and return immediately. When thePlayercompletes the requested operation, it posts aRealizeCompleteEventorPrefetchCompleteEvent. Player States describes the operations that aPlayerperforms in each of these states.A
Playerin the Prefetched state is prepared to start and its start-up latency cannot be further reduced. However, setting the media time throughsetMediaTimemight return thePlayerto the Realized state and increase its start-up latency.Keep in mind that a Prefetched
Playerties up system resources. Because some resources, such as sound cards, might only be usable by one program at a time, having aPlayerin the Prefetched state might prevent otherPlayersfrom starting.Determining the Start Latency
To determine how much time is required to start a
Player, you can callgetStartLatency. ForPlayersthat have a variable start latency, the return value ofgetStartLatencyrepresents the maximum possible start latency. For some media types,getStartLatencymight returnLATENCY_UNKNOWN.The start-up latency reported by
getStartLatencymight differ depending on thePlayerobject'scurrent state. For example, after aprefetchoperation, the value returned bygetStartLatencyis typically smaller. AControllerthat can be added to aPlayerwill return a useful value once it is Prefetched. (For more information, see Using a Player to Synchronize Controllers.)Starting and Stopping the Presentation
The
ClockandPlayerinterfaces define the methods for starting and stopping presentation.Starting the Presentation
You typically start the presentation of media data by calling
start. Thestartmethod tells thePlayerto begin presenting media data as soon as possible. If necessary,startprepares thePlayerto start by performing the realize and prefetch operations. Ifstartis called on a StartedPlayer, the only effect is that aStartEventis posted in acknowledgment of the method call.Clock defines a
syncStartmethod that can be used for synchronization. See Synchronizing Multiple Media Streams for more information.To start a
Playerat a specific point in a media stream:
- Specify the point in the media stream at which you want to start by calling
setMediaTime.- Call
starton thePlayer.Stopping the Presentation
There are four situations in which the presentation will stop:
- When the
stopmethod is called- When the specified stop time is reached
- When there's no more media data to present
- When the media data is being received too slowly for acceptable playback
When a
Playeris stopped, its media time is frozen if the source of the media can be controlled. If thePlayeris presenting streamed media, it might not be possible to freeze the media time. In this case, only the receipt of the media data is stopped--the data continues to be streamed and the media time continues to advance.When a Stopped
Playeris restarted, if the media time was frozen, presentation resumes from the stop time. If media time could not be frozen when thePlayerwas stopped, reception of the stream resumes and playback begins with the newly-received data.To stop a
Playerimmediately, you call thestopmethod. If you callstopon a StoppedPlayer, the only effect is that aStopByRequestEventis posted in acknowledgment of the method call.Stopping the Presentation at a Specified Time
You can call
setStopTimeto indicate when aPlayershould stop. ThePlayerstops when its media time passes the specified stop time. If thePlayerobject'srate is positive, thePlayerstops when the media time becomes greater than or equal to the stop time. If thePlayerobject's rate is negative, thePlayerstops when the media time becomes less than or equal to the stop time. ThePlayerstops immediately if its current media time is already beyond the specified stop time.For example, assume that a
Playerobject's media time is 5.0 andsetStopTimeis called to set the stop time to 6.0. If thePlayerobject's rate is positive, media time is increasing and thePlayerwill stop when the media time becomes greater than or equal to 6.0. However, if thePlayerobject's rate is negative, it is playing in reverse and thePlayerwill stop immediately because the media time is already beyond the stop time. (For more information aboutPlayerrates, see Setting the Playback Rate.)You can always call
setStopTimeon a StoppedPlayer. However, you can only set the stop time on a StartedPlayerif the stop time is not currently set. If the StartedPlayeralready has a stop time,setStopTimethrows an error.You can call
getStopTimeto get the currently scheduled stop time. If the clock has no scheduled stop time,getStopTimereturnsClock.RESET. To remove the stop time so that thePlayercontinues until it reaches end-of-media, callsetStopTime(Clock.RESET).Releasing Player Resources
The
deallocatemethod tells aPlayerto release any exclusive resources and minimize its use of non-exclusive resources. Although buffering and memory management requirements forPlayersare not specified, mostPlayersallocate buffers that are large by the standards of Java objects. A well-implementedPlayerreleases as much internal memory as possible whendeallocateis called.The
deallocatemethod can only be called on a StoppedPlayer. To avoidClockStartedErrors, you should callstopbefore you calldeallocate. Callingdeallocateon aPlayerin the Prefetching or Prefetched state returns it to the Realized state. Ifdeallocateis called while thePlayeris realizing, thePlayerposts aDeallocateEventand returns to the Unrealized state. (Once aPlayerhas been realized, it can never return to the Unrealized state.)You generally call
deallocatewhen thePlayeris not being used. For example, an applet should calldeallocateas part of itsstopmethod. By callingdeallocate, the program can maintain references to thePlayer, while freeing other resources for use by the system as a whole. (JMF does not prevent a RealizedPlayerthat has formerly been Prefetched or Started from maintaining information that would allow it to be started up more quickly in the future.)When you are finished with a
Player(or any otherController) and are not going to use it anymore, you should callclose. Theclosemethod indicates that theControllerwill no longer be used and can shut itself down. Callingclosereleases all of the resources that theControllerwas using and causes it to cease all activity. When aControlleris closed, it posts aControllerClosedEvent. A closedControllercannot be reopened and invoking methods on a closedControllermight generate errors.Querying a Player
A
Playercan provide information about its current parameters, including its rate, media time, and duration.Getting the Playback Rate
To get a
Playerobject's current rate, you callgetRate. CallinggetRatereturns the playback rate as a float value.Getting the Media Time
To get a
Playerobject's current media time, you callgetMediaTime. CallinggetMediaTimereturns the current media time as aTimeobject. If thePlayeris not presenting media data, this is the point from which media presentation will commence.Note that there is not a one-to-one correspondence between media times and frames. Each frame is presented for a certain period of time, and the media time continues to advance during that period.
For example, imagine you have a slide show
Playerthat displays each slide for 5 seconds--thePlayeressentially has a frame rate of 0.2 frames per second.![]()
Figure 3-1: Frame duration and media time.
If you start the
Playerat time 0.0, while the first frame is displayed, the media time advances from 0.0 to 5.0. If you start at time 2.0, the first frame is displayed for 3 seconds, until time 5.0 is reached.Getting the Time-Base Time
You can get a
Playerobject's current time-base time by getting thePlayerobject'sTimeBaseand callinggetTime:myCurrentTBTime = player1.getTimeBase().getTime();When a
Playeris running, you can get the time-base time that corresponds to a particular media time by callingmapToTimeBase.Getting the Duration of the Media Stream
Since programs often need to know how long a particular media stream will run, all
Controllersimplement theDurationinterface. This interface defines a single method,getDuration. The duration represents the length of time that a media object would run, if played at the default rate of 1.0. A media stream's duration is only accessible through aPlayer.If the duration can't be determined when
getDurationis called,DURATION_UNKNOWNis returned. This can happen if thePlayerhas not yet reached a state where the duration of the media source is available. At a later time, the duration might be available and a call togetDurationwould return the duration value. If the media source does not have a defined duration, as in the case of a live broadcast,getDurationreturnsDURATION_UNBOUNDED.Responding to Media Events
ControllerListeneris an asynchronous interface for handling events generated byControllerobjects. Using theControllerListenerinterface enables you to manage the timing of potentially time-consumingPlayeroperations such as prefetching.Implementing the ControllerListener Interface
To implement the
ControllerListenerinterface, you need to:
- Implement the
ControllerListenerinterface in a class.- Register that class as a listener by calling
addControllerListeneron theControllerthat you want to receive events from.When a
Controllerposts an event, it callscontrollerUpdateon each registered listener.Typically,
controllerUpdateis implemented as a series of if-else statements.
Example 3-3: Implementing controllerUpdate. if (event instanceof EventType){ ... } else if (event instanceof OtherEventType){ ... }
This filters out the events that you are not interested in. If you have registered as a listener with multiple
Controllers, you also need to determine whichControllerposted the event.ControllerEventscome "stamped" with a reference to their source that you can access by callinggetSource.When you receive events from a
Controller, you might need to do some additional processing to ensure that theControlleris in the proper state before calling a control method. For example, before calling any of the methods that are restricted to StoppedPlayers, you should check thePlayerobject's target state by callinggetTargetState. Ifstarthas been called, thePlayeris considered to be in the Started state, though it might be posting transition events as it prepares thePlayerto present media.Some types of
ControllerEventscontain additional state information. For example, theStartEventandStopEventclasses each define a method that allows you to retrieve the media time at which the event occurred.Using ControllerAdapter
ControllerAdapteris a convenience class that implementsControllerListenerand can be easily extended to respond to particularEvents. To implement theControllerListenerinterface usingControllerAdapter, you need to:
- Subclass
ControllerAdapterand override the event methods for the events that you're interested in.- Register your
ControllerAdapterclass as a listener for a particularControllerby callingaddControllerListener.When a
Controllerposts an event, it callscontrollerUpdateon each registered listener.ControllerAdapterautomatically dispatches the event to the appropriate event method, filtering out the events that you're not interested in.For example, the following code extends a
ControllerAdapterwith a JDK 1.1 anonymous inner-class to create a self-containedPlayerthat is automatically reset to the beginning of the media and deallocated when thePlayerreaches the end of the media.
If you register a single
ControllerAdapteras a listener for multiplePlayers, in your event method implementations you need to determine whichPlayergenerated the event. You can callgetSourceto determine where aControllerEventoriginated.Synchronizing Multiple Media Streams
To synchronize the playback of multiple media streams, you can synchronize the
Playersby associating them with the sameTimeBase. To do this, you use thegetTimeBaseandsetTimeBasemethods defined by theClockinterface. For example, you could synchronizeplayer1withplayer2by settingplayer1to useplayer2'stime base:player1.setTimeBase(player2.getTimeBase());When you synchronize
Playersby associating them with the sameTimeBase, you must still manage the control of eachPlayerindividually. Because managing synchronizedPlayersin this way can be complicated, JMF provides a mechanism that allows aPlayerto assume control over any otherController. ThePlayermanages the states of theseControllersautomatically, allowing you to interact with the entire group through a single point of control. For more information, see See "Using a Player to Synchronize Controllers".Using a Player to Synchronize Controllers
Synchronizing
Playersdirectly usingsyncStartrequires that you carefully manage the states of all of the synchronizedPlayers. You must control each one individually, listening for events and calling control methods on them as appropriate. Even with only a fewPlayers, this quickly becomes a difficult task. Through thePlayerinterface, JMF provides a simpler solution: aPlayercan be used to manage the operation of anyController.When you interact with a managing
Player, your instructions are automatically passed along to the managedControllersas appropriate. The managingPlayertakes care of the state management and synchronization for all of the otherControllers.This mechanism is implemented through the
addControllerandremoveControllermethods. When you calladdControlleron aPlayer, theControlleryou specify is added to the list ofControllersmanaged by thePlayer. Conversely, when you callremoveController, the specifiedControlleris removed from the list of managedControllers.Typically, when you need to synchronize
Playersor otherControllers, you should use thisaddControllermechanism. It is simpler, faster, and less error-prone than attempting to manage synchronizedPlayersindividually.When a
Playerassumes control of aController:
- The
Controllerassumes thePlayerobject's time base.- The
Playerobject'sduration becomes the longer of theControllerobject's duration and its own. If multipleControllersare placed under aPlayerobject's control, thePlayerobject's duration is set to longest duration.- The
Playerobject's start latency becomes the longer of theControllerobject's start latency and its own. If multipleControllersare placed under aPlayerobject's control, thePlayerobject's start latency is set to the longest latency.A managing
Playeronly posts completion events for asynchronous methods after each of its managedControllershave posted the event. The managingPlayerreposts other events generated by theControllersas appropriate.Adding a Controller
You use the
addControllermethod to add aControllerto the list ofControllersmanaged by a particularPlayer. To be added, aControllermust be in the Realized state; otherwise, aNotRealizedErroris thrown. TwoPlayerscannot be placed under control of each other. For example, ifplayer1is placed under the control ofplayer2,player2cannot be placed under the control ofplayer1without first removingplayer1fromplayer2'scontrol.Once a
Controllerhas been added to aPlayer, do not call methods directly on the managedController. To control a managedController, you interact with the managingPlayer.To have
player2assume control ofplayer1, call:player2.addController(player1);Controlling Managed Controllers
To control the operation of a group of
Controllersmanaged by a particularPlayer, you interact directly with the managingPlayer.For example, to prepare all of the managed
Controllersto start, callprefetchon the managingPlayer. Similarly, when you want to start them, callstarton the managingPlayer. The managingPlayermakes sure that all of theControllersare Prefetched, determines the maximum start latency among theControllers, and callssyncStartto start them, specifying a time that takes the maximum start latency into account.When you call a
Controllermethod on the managingPlayer, thePlayerpropagates the method call to the managedControllersas appropriate. Before calling aControllermethod on a managedController, thePlayerensures that theControlleris in the proper state. The following table describes what happens to the managedControllerswhen you call control methods on the managingPlayer.
Table 3-1: Calling control methods on a managing player.
Removing a Controller
You use the
removeControllermethod to remove aControllerfrom the list of controllers managed by a particularPlayer.To have
player2release control ofplayer1, call:player2.removeController(player1);Synchronizing Players Directly
In a few situations, you might want to manage the synchronization of multiple
Playerobjects yourself so that you can control the rates or media times independently. If you do this, you must:
- Register as a listener for each synchronized
Player.- Determine which
Playerobject's time base is going to be used to drive the otherPlayerobjects and set the time base for the synchronizedPlayerobjects. Not allPlayer objectscan assume a new time base. For example, if one of thePlayerobjects you want to synchronize has a push data-source, thatPlayerobject'stime base must be used to drive the otherPlayer objects.- Set the rate for all of the
Players. If aPlayercannot support the rate you specify, it returns the rate that was used. (There is no mechanism for querying the rates that aPlayersupports.)- Synchronize the states of all of the
Playerobjects. (For example, stop all of the players.)- Synchronize the operation of the
Playerobjects:You must listen for transition events for all of the
Player objectsand keep track of which ones have posted events. For example, when you prefetch thePlayerobjects, you need to keep track of which ones have postedPrefetchCompleteevents so that you can be sure all of them are Prefetched before callingsyncStart. Similarly, when you request that the synchronizedPlayerobjects stop at a particular time, you need to listen for the stop event posted by eachPlayerto determine when all of them have actually stopped.In some situations, you need to be careful about responding to events posted by the synchronized
Playerobjects. To be sure of the state of all of thePlayerobjects, you might need to wait at certain stages for all of them to reach the same state before continuing.For example, assume that you are using one
Playerto drive a group of synchronizedPlayerobjects. A user interacting with thatPlayersets the media time to 10, starts thePlayer, and then changes the media time to 20. You then:
- Pass along the first
setMediaTimecall to all of the synchronizedPlayerobjects.- Call
prefetchon eachPlayerto prepare them to start.- Call
stopon eachPlayerwhen the second set media time request is received.- Call
setMediaTimeon eachPlayerwith the new time.- Restart the prefetching operation.
- When all of the
Playerobjects have been prefetched, start them by callingsyncStart, taking into account their start latencies.In this case, just listening for
PrefetchCompleteevents from all of thePlayerobjects before callingsyncStartisn't sufficient. You can't tell whether those events were posted in response to the first or second prefetch operation. To avoid this problem, you can block when you callstopand wait for all of thePlayerobjects to post stop events before continuing. This guarantees that the nextPrefetchCompleteevents you receive are the ones that you are really interested in.Example: Playing an MPEG Movie in an Applet
The sample program
PlayerAppletdemonstrates how to create aPlayerand present an MPEG movie from within a Java applet. This is a general example that could easily be adapted to present other types of media streams.The
Playerobject's visual presentation and its controls are displayed within the applet's presentation space in the browser window. If you create aPlayerin a Java application, you are responsible for creating the window to display thePlayerobject's components.Note: While
PlayerAppletillustrates the basic usage of aPlayer, it does not perform the error handling necessary in a real applet or application. For a more complete sample suitable for use as a template, see JMF Applet.Overview of PlayerApplet
The
APPLETtag is used to invokePlayerAppletin anHTMLfile. TheWIDTHandHEIGHTfields of the HTMLAPPLETtag determine the dimensions of the applet's presentation space in the browser window. ThePARAMtag identifies the media file to be played.
Example 3-5: Invoking PlayerApplet. <APPLET CODE=ExampleMedia.PlayerApplet WIDTH=320 HEIGHT=300> <PARAM NAME=FILE VALUE="sample2.mpg"> </APPLET>
When a user opens a web page containing
PlayerApplet, the applet loads automatically and runs in the specified presentation space, which contains thePlayerobject's visual component and default controls. ThePlayerstarts and plays the MPEG movie once. The user can use the defaultPlayercontrols to stop, restart, or replay the movie. If the page containing the applet is closed while thePlayeris playing the movie, thePlayerautomatically stops and frees the resources it was using.To accomplish this,
PlayerAppletextendsAppletand implements theControllerListenerinterface.PlayerAppletdefines five methods:
init--creates aPlayerfor the file that was passed in through thePARAMtag and registersPlayerAppletas a controller listener so that it can observe media events posted by thePlayer. (This causes thePlayerAppletcontrollerUpdatemethod to be called whenever thePlayerposts an event.)start--starts thePlayerwhenPlayerAppletis started.stop--stops and deallocates thePlayerwhenPlayerAppletis stopped.destroy--closes thePlayerwhenPlayerAppletis removed.controllerUpdate--responds toPlayerevents to display thePlayerobject's components.
Initializing the Applet
When a Java applet starts, its
initmethod is invoked automatically. You overrideinitto prepare your applet to be started.PlayerAppletperforms four tasks ininit:
- Retrieves the applet's FILE parameter.
- Uses the FILE parameter to locate the media file and build a
URLobject that describes that media file.- Creates a
Playerfor the media file by callingManager.createPlayer.- Registers the applet as a controller listener with the new
Playerby callingaddControllerListener. Registering as a listener causes thePlayerAppletcontrollerUpdatemethod to be called automatically whenever thePlayerposts a media event. ThePlayerposts media events whenever its state changes. This mechanism allows you to control thePlayerobject's transitions between states and ensure that thePlayeris in a state in which it can process your requests. (For more information, see Player States.)
Controlling the Player
The
Appletclass definesstartandstopmethods that are called automatically when the page containing the applet is opened and closed. You override these methods to define what happens each time your applet starts and stops.
PlayerAppletimplementsstartto start thePlayerwhenever the applet is started.
Example 3-8: Starting the Player in PlayerApplet. public void start() { player.start(); }
Similarly,
PlayerAppletoverridesstopto stop and deallocate thePlayer:
Example 3-9: Stopping the Player in PlayerApplet. public void stop() { player.stop(); player.deallocate(); }
Deallocating the
Playerreleases any resources that would prevent anotherPlayerfrom being started. For example, if thePlayeruses a hardware device to present its media,deallocatefrees that device so that otherPlayerscan use it.When an applet exits,
destroyis called to dispose of any resources created by the applet.PlayerAppletoverridesdestroyto close thePlayer. Closing aPlayerreleases all of the resources that it's using and shuts it down permanently.
Example 3-10: Destroying the Player in PlayerApplet. public void destroy() { player.close(); }
Responding to Media Events
PlayerAppletregisters itself as aControllerListenerin itsinitmethod so that it receives media events from thePlayer. To respond to these events,PlayerAppletimplements thecontrollerUpdatemethod, which is called automatically when thePlayerposts an event.
PlayerAppletresponds to one type of event,RealizeCompleteEvent. When thePlayerposts aRealizeCompleteEvent,PlayerAppletdisplays thePlayerobject's components.
A
Playerobject's user-interface components cannot be displayed until thePlayeris Realized; an UnrealizedPlayerdoesn't know enough about its media stream to provide access to its user-interface components.PlayerAppletwaits for thePlayerto post aRealizeCompleteEventand then displays thePlayerobject's visual component and default control panel by adding them to the applet container. Callingvalidatetriggers the layout manager to update the display to include the new components.Presenting Media with the MediaPlayer Bean
Using the
MediaPlayerJava Bean (javax.media.bean.playerbean.MediaPlayer) is the simplest way to present media streams in your applets and applications.MediaPlayerencapsulates a full-featured JMFPlayerin a Java Bean. You can either use theMediaPlayerbean's default controls or customize its controlComponents.One key advantage to using the
MediaPlayerbean is that it automatically constructs a newPlayerwhen a different media stream is selected for playback. This makes it easy to play a series of media clips or enable the user to select the media clip that they want to play.A
MediaPlayerbean has several properties that you can set, including the media source:
Table 3-2: Media bean properties.
To play a media clip with the
MediaPlayerbean:
MediaPlayer mp1 = new javax.media.bean.playerbean.MediaPlayer();mp1.setMediaLocation(new java.lang.String("file:///E:/jvideo/media/ Sample1.mov"));mp1.start();You can stop playback by calling
stopon theMediaPlayer:mp1.stop();By setting up the
MediaPlayerin your Applet'sinitmethod and starting theMediaPlayerin your Applet'sstartmethod, you can automatically begin media presentation when the Applet is loaded. You should callstopin the Applet'sstopmethod so that playback halts when the Applet is stopped.Alternatively, you can display the
MediaPlayerbean's default control panel or provide custom controls to allow the user to control the media presentation. If you provide custom controls, call the appropriateMediaPlayercontrol and properties methods when the user interacts with the controls. For example, if you provide a custom Start button in your Applet, listen for the mouse events and callstartwhen the user clicks on the button.Presenting RTP Media Streams
You can present streaming media with a JMF
Playerconstructed through theManagerusing aMediaLocatorthat has the parameters of an RTP session. For more information about streaming media and RTP, see Working with Real-Time Media Streams.When you use a
MediaLocatorto construct aPlayerfor an RTP session, only the first RTP stream that's detected in the session can be presented--Managercreates aPlayerfor the first stream that's detected in the RTP session. For information about playing multiple RTP streams from the same session, see Receiving and Presenting RTP Media Streams.Note: JMF-compliant implementations are not required to support the RTP APIs in
javax.media.rtp,javax.media.rtp.event, and javax.media.rtp.rtcp. The reference implementations of JMF provided by Sun Microsystems, Inc. and IBM Corporation fully support these APIs.
When data is detected on the session, the
Playerposts aRealizeCompleteEvent. By listening for this event, you can determine whether or not any data has arrived and if thePlayeris capable of presenting any data. Once thePlayerposts this event, you can retrieve its visual and control components.Listening for RTP Format Changes
When a
Playerposts aFormatChangeEvent, it can indicate that a payload change has occurred.Playerobjects constructed with aMediaLocatorautomatically process payload changes. In most cases, this processing involves constructing a newPlayerto handle the new format. Programs that present RTP media streams need to listen forFormatChangeEventsso that they can respond if a newPlayeris created.When a
FormatChangeEventis posted, check whether or not thePlayerobject's control and visual components have changed. If they have, a newPlayerhas been constructed and you need to remove references to the oldPlayerobject's components and get the newPlayerobject's components.