关于java rtp传输媒体流时怎么调节流量的大小,很着急

Justin丶Lin 2015-05-14 09:36:44
以下是rtp传输的类

package Lin;

import java.io.*;
import java.awt.Component;
import java.awt.Dimension;
import java.net.InetAddress;

import javax.media.*;
import javax.media.protocol.*;
import javax.media.format.*;
import javax.media.control.FrameRateControl;
import javax.media.control.TrackControl;
import javax.media.rtp.*;

// 用RTP协议传输数据的类
public class RTPTransmit {
private MediaLocator locator; // 媒体定位,可以是一个本机文件,也可以是一个网络文件或采集设备得到的数据源
private String ipAddress; // 发送目的地(接收端)的IP地址
private int portBase; // 传输端口号
private float Framerate=1f;
private Processor processor = null; // 处理器
private RTPManager rtpMgrs[]; // RTP管理器
private DataSource dataOutput = null; // 输出的数据源

// 构造函数
public RTPTransmit(MediaLocator locator, String ipAddress,String pb,Format format) {
this.locator = locator;
this.ipAddress = ipAddress;
Integer integer = Integer.valueOf(pb);
if (integer != null)
this.portBase = integer.intValue();
}

// 开始传输
// 如果一切正常,就返回 null,否则返回出错原因
public synchronized String start() {
String result;

result = createProcessor(); // 产生一个处理器
if (result != null)
return result;

result = createTransmitter(); // 产生RTP会话,将处理器输出的数据传给指定的IP地址的指定的端口号
if (result != null) {
processor.close();
processor = null;
return result;
}

processor.start(); // 让处理器开始传输

return null;
}

// 为指定的媒体定位器产生一个处理器
private String createProcessor() {

if (locator == null)
return "Locator is null";

DataSource ds;

try {
ds = javax.media.Manager.createDataSource(locator); // 为定义的MediaLocator定位并实例化一个适当的数据源。
}
catch (Exception e) {
return "Couldn't create DataSource";
}

try {
processor = javax.media.Manager.createProcessor(ds); // 通过数据源来产生一个处理器
}
catch (NoProcessorException npe) {
return "Couldn't create processor";
}
catch (IOException ioe) {
return "IOException creating processor";
}

boolean result = waitForState(processor, Processor.Configured); // 等待处理器配置好
if (result == false)
return "Couldn't configure processor";

TrackControl [] tracks = processor.getTrackControls(); // 为媒体流中的每一个磁道得到一个控制器

if (tracks == null || tracks.length < 1) // 确保至少有一个可用的磁道
return "Couldn't find tracks in processor";

ContentDescriptor cd = new ContentDescriptor(ContentDescriptor.RAW_RTP);
processor.setContentDescriptor(cd); // 设置输出的内容描述为RAW_RTP
// 从而限定每个磁道支持的格式仅为合法的RTP格式,即它影响后面的 Track.getSupportedFormats()
Format supported[];
Format chosen = null;
boolean atLeastOneTrack = false;

for (int i = 0; i < tracks.length; i++) { // 对每一个磁道,选择一种RTP支持的传输格式
Format format = tracks[i].getFormat();
if (tracks[i].isEnabled()) { // 如果该磁道可用
supported = tracks[i].getSupportedFormats();

if (supported.length > 0) {
if (supported[0] instanceof VideoFormat) {
chosen = checkForVideoSizes(tracks[i].getFormat(),supported[0]); // 检查视频格式的尺寸,以确保正常工作
}
else
chosen = supported[0]; // 前面已经设置了输出内容描述为RIP,这里支持的格式都可以与RTP配合工作
// 这里选择第一种支持的格式

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";

result = waitForState(processor, Controller.Realized); // 等待处理器实现
if (result == false)
return "Couldn't realize processor";

dataOutput = processor.getDataOutput(); // 从处理器得到输出的数据源

return null;
}

// 为处理器的每一个媒体磁道产生一个RTP会话
private String createTransmitter() {
PushBufferDataSource pbds = (PushBufferDataSource)dataOutput; // 将数据源转化为“Push”(推)数据源
PushBufferStream pbss[] = pbds.getStreams(); // 得到“Push”数据流

rtpMgrs = new RTPManager[pbss.length]; // 为每个磁道产生一个RTP会话管理器

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

int port = portBase + 2 * i; // 每增加一个磁道,端口号加2
InetAddress ipAddr = InetAddress.getByName(ipAddress); // 得到发送目的地的IP地址

SessionAddress localAddr = new SessionAddress( InetAddress.getLocalHost(),port); // 得到本机的会话地址
// 这里传输端使用和接收目的端相同的端口号(实际上也可以不同)
SessionAddress destAddr = new SessionAddress( ipAddr, port); // 得到目的机器(接收端)的会话地址

rtpMgrs[i].initialize( localAddr); // 将本机会话地址传给RTP管理器

rtpMgrs[i].addTarget( destAddr); // 加入目的会话地址

System.err.println( "Created RTP session: " + ipAddress + " " + port);

SendStream sendStream = rtpMgrs[i].createSendStream(dataOutput, i); // 产生数据源的RTP传输流

sendStream.start(); // 开始RTP数据流发送
}
catch (Exception e) {
return e.getMessage();
}
}

return null;
}

// 由于JPEG和H.263编码标准,只支持一些特定的图像大小,所以这里进行必要的检查,以确保其可以正确编码
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格式,视频图像的宽和高必须是8像素的整数倍
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)) { // H.263格式仅支持三种特定的图像尺寸
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); // 返回经过处理后的视频格式
}

// 停止传输
public void stop() {
synchronized (this) {
if (processor != null) {
processor.stop();
processor.close(); // 停止处理器
processor = null; // 关闭处理器
for (int i = 0; i < rtpMgrs.length; i++) { // 删除所有RTP管理器
rtpMgrs[i].removeTargets( "Session ended.");
rtpMgrs[i].dispose();
}
}
}
}

// 以下两个变量为对处理器状态改变的处理服务
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;

if (state == Processor.Configured) { // 配置处理器
p.configure();
}
else if (state == Processor.Realized) { // 实现处理器
p.realize();
}

// 一直等待,直到成功达到所需状态,或失败
while (p.getState() < state && !failed) {
synchronized (getStateLock()) {
try {
getStateLock().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) // 控制器关闭
setFailed();

// 对于所有的控制器事件,通知在waitForState方法中等待的线程
if (ce instanceof ControllerEvent) {
synchronized (getStateLock()) {
getStateLock().notifyAll();
}
}
}
}



}



...全文
146 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复
Justin丶Lin 2015-05-14
  • 打赏
  • 举报
回复
主函数 package Lin; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.io.*; import java.net.InetAddress; import javax.swing.filechooser.FileFilter; import javax.media.control.FrameRateControl; import javax.media.format.*; import javax.media.*; import java.util.*; // 主界面类 public class MainFrame extends Frame implements FrameRateControl{ private String fileName = null; // 获取要传输的文件名 private RTPTransmit rtpTransmit = null; // RTP传输类的对象 private float Framerate; Label labelIP = new Label(); TextField textIPAdd1 = new TextField(); // IP地址编辑框 TextField textIPAdd2 = new TextField(); TextField textIPAdd3 = new TextField(); TextField textIPAdd4 = new TextField(); Label labelPort = new Label(); TextField textPort = new TextField(); // 端口编辑框 JLabel jLabelIP = new JLabel(); Label labelFile = new Label(); CheckboxGroup checkboxGroupFiles = new CheckboxGroup(); Checkbox checkboxMov = new Checkbox(); // 选择QuickTime文件(Mov)单选框 Checkbox checkboxAudio = new Checkbox(); // 选择Audio文件单选框 Checkbox checkboxMPEG = new Checkbox(); // 选择MPEG文件单选框 Button buttonFile = new Button(); // “浏览”文件按钮 TextField textFile = new TextField(); // 显示文件名编辑框 JLabel jLabelFile = new JLabel(); Button buttonBeginTransmit = new Button(); // “传输”按钮 Button buttonStopTransmit = new Button(); // “停止”按钮 // 设置界面和添加事件的监听 private void jbInit() throws Exception { this.setLayout(null); this.setBackground(Color.lightGray); labelIP.setText("IP地址:"); labelIP.setBounds(new Rectangle(50, 50, 50, 20)); textIPAdd1.setBounds(new Rectangle(125, 50, 40, 20)); textIPAdd2.setBounds(new Rectangle(175, 50, 40, 20)); textIPAdd3.setBounds(new Rectangle(225, 50, 40, 20)); textIPAdd4.setBounds(new Rectangle(275, 50, 40, 20)); labelPort.setText("端口号:"); labelPort.setBounds(new Rectangle(50, 90, 50, 20)); textPort.setBounds(new Rectangle(125, 90, 40, 20)); jLabelIP.setBorder(BorderFactory.createEtchedBorder()); jLabelIP.setBounds(new Rectangle(29, 33, 313, 91)); labelFile.setText("文件类型:"); labelFile.setBounds(new Rectangle(50, 180, 70, 20)); checkboxMov.setLabel("QuickTime Files"); checkboxMov.setBounds(new Rectangle(125, 160, 120, 15)); checkboxMov.setCheckboxGroup(checkboxGroupFiles); checkboxAudio.setLabel("Audio Files"); checkboxAudio.setBounds(new Rectangle(125, 180, 120, 15)); checkboxAudio.setCheckboxGroup(checkboxGroupFiles); checkboxMPEG.setLabel("MPEG Files"); checkboxMPEG.setBounds(new Rectangle(125, 200, 120, 15)); checkboxMPEG.setCheckboxGroup(checkboxGroupFiles); checkboxGroupFiles.setSelectedCheckbox(checkboxMov); buttonFile.setLabel("浏览"); buttonFile.setBounds(new Rectangle(50, 240, 58, 20)); buttonFile.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { buttonFile_actionPerformed(e); } }); textFile.setBounds(new Rectangle(125, 240, 190, 20)); jLabelFile.setBorder(BorderFactory.createEtchedBorder()); jLabelFile.setBounds(new Rectangle(29, 147, 314, 127)); buttonBeginTransmit.setLabel("传输"); buttonBeginTransmit.setBounds(new Rectangle(94, 296, 58, 20)); buttonBeginTransmit.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { buttonBeginTransmit_actionPerformed(e); } }); buttonStopTransmit.setLabel("停止"); buttonStopTransmit.setBounds(new Rectangle(214, 297, 58, 20)); buttonStopTransmit.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(ActionEvent e) { buttonStopTransmit_actionPerformed(e); } }); this.addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(WindowEvent e) { this_windowClosing(e); } }); this.add(buttonStopTransmit, null); this.add(buttonBeginTransmit, null); this.add(checkboxMov, null); this.add(labelIP, null); this.add(textIPAdd1, null); this.add(textIPAdd2, null); this.add(textIPAdd3, null); this.add(textIPAdd4, null); this.add(labelPort, null); this.add(textPort, null); this.add(jLabelIP, null); this.add(labelFile, null); this.add(checkboxAudio, null); this.add(checkboxMPEG, null); this.add(buttonFile, null); this.add(textFile, null); this.add(jLabelFile, null); this.setSize(new Dimension(371, 335)); this.setTitle("RTP Transmit"); // 设置框架标题 this.setVisible(true); // 显示出框架 } // 构造函数 public MainFrame() { try { jbInit(); // 显示出界面 } catch(Exception e) { e.printStackTrace(); } } // 得到所需传输文件的类型 int getFileType() { int indexTypeFile = 0; if(checkboxGroupFiles.getSelectedCheckbox() == checkboxMov) // QuickTime文件 indexTypeFile = 0; if(checkboxGroupFiles.getSelectedCheckbox() == checkboxAudio) // 音频文件 indexTypeFile = 1; if(checkboxGroupFiles.getSelectedCheckbox() == checkboxMPEG) // MPEG文件 indexTypeFile = 2; return indexTypeFile; } // 响应“浏览”按钮的点击消息 void buttonFile_actionPerformed(ActionEvent e) { JFileChooser fileChooser = new JFileChooser("D:"); // 选择文件的默认路径是“D:”盘 ExampleFileFilter filter = new ExampleFileFilter(); // 实例化一个文件过滤器 int iTypeFile = getFileType(); // 得到所需传输文件的类型 switch(iTypeFile) { case 0: // QuickTime文件 filter.addExtension("mov"); // 设置文件扩展名 filter.setDescription("QuickTime Files"); // 设置文件的类型描述 break; case 1: // 音频文件 filter.addExtension("au"); filter.addExtension("wav"); filter.setDescription("Audio Files"); break; case 2: // MPEG文件 filter.addExtension("mpg"); filter.addExtension("mpeg"); filter.setDescription("MPEG Files"); break; } fileChooser.setFileFilter(filter); int retVal = fileChooser.showOpenDialog(this); // 打开文件选择对话框 if(retVal == JFileChooser.APPROVE_OPTION){ fileName = fileChooser.getSelectedFile().getAbsolutePath(); // 得到所选文件 textFile.setText(fileName); // 将文件名显示到界面上 } } // 响应“传输”按钮的点击消息,开始传输数据 void buttonBeginTransmit_actionPerformed(ActionEvent e) { String strIPAddr = textIPAdd1.getText()+"."+textIPAdd2.getText()+"."+textIPAdd3.getText()+"."+textIPAdd4.getText(); // 组合得到完整的IP地址 String strPort = textPort.getText(); // 得到端口地址 fileName = textFile.getText(); // 得到文件名 fileName = "file:/" + fileName; // 加上文件标识,以便媒体定位器确认数据类型 MediaLocator medLoc = new MediaLocator(fileName); // 用本机的一个磁盘文件作为待传输的媒体数据 Format fmt = null; rtpTransmit = new RTPTransmit(medLoc,strIPAddr,strPort,fmt); String result = rtpTransmit.start(); // 开始传输 if (result != null) { // 显示传输错误 System.out.println("Error : " + result); } else { System.out.println("Start transmission ..."); } } // 响应“停止”按钮的点击消息,停止发送数据 void buttonStopTransmit_actionPerformed(ActionEvent e) { if(rtpTransmit == null) return; this.setFrameRate(10f); rtpTransmit.stop(); // 停止传输 System.out.println("...transmission ended."); } // 关闭窗口,退出程序 void this_windowClosing(WindowEvent e) { System.exit(0); } // 主函数 public static void main(String [] args) { new MainFrame(); } public Component getControlComponent() { // TODO Auto-generated method stub return null; } @Override public float getFrameRate() { // TODO Auto-generated method stub return Framerate; } @Override public float getMaxSupportedFrameRate() { // TODO Auto-generated method stub return 0; } @Override public float getPreferredFrameRate() { // TODO Auto-generated method stub return 0; } @Override public float setFrameRate(float Framerate) { // TODO Auto-generated method stub return Framerate; } }

62,614

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧