⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 videotransmitter.java

📁 Its video trNSMITT FILE USING JMF
💻 JAVA
字号:
/*
 * @(#)VideoTransmitter.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.
 *
 * Modified by Frank McCown on May 2002 for use in ROCW - thesis project.
 *
 * Transmits a video file from the MediaServer or captured video from a CamProcessor
 * to a CamController using RTP.
 */

import java.awt.*;
import javax.media.*;
import javax.media.rtp.*;
import javax.media.rtp.event.*;
import javax.media.datasink.*;
import javax.media.protocol.*;
import javax.media.format.*;
import javax.media.control.TrackControl;
import javax.media.control.QualityControl;
import java.io.*;

public class VideoTransmitter implements DataSinkListener
{
  private String ipAddress;
  private String port;

  public static Processor processor = null;  // made static to test with RTPExport
  private DataSink  rtptransmitter = null;	 // Data sink for transmitting to CamControllers
  private DataSource dataOutput = null;      // RTP-encoded data source
	private DataSource dataSource = null;	     // .mov file or web cam data source

	    
  public VideoTransmitter(DataSource dataSource, String ipAddress, String port) 
  {
		this.dataSource = dataSource;
		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();   // Returns error message as result, so null means no errors
		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();  // Returns error message as result, so null means no errors
		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) 
  		{
  			System.out.println("Stopping processor...");
				processor.stop();
				processor.close();  // TENDS TO HANG A LOT.  WHY???
				processor = null;
				System.out.println("Stopping rtptransmitter...");
				rtptransmitter.close();
				rtptransmitter = null;
				System.out.println("Everything is stopped.");
	    }
		}
  }

  private String createProcessor() 
  {
		// Try to create a processor to handle the input data source
		try 
		{
		  processor = Manager.createProcessor(dataSource);
		} 
		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: " + 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);
		
		System.out.println("Transmitting video to " + 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.addDataSinkListener(this);
		  rtptransmitter.open();
		  rtptransmitter.start();
		  dataOutput.start();
//System.out.println("dataOutput="+dataOutput);
//System.out.println("dataSource="+dataSource);
		} 
		catch (Exception e) 
		{
			e.printStackTrace();
		  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) 
  {
		Control cs[] = p.getControls();
		QualityControl qc = null;
		VideoFormat jpegFmt = new VideoFormat(VideoFormat.JPEG);
	
		// Loop through the controls to find the Quality control for
	 	// the JPEG encoder.
		for (int i = 0; i < cs.length; i++) 
		{
	    if (cs[i] instanceof QualityControl && cs[i] instanceof Owned) 
	    {
				Object owner = ((Owned)cs[i]).getOwner();
	
				// Check to see if the owner is a Codec.
				// Then check for the output format.
				if (owner instanceof Codec) 
				{
			    Format fmts[] = ((Codec)owner).getSupportedOutputFormats(null);
			    for (int j = 0; j < fmts.length; j++) 
			    {
						if (fmts[j].matches(jpegFmt)) 
						{
				    	qc = (QualityControl)cs[i];
		    		  qc.setQuality(val);
				    	System.err.println("- Setting quality to " + 	val + " on " + qc);
				    	break;
						}
			    }
				}
			
				if (qc != null)
			    break;
		  }
		}
  }
  
  
  /**
   * DataSinkListener - not receiving EndOfStreamEvent because dataSource
   * is not used for output DataSource.  Must instead check media time
   * in processing thread.
   */
  public synchronized void dataSinkUpdate(DataSinkEvent evt) 
  {
  	System.out.println("\nReceived DataSinkEvent\n");
  	if (evt instanceof EndOfStreamEvent) 
		{
			System.out.println("EndOfStreamEvent");
		}
  }
  

    /****************************************************************
     * Convenience methods to handle processor's state changes.
     ****************************************************************/
    
  private Integer stateLock = new Integer(0);
  private boolean failed = false;
    
  Integer getStateLock() 
  {
		return stateLock;
  }

  void setFailed() 
  {
		failed = true;
  }
    
  private synchronized boolean waitForState(Processor p, int state) 
  {
		p.addControllerListener(new StateListener());
		failed = false;
	
		// Call the required method on the processor
		if (state == Processor.Configured) 
		  p.configure();
		else if (state == Processor.Realized) 
		  p.realize();
		
	
		// Wait until we get an event that confirms the
		// success of the method, or a failure event.
		// See StateListener inner class
		while (p.getState() < state && !failed) 
		{
		  synchronized (getStateLock()) 
		  {
				try 
				{
			    getStateLock().wait();
				} 
				catch (InterruptedException ie) 
				{
			    return false;
				}
		  }
		}
	
		if (failed)
		  return false;
		else
		  return true;
	}

    /****************************************************************
     * Inner Classes
     ****************************************************************/

  class StateListener implements ControllerListener 
  {
		public void controllerUpdate(ControllerEvent ce) 
		{
	    // If there was an error during configure or
	    // realize, the processor will be closed
	    if (ce instanceof ControllerClosedEvent)
				setFailed();
	
		  // All controller events, send a notification
		  // to the waiting thread in waitForState method.
		  if (ce instanceof ControllerEvent) 
		  {
				synchronized (getStateLock()) 
				{
			    getStateLock().notifyAll();
				}
		  }
		}
  }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -