RTP头解析、RTP头部创建

文章目录

    • RTP头解析

RTP头解析

RTP协议格式:
RTP头解析、RTP头部创建_第1张图片

1.V:RTP协议的版本号,占2位,当前协议版本号为2。

  1. P:填充标志,占1位,如果P=1,则在该报文的尾部填充一个或多个额外的八位组,它们不是有效载荷的一部分。

  2. X:扩展标志,占1位,如果X=1,则在RTP报头后跟有一个扩展报头。

  3. CC:CSRC计数器,占4位,指示CSRC 标识符的个数。

  4. M: 标记,占1位,不同的有效载荷有不同的含义,对于视频,标记一帧的结束;对于音频,标记会话的开始。

  5. PT: 有效载荷类型,占7位,用于说明RTP报文中有效载荷的类型,如GSM音频、JPEM图像等,在流媒体中大部分是用来区分音频流和视频流的,这样便于客户端进行解析。

  6. 序列号:占16位,用于标识发送者所发送的RTP报文的序列号,每发送一个报文,序列号增1。
    应用场景:对视频进行无变形缩放选定要裁剪的坐标点、对应的宽高进行裁

RTP头部协议,前12位为基础字节,对应第一个结构体,如果extension为1时候,才有外部扩展信息,外部扩展信息结构对应第二个结构体,分别对应profile、length、data。

RTP头解析、RTP头部创建_第2张图片

创建RTP头部:

void create_rtp_header( ) {
    uint8_t *buf;
    int version=2;
    int padding=0;
    int extension=1;
    int csrc_count=2;
    int marker=2;
    int payload_type=96;
    uint16_t sequence_number=12345;
    uint32_t timestamp=1234567890;
    uint32_t ssrc=987654321;
    //extension扩展信息
    int profile=7;
    int length=1;
    uint16_t data[]={0x0001};
    
    //Version (2 bits) + Padding (1 bit) + Extension (1 bit) + CSRC count (4 bits)
    buf[0] = (version << 6) | (padding << 5) | (extension << 4) | csrc_count;
    //Marker (1 bit) + Payload type (7 bits)
    buf[1] = (marker << 7) | payload_type;
    // 设置序列号
    buf[2] = (sequence_number >> 8) & 0xFF;
    buf[3] = sequence_number & 0xFF;
    // 设置时间戳
    buf[4] = (timestamp >> 24) & 0xFF;
    buf[5] = (timestamp >> 16) & 0xFF;
    buf[6] = (timestamp >> 8) & 0xFF;
    buf[7] = timestamp & 0xFF;
    // 设置同步源ID
    buf[8] = (ssrc >> 24) & 0xFF;
    buf[9] = (ssrc >> 16) & 0xFF;
    buf[10] = (ssrc >> 8) & 0xFF;
    buf[11] = ssrc & 0xFF;
    // 添加扩展信息头profile
    buf[12] = profile >> 8;
    buf[13] = profile & 0xff;
    // 设置扩展信息头长度
    buf[14] = (length >> 8) & 0xFF;
    buf[15] = length & 0xFF;
    // 设置扩展信息data
    buf[16] = (data[0] >> 8) & 0xFF;
    buf[17] = data[0] & 0xFF;
    // 复制扩展信息到RTP头中
    memcpy(buf + 16, data, length);
}

解析RTP头部:

  // 读取版本号和填充位
    uint8_t version = (buf[0] >> 6) & 0x03;
    uint8_t padding = (buf[0] >> 5) & 0x01;
    // 读取扩展位和CSRC计数器
    uint8_t extension = (buf[0] >> 4) & 0x01;
    uint8_t csrc_count = buf[0] & 0x0f;
    // 读取标记位和负载类型
    uint8_t marker = (buf[1] >> 7) & 0x01;
    uint8_t payload_type = buf[1] & 0x7f;
    // 读取序列号
    seq_num = (buf[2] << 8) | buf[3];
    // 读取时间戳
   timestamp = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
    // 读取同步源标识符
    ssrc = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
    //profile
    uint16_t profile = ntohs(*((uint16_t*)(data + 12)));
   //length
    uint32_t length = ntohl(*((uint16_t*)(data + 14)));
    //data
    uint32_t data = ntohl(*((uint16_t*)(data + 16)));


void parse_rtp_header(const uint8_t *buf, rtp_header *header) {
    // 读取版本号和填充位
    uint8_t version = (buf[0] >> 6) & 0x03;
    uint8_t padding = (buf[0] >> 5) & 0x01;
    // 读取扩展位和CSRC计数器
 
    int extension = (buf[0] & 0x10) >> 4;
    uint8_t csrc_count = buf[0] & 0x0f;
    // 读取标记位和负载类型
    uint8_t marker = (buf[1] >> 7) & 0x01;
    int payload_type = buf[1] & 0x7f;
    // 读取序列号
    header->seq_num = (buf[2] << 8) | buf[3];
    // 读取时间戳
    header->timestamp = (buf[4] << 24) | (buf[5] << 16) | (buf[6] << 8) | buf[7];
    // 读取同步源标识符
    header->ssrc = (buf[8] << 24) | (buf[9] << 16) | (buf[10] << 8) | buf[11];
    if (extension) {
        uint16_t extension__len = AV_RB16(&buf[14]);
        printf("Extension length: %d\n", extension__len);
        uint16_t ext_id = (((const uint8_t*)(buf+16))[1]);
    
      //  uint16_t ext_id = AV_RB16(&buf[12]);

       // int  extension_data=  AV_RB16(&buf[16]);
        //int ext = (AV_RB16(buf + 2) + 1) << 2;
      //  printf("extension_data: %d\n",  extension_data);
        printf("  Profile: %d\n", ext_id);
      
    }
    // 输出解析结果
    printf("RTP header:\n");
    printf("Version: %u\n", version);
    printf("Padding: %u\n", padding);
    printf("Extension: %d\n", extension);
    printf("CSRC count: %u\n", csrc_count);
    printf("Marker: %u\n", marker);
    printf("Payload type: %d\n", payload_type);
    printf("Sequence number: %u\n", header->seq_num);
    printf("Timestamp: %u\n", header->timestamp);
    printf("SSRC: %u\n", header->ssrc);
}

解析日记:
RTP头解析、RTP头部创建_第3张图片

xcode-demo下载地址:
demo下载

你可能感兴趣的:(视频,c++)