欢迎关注公众号:冒泡的肥皂
1.数据快结构
2.Message Header说明
message header长度不是固定的,跟fmt(2 bit)有关系。
Chunk Type(fmt) = 0:11 bytes 时间+消息长度+消息类型+流ID
Chunk Type(fmt) = 1:7 bytes 时间差+消息长度+消息类型+(省略上次流ID相同
Chunk Type(fmt) = 2:3 bytes 时间差+(省略消息长度+消息类型+上次流ID相同Chunk Type(fmt) = 3: 0 byte (省略表示和上次完全相同
下面是结构图
2.Message Header解析
消息头定义
public class MessageHeader {
int timestamp;//时间戳
int messageLength;//消息长度
short messageTypeId;//消息类型
int messageStreamId;//流ID
int timestampDelta;//时间差
long extendedTimestamp;//额外时间
}
解析当前消息
//解析当前消息
switch (fmt) {
case 0: {//总11字节结构
//读取三个字节的int值
int timestamp = in.readMedium();
//读取三个字节的int值
int messageLength = in.readMedium();
//读取一个字节
short messageTypeId = (short) (in.readByte() & 0xff);
//流ID小端数据
int messageStreamId = in.readIntLE();
headerLength += 11;
//如果时间戳都是1 则取额外的四字节日期
if (timestamp == MAX_TIMESTAMP) {
//读取四字节
long extendedTimestamp = in.readInt();
MessageHeader.setExtendedTimestamp(extendedTimestamp);
headerLength += 4;
}
MessageHeader.setTimestamp(timestamp);
MessageHeader.setMessageTypeId(messageTypeId);
MessageHeader.setMessageStreamId(messageStreamId);
MessageHeader.setMessageLength(messageLength);
}
break;
case 1: {//7字节同上
int timestampDelta = in.readMedium();
int messageLength = in.readMedium();
short messageType = (short) (in.readByte() & 0xff);
headerLength += 7;
if (timestampDelta == MAX_TIMESTAMP) {
long extendedTimestamp = in.readInt();
MessageHeader.setExtendedTimestamp(extendedTimestamp);
headerLength += 4;
}
MessageHeader.setTimestampDelta(timestampDelta);
MessageHeader.setMessageLength(messageLength);
MessageHeader.setMessageTypeId(messageType);
}
break;
case 2: {//三字节同上
int timestampDelta = in.readMedium();
headerLength += 3;
MessageHeader.setTimestampDelta(timestampDelta);
if (timestampDelta == MAX_TIMESTAMP) {
long extendedTimestamp = in.readInt();
MessageHeader.setExtendedTimestamp(extendedTimestamp);
headerLength += 4;
}
}
break;
case 3: {//空同上
}
break;
default:
throw new RuntimeException("illegal fmt type:" + fmt);
}
重置头信息 fmt:1,2,3的
//重置头信息 类型1,2,3的
private void completeHeader(MessageHeader rtmpHeader) {
//获取上个消息的头
MessageHeader prev = prevousHeaders.get(rtmpHeader.getCsid());
if (prev == null) {
return;
}
switch (rtmpHeader.getFmt()) {
case 1://省略的流ID
MessageHeader.setMessageStreamId(prev.getMessageStreamId());
break;
case 2://省略的长度+类型+流ID
MessageHeader.setMessageLength(prev.getMessageLength());
MessageHeader.setMessageStreamId(prev.getMessageStreamId());
MessageHeader.setMessageTypeId(prev.getMessageTypeId());
break;
case 3://都省略的
MessageHeader.setMessageStreamId(prev.getMessageStreamId());
MessageHeader.setMessageTypeId(prev.getMessageTypeId());
MessageHeader.setTimestamp(prev.getTimestamp());
MessageHeader.setTimestampDelta(prev.getTimestampDelta());
break;
default:
break;
}
}