It's All About Control

The various objects provided by the JMF such as Players, Processors, DataSources, DataSinks, and plug-ins have complex and configurable behavior. For instance, it is desirable to allow the frame that a Player starts playing from to be set, or the bit rate for a codec to be specified. The JMF provides a uniform model for controlling the behavior of objects through the Control interface.

Many JMF objects expose Control objects through accessor (get) methods. These can be obtained and used to alter the behavior of the associated objects. Indeed, there is an interface known as Controls that many objects implement as a uniform means of providing Control objects that specify their behavior.

Hence the standard approach in tailoring a Processor, Player, DataSource, or DataSink to match a particular need is as follows:

1.
Create the Player, Processor, DataSource, or DataSink.

2.
Obtain the Control object appropriate to the behavior to be configured.

3.
Use methods on Control object to configure the behavior.

4.
Use the original Player, Processor, DataSource, or DataSink.

Because of some unfortunate naming choice for classes and interfaces in the JMF, the following classes bear similar names: Control, Controls (x2), and Controller, as well as a package known as control. It is worth taking this opportunity to delineate the differences among these confusingly named classes:

Control— An interface describing an object that can be used to control the behavior of a JMF object such as a Player or Processor. The Control interface is discussed in this section. It is extended to a number of specialized Control Interfaces, such as FramePositioningControl.

Controller— An interface upon which Player and Processor are built and which is intimately associated with the timing model of the JMF. The Controller interface was discussed in an earlier section of this chapter.

Controls (javax.media.Controls and javax.media.protocol.Controls)— An interface implemented by objects that provide a uniform mechanism for obtaining their Control objects(s).

javax.media.control— A package within the JMF API that contains 18 interfaces that extend the basic Control interface. Examples include FramePositioningControl, TrackControl, and FormatControl.

The Control interface itself is particularly simple, possessing a single method only, with the real control functionality being specified in the various 18 Control interfaces that extend Control in the JMF API. Each of those interfaces has a specific functionality as detailed by its name and methods. Instances of these interfaces are the means of configuring the behavior of the object from which they were obtained. The following list quickly summarizes each of them:

BitRateControl— A control for specifying and querying the bit rate settings, such as the encoding bit rate for a compressor (codec).

BufferControl— A control for querying and specifying buffer thresholds and sizes.

FormatControl— A control for querying the format support as well as setting the format for the associated object.

FrameGrabbingControl— A control for enabling the grabbing of still video frames from a video stream.

FramePositioningControl— A control to allow the precise positioning of a video stream as either a frame number of time (from start).

FrameProcessingControl— A control to specify the parameters employed in frame processing.

FrameRateControl— A means of querying as well as setting the frame rate.

H261Control— A control for specifying the parameters of the H.261 video codec.

H263Control— A control for specifying the parameters of the H.263 video codec.

KeyFrameControl— A control for specifying or querying the KeyFrame interval: the interval between transmission of complete (keyframes) rather than delta frames in codecs (such as mpeg) that use temporal based compression.

MonitorControl— A control for specifying the degree of monitoring (viewing or listening to) of media as it is captured.

MpegAudioControl— A control for specifying the parameters of MPEG Audio encoding.

PacketSizeControl— A control for specifying the packet size parameters.

PortControl— A control to access the input and output ports of a device (such as a capture device).

QualityControl— A control for specifying the parameters of quality (higher quality generally comes at the expense of higher processing demands).

SilenceSuppressionControl— A control for specifying the parameters of silence suppression. Silence suppression is an audio compression scheme whereby silent passages aren't transmitted.

StreamWriterControl— A control by which the maximum size for an output stream (for example, DataSink or Multiplexer) can be set as well as the size queried.

TrackControl— A control to query, manipulate, and control the data of individual media tracks in a Processor.

Each of these Control interfaces can be found in the javax.media.control package, which necessitates the import of that package if they are to be employed.

As mentioned previously, each interface possesses methods specific to its functionality. Some are simple such as FrameGrabbingControl with its single method grabFrame() that returns a Buffer object; others such as MpegAudioControl have more than a dozen methods plus associated constants. However, most interfaces are small, with 3–5 methods, and quite easy to understand.

Visual Control for the User

Time-based media, as defined in the Chapter 7, is intended for presentation to a human being. It is natural, then, to provide the viewer or listener with maximum control over that experience. To that end, many Control objects have an associated visual Component. That Component can be obtained and added to the graphical user interface provided for the user. Actions upon the Component result in method calls on the associated Control object that hence alter the behavior of the associated Player, Processor, DataSource, or DataSink.

The Control interface that is the superclass of the previous 18 possesses a single method, getControlComponent(), that returns an AWT Component—a graphical component that can be added to a graphical user interface and through which the user can directly and intuitively set the control parameters.

However, not all Controls have an associated graphical Component. Those that don't have a Component return null to the getControlComponent() method call. Thus code using the method should check to ensure that a non-null reference was returned before attempting to add the Component to an AWT Container (for example, Applet, Frame, or Panel). Adding a null Component to a Container will result in an exception being thrown.

Getting Control Objects

There are two methods by which Control objects can be obtained. These methods, getControl(), and getControls() are defined in the Controls interface. The Controls interface is extended by many important interfaces including DataSink, Codec, Renderer, and the various pull and push data and buffer streams. Other important classes such as Controller (that is, the superclass of Player and Processor) also provide the two methods.

The getControl() method is used to obtain a single Control object. The method is passed the complete name of the Control class as a String and returns an object implementing that interface. The fully qualified name of the class must be passed, thus listing the package "path" to the class. Then the method returns an object of class Control, necessitating it to be cast to the type of Control before its methods can be employed. For example,

BitRateControl bitControl = (BitRateControl)
processor.getControl("javax.media.control.BitRateControl");

The second means of obtaining Control objects is through the getControls() method. The method accepts no arguments and returns (supposedly) all the Control objects, as an array, associated with the object on which getControls() was called. Look at the following example:

Control[] allControls = player.getControls();

As an example of the Control objects associated with a Player, Listing 8.6 shows the Control objects obtained from the Player used in the BBPApplet example of Chapter 7. The getControls() method of the Player object (actually inherited from Controller) was called once the Player was realized and the objects returned were printed.

Listing 8.6 The 11 Control Objects Obtained on a Particular Player Object when getControls() Was Called
11 controls for a Player @ REALIZED:
1: com.ibm.media.codec.video.mpeg.MpegVideo
2: com.sun.media.codec.video.colorspace.YUVToRGB
3: com.sun.media.renderer.video.DDRenderer
4: com.sun.media.renderer.audio.DirectAudioRenderer$MCA
5: com.sun.media.renderer.audio.AudioRenderer$BC
6: com.sun.media.PlaybackEngine$BitRateA
7: com.sun.media.PlaybackEngine$1
8: com.sun.media.controls.FramePositioningAdapter
9: com.sun.media.BasicJMD
10: com.sun.media.PlaybackEngine$PlayerTControl
11: com.sun.media.PlaybackEngine$PlayerTControl

It is worth noting several points in connection with Listing 8.6. First, the 11 controls case corresponds to the Manager being instructed to create Players that support plug-ins for demultiplexing, codecs, and so on. In the case where the created Player wasn't plug-in enabled, only three Controls were obtained. Enabling plug-in based Players was achieved as follows:

Manager.setHint(Manager.PLUGIN_PLAYER,new Boolean(true));

Second, all the Controls returned by the previous call are from the Sun and IBM packages (com.sun.media and com.ibm.media) and hence aren't documented in the API. Further, only the BasicJMD Control had a visual component, that being the PlugIn Viewer. That combination of undocumented classes plus lack of visual components makes the getControls() approach of exerting control not particularly helpful and next to useless, at least in this case.

However, it appears that controller's getControls() method doesn't actually return all possible Control objects for a Player. As noted previously, rather than asking for all Control objects, it is possible to ask for them by name. When that was done, it was possible to obtain a number of Control objects including FrameRateControl and FrameGrabbingControl among others as follows:

FrameGrabbingControl frameControl = (FrameGrabbingControl)
player.getControl("javax.media.control.FrameGrabbingControl");

As in the previous case, these Controls were only available when the Manager's PLUGIN_PLAYER hint had been set to true.

Thus, the surest and safest means of obtaining the appropriate Control objects and using them is with the following algorithm:

If using a Player
       Set Manager's PLUGIN_PLAYER hint to true prior to creating the Player
For each Controller needed
        Get it by name (full class name to getControl() method).
        If object returned not null
               "Use it"
               If want to provide direct user control
                       Call getControlComponent() on Controller object
                       If object returned is not null
                              Add that to GUI
                       else
                              Implement own GUI interface

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset