Methods Summary |
---|
protected synchronized void | abortConfigure()Called when doConfigure() is aborted.
// The parser could be in the middle of realizing. We'll need to
// abort it.
if (source != null)
source.abortRealize();
|
protected synchronized void | abortPrefetch()Called when the prefetch() is aborted, i.e. deallocate() was called
while prefetching. Release all resources claimed previously by the
prefetch call.
Override this to implement subclass behavior.
// Mark the time before the prefetch. At the next prefetch,
// we'll sync up the media with this time.
timeBeforeAbortPrefetch = getMediaTime();
doReset();
StateTransistor m;
int size = modules.size();
for (int i = 0; i < size; i++) {
m = (StateTransistor)modules.elementAt(i);
m.abortPrefetch();
}
deallocated = true;
|
protected synchronized void | abortRealize()Called when the realize() is aborted, i.e. deallocate() was called
while realizing. Release all resources claimed previously by the
realize() call.
StateTransistor m;
int size = modules.size();
for (int i = 0; i < size; i++) {
m = (StateTransistor)modules.elementAt(i);
m.abortRealize();
}
|
public boolean | audioEnabled()Return true if audio is present.
for (int i = 0; i < trackControls.length; i++) {
if (trackControls[i].isEnabled() &&
trackControls[i].getOriginalFormat() instanceof AudioFormat)
return true;
}
return false;
|
public void | bufferPrefetched(com.sun.media.Module src)
if (!prefetchEnabled)
return;
if (src instanceof BasicSinkModule) {
synchronized (waitPrefetched) {
if (waitPrefetched.contains(src))
waitPrefetched.removeElement(src);
if (waitPrefetched.isEmpty()) {
// All sinks are prefetched. Wake up the
// doPrefetch() wait.
waitPrefetched.notifyAll();
if (!prefetchLogged) {
profile("prefetch", prefetchTime);
prefetchLogged = true;
}
if (getState() != Controller.Started &&
getTargetState() != Controller.Started) {
// Non-blocking stop.
source.pause();
}
prefetched = true;
}
}
}
|
protected com.sun.media.GraphNode | buildTrackFromGraph(com.sun.media.BasicTrackControl tc, com.sun.media.GraphNode node)Construct a track (connected modules) from the specified node graph.
Return a non-null GraphNode if the track cannot be built. The
non-null node returned is the node that failed to be opened.
BasicModule src = null, dst = null;
InputConnector ic = null;
OutputConnector oc = null;
boolean lastNode = true;
Vector used = new Vector(5);
int indent = 0;
if (node.plugin == null) {
// There's nothing to build.
// i.e. the output from the source (demux) works just fine.
// Probably just need to be multiplexed.
return null;
}
Log.setIndent(indent++);
// Build the graph from the last node.
while (node != null && node.plugin != null) {
if ((src = createModule(node, used)) == null) {
// something terrible went wrong.
Log.error("Internal error: buildTrackFromGraph");
node.failed = true;
return node;
}
// Mark the renderer module or the last output connector
// from in the trackcontrol.
if (lastNode) {
if (src instanceof BasicRendererModule) {
tc.rendererModule = (BasicRendererModule)src;
// If we are dealing with an audio renderer here, we'll
// set the jitter buffer size.
if (useMoreRenderBuffer &&
tc.rendererModule.getRenderer() instanceof AudioRenderer)
setRenderBufferSize(tc.rendererModule.getRenderer());
} else if (src instanceof BasicFilterModule) {
tc.lastOC = src.getOutputConnector(null);
tc.lastOC.setFormat(node.output);
}
lastNode = false;
}
ic = src.getInputConnector(null);
ic.setFormat(node.input);
if (dst != null) {
oc = src.getOutputConnector(null);
ic = dst.getInputConnector(null);
oc.setFormat(ic.getFormat());
}
src.setController(this);
if (!src.doRealize()) {
//Log.write("Failed to open plugin: " + node.plugin);
//Log.write(" with input: " + node.input);
Log.setIndent(indent--);
node.failed = true;
return node;
}
if (oc != null && ic != null)
connectModules(oc, ic, dst);
dst = src;
node = node.prev;
}
// All successful, so we need to add each modules under the engine's
// management.
dst = src;
while (true) {
dst.setModuleListener(this);
modules.addElement(dst);
tc.modules.addElement(dst);
if (dst instanceof BasicFilterModule)
filters.addElement(dst);
else if (dst instanceof BasicSinkModule)
sinks.addElement(dst);
oc = dst.getOutputConnector(null);
if (oc == null ||
(ic = oc.getInputConnector()) == null ||
(dst = (BasicModule)ic.getModule()) == null)
break;
}
// Set the first output connector.
tc.firstOC.setFormat(tc.getOriginalFormat());
// Check if the first module has the format set.
ic = src.getInputConnector(null);
Format fmt = ic.getFormat();
if (fmt == null || !fmt.equals(tc.getOriginalFormat()))
ic.setFormat(tc.getOriginalFormat());
connectModules(tc.firstOC, ic, src);
Log.setIndent(indent--);
return null;
|
protected void | connectModules(com.sun.media.OutputConnector oc, com.sun.media.InputConnector ic, com.sun.media.BasicModule dst)Connect the two given modules.
// If the dst is the renderer, adopt the dest's protocol.
// Otherwise, adopt the source's protocol.
if (dst instanceof BasicRendererModule)
oc.setProtocol(ic.getProtocol());
else
ic.setProtocol(oc.getProtocol());
oc.connectTo(ic, ic.getFormat());
|
protected com.sun.media.BasicModule | createModule(com.sun.media.GraphNode n, java.util.Vector used)Create a realized filter module given the plugIn codec.
PlugIn p;
BasicModule m = null;
if (n.plugin == null)
return null;
if (used.contains(n.plugin)) {
// That plugin has already been used in the same path,
// we'll need to instantiate another one of its kind.
if (n.cname == null ||
(p = SimpleGraphBuilder.createPlugIn(n.cname, -1)) == null) {
Log.write("Failed to instantiate " + n.cname);
return null;
}
} else {
p = n.plugin;
used.addElement(p);
}
if ((n.type == -1 || n.type == PlugInManager.RENDERER) &&
p instanceof Renderer) {
m = new BasicRendererModule((Renderer)p);
} else if ((n.type == -1 || n.type == PlugInManager.CODEC) &&
p instanceof Codec) {
m = new BasicFilterModule((Codec)p);
}
if (DEBUG && m != null) m.setJMD(jmd);
return m;
|
public void | createProgressControl()Create the progress status control.
// Build the progress control.
StringControl frameRate;
StringControl bitRate;
StringControl videoProps;
StringControl audioProps;
StringControl videoCodec;
StringControl audioCodec;
frameRate = new StringControlAdapter();
frameRate.setValue(JMFI18N.getResource("mediaplayer.N/A"));
bitRate = new StringControlAdapter();
bitRate.setValue(JMFI18N.getResource("mediaplayer.N/A"));
videoProps = new StringControlAdapter();
videoProps.setValue(JMFI18N.getResource("mediaplayer.N/A"));
audioProps = new StringControlAdapter();
audioProps.setValue(JMFI18N.getResource("mediaplayer.N/A"));
audioCodec = new StringControlAdapter();
audioCodec.setValue(JMFI18N.getResource("mediaplayer.N/A"));
videoCodec = new StringControlAdapter();
videoCodec.setValue(JMFI18N.getResource("mediaplayer.N/A"));
progressControl = new ProgressControlAdapter( frameRate,
bitRate,
videoProps,
audioProps,
videoCodec,
audioCodec );
|
protected java.awt.Component | createVisualContainer(java.util.Vector visuals)
Boolean hint = (Boolean) Manager.getHint(Manager.LIGHTWEIGHT_RENDERER);
if (container == null) {
if (hint == null || hint.booleanValue() == false) {
container = new HeavyPanel(visuals);
} else {
container = new LightPanel(visuals);
}
container.setLayout( new FlowLayout() );
container.setBackground(Color.black);
for (int i = 0; i < visuals.size(); i++) {
Component c = (Component)visuals.elementAt(i);
container.add(c);
c.setSize(c.getPreferredSize());
}
}
return container;
|
public void | dataBlocked(com.sun.media.Module src, boolean blocked)
dataPathBlocked = blocked;
if (blocked) {
// Break the lock for the blocking prefetch & reset.
resetPrefetchedList();
resetResettedList();
}
if ( getTargetState() != Controller.Started) {
return;
}
if (blocked) {
localStop();
setTargetState(Controller.Started); // NOTE: may cause race condition
sendEvent( new RestartingEvent(this,
Controller.Started,
Controller.Prefetching,
Controller.Started,
getMediaTime()));
} else {
sendEvent( new StartEvent(this,
Controller.Prefetched,
Controller.Started,
Controller.Started,
getMediaTime(),
getTimeBase().getTime()));
}
|
protected synchronized void | doClose()Invoked by close() to cleanup the Controller.
Override this to implement subclass behavior.
if (modules == null) {
if (source != null)
source.doClose();
return;
}
if (getState() == Started)
localStop();
if (getState() == Prefetched)
doReset();
StateTransistor m;
int size = modules.size();
for (int i = 0; i < size; i++) {
m = (StateTransistor)modules.elementAt(i);
m.doClose();
}
if (needSavingDB) {
Resource.saveDB();
needSavingDB = false;
}
|
protected boolean | doConfigure()Configuring the engine.
if (!doConfigure1())
return false;
// The indices to the connector names, tracks, and track controls
// should all correspond to each other.
String names[] = source.getOutputConnectorNames();
trackControls = new BasicTrackControl[tracks.length];
for (int i = 0; i < tracks.length; i++) {
trackControls[i] = new PlayerTControl(this, tracks[i],
source.getOutputConnector(names[i]));
}
return doConfigure2();
|
protected boolean | doConfigure1()Configure - Part I.
long parsingTime = System.currentTimeMillis();
modules = new Vector();
filters = new Vector();
sinks = new Vector();
waitPrefetched = new Vector();
waitStopped = new Vector();
waitEnded = new Vector();
waitResetted = new Vector();
source.setModuleListener(this);
source.setController(this);
modules.addElement(source);
// Realize the source.
if (!source.doRealize()) {
Log.error(configError);
if (source.errMsg != null)
Log.error(" " + source.errMsg + "\n");
player.processError = parseError;
return false;
}
// Check for interrupt after a critical section.
if (isInterrupted()) {
Log.error(configError);
Log.error(configIntError);
player.processError = configInt2Error;
return false;
}
if ((parser = source.getDemultiplexer()) == null) {
Log.error(configError);
Log.error(" Cannot obtain demultiplexer for the source.\n");
player.processError = parseError;
return false;
}
// Build the track controls.
try {
tracks = parser.getTracks();
} catch (Exception e) {
Log.error(configError);
Log.error(" Cannot obtain tracks from the demultiplexer: " + e + "\n");
player.processError = parseError;
return false;
}
// Check for interrupt after a critical section.
if (isInterrupted()) {
Log.error(configError);
Log.error(configIntError);
player.processError = configInt2Error;
return false;
}
profile("parsing", parsingTime);
return true;
|
protected boolean | doConfigure2()Configure - Part II.
if (parser.isPositionable() && parser.isRandomAccess()) {
Track master = FramePositioningAdapter.getMasterTrack(tracks);
if (master != null) {
framePositioningControl = new FramePositioningAdapter(player, master);
}
}
return true;
|
protected void | doDeallocate()Called by deallocate().
Subclasses should implement this for its specific behavior.
|
protected synchronized void | doFailedPrefetch()Called when the prefetch() has failed.
StateTransistor m;
int size = modules.size();
for (int i = 0; i < size; i++) {
m = (StateTransistor)modules.elementAt(i);
m.doFailedPrefetch();
}
super.doFailedPrefetch();
|
protected synchronized void | doFailedRealize()Called when realize() has failed.
StateTransistor m;
int size = modules.size();
for (int i = 0; i < size; i++) {
m = (StateTransistor)modules.elementAt(i);
m.doFailedRealize();
}
super.doFailedRealize();
|
protected synchronized boolean | doPrefetch()The stub function to perform the steps to prefetch the controller.
if (prefetched)
return true;
return doPrefetch1() && doPrefetch2();
|
protected boolean | doPrefetch1()doPrefetch - Part I
// If the engine was deallocated before this prefetch, we'll
// need to sync up the media at the time when the prefetch
// happens.
if (timeBeforeAbortPrefetch != null) {
doSetMediaTime(timeBeforeAbortPrefetch);
timeBeforeAbortPrefetch = null;
}
prefetchTime = System.currentTimeMillis();
// Then prefetch the data path by starting the source
// module without starting the renderer modules.
resetPrefetchedList();
// First prefetch each modules.
// Fail if source cannot be prefetched.
if (!source.doPrefetch()) {
Log.error(prefetchError);
if (dsource != null)
Log.error(" Cannot prefetch the source: " + dsource.getLocator() + "\n");
return false;
}
// Prefetch each track.
boolean atLeastOneTrack = false;
boolean usedToFailed;
for (int i = 0; i < trackControls.length; i++) {
usedToFailed = trackControls[i].prefetchFailed;
// If this track used to fail and we haven't been
// deallocated, then we just skip the track.
if (usedToFailed && getState() > Prefetching)
continue;
if (trackControls[i].prefetchTrack()) {
atLeastOneTrack = true;
if (usedToFailed) {
if (!manageTimeBases()) {
Log.error(prefetchError);
Log.error(timeBaseError);
return false;
}
// Sync up all the tracks with the current media time
// since a new track is added.
doSetMediaTime(getMediaTime());
}
} else {
trackControls[i].prError();
// If the failed track contain the time base,
// we'll need to choose a new time base.
if (trackControls[i].isTimeBase()) {
// Fails if no new time base can be found.
// This should be rare.
if (!manageTimeBases()) {
Log.error(prefetchError);
Log.error(timeBaseError);
player.processError = timeBaseError;
return false;
}
}
if (trackControls[i].getFormat() instanceof AudioFormat &&
trackControls[i].rendererFailed) {
player.processError = "cannot open the audio device.";
}
}
}
// Fail if not even one track can be prefetched.
if (!atLeastOneTrack) {
Log.error(prefetchError);
return false;
}
player.processError = null;
return true;
|
protected boolean | doPrefetch2()doPrefetch - Part II
if (prefetchEnabled) {
// Wait for notification from the renderer modules with the
// bufferPrefetched event.
synchronized (waitPrefetched) {
source.doStart();
try {
if (!waitPrefetched.isEmpty()) {
// Block for at most 3 sec. in case anything goes wrong
// at the renderer modules.
waitPrefetched.wait(3000);
}
} catch (InterruptedException e) {}
}
} else
prefetched = true;
deallocated = false;
return true;
|
protected synchronized boolean | doRealize()
return doRealize1() && doRealize2();
|
protected boolean | doRealize1()doRealize Part I
Log.comment("Building flow graph for: " + dsource.getLocator() + "\n");
realizeTime = System.currentTimeMillis();
boolean atLeastOneTrack = false;
int trackID = 0;
int numTracks = getNumTracks();
// Go thru each track to build the graph.
for (int i = 0; i < trackControls.length; i++) {
// Skip the track if its disabled
if (!trackControls[i].isEnabled())
continue;
Log.setIndent(0);
Log.comment("Building Track: " + i);
if (trackControls[i].buildTrack(trackID, numTracks)) {
// We've completed at least one track now.
atLeastOneTrack = true;
trackControls[i].setEnabled(true);
} else if (trackControls[i].isCustomized()) {
// If the track is being customized and we cannot
// build a graph for that track, we won't attempt to
// build the rest of the tracks.
Log.error(realizeError);
trackControls[i].prError();
player.processError = genericProcessorError;
return false;
} else {
// Disable that track
trackControls[i].setEnabled(false);
Log.warning("Failed to handle track " + i);
trackControls[i].prError();
}
// Check for interrupt after a critcial section.
if (isInterrupted()) {
Log.error(realizeError);
Log.error(" The graph building process is being interrupted.\n");
player.processError = "interrupted while the player is being constructed.";
return false;
}
trackID++;
Log.write("\n");
}
// Failed if none of the tracks worked.
if (!atLeastOneTrack) {
Log.error(realizeError);
player.processError = "input media not supported: " + getCodecList();
return false;
}
return true;
|
protected boolean | doRealize2()doRealize Part II
// Locate the set the master time base.
if (!manageTimeBases()) {
Log.error(realizeError);
Log.error(timeBaseError);
player.processError = timeBaseError;
return false;
}
// For debugging
Log.comment("Here's the completed flow graph:");
traceGraph(source);
Log.write("\n");
profile("graph building", realizeTime);
realizeTime = System.currentTimeMillis();
// Update the format info on the progress control.
updateFormats();
// For Java Media Debugger
if (DEBUG) jmd.initGraph(source);
profile("realize, post graph building", realizeTime);
return true;
|
protected synchronized void | doReset()The real reset code.
This is a blocking call and should only be called when the
engine is stopped.
// We'll need to block until the modules are fully resetted to
// move on.
synchronized (waitResetted) {
resetResettedList();
// Put all modules in the reset state. The source module
// is the last to receive the reset call. It will trigger
// zero-length flush buffers to flow from the source to
// the sinks. When the sinks receive the flush buffers,
// it will reply back with the resetted callbacks.
BasicModule m;
int size = modules.size();
for (int i = size-1; i >= 0; i--) {
m = (BasicModule)modules.elementAt(i);
if (!m.prefetchFailed())
m.reset();
}
// The data flow (including the flush buffers) could be blocked
// at the sinks. To initiate the reset, we'll call
// triggerReset on the sinks.
BasicSinkModule bsm;
size = sinks.size();
for (int i = 0; i < size; i++) {
bsm = (BasicSinkModule)sinks.elementAt(i);
if (!bsm.prefetchFailed())
bsm.triggerReset();
}
if (!waitResetted.isEmpty()) {
try {
// Wait at most 3 seconds in case anything goes
// wrong at the plugins. We have no control on
// how plugin writers write their plugin's.
waitResetted.wait(3000);
} catch (Exception e) {}
}
// Some of the sinks may need to be stop again.
size = sinks.size();
for (int i = 0; i < size; i++) {
bsm = (BasicSinkModule)sinks.elementAt(i);
if (!bsm.prefetchFailed())
bsm.doneReset();
}
}
prefetched = false;
|
protected void | doSetMediaTime(javax.media.Time when)
slaveClock.setMediaTime(when);
// Set media time on the renderer modules and the source.
// Check the return time from the parser.
Time t;
if ((t = source.setPosition(when, 0)) == null)
t = when;
int size = sinks.size();
BasicSinkModule bsm;
for (int i = 0; i < size; i++) {
bsm = (BasicSinkModule)sinks.elementAt(i);
bsm.doSetMediaTime(when);
bsm.setPreroll(when.getNanoseconds(), t.getNanoseconds());
}
|
public synchronized float | doSetRate(float r)
if (r <= 0f)
r = 1.0f;
if (r == rate)
return r;
// If the system clock is in use, we need to set rate
// on the system clock. Otherwise, set rate on the
// master clock and let it determine the actual rate use.
if (masterSink == null)
r = getClock().setRate(r);
else
r = masterSink.doSetRate(r);
BasicModule m;
int size = modules.size();
for (int i = 0; i < size; i++) {
m = (BasicModule)modules.elementAt(i);
if (m != masterSink)
m.doSetRate(r);
}
rate = r;
return r;
|
protected synchronized void | doStart()Start immediately.
Invoked from start(tbt) when the scheduled start time is reached.
Use the public start(tbt) method for the public interface.
Override this to implement subclass behavior.
if (started) return;
doStart1();
doStart2();
|
protected void | doStart1()doStart - Part I.
// If the data source is a capture device, we would like
// to flush the data source before starting.
if (dsource instanceof CaptureDevice || isRTP())
reset();
resetPrefetchedList();
resetStoppedList();
resetEndedList();
for (int i = 0; i < trackControls.length; i++) {
if (trackControls[i].isEnabled())
trackControls[i].startTrack();
}
|
protected void | doStart2()doStart - Part II
source.doStart();
started = true;
prefetched = true;
|
protected synchronized void | doStop()Invoked from stop().
Override this to implement subclass behavior.
if (!started) return;
doStop1();
doStop2();
|
protected void | doStop1()doStop - Part I.
resetPrefetchedList();
source.doStop();
for (int i = 0; i < trackControls.length; i++) {
if (trackControls[i].isEnabled())
trackControls[i].stopTrack();
}
|
protected void | doStop2()doStop - Part II.
// If prefetching is disabled, we'll also need to do a
// non-blocking stop on the source since stop is normally
// called when data is prefetched.
if (!prefetchEnabled)
source.pause();
started = false;
|
protected com.sun.media.BasicSinkModule | findMasterSink()Returns the DataSink which holds the timebase.
// Search for all the enabled track for a master time base.
for (int i = 0; i < trackControls.length; i++) {
if (!trackControls[i].isEnabled())
continue;
if (trackControls[i].rendererModule != null &&
trackControls[i].rendererModule.getClock() != null) {
return trackControls[i].rendererModule;
}
}
return null;
|
public void | formatChanged(com.sun.media.Module src, javax.media.Format oldFormat, javax.media.Format newFormat)
Log.comment(src + ": input format changed: " + newFormat);
// Handle size change independently.
if (src instanceof BasicRendererModule &&
oldFormat instanceof VideoFormat &&
newFormat instanceof VideoFormat) {
Dimension s1 = ((VideoFormat)oldFormat).getSize();
Dimension s2 = ((VideoFormat)newFormat).getSize();
if (s2 != null && (s1 == null || !s1.equals(s2))) {
sendEvent(new SizeChangeEvent(this, s2.width, s2.height, 1.0f));
}
}
|
public void | formatChangedFailure(com.sun.media.Module src, javax.media.Format oldFormat, javax.media.Format newFormat)
// Send an internal error event for now.
// Future: need to rebuild the graph.
// -ivg
if (!internalErrorOccurred) {
sendEvent(new InternalErrorEvent(this, "Internal module " + src + ": failed to handle a data format change!"));
internalErrorOccurred = true;
close();
}
|
public void | framesBehind(com.sun.media.Module src, float frames, com.sun.media.InputConnector ic)
OutputConnector oc;
BasicFilterModule bfm;
while (ic != null) {
if ((oc = ic.getOutputConnector()) == null)
break;
if ((src = oc.getModule()) == null)
break;
if (!(src instanceof BasicFilterModule))
break;
bfm = (BasicFilterModule)src;
bfm.setFramesBehind(frames);
ic = src.getInputConnector(null);
}
|
protected long | getBitRate()
return source.getBitsRead();
|
public java.lang.String | getCNAME()
if (rtpInfo == null) {
if ((rtpInfo = (RTPInfo)dsource.getControl("com.sun.media.util.RTPInfo")) == null)
return null;
}
return rtpInfo.getCNAME();
|
java.lang.String | getCodecList()
String list = "";
Format fmt;
for (int i = 0; i < trackControls.length; i++) {
fmt = trackControls[i].getOriginalFormat();
if (fmt == null || fmt.getEncoding() == null)
continue;
list += fmt.getEncoding();
if (fmt instanceof VideoFormat)
list += " video";
else if (fmt instanceof AudioFormat)
list += " audio";
if (i + 1 < trackControls.length)
list += ", ";
}
return list;
|
public javax.media.Control[] | getControls()Return a list of Control objects this Controller
supports.
In this case, it is all the controls from all the modules
controlled by this engine.
// build the list of controls. It is the total of all the
// controls from each module plus the ones that are maintained
// by the engine itself (e.g. progressControl).
Control controls[];
Vector cv = new Vector();
Control c;
Object cs[];
Module m;
int i, size = (modules == null ? 0 : modules.size());
int otherSize = 0;
// Collect controls from all the modules.
for (i = 0; i < size; i++) {
m = (Module)modules.elementAt(i);
cs = m.getControls();
if (cs == null) continue;
for (int j = 0; j < cs.length; j++) {
cv.addElement(cs[j]);
}
}
size = cv.size();
// Controls owned by the engine itself.
if (videoEnabled()) {
if (frameRateControl == null) {
frameRateControl = new FrameRateAdapter(player, 0f, 0f, 30f, false) {
public float setFrameRate(float rate) {
this.value = rate;
return -1f;
}
public Component getControlComponent() {
return null;
}
public Object getOwner() {
return player;
}
};
}
}
if (bitRateControl == null) {
bitRateControl = new BitRateA(0, -1, -1, false);
}
if (frameRateControl != null)
otherSize++;
if (bitRateControl != null)
otherSize++;
if (framePositioningControl != null)
otherSize++;
if (DEBUG) otherSize++;
controls = new Control[size + otherSize + trackControls.length];
for (i = 0; i < size; i++)
controls[i] = (Control)cv.elementAt(i);
if (bitRateControl != null)
controls[size++] = bitRateControl;
if (frameRateControl != null)
controls[size++] = frameRateControl;
if (framePositioningControl != null)
controls[size++] = framePositioningControl;
if (DEBUG)
controls[size++] = jmd;
// and the tracks
for (i = 0; i < trackControls.length; i++) {
controls[size + i] = trackControls[i];
}
return controls;
|
public javax.media.Time | getDuration()Return the duration of the media.
It's unknown until we implement a particular node.
return source.getDuration();
|
public javax.media.GainControl | getGainControl()Get audio gain control.
return (GainControl)getControl("javax.media.GainControl");
|
public long | getLatency()Return the run-time latency. It's the time it takes for a packet
to travel from the first module to the last module.
The time is computed in nanoseconds.
return latency;
|
int | getNumTracks()
int num = 0;
for (int i = 0; i < trackControls.length; i++) {
if (trackControls[i].isEnabled())
num++;
}
return num;
|
protected javax.media.PlugIn | getPlugIn(com.sun.media.BasicModule m)Get the plugin from a module. For debugging.
if (m instanceof BasicSourceModule)
return ((BasicSourceModule)m).getDemultiplexer();
if (m instanceof BasicFilterModule)
return ((BasicFilterModule)m).getCodec();
if (m instanceof BasicRendererModule)
return ((BasicRendererModule)m).getRenderer();
return null;
|
public javax.media.Time | getStartLatency()Returns the start latency.
Don't know until the particular node is implemented.
if ( (state == Unrealized) || (state == Realizing) )
throwError(new NotRealizedError("Cannot get start latency from an unrealized controller"));
return LATENCY_UNKNOWN;
|
public javax.media.TimeBase | getTimeBase()Override the parent's method to not check for realized state. There's
no need to.
return getClock().getTimeBase();
|
public java.awt.Component | getVisualComponent()Get the visual component where the video is presented.
Vector visuals = new Vector(1);
if (modules == null)
return null;
for (int i = 0; i < modules.size(); i++) {
BasicModule bm = (BasicModule) modules.elementAt(i);
PlugIn pi = getPlugIn(bm);
if (pi instanceof VideoRenderer) {
Component comp = ((VideoRenderer)pi).getComponent();
if (comp != null)
visuals.addElement(comp);
}
}
if (visuals.size() == 0)
return null;
else if (visuals.size() == 1)
return (Component) visuals.elementAt(0);
else {
// Multiple components, put them into one container
return createVisualContainer(visuals);
}
|
public void | internalErrorOccurred(com.sun.media.Module src)
if (!internalErrorOccurred) {
sendEvent(new InternalErrorEvent(this, "Internal module " + src + " failed!"));
internalErrorOccurred = true;
close();
}
|
protected boolean | isConfigurable()The PlaybackEngine is configurable.
return true;
|
public boolean | isRTP()
if (testedRTP)
return rtpInfo != null;
rtpInfo = (RTPInfo)dsource.getControl("com.sun.media.util.RTPInfo");
testedRTP = true;
return rtpInfo != null;
|
static boolean | isRawVideo(javax.media.Format fmt)Return true if the given format is a raw video format.
return (fmt instanceof RGBFormat || fmt instanceof YUVFormat);
|
protected com.sun.media.BasicModule | lastModule(com.sun.media.BasicModule bm)Given a chain of FilterModules, return the last one of the chain.
OutputConnector oc;
InputConnector ic;
oc = bm.getOutputConnector(null);
while (oc != null && (ic = oc.getInputConnector()) != null) {
bm = (BasicModule)ic.getModule();
oc = bm.getOutputConnector(null);
}
return bm;
|
protected synchronized void | localStop()
super.stop();
|
boolean | manageTimeBases()Search and update the master time base.
// Obtain a master time base from one of its SinkModules.
masterSink = findMasterSink();
return updateMasterTimeBase();
|
public void | markedDataArrived(com.sun.media.Module src, javax.media.Buffer buffer)
if (src instanceof BasicSourceModule) {
markedDataStartTime = getMediaNanoseconds();
} else {
long t = getMediaNanoseconds() - markedDataStartTime;
if (t > 0 && t < 1000000000) {
if (!reportOnce) {
Log.comment("Computed latency for video: " + t/1000000 + " ms\n");
reportOnce = true;
}
latency = (t + latency)/2;
}
}
|
public void | mediaEnded(com.sun.media.Module src)
if (src instanceof BasicSinkModule) {
synchronized (waitEnded) {
if (waitEnded.contains(src))
waitEnded.removeElement(src);
if (waitEnded.isEmpty()) {
// EOM.
started = false;
stopControllerOnly();
sendEvent(new EndOfMediaEvent(this, Started,
Prefetched, getTargetState(),
getMediaTime()));
slaveClock.reset(USE_MASTER);
} else if (src == masterSink) {
// If the master sink has finished but the
// not all the other tracks are finished, we'll
// need to switch the clock to using a backup for
// the rest of the media.
slaveClock.reset(USE_BACKUP);
}
}
}
|
public void | pluginTerminated(com.sun.media.Module src)
if (!internalErrorOccurred) {
sendEvent(new ControllerClosedEvent(this));
internalErrorOccurred = true;
close();
}
|
static void | profile(java.lang.String msg, long time)
Log.profile("Profile: " + msg + ": " +
(System.currentTimeMillis() - time) + " ms\n");
|
protected synchronized void | reset()Flush (reset) the flow graph.
This is a blocking call and should only be called when the
engine is stopped.
// If a module has been blocked, we'll need
// to return from the reset.
if (started || !prefetched || dataPathBlocked)
return;
doReset();
|
protected void | resetBitRate()
source.resetBitsRead();
|
private void | resetEndedList()Reset the renderer lists.
synchronized (waitEnded) {
waitEnded.removeAllElements();
int size = sinks.size();
BasicSinkModule bsm;
for (int i = 0; i < size; i++) {
bsm = (BasicSinkModule)sinks.elementAt(i);
if (!bsm.prefetchFailed())
waitEnded.addElement(bsm);
}
waitEnded.notifyAll();
}
|
private void | resetPrefetchedList()Reset the renderer lists.
synchronized (waitPrefetched) {
waitPrefetched.removeAllElements();
int size = sinks.size();
BasicSinkModule bsm;
for (int i = 0; i < size; i++) {
bsm = (BasicSinkModule)sinks.elementAt(i);
if (!bsm.prefetchFailed())
waitPrefetched.addElement(bsm);
}
waitPrefetched.notifyAll();
}
|
private void | resetResettedList()Reset the renderer lists.
// Set up the wait queue for the reset notifications first.
// We'll wait for reset note from sinks and the source only.
synchronized (waitResetted) {
waitResetted.removeAllElements();
int size = sinks.size();
BasicSinkModule bsm;
for (int i = 0; i < size; i++) {
bsm = (BasicSinkModule)sinks.elementAt(i);
if (!bsm.prefetchFailed())
waitResetted.addElement(bsm);
}
waitResetted.notifyAll();
}
|
private void | resetStoppedList()Reset the renderer lists.
synchronized (waitStopped) {
waitStopped.removeAllElements();
int size = sinks.size();
BasicSinkModule bsm;
for (int i = 0; i < size; i++) {
bsm = (BasicSinkModule)sinks.elementAt(i);
if (!bsm.prefetchFailed())
waitStopped.addElement(bsm);
}
waitStopped.notifyAll();
}
|
public void | resetted(com.sun.media.Module src)
synchronized (waitResetted) {
if (waitResetted.contains(src)) {
waitResetted.removeElement(src);
}
if (waitResetted.isEmpty()) {
// Everyone modules has been resetted.
waitResetted.notifyAll();
}
}
|
public synchronized void | setMediaTime(javax.media.Time when)Override BasicController's setMediaTime so as not to set the
media time on the master clock twice.
if (state < Realized)
throwError(new NotRealizedError("Cannot set media time on a unrealized controller"));
// Chances of this are really rare. Nevertheless, we'll guard
// against it.
if (when.getNanoseconds() == getMediaNanoseconds())
return;
// Reset everything.
reset();
// In case deallocate was called, we need to
// clear the timeBeforeAbortPrefetch flag since we are
// setting a new time.
timeBeforeAbortPrefetch = null;
doSetMediaTime(when);
// Prefetch the engine again to display the first frame.
doPrefetch();
sendEvent(new MediaTimeSetEvent(this, when));
|
public static void | setMemoryTrace(boolean on)Turn on memory trace to assit debugging.
TRACE_ON = on;
|
public void | setProgressControl(com.sun.media.controls.ProgressControl p)
progressControl = p;
|
protected void | setRenderBufferSize(javax.media.Renderer r)
BufferControl bc = (BufferControl)r.getControl("javax.media.control.BufferControl");
if (bc != null)
bc.setBufferLength(2000);
|
public void | setSource(javax.media.protocol.DataSource ds)Verifies to see if the engine accepts the given source.
try {
source = BasicSourceModule.createModule(ds);
} catch (IOException ioe) {
Log.warning("Input DataSource: " + ds);
Log.warning(" Failed with IO exception: " + ioe.getMessage());
throw ioe;
} catch (IncompatibleSourceException ise) {
Log.warning("Input DataSource: " + ds);
Log.warning(" is not compatible with the MediaEngine.");
Log.warning(" It's likely that the DataSource is required to extend PullDataSource;");
Log.warning(" and that its source streams implement the Seekable interface ");
Log.warning(" and with random access capability.");
throw ise;
}
if (source == null)
throw new IncompatibleSourceException();
// Create the debugger control
if (DEBUG && jmd == null) {
String jmdTitle = "PlugIn Viewer";
if (ds != null && ds.getLocator() != null) {
jmdTitle = ds.getLocator().toString();
// We'll determine here if we want to allocate a
// render buffer for smoother playback.
// Doing that will increase the latency, so we'll
// only do that for a few well-known protocols.
String protocol = ds.getLocator().getProtocol();
if (protocol != null) {
protocol = protocol.toLowerCase();
if (protocol.equals("file") ||
protocol.startsWith("http") ||
protocol.equals("ftp")) {
useMoreRenderBuffer = true;
}
}
}
jmd = new BasicJMD(jmdTitle);
}
if (DEBUG) source.setJMD(jmd);
source.setController(this);
dsource = ds;
// If it's RTP data source, we'll disable prefetch and reset.
if (dsource instanceof com.sun.media.protocol.Streamable &&
!((com.sun.media.protocol.Streamable)dsource).isPrefetchable()) {
prefetchEnabled = false;
dataPathBlocked = true;
}
if (dsource instanceof CaptureDevice)
prefetchEnabled = false;
|
public void | setStopTime(javax.media.Time t)Override BasicController.setStopTime to allow for more
accurate stop time set.
if (getState() < Realized)
throwError(new NotRealizedError("Cannot set stop time on an unrealized controller."));
if ( getStopTime() != null &&
getStopTime().getNanoseconds() != t.getNanoseconds() )
sendEvent(new StopTimeChangeEvent(this, t));
if (getState() == Started &&
t != Clock.RESET && t.getNanoseconds() < getMediaNanoseconds()) {
// We have already passed the stop time.
localStop();
setStopTime(Clock.RESET);
sendEvent(new StopAtTimeEvent(this, getState(),
Prefetched,
getTargetState(),
getMediaTime()));
} else {
getClock().setStopTime(t);
int size = sinks.size();
BasicSinkModule bsm;
for (int i = 0; i < size; i++) {
bsm = (BasicSinkModule)sinks.elementAt(i);
bsm.setStopTime(t);
}
}
|
public void | setTimeBase(javax.media.TimeBase tb)Override the parent's method to not check for realized state. There's
no need to.
getClock().setTimeBase(tb);
// Set the time base on each of the SinkModules.
if (sinks == null)
return;
int size = sinks.size();
BasicSinkModule bsm;
for (int i = 0; i < size; i++) {
bsm = (BasicSinkModule)sinks.elementAt(i);
bsm.setTimeBase(tb);
}
|
public synchronized void | stop()This is stop by request.
super.stop();
sendEvent(new StopByRequestEvent(this, Started,
Prefetched,
getTargetState(),
getMediaTime()));
|
public void | stopAtTime(com.sun.media.Module src)
if (src instanceof BasicSinkModule) {
synchronized (waitStopped) {
if (waitStopped.contains(src))
waitStopped.removeElement(src);
// Check to see if all the tracks have stopped or
// all other tracks have reached EOM and this is the
// only track left behind.
if (waitStopped.isEmpty() ||
waitEnded.size() == 1 && waitEnded.contains(src)) {
// Stop at time.
started = false;
stopControllerOnly();
setStopTime(Clock.RESET);
sendEvent(new StopAtTimeEvent(this, Started,
Prefetched,
getTargetState(),
getMediaTime()));
slaveClock.reset(USE_MASTER);
} else if (src == masterSink) {
// If the master sink has finished but the
// not all the other tracks are finished, we'll
// need to switch the clock to using a backup for
// the rest of the media.
slaveClock.reset(USE_BACKUP);
}
}
}
|
void | traceGraph(com.sun.media.BasicModule source)Trace the flow graph for debugging.
Module m;
OutputConnector oc;
InputConnector ic;
String names[];
names = source.getOutputConnectorNames();
for (int i = 0; i < names.length; i++) {
oc = source.getOutputConnector(names[i]);
if ((ic = oc.getInputConnector()) == null)
continue;
if ((m = ic.getModule()) == null)
continue;
Log.write(" " + getPlugIn(source));
Log.write(" connects to: " + getPlugIn((BasicModule)m));
Log.write(" format: " + oc.getFormat());
traceGraph((BasicModule)m);
}
|
public void | updateFormats()Update the format info per track on the progress control.
// Update formats per track.
for (int i = 0; i < trackControls.length; i++) {
trackControls[i].updateFormat();
}
|
boolean | updateMasterTimeBase()Update the master timebase on all the modules.
BasicSinkModule bsm;
int size = sinks.size();
if (masterSink != null)
slaveClock.setMaster(masterSink.getClock());
else
// No master sink found in the module, we'll use the
// system time base.
slaveClock.setMaster(null);
// Set the master time base to each of the SinkModules.
for (int i = 0; i < size; i++) {
bsm = (BasicSinkModule)sinks.elementAt(i);
if (bsm != masterSink && !bsm.prefetchFailed()) {
try {
bsm.setTimeBase(slaveClock.getTimeBase());
} catch (IncompatibleTimeBaseException e) {
return false;
}
}
}
return true;
|
public void | updateRates()Update the aggregate bit rate and frame rate per track on
the progress control. // so now - lastStatsTime will not be 0.
if (getState() < Realized)
return;
// Update global bit rate.
long now = System.currentTimeMillis();
long rate, avg;
if (now == lastStatsTime)
rate = lastBitRate;
else
rate = (long)((double)getBitRate()*8.0/
(now - lastStatsTime)*1000.0);
avg = (lastBitRate + rate)/2;
if (bitRateControl != null) {
bitRateControl.setBitRate((int)avg);
}
lastBitRate = rate;
lastStatsTime = now;
resetBitRate();
// Update frame rate on a per-track basis.
for (int i = 0; i < trackControls.length; i++) {
trackControls[i].updateRates(now);
}
// Compute the instanteous latency.
source.checkLatency();
|
public boolean | videoEnabled()Return true if video is present.
for (int i = 0; i < trackControls.length; i++) {
if (trackControls[i].isEnabled() &&
trackControls[i].getOriginalFormat() instanceof VideoFormat)
return true;
}
return false;
|