Processors
Can also be used to present media data
Specialized type of Player that provides control
over processing performed on the input media
stream
Processing
Processor Stages
Additional Processor States
Two additional stand-by states:
Configuring
Configured – can use TrackControls
Processing Controls
For a given track, can control processing
operations performed by the Processor by using
the TrackControl for that track.
TrackControl[] = processor.getTrackControls()
Can explicitly select:
Effect, Codec and Renderer plug-ins to use
TrackControl[1].setCodecChain( array_of_codecs )
Configuring the Processor
Consider using a processor to transcode an
(audio+video) QuickTime movie – changing
mpeg video track to h.263…
p = Manager.createProcessor(dataSource)
p.configure()
p.setContentDescriptor.QUICKTIME
tcs[] = p.getTrackControls()
Returns an array, e.g. 2 track controls…
Configuring the Processor
Format f0 = new VideoFormat(VideoFormat.h263,
new Dimension(width, height),
Format.NOT_SPECIFIED,
Format.byteArray,
(float)frameRate);
l Format f1 = new AudioFormat(AudioFormat.mpeg,
8000
8,
2);
tcs[0].setFormat(f0)
tcs[1].setFormat(f1)
p.realize()
p.start()
Processor Summary
A Processor does not have to output data as a
DataSource, such a processor (i.e. one that
renders the data) is effectively a configurable
player.
Data Storage and Transmission
DataSink
Used to read data from a DataSource and render the
media to an output destination
Typical actions…
Write data to a file, across a network etc
Using the DataSink
MediaLocator dest = new
MediaLocator(file://newfile.wav);
dsink = Manager.createDataSink(ds, dest);
dsink.addDataSinkListener(this);
dsink.open();
p.start();
dsink.start();
Wait for EndOfStream event
Close DataSink and remove Listener
dsink.close()
Example
Applet Movie Player
Applet Movie Player
Simple Java Applet that demonstrates how to
create a simple media player with a media event
listener. It will play the media clip right away and
continuously loop.
-->
Basic Steps
Initialisation…
Retrieve applet’s FILE parameter
Use this to locate media file and build URL
Create Player using the Manager object
Register applet as a ControllerListener
Steps 1 & 2: Resolving a URL
for the media stream
// The applet tag should contain the path to the
// source media file, relative to the html page.
if ((mediaFile = getParameter("FILE")) == null)
Fatal("Invalid media file parameter");
try {
// Create a url from the file name and the url
// to the document containing this applet.
if ((url = new URL(codeBase, mediaFile)) == null)
Fatal("Can't build URL for " + mediaFile);
Step 3: Using Manager to
Create a Player
// Create an instance of a player for this media
try {
player = Manager.createPlayer(url);
}
catch (NoPlayerException e) {
System.out.println(e);
Fatal("Could not create player for " + url);
}
Step 4: Register applet as a
ControllerListener
// Add ourselves as listener for player's events
player.addControllerListener(this);
} catch (MalformedURLException e) {
Fatal("Invalid media file URL!");
} catch (IOException e) {
Fatal("IO exception creating player for " +
url);
Controlling the Player…
Starting the Player
public void start() {
if (player != null)
player.realize();
Stopping the Player
public void stop() {
if (player != null) {
player.stop();
player.deallocate();
}
}
Responding to media events
Need to Implement ControllerListener
When the Player is realized
Posts a RealizeCompleteEvent
Get the Visual component
if (( visualComponent =
player.getVisualComponent())!= null) {
cPanel.add(visualComponent);
Get the Control Panel component
When the media has reached the end…
Posts an EndOfMediaEvent
Rewind and start over
player.setMediaTime(new Time(0));
Extensibility
Can extend JMF functionality in two ways:
Using Plug-ins
Effectively implementing custom processing components that can
be interchanged with standard components used by a Processor
By direct implementation
i.e implementing directly the Controller, Player , Processor,
DataSource, or DataSink interfaces
e.g. implementing a player to utilise a h/w MPEG decoder
e.g. integrating existing media engines
Interface Plugin
The base interface for JMF plug-ins.
A PlugIn is a media processing unit that accepts
data in a particular format and processes or
presents the data.
Registered through the PlugInManager.
Methods…
Open(), Close(), getName(), reset()
Sub-interfaces…
Codec, effect, demultiplexer , multiplexer, etc.
Codecs
One input and one output
Methods…
setInputFormat()
setOutputFormat()
getSupportedInputFormats()
getSupportedOutputFormats()
process()
input buffer, output buffer
Example 2
Accessing individual frames
FrameAccess
Problem
How to access individual decoded video frames
from a Processor while processing the media.
This could be used for scanning the decoded data;
computing statistics for each video frame, etc.
FrameAccess
Solution…
use a ‘pass-through’ plugin codec as a callback when
individual frames are being processed.
Steps:
1) Build the pass-through codec.
2) Create a processor from the input file. This processor
will be used as a player to playback the media.
3) Get the TrackControls from the processor.
4) Set your codec on the video track:
TrackControl.setCodecChain(your_codec[])
Basic code
// Get Video track as a track control
TrackControlvideoTrack = null;
for (int i = 0; i < tc.length; i++) {
if (tc[i].getFormat() instanceof VideoFormat) {
videoTrack = tc[i]; break;
}
}
// Instantiate & set frame access codec to data flow path.
Codec codec[] = { new PreAccessCodec(),
new PostAccessCodec() };
PreAccessCodec
public class PreAccessCodec implements Codec {
void accessFrame(Buffer frame) {
long t = (long)(frame.getTimeStamp()/10000000f);
System.err.println("Pre: frame #: " +
frame.getSequenceNumber () +
", time: " + ((float)t)/100f +
", len: " + frame.getLength());
}
…………………
Other methods, e.g. getSupportedInputFormats etc.
The Codec’s Process method
public int process(Buffer in, Buffer out) {
// This is the "Callback" to access individual frames.
accessFrame(in);
// Swap the data between the input & output.
Object data = in.getData ();
in.setData(out.getData ());
out.setData(data );
// Copy the input attributes to the output
out.setFormat(in.getFormat());
out.setLength(in.getLength());
out.setOffset(in.getOffset());