接收RTP流-AudioStream,AudioGroup

问题描述 投票:22回答:2

我想收听RTP音频流,但是语音中的缝隙很小-无法继续。有什么解决方案?我在Receiver(android)端或Streamer(ffmpeg)端是否缺少某些内容?

我正在使用ffmpeg传输RTP音频,

ffmpeg -f lavfi -i aevalsrc="sin(400*2*PI*t)" -ar 8000 -vcodec pcm_u8 -f rtp rtp://192.168.0.15:41954 (port changes.)

这是我相关的android代码:

AudioStream audioStream;
AudioGroup audioGroup;
@Override
public void onStart() {
    super.onStart();
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitNetwork().build();
    StrictMode.setThreadPolicy(policy);
    AudioManager audio = (AudioManager)getSystemService(AUDIO_SERVICE);
    audio.setMode(AudioManager.MODE_IN_COMMUNICATION);
    audioGroup = new AudioGroup();
    audioGroup.setMode(AudioGroup.MODE_ECHO_SUPPRESSION);
    InetAddress inetAddress;
    try {
        inetAddress = InetAddress.getByName("192.168.0.15");
        audioStream = new AudioStream(inetAddress);
        audioStream.setCodec(AudioCodec.PCMU);
        audioStream.setMode(RtpStream.MODE_NORMAL);
        InetAddress inetAddressRemote = InetAddress.getByName("192.168.0.14");
        audioStream.associate(inetAddressRemote, 6000);
        ((TextView)findViewById(R.id.tv_port)).setText("Port : " + String.valueOf(audioStream.getLocalPort()));
        audioStream.join(audioGroup);
    }
    catch ( UnknownHostException e ) {
        e.printStackTrace();
    }
    catch ( SocketException e ) {
        e.printStackTrace();
    }
}
android audio ffmpeg audio-streaming rtp
2个回答
7
投票

回答我自己的问题,问题出在android rtp数据包管理。

Android表示... assume packet interval is 50ms or less.中的AudioGroup source file

但是,RTP数据包以60ms的间隔发送。

这意味着50毫秒是不够的,这将导致如下所述的问题。

Incoming: X X X X X X Y Y Y Y Y Y X X X X X X Y Y Y Y Y Y X X X X X X
Reading : X X X X X Y Y Y Y Y X X X X X Y Y Y Y Y X X X X X Y Y Y Y Y
          ^ ^ ^ ^ ^ - - - - - - - - - - - - - - - - - - - - ^ ^ ^ ^ ^ 
          ^                                                 ^
          |                                                 |
          |---- just these overlapping packets is valid ----|
          |---- and other packets discarding due to --------|
          |---- invalid RTP headers. -----------------------|

X, Y < packets

我每300ms的间隔只有一个数据包。这样会产生不平稳的声音。

我将为此发送错误报告,希望对您有所帮助。

对于真正想收听原始RTP流的人,我建议他们手动读取数据包并将其解码为PCM 16bit(这是android声卡支持的唯一音频格式),然后将其写入AudioTrack。


4
投票

抱歉,以下内容很愚蠢:

ffmpeg命令行似乎正在生成测试声音,并通过RTP将其作为pcm数据流发出。

RTP本身不能保证流式数据的可靠传递,它仅提供足够的信息来告诉接收器它是否已接收到所有数据,以及如果丢失了某些数据则确切地丢失了哪些数据。另外,它通常在UDP上使用。

因此,使用RTP时,重点是RTP的用户发送以这种方式编码的数据(即,使用纠错编码,数据冗余等),以便接收者可以重构足够的原始数据以满足应用程序的需求。因此,对于音频流,您需要某种适合的编码格式。

我尚未找到有关pcm_u8含义的参考,但强烈建议它是具有8位数据的简单脉冲编码调制数据流。听起来好像它没有内置任何纠错编码或数据冗余。丢失一个字节意味着丢失样本,并且在接收端无法完成任何操作。

因此,我认为正在发生的事情是您的网络中的某些设备正在丢弃UDP数据包,RTP告诉AudioStream哪些数据丢失了,结果是出现间隙,因为pcm_u8数据流中没有纠错或数据冗余以允许丢失由AudioStream重构的数据。

我已经看到诸如VMWare之类的东西故意在虚拟网络上丢弃UDP数据包,以确保获得良好的性能,其理由是,无论如何也不能保证UDP的传输,因此“无所谓”。这严重刺伤了一位使用RTP并期望有保证的交付但没有收到的同事。他有一个封闭的网络段,在网络的每一端都有一个服务器,其中一个托管单个VM。

因此,可能只是更改您正在使用的编解码器的情况。我不能推荐一个。首先,值得研究一下广播数字媒体流使用的内容。 DVB-T使用MPEG Transport Stream(具有纠错编码等)作为AFAIK(围绕MPEG-2的包装器)。

© www.soinside.com 2019 - 2024. All rights reserved.