使用jmf进行流媒体传输时为什么在Wireshark中显示的是UDP而不是RTP?

6
我希望使用JMF 2.1.1e以RTP格式捕获和流式传输音频。我编写了一个简单的发射器,可以传输和接收音频。但是,在Wireshark中查看时,我看到数据包是UDP格式的。请问有谁能指出问题所在。
以下是负责音频捕获和传输的函数:
public void captureAudio(){

    // Get the device list for ULAW
    Vector devices = captureDevices();

    CaptureDeviceInfo captureDeviceInfo = null;

    if (devices.size() > 0) {
         //get the first device from the list and cast it as CaptureDeviceInfo
         captureDeviceInfo = (CaptureDeviceInfo) devices.firstElement();
    }
    else {
        // exit if we could not find the relevant capturedevice.
        System.out.println("No such device found");
        System.exit(-1);
    }


    Processor processor = null;
    try {
        //Create a Processor for the specified media.
        processor = Manager.createProcessor(captureDeviceInfo.getLocator());
    } catch (IOException ex) {
        System.err.println(ex);
    } catch (NoProcessorException ex) {
        System.err.println(ex);
    }
    //Prepares the Processor to be programmed.
    //puts the Processor into the Configuring state.
    processor.configure();

    //Wait till the Processor configured.
    while (processor.getState() != Processor.Configured){
       try {
           Thread.sleep(100);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
   }


    //Sets the output content-type for this Processor
    processor.setContentDescriptor(CONTENT_DESCRIPTOR); 
    /** 
         ContentDescriptor CONTENT_DESCRIPTOR
                = new ContentDescriptor(ContentDescriptor.RAW_RTP); 
      */

    //Gets a TrackControl for each track in the media stream.
    TrackControl track[] = processor.getTrackControls();

    boolean encodingOk = false;

    //searching through tracks to get a supported audio format track.
    for (int i = 0; i < track.length; i++) {
        if (!encodingOk && track[i] instanceof FormatControl) {
            if (((FormatControl)
                    track[i]).setFormat( new AudioFormat(AudioFormat.ULAW_RTP, 8000, 8, 1) ) == null)
            {
               track[i].setEnabled(false);
            }
            else {
                encodingOk = true;
                track[i].setEnabled(encodingOk);
                System.out.println("enc: " + i);
            }
        } else {
            // we could not set this track to ULAW, so disable it
            track[i].setEnabled(false);
        }
    }

    //If we could set this track to ULAW we proceed
    if (encodingOk){            
        processor.realize();
        while (processor.getState() != Processor.Realized){
           try {
               Thread.sleep(100);
           } catch (InterruptedException e) {
               e.printStackTrace();
           }
        }

        DataSource dataSource = null;
        try {
            dataSource = processor.getDataOutput();
        } catch (NotRealizedError e) {
            e.printStackTrace();
        }

        try {

            String url= "rtp://192.168.1.99:49150/audio/1";
            MediaLocator m = new MediaLocator(url);
            DataSink d = Manager.createDataSink(dataSource, m);
            d.open();
            d.start();
            System.out.println("transmitting...");
            processor.start();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

请问,如果您发现任何不合适或含糊的地方,请告诉我。 谢谢! :)
澄清:我有一段用于RTP流的C#代码。当我使用wireshark捕获数据时,我可以看到它们是RTP,但问题在于当我从JMF捕获数据流时,wireshark将它们显示为UDP。我的问题是为什么会这样? 我知道UDP和RTP之间的区别。

我认为问题出在CONTENT_DESCRIPTOR上,它是原始的RTP。 - shibli049
我理解你的代码目前运行良好,除了你现在面临的问题。我们需要查看JMF源代码,了解JMF如何实现Processor类,特别是在使用CONTENT_DESCRIPTOR时,就像Obscure所说的那样。也许这就是C#代码和Java JMF代码之间的区别。请问你在C#版本中使用了哪个流媒体库? - ecle
@eee:C#项目正在使用pjsipDll,我只是从朋友那里拿来测试wireshark中的数据包,而且我不习惯使用C#。因此,无法为您提供有关C#的进一步详细信息。 - shibli049
2个回答

8
RTP是应用层, UDP是传输层, 它们不是同一层级! 维基百科可以详细解释这个问题。 因此,您的数据会作为RTP流在UDP“帧”中发送。
简要概述一下... 应用层:
* DHCP
* DHCPv6
* DNS
* FTP
* HTTP
* IMAP
* IRC
* LDAP
* MGCP
* NNTP
* BGP
* NTP
* POP
* RPC
* RTP
* RTSP
* RIP
* SIP
* SMTP
* SNMP
* SOCKS
* SSH
* Telnet
* TLS/SSL
* XMPP
* (more)

传输层

* TCP
* UDP
* DCCP
* SCTP
* RSVP
* (more)

互联网层

* IP
      o IPv4
      o IPv6
* ICMP
* ICMPv6
* ECN
* IGMP
* IPsec
* (more)

链路层

* ARP/InARP
* NDP
* OSPF
* Tunnels
      o L2TP
* PPP
* Media access control
      o Ethernet
      o DSL
      o ISDN
      o FDDI
* (more)

非常感谢您的解释。但是,我已经知道了这些内容。我在我的问题中进行了澄清。请问您能否看到并给我一个答案呢? - shibli049

5
如果我理解您的问题正确,您想知道为什么Wireshark无法将RTP数据包识别为RTP数据包。根据我的经验,这可能是因为Wireshark缺乏有关RTP会话的足够信息。
例如:1)如果我使用RTSP或SIP和SDP设置了RTP会话进行嗅探,则Wireshark将显示检测到RTP。2)但是,在另一个应用程序中,我使用本地SDP描述设置会话时,数据包显示为UDP。在第二种情况下,Wireshark看到了RTP数据包,但缺乏将它们分类为RTP所需的信息。由于RTP通常位于UDP之上,并且Wireshark可以对UDP数据包进行分类,因此它们被归类为UDP。
FYI,然后您可以从您知道是RTP的流中选择一个数据包,并选择“解码为”。然后从协议列表中为适当的流选择RTP(如果适用,则为RTCP),然后Wireshark将显示数据包为RTP,您将能够查看数据包信息。
我不确定这是否是您特定情况的原因,但也许您的JMF和C#示例之间存在信令差异?听起来您可能正在为C#应用程序使用SIP,而对于JMF则没有使用任何东西?

谢谢,这就是我要找的答案,对我非常有效。现在Wireshark可以识别数据包为RTP了。是的,C#有SIP,而JMF没有。 :) - shibli049

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接