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.h和rtp_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都沒有使用