FileDocCategorySizeDatePackage
Handler.javaAPI DocJMF 2.1.1e17443Mon May 12 12:20:58 BST 2003com.sun.media.content.rtsp

Handler

public class Handler extends BasicPlayer implements com.sun.media.protocol.BufferListener, ReceiveStreamListener, TimerListener
MediaPlayer extends BasicPlayer and uses MediaEngine to play media.

Fields Summary
private final int
INITIALIZED
private final int
REALIZED
private final int
PLAYING
private final int
PAUSING
private RtspUtil
rtspUtil
private Player[]
players
private Vector
playerList
private boolean
dataReceived
private com.sun.media.protocol.rtp.DataSource[]
data_sources
private boolean[]
track_ready
private String
url
private Object
readySync
private Object
stateSync
private boolean
waitFailed
private int
state
private boolean
first_pass
private Timer
timer
private Container
container
Constructors Summary
public Handler()

    
      
	rtspUtil = new RtspUtil( this);

        framePositioning = false;

        playerList = new Vector();

        state = INITIALIZED;

	stopThreadEnabled = true;
    
Methods Summary
public synchronized voidaddController(Controller newController)

	int playerState = getState();
	
	if (playerState == Started) {
	    throwError(new ClockStartedError("Cannot add controller to a started player"));
	}
	
	if ( (playerState == Unrealized) || (playerState == Realizing) ) {
	    throwError(new NotRealizedError("A Controller cannot be added to an Unrealized Player"));
	}

	throw new IncompatibleTimeBaseException();
    
public booleanaudioEnabled()

        boolean enabled = true;

        return enabled;
    
private voidclosePlayers()

        for (int i = 0; i < playerList.size(); i++) {
            Player player = (Player) playerList.elementAt(i);

            player.close();
        }
    
protected java.awt.ComponentcreateVisualContainer(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 voiddoClose()

	stopPlayers();

        closePlayers();
		
        if (timer != null) {
            timer.stopTimer();
	    timer.removeListener(this);	    

            timer = null;
        }

	if( state == PLAYING) {	    
            rtspUtil.rtspTeardown();
	}

	state = INITIALIZED;	

        rtspUtil.closeConnection();	

	for( int i = 0; i < rtspUtil.getNumberOfTracks(); i++) {
	    RTPManager mgr= rtspUtil.getRTPManager( i);
	    mgr.removeTargets( "server down.");
	    mgr.dispose();
	}

        super.doClose();
    
public booleandoPrefetch()

        boolean prefetched;

        prefetched = super.doPrefetch();

        return prefetched;
    
protected synchronized booleandoRealize()

        boolean realized = super.doRealize();

        if (realized) {
            realized = initRtspSession();

	    if( !realized) {
		processError= rtspUtil.getProcessError();
	    } else {
		long duration= rtspUtil.getDuration();

                if( duration > 0) {		
		    sendEvent(new DurationUpdateEvent(this, new Time(duration)));
		}
	    }
        }

        return realized;
    
public voiddoSetMediaTime(Time now)

	super.doSetMediaTime(now);

        rtspUtil.setStartPos( now.getNanoseconds());
	
	// Now we need to flush the datasources.
	for( int i = 0; i < rtspUtil.getNumberOfTracks(); i++) {
	    data_sources[ i].flush();
	}
    
public voiddoStart()

        if (state >= REALIZED && state != PLAYING) {

	    for( int i = 0; i < rtspUtil.getNumberOfTracks(); i++) {
		track_ready[ i] = (rtspUtil.getRTPManager( i) == null ? true : false);
		data_sources[ i].prebuffer();
	    }

            boolean success = rtspUtil.rtspStart();

	    // We are waiting for audio and video to be prebuffered
	    // before actually starting the playback.  We'll wait for
	    // at most 3 seconds.
	    synchronized (readySync) {
		boolean ready = true;
		
		for( int i = 0; i < rtspUtil.getNumberOfTracks(); i++) {
		    if( !track_ready[ i]) {
			ready = false;
			break;
		    }
		}
		
		if (!ready) {
		    try {
			readySync.wait(3000);
		    } catch (Exception e) { }
		}
	    }

            if (success) {
                super.doStart();

                startPlayers();

                state = PLAYING;

		// this timer controls the end of media event which is
		// required for looping.
		long duration= rtspUtil.getDuration();

                if( duration > 0) {		
                    timer = new Timer(this,
                            duration + 500000000 - getMediaTime().getNanoseconds());

                    timer.start();
		}
            }
        }
    
public voiddoStop()

	if( state == PLAYING) {	    
            super.doStop();

            if (timer != null) {
                timer.stopTimer();
		timer.removeListener(this);

                timer = null;
            }

	    stopPlayers();

	    rtspStop();

            state = PAUSING;
	}
    
public Control[]getControls()

        int size = 0;
	
        for (int i = 0; i < playerList.size(); i++) {
            Control[] controls = ((Player)(playerList.elementAt(i))).getControls();

            size += controls.length;
        }

	size++;
	
        Control rtspControls[] = new Control[size];

	RtspAdapter rtspAdapter= new RtspAdapter();

	rtspAdapter.setRTPManagers( rtspUtil.getRTPManagers());
	rtspAdapter.setMediaTypes( rtspUtil.getMediaTypes());
	
        int counter = 0;

       	rtspControls[ counter++] = rtspAdapter;
	
        for (int i = 0; i < playerList.size(); i++) {
            Control[] controls = ((Player)(playerList.elementAt(i))).getControls();

            for (int k = 0; k < controls.length; k++) {
                rtspControls[counter++] = controls[k];
            }
        }

        return rtspControls;
    
public TimegetDuration()


	long t = rtspUtil.getDuration();

	if (t <= 0)
	    return Duration.DURATION_UNKNOWN;

        return new Time(t);
    
public GainControlgetGainControl()

        GainControl gainControl = null;

        for (int i = 0; i < playerList.size(); i++) {
            Player player = (Player) playerList.elementAt(i);

            gainControl = player.getGainControl();

            if (gainControl != null) {
                break;
            }
        }

        return gainControl;
    
protected TimeBasegetMasterTimeBase()

        return new SystemTimeBase();
    
public longgetMediaNanoseconds()

        long value= super.getMediaNanoseconds();

        return value;
    
public TimegetMediaTime()

        Time time = super.getMediaTime();

        return time;
    
public java.awt.ComponentgetVisualComponent()

    
       
	Vector visuals = new Vector(1);

	for( int i = 0; i < rtspUtil.getNumberOfTracks(); i++) {
	    if( players[ i] != null) {
	        Component comp= players[ i].getVisualComponent();

	        if( comp != null) {
		    visuals.addElement( comp);
	        }
	    }
	}

	if( visuals.size() == 0) {
	    return null;
	} else if( visuals.size() == 1) {
	    return (Component) visuals.elementAt( 0);
	} else {
	    return createVisualContainer( visuals);
	}
    
private booleaninitRtspSession()

        boolean realized = false;

	rtspUtil.setUrl( url);

        String ipAddress = rtspUtil.getServerIpAddress();
	
        if (ipAddress == null) {
            Log.error( "Invalid server address");
	    
	    rtspUtil.setProcessError( "Invalid server address");

            realized = false;
        } else {
	    realized = rtspUtil.createConnection();

	    if( realized) {
                realized = rtspUtil.rtspSetup();

                try {
                    InetAddress destaddr = InetAddress.getByName(ipAddress);

		    int numberOfTracks= rtspUtil.getNumberOfTracks();
		    int server_ports[]= rtspUtil.getServerPorts();
		    
		    for( int i = 0; i < numberOfTracks; i++) {
                        SessionAddress remoteAddress =
                                new SessionAddress(destaddr, server_ports[ i]);

			RTPManager mgr= rtspUtil.getRTPManager( i);
			
                        mgr.addTarget( remoteAddress);

			// Set 3/4 sec worth of buffering.
			BufferControl bc = (BufferControl)mgr.getControl("javax.media.control.BufferControl");

			String mediaType= rtspUtil.getMediaType( i);
			
			if( mediaType.equals( "audio")) {
			    bc.setBufferLength(250);
			    bc.setMinimumThreshold(125);
			} else if( mediaType.equals( "video")) {
			    bc.setBufferLength(1500);
			    bc.setMinimumThreshold(250);
			}
		    }
                } catch (Exception e) {
                    Log.error(e.getMessage());

                    return realized;
                }
            } 		
        }

        if (realized) {
            state = REALIZED;

	    int size= rtspUtil.getNumberOfTracks();
	    
	    players= new Player[ size];	    
	    data_sources = new DataSource[ size];
    	    track_ready = new boolean[ size];
	
	    dataReceived= false;

	    // Start the server.
            if (!rtspUtil.rtspStart()) {
		if( first_pass &&
		    rtspUtil.getStatusCode() ==
		    com.sun.media.rtsp.protocol.StatusCode.SESSION_NOT_FOUND) {

		    first_pass= false;
		    
		    playerList= new Vector();

		    return initRtspSession();
		}
		
		return false;
	    }

	    // Wait for the initial filling of the data buffers and
	    // the RTP players to fully realized.
            waitForData();

	    if( playerList.size() > 0) {
	        // Now the players are all started.  
	        // Stop the server momentarily.  Rewind the media
	        // so the next start will start from the beginning again.
	        // This is sort of inefficient but will get by the initial
	        // buffering problem.
	        rtspStop();
	        rtspUtil.setStartPos( 0);

	        // Now we need to flush the datasources to make sure
	        // the rewind starts from the very beginning.

	        for( int i = 0; i < rtspUtil.getNumberOfTracks(); i++) {
		    data_sources[ i].flush();
	        }
	    } else {
		rtspUtil.setProcessError( "Media tracks not supported");
		realized= false;
	    }
        }

        return realized;
    
public voidminThresholdReached(javax.media.protocol.DataSource ds)

	synchronized (readySync) {
	    for( int i = 0; i < rtspUtil.getNumberOfTracks(); i++) {
	        if (ds == data_sources[ i]) {		    
		    track_ready[ i] = true;
		    break;
		}
	    }

	    boolean all_ready = true;
	    
	    for( int i = 0; i < rtspUtil.getNumberOfTracks(); i++) {
	        if (!track_ready[ i]) {
		    all_ready = false;
		    break;
		}
	    }

	    if( all_ready) {
		readySync.notifyAll();
	    }
	}
    
public voidrtspStop()

	rtspUtil.setStartPos( getMediaTime().getNanoseconds());
	rtspUtil.rtspStop();
    
public floatsetRate(float rate)

	if (getState() < Realized) {
	    throwError(new NotRealizedError("Cannot set rate on an unrealized Player."));
	}

	// Cannot play any rate other than 1.0.
	return 1.0f;
    
public voidsetSource(javax.media.protocol.DataSource source)


        if (source instanceof com.sun.media.protocol.rtsp.DataSource) {
            MediaLocator ml = source.getLocator();

            try {
                url = ml.toString();
            } catch (Exception e) {
                throw new IncompatibleSourceException();
            }
        } else {
            throw new IncompatibleSourceException();
        }
    
public voidsetStopTime(Time t)

	controllerSetStopTime(t);
    
private voidstartPlayers()

        for (int i = 0; i < playerList.size(); i++) {
            Player player = (Player) playerList.elementAt(i);

            player.start();
        }
    
protected voidstopAtTime()

	controllerStopAtTime();
    
private voidstopPlayers()

        for (int i = 0; i < playerList.size(); i++) {
            Player player = (Player) playerList.elementAt(i);

            player.stop();
        }
    
public voidtimerExpired()

        timer = null;
	
        processEndOfMedia();
    
public synchronized voidupdate(ReceiveStreamEvent event)

        // find the sourceRTPSM for this event
        RTPManager source = (RTPManager) event.getSource();

        // create a new player if a new recvstream is detected
        if (event instanceof NewReceiveStreamEvent) {
            // get a handle over the ReceiveStream
            ReceiveStream stream = ((NewReceiveStreamEvent) event).getReceiveStream();

            Participant part = stream.getParticipant();

            int numberOfTracks= rtspUtil.getNumberOfTracks();
	       
	    for( int i = 0; i < numberOfTracks; i++) {
	        if( source == rtspUtil.getRTPManager( i)) {
	            DataSource ds = (com.sun.media.protocol.rtp.DataSource)stream.getDataSource();
		    
	            try {
	      	        players[ i] = javax.media.Manager.createPlayer(ds);
   		    } catch (Exception e) {
		        System.err.println("Failed to create a player " +
                                           "from the given Data Source: " + e);
		    }
		    
		    try {
                        waitFailed= false;

                        players[ i].addControllerListener(new StateListener());			
 		        players[ i].realize();

		        waitForState(players[ i], Player.Realized);
		    } catch( Exception e) {
		        // System.out.println( failed to realize.");
		    }

	            if( players[ i].getState() == Player.Realized) {
                        playerList.addElement(players[ i]);
						
       	                ds.setBufferListener(this);

		        data_sources[ i]= ds;
		    } else {
			players[ i].close();			
	      	        players[ i]= null;
			
		        rtspUtil.removeTrack( i);
		    }

	            break;
	        }		
	    }

	    // Notify when all the players are realized.
            if (playerList.size() == rtspUtil.getNumberOfTracks()) {
                dataReceived = true;

		synchronized (this) {
                    notifyAll();
                }
            }
        } else if (event instanceof ByeEvent) {
        }
    
public voidupdateStats()


    
public booleanvideoEnabled()

        boolean enabled = true;

        return enabled;
    
private synchronized booleanwaitForData()

                
        try {
            synchronized (this) {
                while (!dataReceived) {
                    wait();
                }
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        return dataReceived;
    
private synchronized voidwaitForState(Player p, int state)

       			
        while (p.getState() < state && !waitFailed) {
            synchronized (stateSync) {
                try {
                    stateSync.wait();
                } catch (InterruptedException ie) {
                }
            }
        }