簡體   English   中英

通過UDP發送音頻時如何減少延遲?

[英]How can I reduce delay when sending audio over UDP?

我已經編寫了一個小型Java程序(pc)和android應用,旨在將音頻從pc傳輸到手機。 我正在通過UDP發送音頻數據,無法確定發生延遲的原因。 從客戶端到服務器,在處理數據包之前大約需要1.5-2秒。

我的程序緩沖512個字節以發送給客戶端,該字節在接收到后立即播放。

我測試了一些不同的配置,任何(基本上)高於此值的配置,延遲只會增加。 使用較低的值,在延遲方面沒有明顯的改善,但是卻存在明顯的質量損失。

根據窗口,設備之間的ping時間僅為3毫秒,因此我認為網絡連接不是問題,盡管我不是很肯定。

我的客戶(PC)的代碼如下所示。

byte[] buffer = new byte[512];
while (true) {
    try {
        audioInput.read(buffer, 0, buffer.length);
        DatagramPacket data = new DatagramPacket(buffer, buffer.length, address, port);
        dout.send(data);
        System.out.println("Sent Packet #" + i++);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

服務器(電話)的代碼如下。

    byte[] buffer = new byte[512];
    DatagramPacket incomingPacket = new DatagramPacket(buffer, buffer.length);
    while (true) {
        try {
            dgs.receive(incomingPacket);
            buffer = incomingPacket.getData();
            audioOutput.write(buffer, 0, buffer.length);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

我期望數據包以接近5ms的網絡延遲的速度到達,但實際上只有在1500ms之后才接收到它們。

我希望你們中的一些人可能對這種問題有經驗。 我知道Discord和Skype之類的應用程序以更高的比特率傳輸流,具有更高的延遲,但是延遲卻低得多,所以我希望可能會錯過一些東西。

您正在嘗試進行實時流式傳輸。 讓我們看看整個過程中的延遲預算。

首先,您使用512字節的緩沖區-假設樣本為float且樣本率為44.1k ,則每次處理128樣本,這將提供~2.9ms的緩沖時間。

在此緩沖區大小下,您可以獲得的最佳值為~7.5ms

控制流程:

1:音頻輸入硬件生成樣本並將其存儲在緩沖區中。 在預定數量的樣本之后,操作系統將中斷以提供音頻。 該緩沖時間可能明顯長於128個樣本。 這是T1

2:操作系統安排音頻守護程序進程運行。 它在運行之前等待S1

3:音頻守護程序運行,處理音頻,將其寫入緩沖區,然后向操作系統發出信號,指出可以讀取樣本。 這段時間短得可以忽略不計。

4:操作系統通過audioInput.read(buffer, 0, buffer.length);audioInput.read(buffer, 0, buffer.length);的調用來調度您的輸入進程audioInput.read(buffer, 0, buffer.length); 它在計划之前等待S2

5:您調用System.out.println() 這可能會阻塞-尤其是在您每秒寫入約350次時-可能直到安排了另一個不相關的進程為止。 S3

6:將UDP寫入網絡套接字。 操作系統可能將其排隊等待發送-稍后發生的時間可能會微不足道

7:通過網絡傳輸。 T2

接收方幾乎與上述相反。

因此總延遲為

2 * (T1 + S1 + S2 + S3 + T2)

我想您的大多數延遲是發送和接收T1的硬件緩沖時間。 如果您得到的值遠低於10ms ,則S1,S2,S3將開始變得有意義。

注意:

  • S1S2是運行調度延遲,並且取決於系統負載和調度程序策略。 音頻渲染處理程序通常以實時威脅優先級運行。
  • 您可以通過不登錄控制台來消除S3 此延遲特別不可預測。
  • Java運行時可能會帶來一些隱藏的運行時成本(例如GC)。 這將是可靠的低延遲音頻的限制因素。

真正降低延遲的方法是:

  • 用C或C ++實現
  • 沒有內存分配,登錄渲染循環
  • 固定堆棧和堆頁面以防止被交換
  • 以實時調度優先級運行音頻渲染線程。
  • 無鎖數據結構可防止優先級倒置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM