RTP协议与实战

2022-09-13 14:44:39 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

一. RTP协议

在实时音视频通话中,我们通常使用 UDP 作为传输层协议,使用 RTP 协议包荷载音视频数据,RTP(Real-time Transport Protocol)是一种在 Internet 上传输多媒体数据的应用层协议,它通常建立在 UDP 之上(也可以建立在 TCP 上)。UDP 协议没有序号等信息,而 RTP 协议可以补充许多音视频传输必要的信息,让音视频数据到达对端后可以重新组合完整,RTP 本身只保证实时数据的传输,并不能提供可靠传输保证,也没有流量控制,拥塞控制机制,它通常与 RTCP 配合使用以提供这些服务。

RTP 协议格式如下,红色部分为 RTP 协议可选字段,RTP 协议最小为 12 byte。

Version:RTP 协议版本号

P:填充标识,如果该位为 1,说明该 RTP 包末尾包含了一个或多个填充字节,最后一个字节的值表示填充的字节数(包含最后一个字节本身),一般在一些需要固定块大小的加密算法中才需要填充

X:扩展标识,如果该位为 1,说明有扩展头部信息(Extension header)

CC:CSRC Count,共享媒体源个数,一般用于混音和混屏中,例如某个音频流是混合了其它音频后的数据,那么其它音频源就是该音频源的 CSRC

M:Mark 标记位,对于不同的负载类型有不同含义,例如使用 RTP 荷载 H264 码流时,可以用该位标记是否为 NALU 的最后一个包

PT:Payload Type,负载包类型,接收端可以根据该信息查找相应的解码器进行解码,Payload Type 值对应的编解码类型参考该文档

Sequence number:序列号,每个 RTP 包序号递增加一,接收端根据序列号可以判断传输是否丢包,序列号初始值是随机的

Timestamp:相对时间戳信息,反映 RTP 数据包数据采样时间,一个帧的数据可能被分成多个 RTP 包发送,同一个帧的时间戳是相同的,不同帧的时间戳是不相同的,该值初始值是随机的,单位的含义与数据采样频率有关

SSRC:媒体源的标识,不同的 SSRC 标识不同的媒体源,例如不同用户的音频就属于不同的媒体源,具有不同的 SSRC

CSRC identifiers:共享媒体源列表,表示对 RTP 包内载荷起作用的媒体源,参见 CC 解释,CSRC 最多 15 个

Profile:RTP 扩展头部有两种类型,one-byte header 和 two-byte header,当 Profile = 0xBEDE 时表示使用 one-byte header,Profile = 0x1000 时表示使用 two-byte header,扩展头部个数由 Extension header length 决定

Extension header length:表示后面的 Extension header 共有几个字节,长度以 4 字节为单位,例如 length = 3 表示 Extension header 一共占 3*4=12 个字节

Extension header:具体的扩展头部,由 ID,L,data 组成,可以是 one-byte header 或者 two-byte header 组织方式

one-byte header 格式如下,它由 ID,L,data 三部分组成。ID 和 L 分别占 4 bit,加起来等于 one-byte,ID 表示扩展头部 ID 标记,L 表示 extension data 所占字节数 -1,例如 L = 0 时实际 data 占一个字节,由于头部需要按 4 字节对齐,因此中间补充了 padding 数据,最后一个 extension header data 占 4 字节。

two-byte header 格式如下,它也是由 ID, L, data 三部分组成,不同之处在于 two-byte header 中 ID,L 各占一字节,而 L 表示 extension data 所占的字节数(不同于 one-byte header 需要减一)。

常见的 header extension ID 类型如下,关于具体某个扩展头部的含义可以参考 RFC 或者 webrtc 文档。

代码语言:javascript复制
enum RTPExtensionType : int {
  kRtpExtensionNone,
  kRtpExtensionTransmissionTimeOffset,
  kRtpExtensionAudioLevel,
  kRtpExtensionInbandComfortNoise,
  kRtpExtensionAbsoluteSendTime,
  kRtpExtensionAbsoluteCaptureTime,
  kRtpExtensionVideoRotation,
  kRtpExtensionTransportSequenceNumber,
  kRtpExtensionTransportSequenceNumber02,
  kRtpExtensionPlayoutDelay,
  kRtpExtensionVideoContentType,
  kRtpExtensionVideoTiming,
  kRtpExtensionFrameMarking,
  kRtpExtensionRtpStreamId,
  kRtpExtensionRepairedRtpStreamId,
  kRtpExtensionMid,
  kRtpExtensionGenericFrameDescriptor00,
  kRtpExtensionGenericFrameDescriptor = kRtpExtensionGenericFrameDescriptor00,
  kRtpExtensionGenericFrameDescriptor02,
  kRtpExtensionColorSpace,
  kRtpExtensionNumberOfExtensions  // Must be the last entity in the enum.
};

如下是 Wireshark 抓取某路流的一个 RTP 数据包。

二. 实战

使用JRTPLIB发送/接收RTP数据包

使用RTP包荷载H264码流

RTP扩展头部Audio Level的应用(mediasoup显示当前通话Speaker)

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/153980.html原文链接:https://javaforall.cn

0 人点赞