灌装在Java中
问题描述:
一个字节数组,对于一个项目我的工作,我实现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();
任何其他的,也许 '更好' 的方式来做到这一点?
答
我想我会用一个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);
答
您可以直接将int
转换为Java中的byte
,而无需创建Integer
对象。因为byte
的可能值范围窄于int
,所以需要进行明确的转换。例如:
header[1] = (byte) (Marker << 7 | PayloadType);
答
这样的数据有一个问题。通常协议在那里使用无符号字节,而Java已经签名字节。因此,对于正确的字节数组填充,我通常使用这样的构造:
bytearray[index] = (byte) ((some integer-result calculation) & 0xff);
简单转换为字节类型将无法正常工作。
更新。 “& 0xff”在这里不需要。简单的演员将工作。
答
随着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);
但是,请记住在这前子编码仍处于早期阶段。对于这个特殊情况,它似乎有效,但我不会作任何保证。
使用前子的好处是很明显的事实是,你不必费心编写了所有的编码和解码逻辑自己。
不要创建一个对象只是为了从中提取一个基元。它丑陋而且效率低下。 – 2010-04-10 21:02:17