音视频同步!RTCP协议解析及代码实现
实时传输协议(RTP)和实时控制协议(RTCP)结合使用,可以监视大型多播网络的数据传递。RTP承载媒体流,而RTCP用于监视传输统计信息和服务质量。监视使接收器能够检测是否有任何丢包并补偿任何延迟抖动。
两种协议都独立于基础传输层协议和网络层协议工作。RTP标头中的信息告诉接收器如何重建数据,并描述编解码器比特流的打包方式。
下面我们重点讲解RTCP功能、RTCP信息包等。最后RTCP协议解析实现。
RTCP有哪些功能
1、RTCP主要功能是提供有关质量的反馈数据分发。这是RTP角色不可或缺的一部分,传输协议,与流量和拥塞有关其他传输协议的控制功能。
2、RTCP带有RTP的持久性传输级别标识符源称为规范名称或CNAME。自从如果发现冲突或程序重新启动,接收方要求CNAME跟踪每个参与者。
接收者也可能要求CNAME将来自给定参与者的多个数据流关联到集合中相关RTP会话的数量,例如同步音频和视频。媒体间同步还需要NTP和RTP数据发送方在RTCP数据包中包含的时间戳。
3、前两个功能要求所有参与者发送RTCP数据包,因此必须控制速率以使RTP能够扩大到大量参与者。通过让每个参与者将其控制包发送给所有其他人,每个人都可以独立观察参与者的数量。
4、这项功能对于参加者可以任意进入和离开的松散会话进程十分有用,参加者可以自由进入或离开,没有成员控制或参数协调。
功能1-3应该在所有环境中使用,尤其是在IP多播环境。RTP应用程序设计师应避免只能在单播模式下工作且无法扩展到的机制更大的数字。RTCP的传输可以单独控制对于发送者和接收者,适用于例如单向链接,而接收者没有反馈可能的。
RTCP协议的端口
RTSP通常使用RTP协议来传送实时流,RTP一般使用偶数端口,而RTCP使用相邻的奇数端口,即RTP端口号+1。
RTP端口
RTCP端口
RTCP信息包有哪些
在RTCP通信控制中,RTCP协议的功能是通过不同类型的RTCP包来实现的。RTCP也是基于UDP包来传送的,主要有五种类型的封包:
SR:发送端报告,由发送RTP数据报的应用程序或中端发出的。
RR:接收端报告,由接受但不发送RTP数据报的应用程序或中端发出。
SDES:源描述,传递与会话成员有关的标识信息的载体,如用户名、邮件、电话等。
BYE:通知离开,通知回话中的其他成员将退出会话。
APP:由应用程序自己定义,作为RTCP协议的扩展。
#defineRTCP_SR200#defineRTCP_RR201#defineRTCP_SDES202#defineRTCP_BYE203#defineRTCP_APP204我们可以根据这五种类型包判断RTCP头部
staticbooldissect_rtcp_heur(u_char*rtcp_info,intPayloadLen){unsignedintoffset=0;unsignedintfirst_byte=0;unsignedintpacket_type=0;/*查看第一个字节*/first_byte=rtcp_info[offset];/*版本位是否设置为2*///printf("version:%d",((first_byte&0xC0)>>6));if(((first_byte&0xC0)>>6)!=2){returnfalse;}/*看包类型*/offset+=1;packet_type=rtcp_info[offset];//printf("packet_type:%d
",packet_type);/*复合数据包中的第一个数据包应该是发送方或接收者报告*/if(!((packet_type==RTCP_SR)||(packet_type==RTCP_RR)||(packet_type==RTCP_BYE)||(packet_type==RTCP_APP)||(packet_type==RTCP_PSFB))){returnfalse;}/*总长度必须是4个字节的倍数*///printf("PayloadLen:%d
",PayloadLen);if(PayloadLen%4){returnfalse;}/*OK,dissectasRTCP*/dissect_rtcp(rtcp_info,packet_type,offset,PayloadLen);returntrue;}
RTCP协议报文格式
SR:发送端报告
版本(V):同RTP包头部
填充(P):同RTP包头部。
接收报告计数器(RC):5b该SR包中接收的报告块的数目。
包类型(PT):8bitSR包类型为200
长度(length):SR包以32bit为1单位的长度减1
同步源(SSRC):SR包发送的同步源标识符。与对应RTP包中的SSRC一样。
NTP时间戳(NetworkTimeProtocol):SR包发送时的绝对时间。用于同步不同的流。
RTP时间戳:与NTP时间戳对应,与RTP包中的时间戳具有相同的初始值。
Send’sPacketcount:从开始发包到产生这个SR包的这段时间内发送者发送的有效数据的总字节数,不包括头部和填充,发送者改变SSRC时,该域要清零。
同步源n的SSRC标识符:该报告中包含的是从该源接收到的包的统计信息。
丢失率:表明从上一个SR或RR包发出依来从同步源n发送的RTP包的丢失率。
累计丢失数据:从开始接受SSRC_n的包到发送SR这个时间段内SSRC_n发送的RTP丢失的总数目。
收到的扩展最大序列号:从SSRC_n收到的从RTP数据包中的最大序列号。
接收抖动(Interarrivaljitter):RTP数据包接收时间的统计方差估计。
上次SR时间戳(LastSR):取最近从SSRC_n收到的SR包中的NTP时间戳中的中间32bit。如果还未收到SR包,则为0。
上次依赖SR延迟(DelaysinceLastSR):从上次SSRC_n收到SR包到发送本包的延迟
Wireshark抓包:
活动会话的参与者在发送和接收RTP分组时使用SR。SR有三个不同的部分:报头信息、发送方信息和许多接收方报告块。SR也可以有一个与大纲相关的扩展域。
Wireshark抓包:
SDES:源描述
SDES提供了传递与会话成员有关的标识信息的载体,如用户名、邮件、电话等。每个RTCP混合分组中必须有SDES分组。
报头包含一个长度域、一个净荷类型域(PT=202)和一个源计数(RC)域。RC域5个bit,表示分组中信息块的数量。
每个信息块包含一个SSRC或CSRC值,其后跟着一个或多个的标识符和一些可用于SSRC或CSRC的信息。
CNAME项的SDES包必须包含在每个组合RTCP包中。SDES包可能包括其他源描述项,这要根据特别的应用需要,并同时考虑带宽限制。
Wireshark抓包:
SDES源描述包提供了直观的文本信息来描述会话的参加者,包括CNAME、NAME、EMAIL、PHONE、LOC等源描述项。
这些为接收方获取发送方的有关信息提供了方便。SDES包由包头与数据块组成,数据块可以没有,也可有多个。包头由版本(V)、填充(P)、长度指示、包类型(PT)和源计数(SC)组成。
PT占8位,用于识别RTCP的SDES包,SC占5位,指示包含在SDES包中的SSRC/CSRC块数量,零值有效,但没有意义。
BYE:通知离开
BYE分组用于表示一个或多个媒体源不再是处于激活状态。
Wireshark抓包:
作为可选项,BYE包可包括一个8位八进制计数,后跟文本信息,表示离开原因。
最后,组合包中每个RTCP包可独立处理,而不需要按照包组合的先后顺序处理。
在组合包中有以下几条强制约束。
只要带宽允许,在SR包或RR包中的接收统计应该经常发送,因此每个周期发送的组合RTCP包中应包含报告包。
每个组合包中都应该包含SDESCNAME,因为新接收者需要通过接收CNAME来识别源,并与媒体联系进行同步。
组合包前面是包类型数量,其增长应该受到限制。
RTCP协议如何实现媒体流的同步
通过抓包分析RTCP发送端报告,RTP的同步其实就靠这三个域:
senderSSRC:SR包发送的同步源标识符。与对应RTP包中的SSRC一样。
NTPtimestamp:SR包发送时的绝对时间。用于同步不同的流。
RTPtimestamp:与NTP时间戳对应,与RTP包中的时间戳具有相同的初始值。
那怎么计算NTP时间呢?在RTCP中NTP时间存放在8个字节中,分为:MSW和LSW,分别占用4个字节。
constchar*tvb_ntp_fmt_ts_sec(u_char*rtcp_info,intoffset){uint32_ttempstmp=0;time_ttemptime=0;structtm*bd;char*buff=NULL;tempstmp=ntohl(*(uint32_t*)(rtcp_info+offset));if(tempstmp==0){return"NULL";}/*Weneedatemporaryvariableheresotheunsignedmath*workscorrectly(foryears>2036accordingtoRFC2030*chapter3).*/temptime=(time_t)(tempstmp-NTP_BASETIME);bd=gmtime(&temptime);if(!bd){return"Notrepresentable";}buff=(char*)malloc(NTP_TS_SIZE);snprintf(buff,NTP_TS_SIZE,"%s%2d,%d%02d:%02d:%02dUTC",mon_names[bd->tm_mon],bd->tm_mday,bd->tm_year+1900,bd->tm_hour,bd->tm_min,bd->tm_sec);returnbuff;}NTPtimestamp
/*NTPtimestamp*/ts_msw=ntohl(*(uint32_t*)(rtcp_info+offset));printf("ts_msw:0x%x",ts_msw);ts_lsw=ntohl(*(uint32_t*)(rtcp_info+offset+4));printf("ts_lsw:0x%x
",ts_lsw);printf("MSW:%s
",tvb_ntp_fmt_ts_sec(rtcp_info,offset));offset+=8;
RTCP协议实现
下面我给出对RTCP协议解析实现的代码,根据回放报文,解析字段信息。
/*接收者/发送者计数是最后5位*/#defineRTCP_COUNT(octet)((octet)&0x1F)#defineRTCP_PT_MIN192/*SupplementalH.261specificRTCPpackettypesaccordingtoSectionC.3.5*/#defineRTCP_FIR192#defineRTCP_NACK193#defineRTCP_SMPTETC194#defineRTCP_IJ195/*RTCPpackettypesaccordingtoSectionA.11.1*//*Andhttps://www.iana.org/assignments/rtp-parameters/rtp-parameters.xhtml*/#defineRTCP_SR200#defineRTCP_RR201#defineRTCP_SDES202#defineRTCP_BYE203#defineRTCP_APP204#defineRTCP_RTPFB205#defineRTCP_PSFB206#defineRTCP_XR207#defineRTCP_AVB208#defineRTCP_RSI209#defineRTCP_TOKEN210#defineRTCP_PT_MAX210staticconstcharmon_names[12][4]={"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};/**datastructuretoholdtimevalueswithnanosecondresolution*/typedefstruct{time_tsecs;intnsecs;}nstime_t;/**1900-01-0100:00:00(proleptic?)UTC.*Usedbyanumberoftimeformats.*/#defineEPOCH_DELTA_1900_01_01_00_00_00_UTC2208988800U/**NTP_BASETIMEisinfactepoch-ntp_start_time;ntp_start_time*isJanuary1,2036,00:00:00UTC.*/#defineNTP_BASETIMEEPOCH_DELTA_1900_01_01_00_00_00_UTC#defineNTP_FLOAT_DENOM4294967296.0#defineNTP_TS_SIZE100/*解剖长度字段。附加到此字段的文字表示转换为的实际字节数(即(原始值+1)*4)*/staticintdissect_rtcp_length_field(u_char*rtcp_info,intoffset){uint16_traw_length=ntohs(*(uint16_t*)(rtcp_info+offset));printf("(%ubytes)",(raw_length+1)*4);offset+=2;returnoffset;}staticintdissect_rtcp_rr(u_char*rtcp_info,intoffset,intcount,intpacket_length){intcounter=0;uint8_trr_flt=0;intrr_offset=offset;counter=1;while(counter<=count){uint32_tlsr=0,dlsr=0;/*Createanewsubtreeforalengthof24bytes*//*SSRC_nsourceidentifier,32bits*/offset+=4;/*Fractionlost,8bits*/rr_flt=rtcp_info[offset];offset++;/*Cumulativenumberofpacketslost,24bits*/offset+=3;/*Sequencenumbercycles*/offset+=2;/*highestsequencenumberreceived*/offset+=2;/*Interarrivaljitter*/offset+=4;/*LastSRtimestamp*/lsr=ntohl(*(uint32_t*)(rtcp_info+offset));printf("LastSRtimestamp:0x%x
",lsr);offset+=4;/*DelaysincelastSRtimestamp*/dlsr=ntohl(*(uint32_t*)(rtcp_info+offset));printf("(%dmilliseconds)
",(int)(((double)dlsr/(double)65536)*1000.0));offset+=4;counter++;}returnoffset;}constchar*tvb_ntp_fmt_ts_sec(u_char*rtcp_info,intoffset){uint32_ttempstmp=0;time_ttemptime=0;structtm*bd;char*buff=NULL;tempstmp=ntohl(*(uint32_t*)(rtcp_info+offset));if(tempstmp==0){return"NULL";}/*Weneedatemporaryvariableheresotheunsignedmath*workscorrectly(foryears>2036accordingtoRFC2030*chapter3).*/temptime=(time_t)(tempstmp-NTP_BASETIME);bd=gmtime(&temptime);if(!bd){return"Notrepresentable";}buff=(char*)malloc(NTP_TS_SIZE);snprintf(buff,NTP_TS_SIZE,"%s%2d,%d%02d:%02d:%02dUTC",mon_names[bd->tm_mon],bd->tm_mday,bd->tm_year+1900,bd->tm_hour,bd->tm_min,bd->tm_sec);returnbuff;}staticintdissect_rtcp_sr(u_char*rtcp_info,intoffset,intcount,intpacket_length){uint32_tts_msw=0,ts_lsw=0;intsr_offset=offset;/*NTPtimestamp*/ts_msw=ntohl(*(uint32_t*)(rtcp_info+offset));printf("ts_msw:0x%x
",ts_msw);ts_lsw=ntohl(*(uint32_t*)(rtcp_info+offset+4));printf("ts_lsw:0x%x
",ts_lsw);//printf("offset:0x%x0x%x0x%x0x%x
",rtcp_info[offset],rtcp_info[offset+1],rtcp_info[offset+2],rtcp_info[offset+3]);printf("MSW:%s
",tvb_ntp_fmt_ts_sec(rtcp_info,offset));offset+=8;/*RTPtimestamp,32bits*/offset+=4;/*Sender'spacketcount,32bits*/offset+=4;/*Sender'soctetcount,32bits*/offset+=4;/*TherestofthepacketisequaltotheRRpacket*/if(count!=0)offset=dissect_rtcp_rr(rtcp_info,offset,count,packet_length-(offset-sr_offset));else{/*Iflengthremaining,assumeprofile-specificextensionbytes*/if((offset-sr_offset)<packet_length){offset=sr_offset+packet_length;}}returnoffset;}staticintdissect_rtcp_sdes(u_char*rtcp_info,intoffset,intcount){intchunk=0;intstart_offset=0;intitems_start_offset=0;uint32_tssrc=0;unsignedintitem_len=0;unsignedintsdes_type=0;unsignedintprefix_len=0;chunk=1;while(chunk<=count){/*Createasubtreeforthischunk;wedon'tyetknowthelength.*/start_offset=offset;ssrc=ntohl(*(uint32_t*)(rtcp_info+offset));printf("Chunk%u,SSRC/CSRC0x%X
",chunk,ssrc);/*SSRC_nsourceidentifier,32bits*/offset+=4;/*CreateasubtreefortheSDESitems;wedon'tyetknowthelength*//**Noteverymessageisendedwith"null"bytes,socheckfor*endofframeaswell.*//*ID,8bits*/sdes_type=rtcp_info[offset];printf("Type:%d
",sdes_type);if(sdes_type==0)break;offset++;/*Itemlength,8bits*/item
音视频同步!RTCP协议解析及代码实现
staticbooldissect_rtcp_heur(u_char*rtcp_info,intPayloadLen){unsignedintoffset=0;unsignedintfirst_byte=0;unsignedintpacket_type=0;\/*查看第一个字节*\/first_byte=rtcp_info[offset];\/*版本位是否设置为2*\/\/\/printf("version:%d\\n",((first_byte&0xC0)>>6));if(((first_byte&0xC0)>>6)!=2){...
RTP协议解析及H264\/H265 音视频RTP打包分析
在RTSP会话成功建立并开始传输后,音频和视频数据通过RTP协议打包发送至客户端;RTP协议与RTP控制协议RTCP结合使用,并基于UDP协议构建。RTP协议的报头解析如下:V:版本号,占据2位,当前版本号为2。P:填充标志,占据1位,当P=1时,在报文尾部填充额外的八位组,这些组不是有效负载的一部分。X:扩展...
RTCP-实时传输协议作用
RTCP,即实时传输控制协议,与RTP(实时传输协议)紧密合作,为一对一或一对多的实时数据传输提供了关键的支持。RTP主要关注数据的实时发送,它利用UDP协议进行数据包传输,但也可在TCP或ATM等其他协议的底层运作。启动RTP会话时,应用程序会占用两个端口,分别用于RTP数据包和RTCP控制信息的传输。RTP本身不...
最详细的音视频流媒体传输协议-rtsp协议详解
RTSP协议的主要方法包括查询服务器端可用方法、得到媒体描述信息、建立RTSP会话、请求开始传送数据、数据传送播放中、关闭会话等。RTSP协议的报文格式简洁,基于文本,易于理解和分析。RTSP请求和响应报文的结构和HTTP协议类似,便于扩展。RTSP协议通过与RTP和RTCP等协议配合使用,实现多媒体数据的高效传输和实时控...
什么是RTCP\/RTP
解析:RTP(Real-time Transport Protocol)是用于Inter上针对多媒体数据流的一种传输协议。RTP被定义为在一对一或一对多的传输情况下工作。其目的是提供时间信息和实现流同步。但RTP通常使用UDP来传送数据。但RTP也可以在TCP或ATM等其他协议之上工作。当应用程序开始一个RTP会话时将使用两个端口:一个给RTP一...
RTP,RTCP,RTSP等网络协议有何用途和区别
RTP\/RTCP是实际传输数据的协议 RTP传输音频\/视频数据,如果是PLAY,Server发送到Client端,如果是RECORD,可以由Client发送到Server 整个RTP协议由两个密切相关的部分组成:RTP数据协议和RTP控制协议(即RTCP)RTSP:实时流协议(Real Time Streaming Protocol,RTSP)RTSP的请求主要有DESCRIBE,SETUP,PLAY,PAUSE,...
音视频开发 RED 与 FEC 的 RTP 格式封装
WebRTC中RED和FEC的实现与处理,在查看代码时,决定重新整理协议并记录下来。RTP(实时传输协议)是一种在互联网上常见的处理媒体数据流的网络协议,适用于单播或多播等多种网络环境下的媒体数据传输。RTP是一种应用层协议,一般使用UDP作为底层协议实现数据传输,但并不强制选择底层协议,如利用RTSP进行流...
[FFmpeg] 自定义IO读入RTP流——详细说明
c中的代码,以阻止RTCP报文发送,避免音视频流数据与RTCP报文数据混杂,确保正确性。综上所述,建议在实现自定义IO读取RTP流时,仅专注于RTP协议,避免涉及RTSP协议及其相关RTCP报文的复杂性。如果需要实现RTSP协议的自定义IO,需谨慎评估修改范围和潜在影响,以免造成不必要的复杂性和潜在问题。
什么是流媒体播放协议
\\x0d\\x0a\\x0d\\x0a在流媒体传输中,标准的协议就是RTP(RealtimeTransportProtocol,实时传输协议)、RTCP(Real-timeTransportControlProtocol,实时传输控制协议)、RTSP(RealTimeStreamingProtocol,实时流媒体协议)和RSVP(ResourceReserveProtocol,资源预订协议),厂商们的产品都是在这些协议的基础上进行...
小程序与WebRTC联姻能擦出怎样的火花?
两者的区别在于:WebRTC底层使用RTP和RTCP协议,支持多种架构方案,底层架构复杂,学习成本较高。小程序音视频接口简单,快速上手,但后台架构受限于腾讯云。腾讯视频云团队在2018年后开始小程序音视频与WebRTC的互通工作,现微信最新版本中已实现二者互通,在PC Chrome浏览器上支持小程序实时音视频功能。方案...