/*
* @(#)Handler.java 1.17 02/08/21
*
* Copyright 1996-1998 by Sun Microsystems, Inc.,
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information
* of Sun Microsystems, Inc. ("Confidential Information"). You
* shall not disclose such Confidential Information and shall use
* it only in accordance with the terms of the license agreement
* you entered into with Sun.
*/
package com.sun.media.processor.rtp;
import java.io.*;
import java.awt.*;
import java.util.Vector;
import javax.media.*;
import com.sun.media.*;
import com.sun.media.ui.*;
import com.sun.media.controls.*;
import com.sun.media.rtp.*;
import javax.media.rtp.*;
import javax.media.rtp.event.*;
import javax.media.rtp.rtcp.*;
import java.net.*;
import javax.media.protocol.*;
import java.awt.event.*;
import com.sun.media.util.*;
import javax.media.format.AudioFormat;
import javax.media.format.VideoFormat;
import javax.media.Format;
import javax.media.format.FormatChangeEvent;
import javax.media.control.TrackControl;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import com.ms.security.PermissionID;
import com.ms.security.PolicyEngine;
public class Handler extends BasicProcessor implements ReceiveStreamListener{
RTPSessionMgr mgrs[] = null;
DataSource sources[] = null;
Processor processor = null;
Format formats[] = null;
Vector locators = null;
Object dataLock = new Object();
boolean dataReady = false;
private boolean closed = false;
private boolean audioEnabled = false;
private boolean videoEnabled = false;
private static JMFSecurity jmfSecurity = null;
private static boolean securityPrivelege=false;
private Method m[] = new Method[1];
private Class cl[] = new Class[1];
private Object args[][] = new Object[1][0];
public Handler() {
framePositioning = false;
}
String sessionError = "cannot create and initialize the RTP Session.";
protected synchronized boolean doConfigure() {
super.doConfigure();
try {
if (source instanceof RTPSocket) {
// this constructor will take care of initliasing and
// starting the session as well as updating the encodings
// from the RTPControl
mgrs = new RTPSessionMgr[1];
mgrs[1] = new RTPSessionMgr((RTPSocket)source);
mgrs[1].addReceiveStreamListener(this);
sources = new DataSource[1];
sources[0] = source;
formats = new Format[1];
dataReady = false;
} else {
RTPMediaLocator rml;
InetAddress ipAddr;
SessionAddress localAddr = new SessionAddress();
SessionAddress destAddr;
mgrs = new RTPSessionMgr[locators.size()];
sources = new DataSource[locators.size()];
formats = new Format[locators.size()];
dataReady = false;
for (int i = 0; i < locators.size(); i++) {
rml = (RTPMediaLocator)locators.elementAt(i);
mgrs[i] = (RTPSessionMgr) RTPManager.newInstance();
mgrs[i].addReceiveStreamListener(this);
ipAddr = InetAddress.getByName(rml.getSessionAddress());
if( ipAddr.isMulticastAddress()) {
// local and remote address pairs are identical:
localAddr= new SessionAddress( ipAddr,
rml.getSessionPort(),
rml.getTTL());
destAddr = new SessionAddress( ipAddr,
rml.getSessionPort(),
rml.getTTL());
} else {
localAddr= new SessionAddress( InetAddress.getLocalHost(),
rml.getSessionPort());
destAddr = new SessionAddress( ipAddr,
rml.getSessionPort());
}
mgrs[ i].initialize( localAddr);
mgrs[i].addTarget(destAddr);
}
}
} catch (Exception e){
Log.error("Cannot create the RTP Session: " + e.getMessage());
processError = sessionError;
return false;
}
// dont configure this meta player until the internal processor
// is configured
try{
synchronized (dataLock) {
while (!dataReady && !isInterrupted() && !closed)
dataLock.wait();
}
} catch (Exception e) {}
// If configure is being interrupted, return failure from configure.
if (closed || isInterrupted()) {
resetInterrupt();
processError = "no RTP data was received.";
return false;
}
return true;
}// end of doConfigure()
protected void completeConfigure() {
state = javax.media.Processor.Configured;
super.completeConfigure();
}
protected void doFailedConfigure() {
closeSessions();
super.doFailedConfigure();
}
Object closeSync = new Object();
private void closeSessions() {
synchronized (closeSync) {
for (int i = 0; i < mgrs.length; i++) {
if (mgrs[i] != null) {
mgrs[i].removeTargets( "Closing session from the RTP Handler");
mgrs[i].dispose();
mgrs[i] = null;
}
}
}
}
protected boolean doRealize() {
return waitForRealize(processor);
}
protected void completeRealize() {
state = Realized;
super.completeRealize();
}
protected void doFailedRealize() {
closeSessions();
super.doFailedRealize();
}
protected void doStart() {
super.doStart();
waitForStart(processor);
}
protected void doStop() {
super.doStop();
waitForStop(processor);
}
protected void doDeallocate() {
processor.deallocate();
synchronized (dataLock) {
dataLock.notifyAll();
}
}
protected void doClose() {
closed = true;
synchronized (dataLock) {
dataLock.notify();
}
stop();
if( processor != null) {
processor.close();
}
closeSessions();
super.doClose();
}
public void setTimeBase(TimeBase tb) throws IncompatibleTimeBaseException {
}
protected TimeBase getMasterTimeBase() {
return new SystemTimeBase();
}
protected boolean audioEnabled(){
return audioEnabled;
}
protected boolean videoEnabled(){
return videoEnabled;
}
private void sendMyEvent(ControllerEvent e){
super.sendEvent(e);
}
public void update( ReceiveStreamEvent event) {
RTPSessionMgr mgr = (RTPSessionMgr)event.getSource();
int idx;
for (idx = 0; idx < mgrs.length; idx++) {
if (mgrs[idx] == mgr)
break;
}
if (idx >= mgrs.length) {
// Something's wrong.
System.err.println("Unknown manager: " + mgr);
return;
}
if (event instanceof RemotePayloadChangeEvent) {
Log.comment("Received an RTP PayloadChangeEvent");
Log.error("The RTP processor cannot handle mid-stream payload change.\n");
sendEvent(new ControllerErrorEvent(this, "Cannot handle mid-stream payload change."));
close();
}// payload change event
if (event instanceof NewReceiveStreamEvent){
if (sources[idx] != null) {
// We've already gotten a source from this session.
return;
}
ReceiveStream stream = null;
try{
// get a handle over the ReceiveStream
stream =((NewReceiveStreamEvent)event).getReceiveStream();
sources[idx] = stream.getDataSource();
RTPControl ctl = (RTPControl)sources[idx].getControl("javax.media.rtp.RTPControl");
if (ctl != null){
formats[idx] = ctl.getFormat();
if (formats[idx] instanceof AudioFormat)
audioEnabled = true;
if (formats[idx] instanceof VideoFormat)
videoEnabled = true;
}
if (source instanceof RTPSocket)
((RTPSocket)source).setChild(sources[idx]);
else
((com.sun.media.protocol.rtp.DataSource)source).
setChild((com.sun.media.protocol.rtp.DataSource)sources[idx]);
for (int i = 0; i < sources.length; i++) {
// Return if not all sessions had yielded a source.
if (sources[i] == null)
return;
}
// We've received all the sources, let create the processor.
DataSource mixDS;
try {
mixDS = javax.media.Manager.createMergingDataSource(sources);
} catch (Exception e) {
System.err.println("Cannot merge data sources.");
return;
}
try {
processor = javax.media.Manager.createProcessor(mixDS);
} catch (Exception e) {
System.err.println("Cannot create the mix processor.");
return;
}
if (!waitForConfigure(processor))
return;
// We are done generating the internal processor.
synchronized(dataLock) {
dataReady = true;
dataLock.notifyAll();
}
} catch (Exception e){
System.err.println("NewReceiveStreamEvent exception " +
e.getMessage());
return;
}
}// instanceof newReceiveStreamEvent
}
public void setSource(javax.media.protocol.DataSource source)
throws IOException, IncompatibleSourceException {
super.setSource(source);
if (source instanceof com.sun.media.protocol.rtp.DataSource){
MediaLocator ml = source.getLocator();
String mlStr = ml.getRemainder();
String str;
int start, idx;
start = 0;
while (mlStr.charAt(start) == '/')
start++;
locators = new Vector();
RTPMediaLocator rml;
try {
while (start < mlStr.length() &&
(idx = mlStr.indexOf("&", start)) != -1) {
str = mlStr.substring(start, idx);
rml = new RTPMediaLocator("rtp://" + str);
locators.addElement(rml);
start = idx+1;
}
if (start != 0)
str = mlStr.substring(start);
else
str = mlStr;
rml = new RTPMediaLocator("rtp://" + str);
locators.addElement(rml);
} catch (Exception e) {
throw new IncompatibleSourceException();
}
} else if (!(source instanceof RTPSocket)) {
throw new IncompatibleSourceException();
}
// we will set the dynamic encoding for the one
// encoding we dont use from static RTP payloads
RTPControl ctl = (RTPControl)
source.getControl("javax.media.rtp.RTPControl");
if (ctl != null)
ctl.addFormat(new AudioFormat(AudioFormat.DVI_RTP,
44100,
4,
1),
18);
}
private void invalidateComp() {
controlComp = null;
controls = null;
}
/**
* Obtain the visiual component from the media engine.
*/
public Component getVisualComponent() {
/**
* Call the superclass method to ensure that restrictions
* on player methods are enforced
*/
super.getVisualComponent();
return processor.getVisualComponent();
}
/**
* Return the list of controls from its slave controllers plus the
* ones that this player supports.
* @return the list of controls supported by this player.
*/
public Control [] getControls() {
return processor.getControls();
}
public void updateStats(){
if ( processor != null) {
((BasicProcessor) processor).updateStats();
}
}
public TrackControl[] getTrackControls() throws NotConfiguredError {
super.getTrackControls();
return processor.getTrackControls();
}
public ContentDescriptor[] getSupportedContentDescriptors()
throws NotConfiguredError {
super.getSupportedContentDescriptors();
return processor.getSupportedContentDescriptors();
}
public ContentDescriptor setContentDescriptor(ContentDescriptor ocd)
throws NotConfiguredError {
super.setContentDescriptor(ocd);
return processor.setContentDescriptor(ocd);
}
public ContentDescriptor getContentDescriptor()
throws NotConfiguredError {
super.getContentDescriptor();
return processor.getContentDescriptor();
}
public DataSource getDataOutput() throws NotRealizedError {
super.getDataOutput();
return processor.getDataOutput();
}
private boolean waitForConfigure(Processor p) {
return (new StateWaiter()).waitForConfigure(p);
}
private boolean waitForRealize(Processor p) {
return (new StateWaiter()).waitForRealize(p);
}
private void waitForStart(Player p) {
(new StateWaiter()).waitForStart(p, true);
}
private void waitForStop(Player p) {
(new StateWaiter()).waitForStart(p, false);
}
private void waitForClose(Player p) {
(new StateWaiter()).waitForClose(p);
}
class StateWaiter implements ControllerListener {
boolean closeDown = false;
Object stateLock = new Object();
public boolean waitForConfigure(Processor p) {
p.addControllerListener(this);
p.configure();
synchronized (stateLock) {
while (p.getState() != javax.media.Processor.Configured && !closeDown) {
try {
stateLock.wait(1000);
} catch (InterruptedException ie) {
break;
}
}
}
p.removeControllerListener(this);
return !closeDown;
}
public boolean waitForRealize(Processor p) {
p.addControllerListener(this);
p.realize();
synchronized (stateLock) {
while (p.getState() != Realized && !closeDown) {
try {
stateLock.wait(1000);
} catch (InterruptedException ie) {
break;
}
}
}
p.removeControllerListener(this);
return !closeDown;
}
public void waitForStart(Player p, boolean startOn) {
p.addControllerListener(this);
if (startOn)
p.start();
else
p.stop();
synchronized (stateLock) {
while (((startOn && p.getState() != Started) ||
(!startOn && p.getState() == Started)) &&
!closeDown) {
try {
stateLock.wait(1000);
} catch (InterruptedException ie) {
break;
}
}
}
p.removeControllerListener(this);
}
public void waitForClose(Player p) {
p.addControllerListener(this);
p.close();
synchronized (stateLock) {
while (!closeDown) {
try {
stateLock.wait(1000);
} catch (InterruptedException ie) {
break;
}
}
}
p.removeControllerListener(this);
}
public void controllerUpdate(ControllerEvent ce) {
if (ce instanceof ControllerClosedEvent ||
ce instanceof ControllerErrorEvent) {
closeDown = true;
}
synchronized (stateLock) {
stateLock.notify();
}
}
}
}
|