⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rtptransmit.java

📁 Java 多媒体技术(附源码) Java 3D API JavaSound API 各种格式的多媒体数据文件 JBuilder开发环境
💻 JAVA
字号:
package RTPTransmit;import java.io.*;import java.awt.Dimension;import java.net.InetAddress;import javax.media.*;import javax.media.protocol.*;import javax.media.protocol.DataSource;import javax.media.format.*;import javax.media.control.TrackControl;import javax.media.rtp.*;// 用RTP协议传输数据的类public class RTPTransmit {  private MediaLocator locator;     // 媒体定位,可以是一个本机文件,也可以是一个网络文件或采集设备得到的数据源  private String ipAddress;         // 发送目的地(接收端)的IP地址  private int portBase;             // 传输端口号  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();        }      }    }  }}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -