我想做一个audio/video streaming,从一台机器发送到另外一台机器。
原始数据来自硬盘上的一个mpeg-1文件,我使用JMF标准结构来封装它(DataSource, Processor等),使用JMF自带的格式进行编码(G723_RTP, GSM_RTP, JPEG_RTP等),使用RTPManager来传输数据。所有代码均改编自java.sun.com网站上的example code。
经过实验,audio/video数据的确能够传输到接收端。实现了这个基本功能后,我需要实现的另外一个目标是在传输过程中改变数据编码格式。以video轨道为例,发送端初始编码格式为MPEG_RTP(通过processor的trackControl设定),运行时,我需要改变编码格式(比如说改变为JPEG_RTP)。我查了很多资料,都没有得到解决方法或例程。主要困难在于:
编码格式是在processor.configured状态下设定的,当rtp传输建立后,似乎已经不能够改变processor输出格式了(因为processor已经realized了)。为了解决这个问题,我试图在rtp传输过程中重新生成一个datasource,用这个datasource生成一个新的processor,在这个processor configure()之后设定它的格式为JPEG_RTP,然后把这个新生成的datasource, processor对象付给现有的rtp session。可是实验中我发现,一旦进行进行对象赋予的操作,就会出现hotfix。部分核心代码如下,主要有两个类。一个是Sender类进行数据打包,制定格式,一个是RTPTransmit类,进行rtp数据传输,这两个类都运行在发送端。执行流程是Sender.function1 -> RTPTransmit.function2 -> Sender.function2 -> RTPTransmit.updateProcessor。    public class Sender {
       public RTPTransmit rtp; // 记录相关的rtp传输对象       public void function1 () { //这是执行流程的第一步
           //这里执行生成初始datasource, processor等操作 
           ........
            DataSource ds = Manager.createDataSource(ml);
            Processor processor = Manager.createProcessor(ds);
            track[i].setFormat(new VideoFormat(VideoFormat.MPEG_RTP));
           // 最后生成RTPTransmit类的对象传输数据
            ........
       }       public void function3 () { //这是执行流程的第三步
           //运行过程中,这里根据新格式生成一个新的dataSource, processor
            ........
            DataSource ds = Manager.createDataSource(ml);
            Processor processor = Manager.createProcessor(ds);
            track[i].setFormat(new VideoFormat(VideoFormat.JPEG_RTP)); //新格式
            ........
            //接着把生成的process对象传给正在传输数据的RTPTransmit类的对象
            this.rtp.updateProcessor(processor)
        }
    } // end of class Sender
 
    public class RTPTransmit {  //这里是启动rtp传输的类
        public Processor processor; // 这两个数据结构在运行时
        public DataSource dataOutput; //被我试图重新赋值,出错        public void function 2 () { //这是执行流程的第二步
            //传输数据
            ........
            RTPManager rtpMgrs[i] = RTPManager.newInstance();
            dataOutput = processor.getDataOutput();
            sendStream = rtpMgrs[i].createSendStream(dataOutput, i);
            sendStream.start();
            processor.start();
            ........
      }      public void updateProcessor (Processor p) { //这是执行流程的第四步
            //这里先停止RTPTransmit对象的数据传输,
            //付给新的dataSource, processor,再重启传输
            this.dataOutput.stop();
            this.processor.stop(); // this.processor.deallocate();
            this.dataOutput = p.getDataOutput();
            this.dataOutput.start();
            this.processor.start();
      }
    } // end of class RTPTransmit紧急求救各位大侠啊,是不是我的思路有问题,或者是实现发现有问题?多谢多谢

解决方案 »

  1.   

    好贴~~顶下 LZ有联系方式不,我也要研究下JMF
      

  2.   

    问题可能出在你的DataSource重复使用上(可能不是产生你所说的问题的直接原因),我也在做这方面的一个应用程序,将DataSource进行Clone,用这个Clone后的DataSource生成processor,原程序中用同一个DataSource好象是不行的。只能提这点意见了,我也在学习JMF中,希望多多交流。
      

  3.   

    多谢popking的回复。我的做法是用同一个mediaLocator生成两个DataSource,进而创建两个Processor,分别采用不同的编码格式,运行时通过两组DataSource和Processor的替代实现编码方式的改变。这样就不会影响到rtp管道的运行。你的意思是通过一个mediaLocator创建两个DataSource的方法不可行,需要采用clone已经生成的DataSource来构造第二个DataSource?盼回复。
      

  4.   

    嗯,是这样的。我的程序需要采集视频并发送到其他用户显示,而且本机可以回放,起初用一个DataSource总是报错,将一开始产生的DataSource马上Clone成两个dataSourceClone对象,一个用于回放,一个传送到网络上,就没有问题了。
      

  5.   

    明白你的意思了,我试试看。
    不过有个小疑问,两个clone的DataSource视频同步吗?如果我操作其中一个,会不会影响到另外一个?比如我stop其中一个,另外一个还有数据输出吗?
      

  6.   

    试过了,复制DataSource的时候的确不报错了,但是更换dataOutput之后数据传输就中止了
      

  7.   

    to vivijane(baby) ( ) 信誉:100    Blog 
    CLONE了 则互不干扰了
      

  8.   

    原来还有人做JMF啊
    不过JAVA搞JMF的人真的很少哦
      

  9.   

    ^_^ 有是有人搞JMF 就是少
    国防科大有些人在搞这个 而且有些成果了 可惜不知如何联系