本文主要是介绍H264 over RTP 的解包,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
前一版博文《H264 over RTP 的打包》已经详细介绍了发送端如何将H264视频帧打包到RTP进行传输,现在我们书接上文,介绍接收端收到RTP包后如何解包组装还原出来H264帧。从前文我们知道发送端发送一帧H264数据时会遍历H264帧逐个将NALU打包成RTP包(当然NALU大于MTU时会进行分片),每一帧数据对应的RTP包的时间戳都是相同的,最后一个RTP包的marked位为TRUE;因此接收到只需要将接收到的RTP包组装成NALU,然后将NALU连接起来就可以还原H264帧了,由于网络传输可能会丢包和乱序,所以接收端还要有RTP接收缓存,用于RTP包排序(根据RTP头的SN进行排序)。
一个H264帧由一些列NALU构成,每个NALU又被拆解(依据传输层的MTU去拆解)为若干个数据段,这些数据段打上一个头后(这个头部有NALU分段的标识,start_bit和end_bit表示起始数据段和结束数据段),再封装成rtp包去发送。传输同一个H264帧的rtp包都具有相同的时间戳。
rtp_j1为第j个NALU的起始数据段,其分段标识有start_bit=1;
rtp_jk为第j个NALU的结束数据段,其分段标识有end_bit=1;
在起始数据段和结束数据段之间的其它数据段由rtp的SN标识其先后顺序;
接收端可以根据收到rtp包的SN的连续性、以及start_bit和end_bit标志位来组成一个完整的NALU,以及判断一个NALU是否有丢包。
- 接收Buffer设计
接收端采用双缓存机制,一个RTP缓存,用于RTP包的排序,一个帧缓存,用于存放组装出来的H264帧,解码和播放线程从帧缓存取数据。
RTP接收缓存的设计如下图所示,
缓存设计为二维的结构,横向是按照RTP包的时间排序,纵向按照rtp的SN排序,由于一个H264帧在发送端发送时其承载的所有rtp包都具有相同的时间戳,不同的H264帧其传输的rtp时间戳不一样,所以上图中某个时间节点下的所有rtp包属于同一个H264帧。
比如时间节点ti ,那么其对应的所有rtp包rtp_i1、rtp_i2、…、rtp_ik都是属于H264帧Frame_i的;其中,i=1、2、…、n, k=1、2、…。
RTP的接收缓存大小为RTP_BUFFER_SIZE帧,如果接收buffer已满时收到新帧的RTP包,则对头节点出队列,强制将这个不完整的节点数据组成H264帧或者丢弃,这可取决于用户的配置。
帧缓存就是一个简单的链表,如下所示,
帧缓存里存放的是一个个完整的H264帧,播放线程会按照媒体协商的帧率(比如25帧/秒)的速率进行播放。
帧缓存的大小为FRAME_BUFFER_SIZE,如果接收到新帧时缓存已经满了,则从队头开始寻找一个P帧丢弃,然后把新帧插入对尾。
另外可以设计一个初始播放因子α,呼叫接通后,等帧缓存达到一定帧数后再开始播放,这样可以起到抗抖动的作用;α的取值为[0-1.0],当帧缓存的帧数达到α*FRAME_BUFFER_SIZE再开始播放。
这篇关于H264 over RTP 的解包的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!