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 rtpパケット管理にありました。
Androidは、 AudioGroupソースファイル の... 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間隔ごとに1つのパケットしかありません。その結果、音がぎくしゃくします。
これに関するバグレポートを送信します。誰かに役立つことを願っています。
生のRTPストリームを本当に聴きたい人は、パケットを手動で読み取り、PCM 16ビット(Androidサウンドカードがサポートする唯一のオーディオ形式)にデコードしてAudioTrackに書き込むことをお勧めします。 。
以下が馬鹿げている場合はお詫びします。
Ffmpegコマンドラインは、テストサウンドを生成し、RTPを介してpcmデータストリームとして出力しているように見えます。
RTP自体は、ストリーミングデータの信頼性の高い配信を保証するものではなく、受信者にすべてのデータを受信したかどうか、および転送中に一部が失われた場合にどのデータが欠落しているかを正確に伝えるのに十分な情報を提供するだけです。さらに、通常はUDPを介して使用されます。
したがって、RTP)では、RTPのユーザーが、そのような方法でエンコードされたデータを送信することに重点が置かれます(つまり、エラー訂正コーディング、データの冗長性)など)を使用して、受信者がアプリケーションのニーズを満たすのに十分な元のデータを再構築できるようにします。したがって、オーディオストリームでは、適切な何らかのエンコード形式が必要になります。
Pcm_u8の意味についてのリファレンスは見つかりませんでしたが、8ビットデータを使用した単純なパルス符号変調データストリームであることを強く示唆しています。エラー訂正エンコーディングやデータ冗長性が組み込まれているようには思えません。そのバイトを失うことはサンプルを失うことを意味し、入力するために受信側でできることは何もありません。
だから私はあなたのネットワークの何かがUDPパケットをドロップしていると思います、それはRTPはAudioStreamにどのデータが欠落しているかを伝えており、エラー訂正やデータの冗長性がないためにギャップが生じます失われたデータをAudioStreamで再構築できるようにするpcm_u8データストリーム。
VMWareのようなものは、良好なパフォーマンスを確保する方法として、仮想ネットワーク上に意図的にUDPパケットをドロップするのを見てきました。その理由は、UDPが配信を保証されていないため、「問題ではない」ということです。これは、RTPを使用していて、保証された配信を期待していたが、それを取得できなかった同僚をひどく悩ませました。彼は、ワイヤの両端にサーバーがあり、そのうちの1つがホストしている閉じたネットワークセグメントを持っていました。単一のVM。
したがって、使用しているコーデックを変更する場合にすぎない可能性があります。お勧めできません。まず、ブロードキャストデジタルメディアストリームが何を使用しているかを調べる価値があります。 DVB-Tは、MPEG-2のラッパーであるAFAIKとしてMPEGトランスポートストリーム(エラー訂正コーディングなどを含む)を使用します。