RTP头解析、RTP头部创建

文章目录

RTP头解析

RTP协议格式:
请添加图片描述

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头部:

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

解析日记:
在这里插入图片描述

xcode-demo下载地址:
demo下载

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
RTP(Real-time Transport Protocol)是一种用于实时传输音视频数据的协议,其数据单元称为RTP包。RTP包由头部和有效载荷两部分组成,其中头部信息包含了一些必要的元数据,以便接收端正确解析和播放音视频数据。下面是RTP头部信息的详细解释: 1. 版本号(2位):标识RTP协议的版本号,当前协议的版本号为2。 2. 填充位(1位):用于填充RTP包的最后一字节,以保证其长度为32比特的整数倍。 3. 扩展位(1位):用于指示RTP头部是否包含扩展头部信息。 4. CSRC计数器(4位):用于指示RTP头部后面跟着的CSRC标识符的个数,一般为0。 5. 标记位(1位):用于指示RTP包是否为一帧音视频数据的结束包。 6. 负载类型(7位):用于指示RTP包中有效载荷的类型,例如音频、视频或其他数据。 7. 序列号(16位):用于标识RTP包在媒体流中的顺序,每发送一个RTP包,序列号就会加1。 8. 时间戳(32位):用于指示RTP包中有效载荷的时间戳,以便接收端可以根据时间戳来播放音视频数据。 9. 同步源标识符(SSRC)(32位):用于标识发送端的唯一标识符,以便接收端可以识别数据来自哪个发送端。 10. CSRC标识符(0个或多个,每个32位):用于标识产生RTP包的源端,用于多个源端共享同一媒体流时使用。 11. 扩展头部信息(0个或多个):用于在RTP头部添加额外的元数据,例如帧间压缩方式等。 注意:RTP头部信息中的所有字段均为网络字节序(Big-Endian)排列。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

baoyu45585

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值