对RTP实现的一点理解
文章目录
说明
本文性质为个人学习笔记。由于刚刚入门所以看法很浅,如有错误请指正。
例程中使用位字段表示RTP首部,没有问题吗?
位字段是一种通过结构来声明的、对变量进行的位操作方法。经过查阅资料,对位字段有如下论述:
《C Primer Plus(第六版)中文版》第505页:
…位字段是一个signed int或unsigned int类型变量中的一组相邻的位(C99和C11新增了_Bool类型的位字段)。…
《高质量嵌入式Linux C编程(第2版)》第153页:
…使用位段需注意以下几点:
位段的类型只能是int、unsigned int和signed int这3种类型,不能是char型或者浮点型。
…
然而在我所学习并查找到的RTP实现中,RTP首部通常被定义为以下的样子:
typedef struct
{
unsigned char u4CSrcLen :4;
unsigned char u1Externsion:1;
unsigned char u1Padding :1;
unsigned char u2Version :2;
unsigned char u7Payload :7;
unsigned char u1Marker :1;
unsigned short u16SeqNum;
unsigned long u32TimeStamp;
unsigned long u32SSrc;
}stRTPHeader;
可以看到,其中大量使用了unsigned char型的变量,这显然有悖于标准中的叙述。但是实际测试中发现这 并不影响编译和传输 。姑且如此。
为什么要使用位字段?
位字段的使用,方便了修改RTP首部中指定位时的操作,减少了移位带来的麻烦,另外一点是, RTP规定中,是以大端方式进行定义的。 使用位字段的操作,可以方便在大小端系统上进行移植,例如这样定义(此处引用来源见参考1):
struct MBRTPHeader
{
#ifdef RTP_BIG_ENDIAN
unsigned char version:2;
unsigned char padding:1;
unsigned char extension:1;
unsigned char csrccount:4;
unsigned char marker:1;
unsigned char payloadtype:7;
#else
unsigned char csrccount:4;
unsigned char extension:1;
unsigned char padding:1;
unsigned char version:2;
unsigned char payloadtype:7;
unsigned char marker:1;
#endif
unsigned short sequencenumber;
unsigned int timestamp;
unsigned int ssrc;
};
通过在编译时开启不同的宏,达到增加可移植性的效果。
另外需要注意,对RTP首部(以及分片的指示首部)中的成员赋值时, 均需转换为网络字节序再进行传输 。
关于socket的使用
本部分内容引用自参考2。
…
Socket使用中,需要首先初始化一个sockaddr_in结构,其中的sin_family成员可以设置为AF_INET协议族或者PF_INET协议族。在Windows下,AF_INET与PF_INET完全一样.。而在Unix/Linux系统中,在不同的版本中这两者有微小差别。对于BSD,是AF,对于POSIX是PF。
理论上建立socket时是指定协议,应该用PF_xxxx,设置地址时应该用AF_xxxx。当然AF_INET和PF_INET的值是相同的,混用也 不会有太大的问题。也就是说你socket时候用PF_xxxx,设置的时候用AF_xxxx也是没关系的。
…
为什么要在应用层对RTP报文进行分片?
RTP分片并不是为了适配UDP报文长度,而是取了一个比较理想的值用以适配MTU大小,使一条报文传递到数据链路层后不会被分割成更小的包。
一般而言,当传输一个较大的UDP数据报时,数据被层层封包和分割,而后进行发送,在网络情况较好的时候这样做倒是没什么,但是如果路由或网络发生状况,分包的动作有可能会有延迟或者出错,将影响到RTP流的传输。
所以我所见的RTP实现,以一个理想的MTU大小为阈值对包在应用层进行分割,这样传到底层的包,路由只需要转发不需要额外的操作,对网络稳定性有了更好的容错。
实际上,对于H264视频流而言,进行稍微大一点的画面编码时,基本上只有IDR帧的SPS、PPS和SEI包可以在一个RTP报文中传输而不需要分片。
然而这样做的时候,如果传输中发生包的丢失,RTP依旧无法处理,只能丢弃,这也体现了RTP不保证服务质量这一特点。
另外,分片和不分片,对NALU头的处理方式是不同的。在不分片的情况下,一个RTP包格式是这样的:
RTP首部(12Bytes)+NALU(1Byte)+数据
在分片的时候,分片前端是这样的:
RTP首部(12Bytes)+FUA指示(1Byte)+FUA头(1Byte)+数据+…
这时,NALU头会被分为两个部分分别存放在FUA指示字节和FUA头中。这也是NALU头需要专门取出处理的原因之一。
编码的H264流的RTP时间戳应该如何设置?
我测试时使用的编码平台为Hi3516DV300,海思编码器的每个码流包中会给出一个时间戳信息,为无符号64位整型值,单位是us。RTP码流中视频时间戳是基于90KHz的,故其单位为1/90000,RTP首部中的时间戳要换算成该单位下的变量,方法是(以下计算忽略了变量范围): RTPTimeStamp=H264TimeStamp*90000/1000000 。
这样就借由编码器的时间戳获得RTP报文的时间戳,而且不需要再查询系统时间了。
参考
- 分享
- 举报
-
浏览量:1913次2018-12-25 15:48:04
-
浏览量:20399次2022-02-11 09:00:22
-
浏览量:2954次2017-12-27 14:04:22
-
浏览量:625次2023-09-18 14:26:23
-
2020-09-28 11:34:56
-
浏览量:2158次2019-11-22 14:11:11
-
浏览量:3619次2020-07-27 16:07:46
-
浏览量:391次2023-09-05 09:12:28
-
浏览量:2484次2020-08-06 18:56:10
-
浏览量:3231次2020-08-04 17:37:01
-
浏览量:2982次2022-08-17 09:00:39
-
浏览量:5343次2021-05-08 15:04:36
-
浏览量:2567次2022-02-13 09:00:17
-
浏览量:2490次2019-12-31 16:23:45
-
浏览量:4965次2021-07-30 15:32:45
-
浏览量:1324次2024-01-24 17:07:21
-
浏览量:1554次2019-02-26 16:42:37
-
浏览量:6077次2021-08-03 11:36:37
-
浏览量:1611次2020-08-05 20:33:33
-
广告/SPAM
-
恶意灌水
-
违规内容
-
文不对题
-
重复发帖
风清扬
感谢您的打赏,如若您也想被打赏,可前往 发表专栏 哦~
举报类型
- 内容涉黄/赌/毒
- 内容侵权/抄袭
- 政治相关
- 涉嫌广告
- 侮辱谩骂
- 其他
详细说明