WebRTC之RTP包

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/momo0853/article/details/87631434

RTP固定头部

RTP的固定头部,详情可以阅读rfc文档5.1 RTP Fixed Header Fields

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|V=2|P|X|  CC   |M|     PT      |       sequence number         |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                           timestamp                           |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|           synchronization source (SSRC) identifier            |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|            contributing source (CSRC) identifiers             |
|                             ....                              |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  • V版本号位,必须等于2
  • P填充位
  • X扩展位,标志是否存在扩展
  • CC CSRC个数
  • M Mark标志位,标志是否是一帧的结束,音频帧几乎每个包都是一个完整的帧,所以M一般情况都等于1,视频包因为一帧比较大,会被分为几个包发送,最后一个包标志需要Mark一下
  • PT负载类型,不同的负载类型对应不同的编解码类型(音频根据采样率和通道不同都要对应不同的负载类型),FEC类型等。
  • sequence number,包序号,发送端指定一个起始序号(如果不指定则随机一个),然后每个包的序号依次递增;如果存在RTX,重发是此序号是rtx的序号,详情请看RTPSender::SendPadData的实现
  • timestamp,包的时间戳,如果一个视频帧被分为几个包,则这个帧对应的几个包的时间戳是一样的;发送端可以指定一个起始时间戳timestamp_offset_(如果不指定则随机一个),然后每个帧的时间戳等于起始时间戳加上采集时间戳timestamp_offset_ + capture_timestamp,详情可以看RTPSender::SendOutgoingData的实现
  • SSRC,同步源的唯一标识,每一个源(音频或者视频,文件)都必须要有一个唯一的标识码,用于区分不同的流
  • CSRC,贡献源,列举此SSRC的资源是由多少个其他的资源(其他资源的SSRC)混合而来的。例如MCU混音之后就需要修改这个;最多只能表示15源

RTP扩展

如果存在RTP扩展则标志位X必须置为1,除了标准扩展外,WebRTC还有自己的扩展,所以服务端如果使用标准rtp解析库需要添加一下WebRTC的RTP扩展。
扩展相关的几个文件rtp_header_extensions.hrtp_utility.cc可以阅读一下

  • kRtpExtensionTransmissionTimeOffset,一个包相对于采集时间的偏移的滴答数
# rtp_sender.cc +569
if (capture_time_ms > 0) {
  padding_packet.SetExtension<TransmissionOffset>(
      (now_ms - capture_time_ms) * kTimestampTicksPerMs);
}
  • kRtpExtensionAudioLevel,一帧音频数据的分贝值
# rtp_sender_audio.cc +226
packet->SetExtension<AudioLevel>(frame_type == kAudioFrameSpeech, audio_level_dbov);
  • kRtpExtensionAbsoluteSendTime,一个包的绝对发送时间
# rtp_sender.cc +572
padding_packet.SetExtension<AbsoluteSendTime>(AbsoluteSendTime::MsTo24Bits(now_ms));
  • kRtpExtensionVideoRotation,帧视频帧的方向
# rtp_sender_video.cc +331
last_packet->SetExtension<VideoOrientation>(current_rotation);
  • kRtpExtensionTransportSequenceNumber,扩展序号,不管是第一次发送还是重发的包,此需要都会递增
# rtp_sender.cc +1066
*packet_id = transport_sequence_number_allocator_->AllocateSequenceNumber();
 if (!packet->SetExtension<TransportSequenceNumber>(*packet_id))
  • kRtpExtensionPlayoutDelay

  • kRtpExtensionVideoContentType,视频源是否是屏幕资源

# rtp_sender_video.cc +336
last_packet->SetExtension<VideoContentTypeExtension>(video_header->content_type);
  • kRtpExtensionVideoTiming,记录视频编码开始,编码结束,打包完成,平滑发送等时间戳,不过这几个时间戳都是相对时间
# 填充此结构体 frame_object.cc +121
timing_.encode_start_ms = ntp_time_ms_ + last_packet->video_header.video_timing.encode_start_delta_ms;
timing_.encode_finish_ms = ntp_time_ms_ + last_packet->video_header.video_timing.encode_finish_delta_ms;
timing_.packetization_finish_ms = ntp_time_ms_ + last_packet->video_header.video_timing.packetization_finish_delta_ms;
timing_.pacer_exit_ms = ntp_time_ms_ + last_packet->video_header.video_timing.pacer_exit_delta_ms;
timing_.network_timestamp_ms = ntp_time_ms_ + last_packet->video_header.video_timing.network_timstamp_delta_ms;
timing_.network2_timestamp_ms = ntp_time_ms_ + last_packet->video_header.video_timing.network2_timstamp_delta_ms;

# 打包到rtp包中 rtp_sender_video.cc +340
last_packet->SetExtension<VideoTimingExtension>(video_header->video_timing);
  • 这几个扩展kRtpExtensionRtpStreamId,kRtpExtensionRepairedRtpStreamId,kRtpExtensionMid,WebRTC都没有使用

猜你喜欢

转载自blog.csdn.net/momo0853/article/details/87631434