RTMP学习笔记(二) Message Header说明与解析

175 阅读1分钟

欢迎关注公众号:冒泡的肥皂

image.png

1.数据快结构

image.png

2.Message Header说明

message header长度不是固定的,跟fmt(2 bit)有关系。
Chunk Type(fmt) = 011 bytes   时间+消息长度+消息类型+流ID
Chunk Type(fmt) = 17 bytes  时间差+消息长度+消息类型+(省略上次流ID相同
Chunk Type(fmt) = 23 bytes   时间差+(省略消息长度+消息类型+上次流ID相同Chunk Type(fmt) = 30 byte    (省略表示和上次完全相同
下面是结构图

image.png

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;
    }
  }