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

📄 videotransmitnat.java

📁 本视频会议服务器端代码:根据自己定义的协议:能构穿透nat 需要java jmf框架 * 我开放源代码是为了更好的让java这门程序艺术更好的发展
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 *     程序员杨龙:本视频会议服务器端代码:根据自己定义的协议:能构穿透nat 需要java jmf框架
 *     我开放源代码是为了更好的让java这门程序艺术更好的发展:您可以研究代码,您可以自己使用
 *     但是不要使用在商业用途上 让我们更好的把开源事业在中国做下去
 *     2008年 3月  杨龙 完成服务器端的框架 
 *     信箱 :y_flash@163.com
 *     QQ:274797328
 *     www.0351soft.com   www.lx08.com  
 */

package ytp.javaserver.server;

/**
 *
 * @author Administrator
 */
import java.io.*;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.SocketException;
import javax.media.*;
import javax.media.protocol.*;
import javax.media.protocol.DataSource;
import javax.media.format.*;
import javax.media.control.TrackControl;
import javax.media.rtp.*;
import javax.media.rtp.rtcp.*;

public class VideoTransmitNat {

    // Input MediaLocator
    // Can be a file or http or capture source
    private MediaLocator locator;
    private String ipAddress;
    private String port;
    private String ipData;
    private String portData;
    private String ipCon;
    private String portCon;

    private Processor processor = null;
    private Processor proCone = null;
    private DataSink  rtptransmitter = null;
    private DataSource dataOutput = null;

    private int portBase;

    private RTPManager rtpMgrs[];

    public VideoTransmitNat(MediaLocator locator,
			 String ipAddressData,
			 String portData,
                         String ipCon,
                         String portCon,
                         Format format) {
	
	this.locator = locator;
	this.ipAddress = ipAddress;
	this.port = port;
        
        this.ipData = ipAddressData;
        this.ipCon = ipCon;
        this.portData = portData;
        this.portCon = portCon;
        
    }

    /**
     * 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;
		for (int i = 0; i < rtpMgrs.length; i++) {
		    rtpMgrs[i].removeTargets( "Session ended.");
		    rtpMgrs[i].dispose();
		}
	    }
	}
    }

    private String createProcessor() {
	if (locator == null)
	    return "Locator is null";

	DataSource ds;
	DataSource clone;

	try {
	    ds = javax.media.Manager.createDataSource(locator);
	} catch (Exception e) {
	    return "Couldn't create DataSource";
	}

	// Try to create a processor to handle the input media locator
	try {
	    processor = javax.media.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";

	// Set the output content descriptor to RAW_RTP
	// This will limit the supported formats reported from
	// Track.getSupportedFormats to only valid RTP formats.
	ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
	processor.setContentDescriptor(cd);

	Format supported[];
	Format chosen;
	boolean atLeastOneTrack = false;

	// Program the tracks.
	for (int i = 0; i < tracks.length; i++) {
	    Format format = tracks[i].getFormat();
	    if (tracks[i].isEnabled()) {

		supported = tracks[i].getSupportedFormats();

		// We've set the output content to the RAW_RTP.
		// So all the supported formats should work with RTP.
		// We'll just pick the first one.

		if (supported.length > 0) {
		    if (supported[0] instanceof AudioFormat) {
			// For video formats, we should double check the
			// sizes since not all formats work in all sizes.
			chosen = tracks[i].getFormat();
		    } else
		    chosen = supported[0];
		    tracks[i].setFormat(chosen);
		    System.err.println("Track " + i + " is set to transmit as:");
		    System.err.println("  " + chosen);
		    atLeastOneTrack = true;
		} else
		    tracks[i].setEnabled(false);
	    } else
		tracks[i].setEnabled(false);
	}

	if (!atLeastOneTrack)
	    return "Couldn't set any of the tracks to a valid RTP format";

	// Realize the processor. This will internally create a flow
	// graph and attempt to create an output datasource for JPEG/RTP
	// audio 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;
    }


    /**
     * Use the RTPManager API to create sessions for each media 
     * track of the processor.
     */
    private String createTransmitter() {

	// Cheated.  Should have checked the type.
	PushBufferDataSource pbds = (PushBufferDataSource)dataOutput;
	PushBufferStream pbss[] = pbds.getStreams();

	rtpMgrs = new RTPManager[pbss.length];
	SendStream sendStream;
	int port;
	SourceDescription srcDesList[];

	for (int i = 0; i < pbss.length; i++) {
	    try {
		rtpMgrs[i] = RTPManager.newInstance();	    

		port = portBase + 2*i;
		
		// Initialize the RTPManager with the RTPSocketAdapter
		
                
                SessionAddress romoto = new SessionAddress();
                romoto.setDataHostAddress(InetAddress.getByName(this.ipData));
                romoto.setDataPort(Integer.parseInt(this.portData));
                romoto.setControlHostAddress(InetAddress.getByName(this.ipData));
                romoto.setControlPort(Integer.parseInt(this.portCon));
                
                SessionAddress local = new SessionAddress(InetAddress.getLocalHost(),port);
                
                
                
                
                rtpMgrs[i].initialize(local);
                rtpMgrs[i].addTarget(romoto);
                //这个地方应该加入远程地址的Inetaddress
                
                

		System.err.println( "Created RTP session: " + ipAddress + " " + port);
		
		sendStream = rtpMgrs[i].createSendStream(dataOutput, i);		
		sendStream.start();
	    } catch (Exception  e) {
		return e.getMessage();
	    }
	}

	return null;
    }
    /****************************************************************
     * 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();
		}
	    }
	}
    }


    /****************************************************************
     * Sample Usage for AVTransmit3 class
     ****************************************************************/
    
    public static void main(String [] args) {
	// We need three parameters to do the transmission
	// For example,
	//   java AVTransmit3 file:/C:/media/test.mov  129.130.131.132 42050
	
/*	if (args.length < 3) {

⌨️ 快捷键说明

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