WebRTC之RTP包

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都沒有使用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章