接收RTP流 - 音频流,音频组

22

我想听取一个RTP音频流,但是声音中有一些小间隔 - 不连续。可能的解决方案是什么?接收者(android)或流媒体(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();
    }
}

你尝试过在VLC中打开RTP流以检查它是否像发送时一样播放(数据丢失)。这也将允许您使用Wireshark分析网络流量,我相信VLC将允许您将其流回并连接到该设备,以查看它是否与PC上接收到的流不同。 - Shaun07776
是的,我检查了一下。使用VLC播放音频声音很好。 - totten
如果您在设备上使用 VLC,那么您能否监视从服务器到设备的流量?如果您可以在设备上获得 VLC 或其他播放器,则可能有助于排除 Ffmpeg 作为问题,留下连接问题。 - Shaun07776
谢谢你的代码。我已经使用这个Android代码将语音数据发送到VLC播放器(另一部Android手机)。然而,我无法从VLC流中接收任何语音数据(你已经完成了这个)。我无法解决这个问题。我是否缺少某些权限?我已经使用了这个权限。android:minSdkVersion="17" <uses-permission android:name="android.permission.INTERNET" > <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" > <uses-permission android:name="android.permission.RECORD_AUDIO" > 谢谢。 - user1850484
在评论中提问并不是一个好的方式,只需直接提问并在此处发布链接,而不是非常长的评论。我会查看它。 - totten
显示剩余6条评论
2个回答

7
回答我的问题,问题出在Android的rtp数据包管理上。
Android声称在AudioGroup源文件中“假定数据包间隔为50ms或更短”。
然而,RTP数据包的发送间隔为60ms。
这意味着50ms不足以解决问题,导致下面所描述的问题。
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

我每300毫秒只有一个数据包,这导致声音不稳定。

我将发送一个错误报告,希望对某些人有所帮助。

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


我能否重新构建rtp库或vlc库以修复间隙?如何操作? - nobjta_9x_tq
它是实时的吗?您能提供一些示例代码或链接吗?谢谢! - nobjta_9x_tq

4
抱歉如果下面的内容有些愚蠢:
ffmpeg命令行似乎正在生成测试音频并将其作为PCM数据流通过RTP发送。 RTP本身并不能保证流数据的可靠传输,它仅提供足够的信息告诉接收方是否已接收到所有数据,以及如果在传输过程中丢失了一些数据,则确切地丢失了哪些数据。此外,通常使用UDP进行传输。
因此,在RTP中,重点是要求RTP的用户发送经过编码的数据(即具有纠错编码、数据冗余等),以便接收方可以重构足够的原始数据以满足应用程序的需求。因此,在音频流中,您需要一种适合的编码格式。
我没有找到pcm_u8表示什么的参考资料,但它极有可能是一个简单的脉冲编码调制数据流,带有8位数据。这听起来似乎没有任何纠错编码或数据冗余。丢失其中一个字节就意味着丢失一个样本,接收端无法填充缺失的数据。
因此,我认为发生的情况是网络中的某个部分正在丢弃UDP数据包,RTP告诉AudioStream哪些数据丢失了,结果是由于pcm_u8数据流中没有错误校正或数据冗余而导致间隙,无法通过AudioStream重构丢失的数据。
我曾经见过像VMWare这样的东西在虚拟网络上故意丢弃UDP数据包,以确保良好的性能,理由是UDP本身就不能保证传输的可靠性,因此“没关系”。这严重伤害了一个同事,他正在使用RTP并期望得到保证的传输,但没有得到。他在一根电线的两端有一个封闭的网络段,其中一个主机托管一个单独的虚拟机。
因此,可能只需要更改所使用的编解码器。我无法推荐一种。首先,值得检查广播数字媒体流使用什么。DVB-T使用MPEG传输流(具有纠错编码等)作为MPEG-2的封装器,据我所知。

似乎安卓在RTP打包方面存在一个bug。请查看我的答案。 - totten

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