2012-02-01 69 views
3

我做了一些關於在小型網絡中使用voip over udp的學習。我知道有很多庫可以做,並且只需要幾個方法調用就可以完成所有我需要的東西,但正如我所說的,我正在學習,所以需要重新發明輪子以瞭解它是如何工作的。voip基礎 - 包頭信息?

我目前正在研究DatagramPacket類,我注意到沒有方法可以在DatagramPacket類中設置標題信息(即,我需要知道的用於交織的信息包順序號)。

一些代碼來反映環境:

byte[] block; 
DatagramPacket packet; // UDP packet     

/* x Bytes per block , y blocks per second, 
    z ms time block playback duration */ 

block = recorder.getBlock(); // assume I have class that handles audio 
           // recording and returns speech in a 
           // uncompressed form of bytes 

packet = new DatagramPacket(block, block.length, clientIP, PORT); 

首先,我認爲,因爲它是UDP,發送者並沒有真正關心任何事情除了簡單的事實,他拋出的數據包的地方。所以這就是爲什麼裏面沒有這樣的方法。

其次,我假設我需要自己做 - 爲要發送的字節塊添加額外的字節,其中包含一個數據包的序列號?但是我也擔心,如果我這樣做,那麼如何識別字節是頭字節而不是音頻字節?我可以假定第一個字節代表一個數字,但是我們知道該字節只能代表258個數字。我從來沒有真正在字節級別上工作過。或者還有其他技術?

不久說,做交錯,我需要知道如何設置數據包的序列號,因爲我不能爲了無序的數據包:-)

謝謝你,

回答

6

你需要序列化/反序列化您的程序在字節數組上使用的數據類型。

讓我們假設你在談論RTP,和你想發送具有這些領域 - 看第5章在RTP規格:

版本= 2 填充= 0 延長= 0 CSRC計數= 1 標記= 0 有效載荷類型= 8(G711阿勞) 序列號= 1234 時間戳= 1 一個CSRC = 4321

讓我們把這些成一些變量,使用整數爲了容易,或長當我們需要時對付一個32位無符號值:

int version = 2; 
int padding = 0; 
int extension = 0; 
int csrcCount = 1; 
int marker = 0; 
int payloadType = 8; 
int sequenceNumber = 1234; 
long timestamp = 1; 
long ourCsrc = 4321; 

byte buf[] = ...; //allocate this big enough to hold the RTP header + audio data 

//assemble the first bytes according to the RTP spec (note, the spec marks version as bit 0 and 1, but 
//this is really the high bits of the first byte ... 
buf[0] = (byte) ((version & 0x3) << 6 | (padding & 0x1) << 5 | (extension & 0x1) << 4 | (csrcCount & 0xf)); 

//2.byte 
buf[1] = (byte)((marker & 0x1) << 7 | payloadType & 0x7f); 

//squence number, 2 bytes, in big endian format. So the MSB first, then the LSB. 
buf[2] = (byte)((sequenceNumber & 0xff00) >> 8); 
buf[3] = (byte)(sequenceNumber & 0x00ff); 

//packet timestamp , 4 bytes in big endian format 
buf[4] = (byte)((timestamp & 0xff000000) >> 24); 
buf[5] = (byte)((timestamp & 0x00ff0000) >> 16); 
buf[6] = (byte)((timestamp & 0x0000ff00) >> 8); 
buf[7] = (byte) (timestamp & 0x000000ff); 
//our CSRC , 4 bytes in big endian format 
buf[ 8] = (byte)((sequenceNumber & 0xff000000) >> 24); 
buf[ 9] = (byte)((sequenceNumber & 0x00ff0000) >> 16); 
buf[10] = (byte)((sequenceNumber & 0x0000ff00) >> 8); 
buf[11] = (byte) (sequenceNumber & 0x000000ff); 

這是頭,現在你可以將音頻字節複製到buf,開始buf[12]和發送buf爲一個包。

現在,以上只是爲了說明原理,根據RTP規範,RTP數據包的實際串行器將不得不處理更多的事情(例如,您可能需要一些擴展頭,您可能需要更多根據您所擁有的音頻數據的格式,您需要正確的有效負載類型,您需要正確打包和調度這些音頻數據 - 例如,對於G.711Alaw,您應該爲每個RTP數據包填充160個字節的音頻數據和每20毫秒發送一個數據包

+0

哦,這就是我正在尋找的東西,這麼多的學習和分析,但我現在有方向,這是非常重要的,謝謝 – Aubergine 2012-02-01 17:17:23

+0

我問博士們有關位移的顯示你的代碼他們說單獨鑄造就夠了。所以如果我可以調用,我必須嚴格使用你提供的移位:buf [4] =(byte)sequenceNumber?謝謝。 – Aubergine 2012-02-06 16:56:07

+0

@Aubergine您需要將4字節整數的最高有效字節放入buf [4]中,並且您無法通過將整型轉換爲字節來完成此操作。對於最低有效字節,'buf [7] =(byte)timestamp;'就足夠了,而不是buf [7] =(byte)(timestamp&0x000000ff);' – nos 2012-02-07 08:04:33