gt: 	Control cs[] = p.getControls();
context: package rtp.rtptransmit.videotransmit;
  /*
   * @(#)VideoTransmit.java	1.7 01/03/13
   *
   * Copyright (c) 1999-2001 Sun Microsystems, Inc. All Rights Reserved.
   *
   * Sun grants you ("Licensee") a non-exclusive, royalty free, license to use,
   * modify and redistribute this software in source and binary code form,
   * provided that i) this copyright notice and license appear on all copies of
   * the software; and ii) Licensee does not utilize the software in a manner
   * which is disparaging to Sun.
   *
   * This software is provided "AS IS," without a warranty of any kind. ALL
   * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING ANY
   * IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
   * NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN AND ITS LICENSORS SHALL NOT BE
   * LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING
   * OR DISTRIBUTING THE SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR ITS
   * LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR DIRECT,
   * INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER
   * CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, ARISING OUT OF THE USE OF
   * OR INABILITY TO USE SOFTWARE, EVEN IF SUN HAS BEEN ADVISED OF THE
   * POSSIBILITY OF SUCH DAMAGES.
   *
   * This software is not designed or intended for use in on-line control of
   * aircraft, air traffic, aircraft navigation or aircraft communications; or in
   * the design, construction, operation or maintenance of any nuclear
   * facility. Licensee represents and warrants that it will not use or
   * redistribute the Software for such purposes.
   */
  
  import java.awt.Dimension;
  import java.io.IOException;
  
  import javax.media.Codec;
  import javax.media.Control;
  import javax.media.Controller;
  import javax.media.ControllerClosedEvent;
  import javax.media.ControllerEvent;
  import javax.media.ControllerListener;
  import javax.media.DataSink;
  import javax.media.Format;
  import javax.media.Manager;
  import javax.media.MediaException;
  import javax.media.MediaLocator;
  import javax.media.NoProcessorException;
  import javax.media.Owned;
  import javax.media.Player;
  import javax.media.Processor;
  import javax.media.control.QualityControl;
  import javax.media.control.TrackControl;
  import javax.media.format.VideoFormat;
  import javax.media.protocol.ContentDescriptor;
  import javax.media.protocol.DataSource;
  
  public class VideoTransmit {
  
      // Input MediaLocator
      // Can be a file or http or capture source
      private MediaLocator locator;
      private String ipAddress;
      private String port;
  
      private Processor processor = null;
      private DataSink  rtptransmitter = null;
      private DataSource dataOutput = null;
      
      public VideoTransmit(MediaLocator locator,
  			 String ipAddress,
  			 String port) {
  	
  	this.locator = locator;
  	this.ipAddress = ipAddress;
  	this.port = port;
      }
  
      /**
       * Starts the transmission. Returns null if transmission started ok.
       * Otherwise it returns a string with the reason why the setup failed.
       */
      public synchronized String start() {
  	String result;
  
  	// Create a processor for the specified media locator
  	// and program it to output JPEG/RTP
  	result = createProcessor();
  	if (result != null)
  	    return result;
  
  	// Create an RTP session to transmit the output of the
  	// processor to the specified IP address and port no.
  	result = createTransmitter();
  	if (result != null) {
  	    processor.close();
  	    processor = null;
  	    return result;
  	}
  
  	// Start the transmission
  	processor.start();
  	
  	return null;
      }
  
      /**
       * Stops the transmission if already started
       */
      public void stop() {
  	synchronized (this) {
  	    if (processor != null) {
  		processor.stop();
  		processor.close();
  		processor = null;
  		rtptransmitter.close();
  		rtptransmitter = null;
  	    }
  	}
      }
  
      private String createProcessor() {
  	if (locator == null)
  	    return "Locator is null";
  
  	DataSource ds;
  	DataSource clone;
  
  	try {
  	    ds = Manager.createDataSource(locator);
  	} catch (Exception e) {
  	    return "Couldn't create DataSource";
  	}
  
  	// Try to create a processor to handle the input media locator
  	try {
  	    processor = Manager.createProcessor(ds);
  	} catch (NoProcessorException npe) {
  	    return "Couldn't create processor";
  	} catch (IOException ioe) {
  	    return "IOException creating processor";
  	} 
  
  	// Wait for it to configure
  	boolean result = waitForState(processor, Processor.Configured);
  	if (result == false)
  	    return "Couldn't configure processor";
  
  	// Get the tracks from the processor
  	TrackControl [] tracks = processor.getTrackControls();
  
  	// Do we have atleast one track?
  	if (tracks == null || tracks.length < 1)
  	    return "Couldn't find tracks in processor";
  
  	boolean programmed = false;
  
  	// Search through the tracks for a video track
  	for (int i = 0; i < tracks.length; i++) {
  	    Format format = tracks[i].getFormat();
  	    if (  tracks[i].isEnabled() &&
  		  format instanceof VideoFormat &&
  		  !programmed) {
  		
  		// Found a video track. Try to program it to output JPEG/RTP
  		// Make sure the sizes are multiple of 8's.
  		Dimension size = ((VideoFormat)format).getSize();
  		float frameRate = ((VideoFormat)format).getFrameRate();
  		int w = (size.width % 8 == 0 ? size.width :
  				(int)(size.width / 8) * 8);
  		int h = (size.height % 8 == 0 ? size.height :
  				(int)(size.height / 8) * 8);
  		VideoFormat jpegFormat = new VideoFormat(VideoFormat.JPEG_RTP,
  							 new Dimension(w, h),
  							 Format.NOT_SPECIFIED,
  							 Format.byteArray,
  							 frameRate);
  		tracks[i].setFormat(jpegFormat);
  		System.err.println("Video transmitted as:");
  		System.err.println("  " + jpegFormat);
  		// Assume succesful
  		programmed = true;
  	    } else
  		tracks[i].setEnabled(false);
  	}
  
  	if (!programmed)
  	    return "Couldn't find video track";
  
  	// Set the output content descriptor to RAW_RTP
  	ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
  	processor.setContentDescriptor(cd);
  
  	// Realize the processor. This will internally create a flow
  	// graph and attempt to create an output datasource for JPEG/RTP
  	// video frames.
  	result = waitForState(processor, Controller.Realized);
  	if (result == false)
  	    return "Couldn't realize processor";
  
  	// Set the JPEG quality to .5.
  	setJPEGQuality(processor, 0.5f);
  
  	// Get the output data source of the processor
  	dataOutput = processor.getDataOutput();
  	return null;
      }
  
      // Creates an RTP transmit data sink. This is the easiest way to create
      // an RTP transmitter. The other way is to use the RTPSessionManager API.
      // Using an RTP session manager gives you more control if you wish to
      // fine tune your transmission and set other parameters.
      private String createTransmitter() {
  	// Create a media locator for the RTP data sink.
  	// For example:
  	//    rtp://129.130.131.132:42050/video
  	String rtpURL = "rtp://" + ipAddress + ":" + port + "/video";
  	MediaLocator outputLocator = new MediaLocator(rtpURL);
  
  	// Create a data sink, open it and start transmission. It will wait
  	// for the processor to start sending data. So we need to start the
  	// output data source of the processor. We also need to start the
  	// processor itself, which is done after this method returns.
  	try {
  	    rtptransmitter = Manager.createDataSink(dataOutput, outputLocator);
  	    rtptransmitter.open();
  	    rtptransmitter.start();
  	    dataOutput.start();
  	} catch (MediaException me) {
  	    return "Couldn't create RTP data sink";
  	} catch (IOException ioe) {
  	    return "Couldn't create RTP data sink";
  	}
  	
  	return null;
      }
  
  
      /**
       * Setting the encoding quality to the specified value on the JPEG encoder.
       * 0.5 is a good default.
       */
      void setJPEGQuality(Player p, float val) {
  
  