java调用摄像头基于JMF的视频传输源码实例教程



java调用摄像头基于JMF的视频传输源码实例教程。

接收端

  1. import java.applet.Applet;
  2. import java.awt.Button;
  3. import java.awt.Component;
  4. import java.awt.TextField;
  5. import java.awt.event.ActionEvent;
  6. import java.awt.event.ActionListener;
  7. import java.net.InetAddress;
  8. import javax.media.ControllerEvent;
  9. import javax.media.ControllerListener;
  10. import javax.media.Player;
  11. import javax.media.RealizeCompleteEvent;
  12. import javax.media.control.BufferControl;
  13. import javax.media.protocol.DataSource;
  14. import javax.media.rtp.Participant;
  15. import javax.media.rtp.RTPControl;
  16. import javax.media.rtp.RTPManager;
  17. import javax.media.rtp.ReceiveStream;
  18. import javax.media.rtp.ReceiveStreamListener;
  19. import javax.media.rtp.SessionAddress;
  20. import javax.media.rtp.SessionListener;
  21. import javax.media.rtp.event.ByeEvent;
  22. import javax.media.rtp.event.NewParticipantEvent;
  23. import javax.media.rtp.event.NewReceiveStreamEvent;
  24. import javax.media.rtp.event.ReceiveStreamEvent;
  25. import javax.media.rtp.event.SessionEvent;
  26. import javax.media.rtp.event.StreamMappedEvent;
  27. // 头一段时间做jmf程序,要把截获的视频流,潜入到网页中,并播放;
  28. // 在网上找了很多例子,是弹出 frame 框形式的,没有做成嵌入到 applet 里面,
  29. // 自己做了一个嵌入到 applet 里面的。也就是把播放器嵌入到 applet 里面,
  30. // 而不是弹出一个 Frame 框,并且定义了两个按钮;一个启动,一个停止;以下是源码;
  31. // 解压码是:xuedijiujiu 这是个客户端 applet 程序程序,实现视频的接受和播放;
  32. // 服务器端可以用JMStudio来辅助调试; 程序仅供研究
  33. public class AudioVideoReceiver extends Applet implements ControllerListener,
  34.         ReceiveStreamListener, SessionListener, Runnable {
  35.     private static final long serialVersionUID = -5570418604643606114L;
  36.     RTPManager rtpManager = null;
  37.     Player player = null;
  38.     boolean dataReceived = false; // 是否接收到数据的标志
  39.     Object dataSync = new Object(); // 专门用于锁的对象
  40.     Component component1;
  41.     Component component2;
  42.     Button btnStartVideo;
  43.     Button btnStopVideo;
  44.     TextField tfServerIP;
  45.     public void init() {
  46.         this.setLayout(null);
  47.         // 添加两个按钮,并注册相应的事件!
  48.         btnStartVideo = new Button(“start”);
  49.         btnStartVideo.setBounds(10, 350, 80, 20);
  50.         btnStartVideo.addActionListener(new ActionListener() {
  51.             public void actionPerformed(ActionEvent e) {
  52.                 if (player == null) {
  53.                     Thread t = new Thread(AudioVideoReceiver.this);
  54.                     t.start();
  55.                     System.out.println(“thread start”);
  56.                 }
  57.             }
  58.         });
  59.         this.add(btnStartVideo);
  60.         // —————————————————–
  61.         btnStopVideo = new Button(“stop”);
  62.         btnStopVideo.setBounds(150, 350, 80, 20);
  63.         btnStopVideo.addActionListener(new ActionListener() {
  64.             public void actionPerformed(ActionEvent e) {
  65.                 if (player != null) {
  66.                     remove(component1);
  67.                     remove(component2);
  68.                 }
  69.                 stopVideo();
  70.                 System.out.println(“thread stop”);
  71.             }
  72.         });
  73.         this.add(btnStopVideo);
  74.         this.setSize(350, 380);
  75.     }
  76.     protected boolean initialize() {
  77.         try {
  78.             rtpManager = RTPManager.newInstance();  // 为每一个RTP会话产生一个RTP管理器
  79.             rtpManager.addSessionListener(this);    // 添加会话监听
  80.             rtpManager.addReceiveStreamListener(this); // 添加接收到数据的监听
  81.             // 特别注意的地方:不能将本地地址设置为“127.0.0.1”,必须要实际的ip地址!!
  82. //          InetAddress ipAddress = InetAddress.getByName(“224.224.123.123″);   // 接收广播
  83.             InetAddress ipAddress = InetAddress.getByName(“172.17.21.170″); // 接收单播
  84.             SessionAddress localAddress = null;
  85.             SessionAddress targetAddress = null;
  86.             // 说明:当 ip 地址为“224.224.123.123”的时候,属于组播(亦称广播,能被多个接收端接收)
  87.             //      当 ip 地址为“110.52.206.144”的时候,属于单播,会自动跳到 else 分支中去!!
  88.             if (ipAddress.isMulticastAddress()) { // 对于组播,本地和目的地的IP地址相同,均采用组播地址
  89. System.out.println(“is MulticastAddress()”);
  90.                 localAddress = new SessionAddress(ipAddress, 22222);
  91.                 targetAddress = new SessionAddress(ipAddress, 22222);
  92.             } else {
  93. System.out.println(“is Not MulticastAddress()”);
  94.                 localAddress = new SessionAddress(InetAddress.getLocalHost(), 8888); // 用本机IP地址和端口号构造源会话地址
  95.                 targetAddress = new SessionAddress(ipAddress, 3000); // 用目的机(发送端)的IP地址和端口号构造目的会话地址
  96.             }
  97.             rtpManager.initialize(localAddress); // 将本机会话地址给RTP管理器
  98.             BufferControl bc = (BufferControl)rtpManager.getControl(“javax.media.control.BufferControl”);
  99.             if (bc != null) {
  100.                 bc.setBufferLength(350); // 设置缓冲区大小(也可以使用其他值)
  101.             }
  102.             rtpManager.addTarget(targetAddress); // 加入目的会话地址
  103.         } catch (Exception e) {
  104.             System.err.println(“Cannot create the RTP Session: ” + e.getMessage());
  105.             return false;
  106.         }
  107.         // 等待数据到达
  108.         long then = System.currentTimeMillis();
  109.         long waitingPeriod = 6000; // 最多等待60秒
  110.         try {
  111.             synchronized (dataSync) {
  112.                 // 等待上面所设定的时间
  113.                 while (!dataReceived && System.currentTimeMillis() – then < waitingPeriod) {
  114.                     if (!dataReceived) {
  115.                         System.err.println(“  – Waiting for RTP data to arrive…”);
  116.                     }
  117.                     dataSync.wait(1000);
  118.                 }
  119.             }
  120.         } catch (Exception e) {
  121.             e.printStackTrace();
  122.         }
  123.         if (!dataReceived) { // 在设定的时间内没有等到数据
  124.             System.err.println(“No RTP data was received.”);
  125.             player.close();
  126.             player.stop();
  127.             return false;
  128.         }
  129.         return true;
  130.     }
  131.     public void start() {
  132.         if (player != null) {
  133.             player.start();
  134.         }
  135.     }
  136.     public void stopVideo() {
  137.         if (player != null) {
  138.             player.close();
  139.             player = null;
  140.         }
  141.         if (rtpManager != null) {
  142.             rtpManager.removeTargets(“Closing session from RTPReceive”);
  143.             rtpManager.dispose(); // 关闭RTP会话管理器
  144.             rtpManager = null;
  145.         }
  146.     }
  147.     public void destroy() {
  148.         if (player != null) {
  149.             player.close();
  150.             player = null;
  151.         }
  152.         if (rtpManager != null) {
  153.             rtpManager.removeTargets(“Closing session from RTPReceive”);
  154.             rtpManager.dispose(); // 关闭RTP会话管理器
  155.             rtpManager = null;
  156.         }
  157.     }
  158.     public synchronized void controllerUpdate(ControllerEvent event) {
  159.         if (event instanceof RealizeCompleteEvent) {
  160.             if ((component1 = player.getVisualComponent()) != null) {
  161.                 this.add(component1);
  162.             }
  163.             component1.setBounds(10, 10, 300, 300);
  164.             if ((component2 = player.getControlPanelComponent()) != null) {
  165.                 this.add(component2);
  166.             }
  167.             component2.setBounds(10, 310, 300, 20);
  168.             validate();
  169.             System.out.println(“palyer”);
  170.         }
  171.     }
  172.     public synchronized void update(ReceiveStreamEvent evt) {
  173.         @SuppressWarnings(“unused”)
  174.         RTPManager mgr = (RTPManager) evt.getSource();
  175.         Participant participant = evt.getParticipant(); // 得到加入者(发送者)
  176.         ReceiveStream stream = evt.getReceiveStream(); // 得到接收到的数据流
  177.         if (evt instanceof NewReceiveStreamEvent) { // 接收到新的数据流
  178.             try {
  179.                 stream = ((NewReceiveStreamEvent) evt).getReceiveStream(); // 得到新数据流
  180.                 DataSource ds = stream.getDataSource(); // 得到数据源
  181.                 RTPControl ctl = (RTPControl) ds
  182.                         .getControl(“javax.media.rtp.RTPControl”); // 得到RTP控制器
  183.                 if (ctl != null) {
  184.                     System.err.println(“Recevied new RTP stream: ” + ctl.getFormat()); // 得到接收数据的格式
  185.                 } else {
  186.                     System.err.println(“Recevied new RTP stream”);
  187.                 }
  188.                 if (participant == null) {
  189.                     System.err.println(“The sender of this stream had yet to be identified.”);
  190.                 } else {
  191.                     System.err.println(“The stream comes from: ” + participant.getCNAME());
  192.                 }
  193.                 player = javax.media.Manager.createPlayer(ds); // 通过数据源构造一个媒体播放器
  194.                 if (player == null) {
  195.                     return;
  196.                 }
  197.                 player.addControllerListener(this); // 给播放器添加控制器监听
  198.                 player.realize();
  199.                 synchronized (dataSync) {
  200.                     dataReceived = true;
  201.                     dataSync.notifyAll();
  202.                 }
  203.             } catch (Exception e) {
  204.                 System.err.println(“NewReceiveStreamEvent exception” + e.getMessage());
  205.                 return;
  206.             }
  207.         } else if (evt instanceof StreamMappedEvent) { // 数据流映射事件
  208.             if (stream != null && stream.getDataSource() != null) {
  209.                 DataSource ds = stream.getDataSource();
  210.                 RTPControl ctl = (RTPControl)ds.getControl(“javax.media.rtp.RTPControl”);
  211.                 System.err.println(“  – The previously unidentified stream “);
  212.                 if (ctl != null) {
  213.                     System.err.println(“      ” + ctl.getFormat()); // 得到格式
  214.                 }
  215.                 System.err.println(“      had now been identified as sent by: “
  216.                         + participant.getCNAME());
  217.             }
  218.         } else if (evt instanceof ByeEvent) { // 数据接收完毕
  219.             System.err.println(“  – Got /’bye/’ from: ” + participant.getCNAME());
  220.             if (player != null) {
  221.                 player.close(); // 关闭播放窗口
  222.             }
  223.         }
  224.     }
  225.     public synchronized void update(SessionEvent evt) {
  226.         if (evt instanceof NewParticipantEvent) {
  227.             Participant p = ((NewParticipantEvent) evt).getParticipant();
  228.             System.err.println(“  – A new participant had just joined: “
  229.                     + p.getCNAME());
  230.         }
  231.     }
  232.     public void run() {
  233.         this.initialize();
  234.         try {
  235.             Thread.sleep(1000);
  236.         } catch (InterruptedException e) {
  237.             e.printStackTrace();
  238.         }
  239.         player.start();
  240.     }
  241. }
import java.applet.Applet;
import java.awt.Button;
import java.awt.Component;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.net.InetAddress;

import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.Player;
import javax.media.RealizeCompleteEvent;
import javax.media.control.BufferControl;
import javax.media.protocol.DataSource;
import javax.media.rtp.Participant;
import javax.media.rtp.RTPControl;
import javax.media.rtp.RTPManager;
import javax.media.rtp.ReceiveStream;
import javax.media.rtp.ReceiveStreamListener;
import javax.media.rtp.SessionAddress;
import javax.media.rtp.SessionListener;
import javax.media.rtp.event.ByeEvent;
import javax.media.rtp.event.NewParticipantEvent;
import javax.media.rtp.event.NewReceiveStreamEvent;
import javax.media.rtp.event.ReceiveStreamEvent;
import javax.media.rtp.event.SessionEvent;
import javax.media.rtp.event.StreamMappedEvent;

// 头一段时间做jmf程序,要把截获的视频流,潜入到网页中,并播放;
// 在网上找了很多例子,是弹出 frame 框形式的,没有做成嵌入到 applet 里面,
// 自己做了一个嵌入到 applet 里面的。也就是把播放器嵌入到 applet 里面,
// 而不是弹出一个 Frame 框,并且定义了两个按钮;一个启动,一个停止;以下是源码; 
// 解压码是:xuedijiujiu 这是个客户端 applet 程序程序,实现视频的接受和播放;
// 服务器端可以用JMStudio来辅助调试; 程序仅供研究
public class AudioVideoReceiver extends Applet implements ControllerListener,
		ReceiveStreamListener, SessionListener, Runnable {
	private static final long serialVersionUID = -5570418604643606114L;

	RTPManager rtpManager = null;
	Player player = null;
	boolean dataReceived = false; // 是否接收到数据的标志
	Object dataSync = new Object();	// 专门用于锁的对象

	Component component1;
	Component component2;

	Button btnStartVideo;
	Button btnStopVideo;

	TextField tfServerIP;

	public void init() {
		this.setLayout(null);
		// 添加两个按钮,并注册相应的事件!
		btnStartVideo = new Button("start");
		btnStartVideo.setBounds(10, 350, 80, 20);
		btnStartVideo.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (player == null) {
					Thread t = new Thread(AudioVideoReceiver.this);
					t.start();
					System.out.println("thread start");
				}
			}
		});
		this.add(btnStartVideo);
		// -----------------------------------------------------
		btnStopVideo = new Button("stop");
		btnStopVideo.setBounds(150, 350, 80, 20);
		btnStopVideo.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				if (player != null) {
					remove(component1);
					remove(component2);
				}
				stopVideo();
				System.out.println("thread stop");
			}
		});
		this.add(btnStopVideo);
		this.setSize(350, 380);
	}

	protected boolean initialize() {
		try {
			rtpManager = RTPManager.newInstance();	// 为每一个RTP会话产生一个RTP管理器
			rtpManager.addSessionListener(this);	// 添加会话监听
			rtpManager.addReceiveStreamListener(this); // 添加接收到数据的监听

			// 特别注意的地方:不能将本地地址设置为“127.0.0.1”,必须要实际的ip地址!!
//			InetAddress ipAddress = InetAddress.getByName("224.224.123.123");	// 接收广播
			InetAddress ipAddress = InetAddress.getByName("172.17.21.170");	// 接收单播

			SessionAddress localAddress = null;
			SessionAddress targetAddress = null;
			// 说明:当 ip 地址为“224.224.123.123”的时候,属于组播(亦称广播,能被多个接收端接收)
			// 		当 ip 地址为“110.52.206.144”的时候,属于单播,会自动跳到 else 分支中去!!
			if (ipAddress.isMulticastAddress()) { // 对于组播,本地和目的地的IP地址相同,均采用组播地址
System.out.println("is MulticastAddress()");
				localAddress = new SessionAddress(ipAddress, 22222);
				targetAddress = new SessionAddress(ipAddress, 22222);
			} else {
System.out.println("is Not MulticastAddress()");				
				localAddress = new SessionAddress(InetAddress.getLocalHost(), 8888); // 用本机IP地址和端口号构造源会话地址
				targetAddress = new SessionAddress(ipAddress, 3000); // 用目的机(发送端)的IP地址和端口号构造目的会话地址
			}

			rtpManager.initialize(localAddress); // 将本机会话地址给RTP管理器
			BufferControl bc = (BufferControl)rtpManager.getControl("javax.media.control.BufferControl");
			if (bc != null) {
				bc.setBufferLength(350); // 设置缓冲区大小(也可以使用其他值)
			}

			rtpManager.addTarget(targetAddress); // 加入目的会话地址
		} catch (Exception e) {
			System.err.println("Cannot create the RTP Session: " + e.getMessage());
			return false;
		}

		// 等待数据到达
		long then = System.currentTimeMillis();
		long waitingPeriod = 6000; // 最多等待60秒
		try {
			synchronized (dataSync) {
				// 等待上面所设定的时间
				while (!dataReceived && System.currentTimeMillis() - then < waitingPeriod) { 
					if (!dataReceived) {
						System.err.println("  - Waiting for RTP data to arrive...");
					}
					dataSync.wait(1000);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		if (!dataReceived) { // 在设定的时间内没有等到数据
			System.err.println("No RTP data was received.");
			player.close();
			player.stop();
			return false;
		}
		return true;
	}

	public void start() {
		if (player != null) {
			player.start();
		}
	}

	public void stopVideo() {
		if (player != null) {
			player.close();
			player = null;
		}
		if (rtpManager != null) {
			rtpManager.removeTargets("Closing session from RTPReceive");
			rtpManager.dispose(); // 关闭RTP会话管理器
			rtpManager = null;
		}
	}

	public void destroy() {
		if (player != null) {
			player.close();
			player = null;
		}
		if (rtpManager != null) {
			rtpManager.removeTargets("Closing session from RTPReceive");
			rtpManager.dispose(); // 关闭RTP会话管理器
			rtpManager = null;
		}
	}

	public synchronized void controllerUpdate(ControllerEvent event) {
		if (event instanceof RealizeCompleteEvent) {
			if ((component1 = player.getVisualComponent()) != null) {
				this.add(component1);
			}
			component1.setBounds(10, 10, 300, 300);
			if ((component2 = player.getControlPanelComponent()) != null) {
				this.add(component2);
			}
			component2.setBounds(10, 310, 300, 20);
			validate();
			System.out.println("palyer");
		}
	}

	public synchronized void update(ReceiveStreamEvent evt) {
		@SuppressWarnings("unused")
		RTPManager mgr = (RTPManager) evt.getSource();
		Participant participant = evt.getParticipant(); // 得到加入者(发送者)
		ReceiveStream stream = evt.getReceiveStream(); // 得到接收到的数据流

		if (evt instanceof NewReceiveStreamEvent) { // 接收到新的数据流
			try {
				stream = ((NewReceiveStreamEvent) evt).getReceiveStream(); // 得到新数据流
				DataSource ds = stream.getDataSource(); // 得到数据源

				RTPControl ctl = (RTPControl) ds
						.getControl("javax.media.rtp.RTPControl"); // 得到RTP控制器
				if (ctl != null) {
					System.err.println("Recevied new RTP stream: " + ctl.getFormat()); // 得到接收数据的格式
				} else {
					System.err.println("Recevied new RTP stream");
				}
				if (participant == null) {
					System.err.println("The sender of this stream had yet to be identified.");
				} else {
					System.err.println("The stream comes from: " + participant.getCNAME());
				}
				player = javax.media.Manager.createPlayer(ds); // 通过数据源构造一个媒体播放器
				if (player == null) {
					return;
				}
				player.addControllerListener(this); // 给播放器添加控制器监听
				player.realize();
				synchronized (dataSync) {
					dataReceived = true;
					dataSync.notifyAll();
				}
			} catch (Exception e) {
				System.err.println("NewReceiveStreamEvent exception" + e.getMessage());
				return;
			}
		} else if (evt instanceof StreamMappedEvent) { // 数据流映射事件
			if (stream != null && stream.getDataSource() != null) {
				DataSource ds = stream.getDataSource();
				RTPControl ctl = (RTPControl)ds.getControl("javax.media.rtp.RTPControl");
				System.err.println("  - The previously unidentified stream ");
				if (ctl != null) {
					System.err.println("      " + ctl.getFormat()); // 得到格式
				}
				System.err.println("      had now been identified as sent by: "
						+ participant.getCNAME());
			}
		} else if (evt instanceof ByeEvent) { // 数据接收完毕
			System.err.println("  - Got /'bye/' from: "	+ participant.getCNAME());

			if (player != null) {
				player.close(); // 关闭播放窗口
			}
		}
	}

	public synchronized void update(SessionEvent evt) {
		if (evt instanceof NewParticipantEvent) {
			Participant p = ((NewParticipantEvent) evt).getParticipant();
			System.err.println("  - A new participant had just joined: "
					+ p.getCNAME());
		}
	}

	public void run() {
		this.initialize();
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		player.start();
	}
}

发送端

 

  1. import javax.media.rtp.*;
  2. import javax.media.*;
  3. import javax.media.protocol.*;
  4. import javax.media.control.FormatControl;
  5. import javax.media.control.TrackControl;
  6. import javax.media.format.*;
  7. import java.io.IOException;
  8. import java.net.InetAddress;
  9. import java.util.*;
  10. // 很漂亮的一个音视频信号发送端的程序!接收端可用JMStudio来代替(Open RTP Session选项)!
  11. public class AudioVideoSender {
  12.     private CaptureDeviceInfo captureVideoDevice = null;
  13.     private CaptureDeviceInfo captureAudioDevice = null;
  14.     private DataSource videoDataSource = null;
  15.     private DataSource audioDataSource = null;
  16.     private Processor videoProcessor = null;
  17.     private Processor audioProcessor = null;
  18.     private RTPManager videortpManager = null;
  19.     private RTPManager audiortpManager = null;
  20.     private SendStream videoRtpstream = null;
  21.     private SendStream audioRtpstream = null;
  22.     private SessionAddress remoteAddress1 = null;
  23.     private SessionAddress remoteAddress2 = null;
  24.     @SuppressWarnings({ “unused”, “unchecked” })
  25.     private Vector sendplayerlist = new Vector();
  26.     @SuppressWarnings(“unused”)
  27.     private boolean terminatedbyClose_sender = false;
  28.     // 以下两个在配置数据源的时候要用到!
  29.     private DataSource ds = null;
  30.     private TrackControl[] track = null;
  31.     // 该方法用于获取 “视频” 和 “音频” 捕获设备的 CaptureDeviceInfo 信息对象!
  32.     private void getDeviceInfo() {
  33.         // ①获取视频捕获设备的 CaptureDeviceInfo 对象!
  34.         Vector<?> deviceList = null;
  35.         deviceList = CaptureDeviceManager.getDeviceList(null);
  36.         for (int i = 0; i < deviceList.size(); i++) {
  37.             captureVideoDevice = (CaptureDeviceInfo) deviceList.elementAt(i);
  38.             String name = captureVideoDevice.getName();
  39.             if (name.startsWith(“vfw:”)) {
  40.                 break;
  41.             }
  42.         }
  43.         // ②获取音频捕获设备的 CaptureDeviceInfo 对象!
  44.         deviceList = null;  // 清空 deviceList
  45.         deviceList = CaptureDeviceManager.getDeviceList(new AudioFormat(“linear”, 8000, 8, 1));
  46.         if (deviceList.size() > 0) {
  47.             captureAudioDevice = (CaptureDeviceInfo) deviceList.elementAt(0);
  48.         } else {
  49.             // 如果找不到支持linear, 8000 Hz, 8 bit, stereo audio这些条件的音频设备的话就退出!
  50.             System.err.println(“Device initializing failure!”);
  51.             System.exit(-1);
  52.         }
  53.     }
  54.     // 为视频捕获设备创建一个视频处理器,如果不能创建的话就退出
  55.     private void setVideoDataSource() throws Exception {
  56.         ds = Manager.createDataSource(captureVideoDevice.getLocator());
  57.         videoProcessor = Manager.createProcessor(ds);
  58.         videoProcessor.configure();
  59.         // 阻塞在这里直到配置完成
  60.         while (true) {
  61.             if (videoProcessor.getState() == Processor.Configured) {
  62.                 break;
  63.             }
  64.         }
  65.         videoProcessor.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW));
  66.         track = videoProcessor.getTrackControls();  //getTrackControls() 方法的返回值类型: TrackControl[]
  67.         boolean encodingOk = false;
  68.         // 将 track 设置成我们想要的 track,不想要的 track 统统 disable 掉!
  69.         for (int i = 0; i < track.length; i++) {
  70.             if (!encodingOk && track[i] instanceof FormatControl) {
  71.                 if (((FormatControl) track[i]).setFormat(new VideoFormat(
  72.                         VideoFormat.JPEG_RTP)) == null) {
  73.                     track[i].setEnabled(false); // 将不可用的(除VideoFormat.JPEG_RTP以外的)磁道全部设为不可用!
  74.                 } else {
  75.                     encodingOk = true;
  76.                 }
  77.             } else {
  78.                 // 我们不能将磁道设置为 .GSM 格式,因此 disable 它!
  79.                 track[i].setEnabled(false);
  80.             }
  81.         }
  82.         videoProcessor.realize();
  83.         // 阻塞直到完成视频处理器的实现!
  84.         while (true) {
  85.             if (videoProcessor.getState() == Processor.Realized) {
  86.                 break;
  87.             }
  88.         }
  89.         try {
  90.             videoDataSource = videoProcessor.getDataOutput();
  91.         } catch (NotRealizedError e) {
  92.             System.exit(-1);    // 不能成功配置视频数据源的话下面肯定进行不下去,直接退出
  93.         }
  94. System.out.println(“videoDataSource is ready!”);
  95.     }
  96.     // 为音频捕获设备创建一个音频处理器,如果不能创建就退出程序
  97.     private void setAudioDataSource() throws Exception {
  98.         ds = Manager.createDataSource(captureAudioDevice.getLocator());
  99.         audioProcessor = Manager.createProcessor(ds);
  100.         audioProcessor.configure();
  101.         // 阻塞直到完成音频处理器的配置!
  102.         while (true) {
  103.             if (audioProcessor.getState() == Processor.Configured) {
  104.                 break;
  105.             }
  106.         }
  107.         audioProcessor.setContentDescriptor(new ContentDescriptor(ContentDescriptor.RAW));
  108.         track = audioProcessor.getTrackControls();
  109.         boolean encodingOk = false;
  110.         for (int i = 0; i < track.length; i++) {
  111.             if (!encodingOk && (track[i] instanceof FormatControl)) {
  112.                 if (((FormatControl) track[i]).setFormat(new AudioFormat(
  113.                         AudioFormat.ULAW_RTP, 8000, 8, 1)) == null) {
  114.                     track[i].setEnabled(false);
  115.                 } else {
  116.                     encodingOk = true;
  117.                 }
  118.             } else {
  119.                 track[i].setEnabled(false);
  120.             }
  121.         }
  122.         audioProcessor.realize();
  123.         while (true) {
  124.             if (audioProcessor.getState() == Processor.Realized) {
  125.                 break;
  126.             }
  127.         }
  128.         try {
  129.             audioDataSource = audioProcessor.getDataOutput();
  130.         } catch (NotRealizedError e) {
  131.             System.exit(-1);
  132.         }
  133. System.out.println(“audioDataSource is ready!”);
  134.     }
  135.     // 开始传送视频和音频数据!
  136.     public void transmitStart(String targetAddress, String targetPort) {
  137.         videortpManager = RTPManager.newInstance();
  138.         audiortpManager = RTPManager.newInstance();
  139.         SessionAddress localAddress1 = null;
  140.         SessionAddress localAddress2 = null;
  141.         // create the local endpoint for the local interface on any local port
  142.         localAddress1 = new SessionAddress();
  143.         localAddress2 = new SessionAddress();
  144.         try {
  145.             videortpManager.initialize(localAddress1);
  146.             audiortpManager.initialize(localAddress2);
  147.         } catch (Exception e) {
  148.             e.printStackTrace();
  149.         }
  150.         // specify the remote endpoint of this unicast session
  151.         try {
  152.             InetAddress ipAddress = InetAddress.getByName(targetAddress);
  153.             remoteAddress1 = new SessionAddress(ipAddress, Integer.parseInt(targetPort));
  154.             videortpManager.addTarget(remoteAddress1);
  155.             remoteAddress2 = new SessionAddress(ipAddress, Integer.parseInt(targetPort) + 2);
  156.             audiortpManager.addTarget(remoteAddress2);
  157.             System.out.println();
  158.             System.out.println(“data address     ” + localAddress1.getDataAddress());
  159.             System.out.println(“contorl address  ” + localAddress1.getControlAddress());
  160.             System.out.println(“data port        ” + localAddress1.getDataPort());
  161.             System.out.println(“control port     ” + localAddress1.getControlPort());
  162.             System.out.println();
  163.             System.out.println(“data address     ” + localAddress2.getDataAddress());
  164.             System.out.println(“contorl address  ” + localAddress2.getControlAddress());
  165.             System.out.println(“data port        ” + localAddress2.getDataPort());
  166.             System.out.println(“control port     ” + localAddress2.getControlPort());
  167.             System.out.println();
  168.             videoRtpstream = videortpManager.createSendStream(videoDataSource, 0);
  169.             audioRtpstream = audiortpManager.createSendStream(audioDataSource, 0);
  170.             videoProcessor.start();
  171.             audioProcessor.start();
  172.             videoRtpstream.start();
  173.             audioRtpstream.start();
  174.         } catch (Exception e) {
  175.             e.printStackTrace();
  176.         }
  177.     }
  178.     // 停止传送视频和音频数据!
  179.     public void transmitStop() throws IOException, InvalidSessionAddressException {
  180.         videoRtpstream.stop();
  181.         videoRtpstream.close();
  182.         videoProcessor.stop();
  183.         audioRtpstream.stop();
  184.         audioRtpstream.close();
  185.         audioProcessor.close();
  186.         // close the connection if no longer needed.
  187.         videortpManager.removeTarget(remoteAddress1, “client disconnected.”);
  188.         audiortpManager.removeTarget(remoteAddress2, “client disconnected.”);
  189.         // call dispose at the end of the life-cycle of this RTPManager so
  190.         // it is prepared to be garbage-collected.
  191.         videortpManager.dispose();
  192.         audiortpManager.dispose();
  193.         System.out.println(“Now releasing the resource!”);
  194.         videoProcessor.deallocate();
  195.         audioProcessor.deallocate();
  196.         videoDataSource.disconnect();
  197.         audioDataSource.disconnect();
  198.     }
  199.     public AudioVideoSender() throws Exception {
  200.         // 初始化音视频捕获设备并为传输做好准备
  201.         this.getDeviceInfo();
  202.         this.setVideoDataSource();
  203.         this.setAudioDataSource();
  204.     }
  205.     public static void main(String[] args) {
  206.         try {
  207.             AudioVideoSender tc = new AudioVideoSender();
  208.             tc.transmitStart(“172.17.21.152″, “8888″);
  209.         } catch(Exception e) {
  210.             e.printStackTrace();
  211.         }
  212.     }
  213. }