整体流程图示:
RTCP
类型
|
JMF
中的事件类
|
SR
|
SendStreamEvent
|
RR
|
ReceiveStreamEvent
|
SDES
|
SenderReportEvent
|
BYE
|
ByeEvent
|
APP
|
ApplicationEvent
:
|
多媒体类别
|
RTP
传输格式
|
音频
|
JAUDIO_G711_ULAW/rtp,dvi/rtp ,g723/rtp ,gsm/rtp |
视频
|
jpeg/rtp,h261/rtp,h263/rtp |
//
从processor获得轨道控制器
TrackControl [] tracks = processor.getTrackControls();
//
为每个轨道的格式进行转制
for (int i = 0; i < tracks.length; i++)
{
//
此处省略获得轨道信息格式和支持格式代码
//
下面一行为转制函数,需要参数为:轨道格式和轨道支持的格式
chosen = checkForVideoSizes(tracks[i].getFormat(), supported[0]);
//
此处省略如果不能对轨道格式转变代码
}
//
转制函数
/*
在传输视频信息时,对于JPEG编码格式,视频图像的宽和高是8像素的整数倍,对于
*H263
编码格式,只支持三种图像的大小,即352X288,176X144,128X96像素,只要满
*
足了这些条件,才可以正常传输视频信息,所以,需要对视频格式进行转制,
*
不负荷条件的都需要转化,以满足正常传输。
*/
Format checkForVideoSizes(Format original, Format supported) {
int width, height;
Dimension size = ((VideoFormat)original).getSize();//
获取视频图像的尺寸
Format jpegFmt = new Format(VideoFormat.JPEG_RTP);
Format h263Fmt = new Format(VideoFormat.H263_RTP);
if (supported.matches(jpegFmt)) {//
如果是JPEG格式
//
调整宽
width = (size.width % 8 == 0 ? size.width :(int)(size.width / 8) * 8);
//
调整高
height = (size.height % 8 == 0 ? size.height :(int)(size.height / 8) * 8);
} else if (supported.matches(h263Fmt)) {//
如果是H263格式
if (size.width < 128) {
width = 128;
height = 96;
} else if (size.width < 176) {
width = 176;
height = 144;
} else {
width = 352;
height = 288;
}
} else {
//
对于其他格式不受理
return supported;
}
return (new VideoFormat(null,
new Dimension(width, height),
Format.NOT_SPECIFIED,
null,
Format.NOT_SPECIFIED)).intersects(supported);
|
//
获得转制后的DataSource
dataOutput = processor.getDataOutput();
//
将DataSource转化为Push数据流
PushBufferDataSource pbds = (PushBufferDataSource)dataOutput;
//
获取Push数据流
PushBufferStream pbss[] = pbds.getStreams();
|
rtpMgrs[i] = RTPManager.newInstance();//RTP
管理器实例化
ipAddr = InetAddress.getByName(
"59.64.84.243"
);//
获得目的地址的IP地址
//
获取本机IP地址
localAddr = new SessionAddress( InetAddress.getLocalHost(),port);
//
获取目的机IP地址
destAddr = new SessionAddress( ipAddr, port);
//
分别将本机和目的机IP地址加入至RTP会话管理器
rtpMgrs[i].initialize( localAddr);
rtpMgrs[i].addTarget( destAddr);
//
产生第N条轨道的传输流
sendStream = rtpMgrs[i].createSendStream(dataOutput, i);
//
传输流开始
sendStream.start();
|
/*
*
目的机建立RTP会话管理器原理和步骤基本与发送端一至,我们主要分析接收多媒体流的事件类。
*/
public synchronized void update( ReceiveStreamEvent evt){
if(evt instanceof NewReceiveStreamEvent) {//
接收到一个新的数据流
//
根据获取的数据流获得一个数据源。这个数据源为播放使用
} else if (evt instanceof StreamMappedEvent) {
//
数据流映射事件
//
如果当前数据源为NULL,根据这个事件获得一个Datasource,否则忽略
}else if (evt instanceof ByeEvent) {//
数据接收完毕
//
播放结束
}
}
|