2010-04-10 50 views
4

一個字節數組,對於一個項目我的工作,我實現RTPpacket,我必須填寫字節的頭陣列RTP報頭字段的一部分。灌裝在Java中

//size of the RTP header: 
    static int HEADER_SIZE = 12; // bytes 

    //Fields that compose the RTP header 
    public int Version; // 2 bits 
    public int Padding; // 1 bit 
    public int Extension; // 1 bit 
    public int CC; // 4 bits 
    public int Marker; // 1 bit 
    public int PayloadType; // 7 bits 
    public int SequenceNumber; // 16 bits 
    public int TimeStamp; // 32 bits 
    public int Ssrc; // 32 bits 

    //Bitstream of the RTP header 
    public byte[] header = new byte[ HEADER_SIZE ]; 

這是我的方法:

/*  
* bits 0-1: Version 
* bit 2: Padding 
* bit 3: Extension 
* bits 4-7: CC 
*/ 
header[0] = new Integer((Version << 6)|(Padding << 5)|(Extension << 6)|CC).byteValue(); 

/* 
* bit 0: Marker 
* bits 1-7: PayloadType 
*/ 
header[1] = new Integer((Marker << 7)|PayloadType).byteValue(); 

/* SequenceNumber takes 2 bytes = 16 bits */ 
header[2] = new Integer(SequenceNumber >> 8).byteValue(); 
header[3] = new Integer(SequenceNumber).byteValue(); 

/* TimeStamp takes 4 bytes = 32 bits */ 
for (int i = 0; i < 4; i++) 
    header[7-i] = new Integer(TimeStamp >> (8*i)).byteValue(); 

/* Ssrc takes 4 bytes = 32 bits */ 
for (int i = 0; i < 4; i++) 
    header[11-i] = new Integer(Ssrc >> (8*i)).byteValue(); 

任何其他的,也許 '更好' 的方式來做到這一點?

+1

不要創建一個對象只是爲了從中提取一個基元。它醜陋而且效率低下。 – 2010-04-10 21:02:17

回答

6

我想我會用一個ByteBuffer

ByteBuffer buf = ByteBuffer.wrap(header); 
buf.setOrder(ByteOrder.BIG_ENDIAN); 
buf.put((byte)((Version << 6)|(Padding << 5)|(Extension << 6)|CC)); 
buf.put((byte)((Marker << 7)|PayloadType)); 
buf.put((short)SequenceNumber); 
buf.put(TimeStamp); 
buf.put(Ssrc); 
2

您可以直接將int轉換爲Java中的byte,而無需創建Integer對象。因爲byte的可能值範圍窄於int,所以需要進行明確的轉換。例如:

header[1] = (byte) (Marker << 7 | PayloadType); 
0

這樣的數據有一個問題。通常協議在那裏使用無符號字節,而Java已經簽名字節。因此,對於正確的字節數組填充,我通常使用這樣的構造:

bytearray[index] = (byte) ((some integer-result calculation) & 0xff); 

簡單轉換爲字節類型將無法正常工作。

更新。 「& 0xff」在這裏不需要。簡單的演員將工作。

+2

真的嗎? 看一看爲'#整數的的byteValue源代碼()': /** * 返回此Integer的值作爲 * byte。 */ 公共字節的byteValue(){ \t回報(字節)值; } – rhu 2010-04-10 19:24:29

+1

對不起,我的壞。這是一個相反的轉換,需要(UByte&0xff) - >正確的整數。當我們將整數轉換爲字節時,可以簡單地進行字節轉換。 – bealex 2010-04-10 19:38:01

0

除了呈現答案給一個嘗試Preon

0

隨着Preon,該RtpHeader可以這樣表示:

public class RtpHeader { 

    @BoundNumber(size = "2") 
    public int version; 

    @Bound 
    public boolean padding; 

    @Bound 
    public boolean extension; 

    @BoundNumber(size="4") 
    public int csrcCount; 

    @Bound 
    public boolean marker; 

    @BoundNumber(size="7") 
    public int payloadType; 

    @BoundNumber(size="16", byteOrder = ByteOrder.BigEndian) 
    public int sequenceNumber; 

    @BoundNumber(size="32", byteOrder = ByteOrder.BigEndian) 
    public int timestamp; 

    @BoundNumber(size="32", byteOrder = ByteOrder.BigEndian) 
    public int synchronizationSource; 

    @BoundList(size="csrcCount") 
    public int[] csrcs; 

} 

將其編碼爲字節可能如此簡單:

Codec<RtpHeader> codec = Codecs.create(RtpHeader.class); 
    RtpHeader header = new RtpHeader(); 
    ... // Setting header values 
    OutputStream out = ...; 
    Codecs.encode(header, codec, out); 

但是,請記住在這前子編碼仍處於早期階段。對於這個特殊情況,它似乎有效,但我不會作任何保證。

使用前子的好處是很明顯的事實是,你不必費心編寫了所有的編碼和解碼邏輯自己。