1. 发送实时媒体数据
如果需要将媒体数据发送到网络,首先需要用Processor生成RTP编码的数据源,然后创建SessionManager或者DataSink来控制传输过程。
下面以实例来讲解从摄像头捕获视频,并且在网上传输的过程。
首先获取视频采集设备具体请参考5.1.2,取得了CaptureDeviceInfo对象为di
第二步创建Processor
Processor p=Manager.createProcessor(di.getLocator());
第三步设置Processor,使它能够生成RTP格式的编码
processor.configure()
//等待,直到processor的状态变成configured,设置输出格式为RAW_RTP
processor.setContentDescriptor(
new ContentDescriptor(ContentDescriptor.RAW_RTP));
//列出所有的和数据轨道相关的控制器
TrackControl track[]=processor.getTrackControls();
boolean encodingOk = false;
//遍历这些控制器,找到可以控制输出格式的控制器
for (int i = 0; i < track.length; i++) {
if (!encodingOk && track[i] instanceof FormatControl) {
//找到了数据轨道的格式控制器之后,设置输出格式,输出格式输出为VideoFormat.JPEG_RTP>。
VideoFormat jpegFormat = new VideoFormat(VideoFormat.JPEG_RTP,new Dimension(w, h),Format.NOT_SPECIFIED,
Format.byteArray,frameRate);
tracks[i].setFormat(jpegFormat);
//这时,准备工作已经做好,可以调用Processor的realize方法
processor.realize()
//当Processor进出realized状态以后,可以取得Processor的输出作为数据源
processor.realize()
DataSource ds=processor.getDataOutput();
//可以把这个数据源作为参数传递给manager,通过manager创建一个RTP的数据池。先设置一个发送数据流的多播目的网址
String url=“rtp://127.0.0.1:49150/audio/1”
MediaLocator mDest=new MediaLocator(url)
//确定了数据源和发送地址,可以建立数据池DataSink了,建立成功后调用open()和start()方法,就可以在网上以多播方式发送捕获的内容了。
DataSink d=Manager.createDataSink(ds,m)
d.open()
d.start()
2. 接收实时视频数据
接收网上传输的数据流时,首先要构建一个MediaLocator来描述RTP 进程,Manager为进程中的第一个数据流创建播放器,当从进程中检测到数据时,Player会发出RealizeComplete事件。
通过监听RealizeComplete事件,你可以确定是否有数据到了,还可以确定Player是否准备好播放数据了。当Player发出这个事件时,就可以获取播放器的可视面板和控制面板了。
参考代码片断如下
//RTP 数据源的地址
String url= "rtp://224.144.251.104:49150/audio/1";
//创建MediaLocator
MediaLocator mrl=new MediaLocator(url);
if (mrl == null) {
System.err.println("Can't build MRL for RTP");
return false;
}
//根据MediaLocator创建Player
try {
player = Manager.createPlayer(mrl);
} catch (NoPlayerException e) {
System.err.println("Error:" + e);
return false;
} catch (MalformedURLException e) {
System.err.println("Error:" + e);
return false;
} catch (IOException e) {
System.err.println("Error:" + e);
return false;
}
//添加监听器,以便监听RealizeComplete事件
if (player != null) {
if (this.player == null) {
this.player = player;
player.addControllerListener(this);
player.realize();
}
}
以上的方式只能接收进程中的第一个数据流。为了播放RTP进程中的全部数据流可以按照以下方式。就为每个数据流创建一个Player。当创建一个新的数据流后,SessionManager会发出一个NewReceiveStream Event。注册了ReceiveStream Listener 接收数据流监听器,就会收到这些事件。就可以为每一个新的接收数据流创建Player。从接收数据流中获取DataSource,并作为参数传递给Manager来创建Player。
1、 建立RTP session
a. 创建一个SessionManager
b. 调用SessionManager的addReceiveStreamListener方法注册一个监听器
c. 调用SessionManager的initSession方法初始化SessionManger
d. 调用startSession方法启动SessionManager
2、当新的数据流检测到的时候,可以在ReceiveStreamListener的update方法中获得发现新数据流事件的通知。
3、数据流通知之后,调用getReceiveStream方法获取新的数据流
4、 调用新的数据流的getDataSource方法获取数据流的RTP数据源。这个数据源是RTP特有格式的PushBufferDataSource。
把数据源对象作为参数传递到Manager的createPlayer方法中来创建Player。如果要成功的创建Palyer需要必要的支持RTP格式的编码、解码的插件。
具体实现参考以下代码片断
//创建SessionManager
public SessionManager createManager(String address,
int port,
int ttl,
boolean listener,
boolean sendlistener)
{
mgr = (SessionManager)new com.sun.media.rtp.RTPSessionMgr();
if (mgr == null) return null;
mgr.addFormat(new AudioFormat(AudioFormat.DVI_RTP,44100,4,1),18);
//添加监听器,监听收到新数据流时间
if (listener) mgr.addReceiveStreamListener(this);
if (sendlistener) new RTPSendStreamWindow(mgr);
…
//初始化SessionManager
mgr.initSession(localaddr, userdesclist,0.05,0.25);
//启动SessionManager
mgr.startSession(sessaddr,ttl,null);
} catch (Exception e) {
System.err.println(e.getMessage());
return null;
}
return mgr;
}
//监听事件,如果接收到新数据流后所做的工作
public void update( ReceiveStreamEvent event)
{
Player newplayer = null;
RTPPlayerWindow playerWindow = null;
// 获取新数据流的数据源
SessionManager source = (SessionManager)event.getSource();
// 当检测到新接收数据源时,创建新的播放器
if (event instanceof NewReceiveStreamEvent)
{
String cname = "Java Media Player";
ReceiveStream stream = null;
try
{
// 获取接收数据流
stream =((NewReceiveStreamEvent)event)
.getReceiveStream();
//获取数据流的发送源地址
Participant part = stream.getParticipant();
if (part != null) cname = part.getCNAME();
// 获取发送数据流的数据源
DataSource dsource = stream.getDataSource();
// 将数据源作为参数传递给MediaManager来创建Player
newplayer = Manager.createPlayer(dsource);
System.out.println("created player " + newplayer);
} catch (Exception e) {
System.err.println("NewReceiveStreamEvent exception "
+ e.getMessage());
return;
}
if (newplayer == null) return;
playerlist.addElement(newplayer);
newplayer.addControllerListener(this);
//更新播放器界面,这样就可以同时显示多个数据流了
playerWindow = new RTPPlayerWindow( newplayer, cname);
}
}