接收RTP流 - AudioStream,AudioGroup

时间:2014-12-03 10:13:57

标签: android audio ffmpeg audio-streaming rtp

我想听一个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.)

这是我的相关安卓代码:

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();
    }
}

2 个答案:

答案 0 :(得分:6)

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

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

但是,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。

答案 1 :(得分:4)

如果以下是愚蠢的话,请道歉:

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

RTP本身并不能保证流数据的可靠传输,它只是提供了足够的信息来告诉接收方它是否已收到所有数据,以及如果某些数据在传输过程中丢失了,究竟丢失了哪些数据。另外,它通常用于UDP。

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

我没有找到pcm_u8意味着什么的参考,但它高度暗示它是一个简单的脉冲编码调制数据流,具有8位数据。这听起来并没有内置任何纠错编码或数据冗余。丢失一个字节意味着丢失样本,并且在接收端无法完成任何操作。

所以我认为发生的事情是网络中的某些内容正在丢弃UDP数据包,RTP告诉AudioStream哪些数据丢失,结果是间隙,因为没有纠错或数据冗余在pcm_u8数据流中,允许AudioStream重建丢失的数据。

我已经看到像VMWare这样的东西故意丢弃虚拟网络上的UDP数据包,以确保良好的性能,理由是UDP无论如何都不能保证交付这样做&#34;它并不重要#34 ;.这严重刺伤了一位正在使用RTP的同事并且期待保证交付,但没有得到它。他有一个封闭的网段,每根线都有一个服务器,其中一个托管一个虚拟机。

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