2010-04-10 76 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); 

但是,请记住在这前子编码仍处于早期阶段。对于这个特殊情况,它似乎有效,但我不会作任何保证。

使用前子的好处是很明显的事实是,你不必费心编写了所有的编码和解码逻辑自己。