转:http://blog.csdn.net/maydie1989/article/details/6820482
http://download.csdn.net/detail/maydie1989/3636156
JMF(Java Media Framework)想必大家都不陌生 它为音频和视频等媒体内容的捕获、回放、传输和编码转换等提供了一个统一的架构 视频传输大概思路如下
其中有几个常用到的类 - > ● 数据源(DataSource) ● 媒体定位器(MediaLocator) ● 播放器(Player)
● 处理器(Processor) ● 管理器(Manager) ● RTP管理器(RTPManager)
一般发送端的情况是首先获得视频音频设备实例(CaptureDeviceInfo) -> 然后得到 DataSource -> Processor -> 得到processor的输出DataSource,通过RTPManager以stream的形式发出
而接收端则是通过RTPManager得到ReceiveStream -> 还原后通过Player进行播放
发送端RTPTransmiter
- public class RTPTransmiter
- {
- private Processor processor;
- private Integer lock = new Integer(0);
- private DataSource dataOutput;
- private boolean failed = false;
- private RTPManager[] rtpMgrs;
- private String ipAddress;
- private int portBase;
- private int destPortBase; //接收端 基础端口
- public RTPTransmiter(String ipAddress,int portBase,int destPortBase) throws Exception
- {
- this.ipAddress = ipAddress;
- this.portBase = portBase;
- this.destPortBase = destPortBase;
- createProcessor() ;
- createTransmitter() ;
- processor.start();
- }
- private void createProcessor() throws Exception
- {
- Vector<?> devices = CaptureDeviceManager.getDeviceList(null);
- CaptureDeviceInfo diVideo = null;
- CaptureDeviceInfo diAudio = null;
- if (devices.size() > 2)
- {
- diVideo = (CaptureDeviceInfo) devices.elementAt(2);//2是视频捕捉器
- diAudio = (CaptureDeviceInfo) devices.elementAt(0);
- DataSource[] dataSources = new DataSource[2];
- dataSources[1] = Manager.createDataSource(diVideo.getLocator());
- dataSources[0] = Manager.createDataSource(diAudio.getLocator());
- processor = Manager.createProcessor(Manager.createMergingDataSource(dataSources));//合并video和audio的 datasource
- }
- if(!waitForState(processor, Processor.Configured)) //configure processor
- throw new Exception("cant configured processor");
- ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
- processor.setContentDescriptor(cd);
- if(!waitForState(processor, Controller.Realized)) //realize processor
- throw new Exception("cant realized processor");
- setJPEGQuality(processor, 0.5f);//设置图像质量 百分比
- dataOutput = processor.getDataOutput();
- }
- private void createTransmitter()
- {
- PushBufferDataSource pbds = (PushBufferDataSource)dataOutput;
- PushBufferStream pbss[] = pbds.getStreams();
- System.out.println("pbss.length is: "+pbss.length);
- rtpMgrs = new RTPManager[pbss.length];//每一个通道由一个RTPManager负责
- SessionAddress localAddr, destAddr;
- InetAddress ipAddr;
- SendStream sendStream;
- int port;
- for (int i = 0; i < pbss.length; i++)
- {
- try
- {
- rtpMgrs[i] = RTPManager.newInstance();
- port = portBase + 2*i;
- int clientPort = destPortBase +2*i;
- ipAddr = InetAddress.getByName(ipAddress);
- localAddr = new SessionAddress( InetAddress.getLocalHost(),port); //本机测 所以IP都是InetAddress.getLocalHost()
- destAddr = new SessionAddress( InetAddress.getLocalHost(), clientPort);
- rtpMgrs[i].initialize( localAddr);
- rtpMgrs[i].addTarget( destAddr);
- System.err.println( "Created RTP session: " + ipAddress + " " + port);
- sendStream = rtpMgrs[i].createSendStream(dataOutput, i);
- sendStream.start(); //开始传输
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
- }
- void setJPEGQuality(Player p, float val)
- {
- Control cs[] = p.getControls();
- QualityControl qc = null;
- VideoFormat jpegFmt = new VideoFormat(VideoFormat.JPEG);
- for (int i = 0; i < cs.length; i++)
- {
- if (cs[i] instanceof QualityControl && cs[i] instanceof Owned)
- {
- Object owner = ((Owned)cs[i]).getOwner();
- 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;
- }
- }
- }
- private synchronized boolean waitForState(Processor p, int state)
- {
- p.addControllerListener(new StateListener());
- failed = false;
- if (state == Processor.Configured)
- {
- p.configure();
- }
- else if (state == Processor.Realized)
- {
- p.realize();
- }
- while (p.getState() < state && !failed)
- {
- synchronized (lock)
- {
- try
- {
- lock.wait();
- }
- catch (InterruptedException ie)
- {
- return false;
- }
- }
- }
- if (failed)
- return false;
- else
- return true;
- }
- class StateListener implements ControllerListener
- {
- public void controllerUpdate(ControllerEvent ce)
- {
- if (ce instanceof ControllerClosedEvent)
- failed = true;
- if (ce instanceof ControllerEvent) {
- synchronized (lock) {
- lock.notifyAll();
- }
- }
- }
- }
- }
public class RTPTransmiter { private Processor processor; private Integer lock = new Integer(0); private DataSource dataOutput; private boolean failed = false; private RTPManager[] rtpMgrs; private String ipAddress; private int portBase; private int destPortBase; //接收端 基础端口 public RTPTransmiter(String ipAddress,int portBase,int destPortBase) throws Exception { this.ipAddress = ipAddress; this.portBase = portBase; this.destPortBase = destPortBase; createProcessor() ; createTransmitter() ; processor.start(); } private void createProcessor() throws Exception { Vector<?> devices = CaptureDeviceManager.getDeviceList(null); CaptureDeviceInfo diVideo = null; CaptureDeviceInfo diAudio = null; if (devices.size() > 2) { diVideo = (CaptureDeviceInfo) devices.elementAt(2);//2是视频捕捉器 diAudio = (CaptureDeviceInfo) devices.elementAt(0); DataSource[] dataSources = new DataSource[2]; dataSources[1] = Manager.createDataSource(diVideo.getLocator()); dataSources[0] = Manager.createDataSource(diAudio.getLocator()); processor = Manager.createProcessor(Manager.createMergingDataSource(dataSources));//合并video和audio的 datasource } if(!waitForState(processor, Processor.Configured)) //configure processor throw new Exception("cant configured processor"); ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP); processor.setContentDescriptor(cd); if(!waitForState(processor, Controller.Realized)) //realize processor throw new Exception("cant realized processor"); setJPEGQuality(processor, 0.5f);//设置图像质量 百分比 dataOutput = processor.getDataOutput(); } private void createTransmitter() { PushBufferDataSource pbds = (PushBufferDataSource)dataOutput; PushBufferStream pbss[] = pbds.getStreams(); System.out.println("pbss.length is: "+pbss.length); rtpMgrs = new RTPManager[pbss.length];//每一个通道由一个RTPManager负责 SessionAddress localAddr, destAddr; InetAddress ipAddr; SendStream sendStream; int port; for (int i = 0; i < pbss.length; i++) { try { rtpMgrs[i] = RTPManager.newInstance(); port = portBase + 2*i; int clientPort = destPortBase +2*i; ipAddr = InetAddress.getByName(ipAddress); localAddr = new SessionAddress( InetAddress.getLocalHost(),port); //本机测 所以IP都是InetAddress.getLocalHost() destAddr = new SessionAddress( InetAddress.getLocalHost(), clientPort); rtpMgrs[i].initialize( localAddr); rtpMgrs[i].addTarget( destAddr); System.err.println( "Created RTP session: " + ipAddress + " " + port); sendStream = rtpMgrs[i].createSendStream(dataOutput, i); sendStream.start(); //开始传输 } catch (Exception e) { e.printStackTrace(); } } } void setJPEGQuality(Player p, float val) { Control cs[] = p.getControls(); QualityControl qc = null; VideoFormat jpegFmt = new VideoFormat(VideoFormat.JPEG); for (int i = 0; i < cs.length; i++) { if (cs[i] instanceof QualityControl && cs[i] instanceof Owned) { Object owner = ((Owned)cs[i]).getOwner(); 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; } } } private synchronized boolean waitForState(Processor p, int state) { p.addControllerListener(new StateListener()); failed = false; if (state == Processor.Configured) { p.configure(); } else if (state == Processor.Realized) { p.realize(); } while (p.getState() < state && !failed) { synchronized (lock) { try { lock.wait(); } catch (InterruptedException ie) { return false; } } } if (failed) return false; else return true; } class StateListener implements ControllerListener { public void controllerUpdate(ControllerEvent ce) { if (ce instanceof ControllerClosedEvent) failed = true; if (ce instanceof ControllerEvent) { synchronized (lock) { lock.notifyAll(); } } } } }
RTPReciver 核心部分 需要为每个rtpManager添加 ReceiveStreamListener和SessionListener ,在ReceiveStreamListener的NewReceiveStreamEvent事件中添加ControllerListener
- mgrs[i] = (RTPManager) RTPManager.newInstance();
- //添加 SessionListener
- mgrs[i].addSessionListener(this);
- //添加 ReceiveStreamListener
- mgrs[i].addReceiveStreamListener(this);
- //得到服务器端IP地址
- ipAddr = InetAddress.getByName("sender ip");
- localAddr= new SessionAddress( InetAddress.getLocalHost(), sendPort);
- destAddr = new SessionAddress( ipAddr, sendPort);
- mgrs[i].initialize( localAddr);
- BufferControl bc = (BufferControl)mgrs[i].getControl("javax.media.control.BufferControl");
- if (bc != null)
- bc.setBufferLength(350);
- mgrs[i].addTarget(destAddr);
mgrs[i] = (RTPManager) RTPManager.newInstance(); //添加 SessionListener mgrs[i].addSessionListener(this); //添加 ReceiveStreamListener mgrs[i].addReceiveStreamListener(this); //得到服务器端IP地址 ipAddr = InetAddress.getByName("sender ip"); localAddr= new SessionAddress( InetAddress.getLocalHost(), sendPort); destAddr = new SessionAddress( ipAddr, sendPort); mgrs[i].initialize( localAddr); BufferControl bc = (BufferControl)mgrs[i].getControl("javax.media.control.BufferControl"); if (bc != null) bc.setBufferLength(350); mgrs[i].addTarget(destAddr);
关于ReceiveStreamListener
- @Override
- public void update(ReceiveStreamEvent evt)
- {
- //从大到小进行定位,RTPManager->Participant->ReceiveStream
- RTPManager mgr = (RTPManager)evt.getSource();
- Participant participant = evt.getParticipant();
- ReceiveStream stream = evt.getReceiveStream();
- if (evt instanceof RemotePayloadChangeEvent){.....};//远程发送者改变负载
- else if(evt instanceof NewReceiveStreamEvent){.....<SPAN style="COLOR: #ff0000">需要添加ControllerListener</SPAN>};//接收到新的stream
- else if (evt instanceof ByeEvent){.....};//结束
- }
@Override
public void update(ReceiveStreamEvent evt)
{
//从大到小进行定位,RTPManager->Participant->ReceiveStream
RTPManager mgr = (RTPManager)evt.getSource();
Participant participant = evt.getParticipant();
ReceiveStream stream = evt.getReceiveStream();
if (evt instanceof RemotePayloadChangeEvent){.....};//远程发送者改变负载
else if(evt instanceof NewReceiveStreamEvent){.....需要添加ControllerListener};//接收到新的stream
else if (evt instanceof ByeEvent){.....};//结束
}
关于SessionListener
- @Override
- public void update(SessionEvent evt)
- {
- //有新的用户加入
- if (evt instanceof NewParticipantEvent)
- {
- Participant p = ((NewParticipantEvent)evt).getParticipant();
- }
- }
@Override public void update(SessionEvent evt) { //有新的用户加入 if (evt instanceof NewParticipantEvent) { Participant p = ((NewParticipantEvent)evt).getParticipant(); } }
关于ControllerListener
- @Override
- public void controllerUpdate(ControllerEvent ce)
- {
- if (ce instanceof RealizeCompleteEvent){......};//player完成了realize
- if (ce instanceof ControllerErrorEvent){......};//出现异常
- }
@Override public void controllerUpdate(ControllerEvent ce) { if (ce instanceof RealizeCompleteEvent){......};//player完成了realize if (ce instanceof ControllerErrorEvent){......};//出现异常 }
jmf的rtp应该是用udp做的...貌似
ps:话说 百度的题好难啊 不如腾讯的友好 哈哈哈
相关推荐
JMF的rtp视频音频聊天,供大家一起共同分享学习。
Java Media Framework (JMF) 和 Real-Time Transport Protocol (RTP) 是在开发视频音频传输聊天应用时常用的技术。本文将详细介绍这两个技术以及如何利用它们实现一个聊天应用。 **Java Media Framework (JMF)** ...
JMF是Java平台上的多媒体处理框架,它提供了一种支持音频、视频捕获、播放和流传输的能力。 描述中提到的“能够进行视频 语音 通信 使用了udp打孔技术nat穿透”,这部分涉及到网络通信的关键技术和概念。首先,音...
Java Media Framework(JMF)是Java平台上用于处理多媒体数据的一个框架,它允许开发者创建和播放音频、视频等多媒体内容。本文将深入探讨基于JMF的视频聊天软件开发,旨在帮助初学者和有经验的开发者更好地理解和...
基于java JMF多媒体框架写的视频和音频通信源码
JMF捕获音频和视频.wps
JMF还支持媒体的混合和编辑,通过Processor对象可以对视频和音频流进行处理,如添加特效、调整音量等。 JMF_Capturing文件可能包含了以下内容: 1. 示例代码:演示如何使用JMF API捕获摄像头视频和麦克风音频。 2....
【标题】"Jmf实现的视频聊天系统"指的是利用Java Media Framework (JMF) 开发的一个视频通信应用。Java Media Framework 是Java平台上的一个开源框架,主要用于处理多媒体数据,包括音频、视频和流媒体。在本系统中...
JMF截取音频和视频 : 1、利用麦克风和摄像机一类的设备截取音频和视频 2、并保存成多媒体文件。 3、完善软件的功能;
JMF 是Sun Microsystems公司开发的Java API,它允许Java应用进行实时音频和视频处理。JMF 支持多种媒体格式,通过插件机制来扩展对不同编码和解码器的支持。这个框架使得开发者能够创建多媒体播放器、流媒体服务器、...
在“jmf.rar_Java视频聊天_java 视频 聊天_java 视频聊天_jmf_jmf__video_chat”这个压缩包中,我们可以推断出它包含了一个使用JMF实现的Java视频聊天程序。这个程序允许用户在局域网(LAN)环境中进行视频通信。 1...
用到多媒体技术(JAVA 多媒体框架JMF),视频和音频用TRP协议传输,用到Socket编程技术,多播技术。网络视频会议首先是基于网络传输的,那么就必然要依托于JAVA网络编程的相关知识。在这基础上,由于相关音频、视频...
总结起来,基于JMF的音视频聊天系统利用了Java的多媒体框架处理音视频数据,通过RTP协议实现实时传输,借助IP组播优化多用户通信,并通过UDP打孔技术克服了NAT的障碍,使得软件具备了在复杂网络环境下的跨域通信能力...
在“JMF的音视频实时交互及存储的具体实现”这一主题中,我们将深入探讨如何利用JMF进行实时音视频交互以及如何进行有效的存储。 一、JMF简介 Java Media Framework(JMF)是由Sun Microsystems开发的开源库,主要...
Java Media Framework (JMF) 是一个用于开发多媒体应用程序的开源框架,它允许开发者处理音频、视频数据,并且支持实时传输协议(RTP)。RTP通常用于在不可靠的网络环境中高效传输时间敏感的数据,如音频和视频流。...
3. **音视频同步**:在音视频聊天程序中,JMF提供了一种机制来保证音频和视频流的同步,确保用户在聊天过程中获得流畅、无延迟的体验。 4. **网络传输**:JMF可以处理实时传输协议(RTP)和实时控制协议(RTCP),...
在本文中,我们将深入探讨如何利用JMF进行视频的播放和录制。 ### JMF 概述 Java Media Framework 是Sun Microsystems开发的一个API,用于在Java应用程序中支持各种多媒体格式。它允许开发者集成音频、视频和流媒体...