Index: webrtc/modules/rtp_rtcp/source/rtp_sender.cc |
diff --git a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc |
index b918a908a7d03d0420b1a4e0e08201f1834e4c91..7377944813ec8f878e91529b5edbe7a840c4ccf9 100644 |
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc |
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc |
@@ -89,13 +89,6 @@ RTPSender::RTPSender( |
sending_media_(true), // Default to sending media. |
max_payload_length_(IP_PACKET_SIZE - 28), // Default is IP-v4/UDP. |
payload_type_(-1), |
- payload_type_map_(), |
- rtp_header_extension_map_(), |
- transmission_time_offset_(0), |
- absolute_send_time_(0), |
- rotation_(kVideoRotation_0), |
- video_rotation_active_(false), |
- transport_sequence_number_(0), |
playout_delay_active_(false), |
packet_history_(clock), |
// Statistics |
@@ -183,46 +176,14 @@ uint32_t RTPSender::NackOverheadRate() const { |
return nack_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0); |
} |
-int32_t RTPSender::SetTransmissionTimeOffset(int32_t transmission_time_offset) { |
- if (transmission_time_offset > (0x800000 - 1) || |
- transmission_time_offset < -(0x800000 - 1)) { // Word24. |
- return -1; |
- } |
- rtc::CritScope lock(&send_critsect_); |
- transmission_time_offset_ = transmission_time_offset; |
- return 0; |
-} |
- |
-int32_t RTPSender::SetAbsoluteSendTime(uint32_t absolute_send_time) { |
- if (absolute_send_time > 0xffffff) { // UWord24. |
- return -1; |
- } |
- rtc::CritScope lock(&send_critsect_); |
- absolute_send_time_ = absolute_send_time; |
- return 0; |
-} |
- |
-void RTPSender::SetVideoRotation(VideoRotation rotation) { |
- rtc::CritScope lock(&send_critsect_); |
- rotation_ = rotation; |
-} |
- |
-int32_t RTPSender::SetTransportSequenceNumber(uint16_t sequence_number) { |
- rtc::CritScope lock(&send_critsect_); |
- transport_sequence_number_ = sequence_number; |
- return 0; |
-} |
- |
int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type, |
uint8_t id) { |
rtc::CritScope lock(&send_critsect_); |
switch (type) { |
- case kRtpExtensionVideoRotation: |
- video_rotation_active_ = false; |
- return rtp_header_extension_map_.RegisterInactive(type, id); |
case kRtpExtensionPlayoutDelay: |
playout_delay_active_ = false; |
return rtp_header_extension_map_.RegisterInactive(type, id); |
+ case kRtpExtensionVideoRotation: |
case kRtpExtensionTransmissionTimeOffset: |
case kRtpExtensionAbsoluteSendTime: |
case kRtpExtensionAudioLevel: |
@@ -425,16 +386,6 @@ int32_t RTPSender::CheckPayloadType(int8_t payload_type, |
return 0; |
} |
-bool RTPSender::ActivateCVORtpHeaderExtension() { |
- if (!video_rotation_active_) { |
- rtc::CritScope lock(&send_critsect_); |
- if (rtp_header_extension_map_.SetActive(kRtpExtensionVideoRotation, true)) { |
- video_rotation_active_ = true; |
- } |
- } |
- return video_rotation_active_; |
-} |
- |
bool RTPSender::SendOutgoingData(FrameType frame_type, |
int8_t payload_type, |
uint32_t capture_timestamp, |
@@ -882,20 +833,6 @@ size_t RTPSender::TimeToSendPadding(size_t bytes, int probe_cluster_id) { |
return bytes_sent; |
} |
-bool RTPSender::SendToNetwork(uint8_t* buffer, |
- size_t payload_length, |
- size_t rtp_header_length, |
- int64_t capture_time_ms, |
- StorageType storage, |
- RtpPacketSender::Priority priority) { |
- size_t length = payload_length + rtp_header_length; |
- std::unique_ptr<RtpPacketToSend> packet( |
- new RtpPacketToSend(&rtp_header_extension_map_, length)); |
- RTC_CHECK(packet->Parse(buffer, length)); |
- packet->set_capture_time_ms(capture_time_ms); |
- return SendToNetwork(std::move(packet), storage, priority); |
-} |
- |
bool RTPSender::SendToNetwork(std::unique_ptr<RtpPacketToSend> packet, |
StorageType storage, |
RtpPacketSender::Priority priority) { |
@@ -1040,299 +977,49 @@ void RTPSender::GetDataCounters(StreamDataCounters* rtp_stats, |
*rtx_stats = rtx_rtp_stats_; |
} |
-size_t RTPSender::CreateRtpHeader(uint8_t* header, |
- int8_t payload_type, |
- uint32_t ssrc, |
- bool marker_bit, |
- uint32_t timestamp, |
- uint16_t sequence_number, |
- const std::vector<uint32_t>& csrcs) const { |
- header[0] = 0x80; // version 2. |
- header[1] = static_cast<uint8_t>(payload_type); |
- if (marker_bit) { |
- header[1] |= kRtpMarkerBitMask; // Marker bit is set. |
- } |
- ByteWriter<uint16_t>::WriteBigEndian(header + 2, sequence_number); |
- ByteWriter<uint32_t>::WriteBigEndian(header + 4, timestamp); |
- ByteWriter<uint32_t>::WriteBigEndian(header + 8, ssrc); |
- int32_t rtp_header_length = kRtpHeaderLength; |
- |
- if (csrcs.size() > 0) { |
- uint8_t* ptr = &header[rtp_header_length]; |
- for (size_t i = 0; i < csrcs.size(); ++i) { |
- ByteWriter<uint32_t>::WriteBigEndian(ptr, csrcs[i]); |
- ptr += 4; |
- } |
- header[0] = (header[0] & 0xf0) | csrcs.size(); |
- |
- // Update length of header. |
- rtp_header_length += sizeof(uint32_t) * csrcs.size(); |
- } |
- |
- uint16_t len = |
- BuildRtpHeaderExtension(header + rtp_header_length, marker_bit); |
- if (len > 0) { |
- header[0] |= 0x10; // Set extension bit. |
- rtp_header_length += len; |
- } |
- return rtp_header_length; |
-} |
- |
-int32_t RTPSender::BuildRTPheader(uint8_t* data_buffer, |
- int8_t payload_type, |
- bool marker_bit, |
- uint32_t capture_timestamp, |
- int64_t capture_time_ms, |
- bool timestamp_provided, |
- bool inc_sequence_number) { |
- return BuildRtpHeader(data_buffer, payload_type, marker_bit, |
- capture_timestamp, capture_time_ms); |
-} |
- |
-int32_t RTPSender::BuildRtpHeader(uint8_t* data_buffer, |
- int8_t payload_type, |
- bool marker_bit, |
- uint32_t capture_timestamp, |
- int64_t capture_time_ms) { |
- assert(payload_type >= 0); |
+std::unique_ptr<RtpPacketToSend> RTPSender::AllocatePacket( |
+ bool minimalistic) const { |
+ std::unique_ptr<RtpPacketToSend> packet( |
+ new RtpPacketToSend(&rtp_header_extension_map_, max_payload_length_)); |
+ rtc::CritScope lock(&send_critsect_); |
+ packet->SetSsrc(ssrc_); |
+ if (!minimalistic) { |
+ packet->SetCsrcs(csrcs_); |
+ // Reserve place for extensions, if registered. |
+ // It is important to reserve those extension before any other: they are set |
+ // in RtpSender _after_ media packets proccessed for fec, meaning they can |
+ // damage any bytes in the packet that are at the same address. |
+ // Reserving these extensions first ensure it is just values of theese |
+ // extensions that are bogus in recovered packets. |
+ packet->ReserveExtension<AbsoluteSendTime>(); |
+ packet->ReserveExtension<TransmissionOffset>(); |
+ packet->ReserveExtension<TransportSequenceNumber>(); |
+ } |
+ return packet; |
+} |
+ |
+bool RTPSender::PrepareToSend(RtpPacketToSend* packet) { |
rtc::CritScope lock(&send_critsect_); |
if (!sending_media_) |
- return -1; |
+ return false; |
- timestamp_ = start_timestamp_ + capture_timestamp; |
+ timestamp_ = start_timestamp_ + packet->Timestamp(); |
last_timestamp_time_ms_ = clock_->TimeInMilliseconds(); |
uint32_t sequence_number = sequence_number_++; |
- capture_time_ms_ = capture_time_ms; |
- last_packet_marker_bit_ = marker_bit; |
- return CreateRtpHeader(data_buffer, payload_type, ssrc_, marker_bit, |
- timestamp_, sequence_number, csrcs_); |
-} |
+ capture_time_ms_ = packet->capture_time_ms(); |
+ last_packet_marker_bit_ = packet->Marker(); |
-uint16_t RTPSender::BuildRtpHeaderExtension(uint8_t* data_buffer, |
- bool marker_bit) const { |
- if (rtp_header_extension_map_.Size() <= 0) { |
- return 0; |
- } |
- // RTP header extension, RFC 3550. |
- // 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 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- // | defined by profile | length | |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- // | header extension | |
- // | .... | |
- // |
- const uint32_t kPosLength = 2; |
- const uint32_t kHeaderLength = kRtpOneByteHeaderLength; |
- |
- // Add extension ID (0xBEDE). |
- ByteWriter<uint16_t>::WriteBigEndian(data_buffer, |
- kRtpOneByteHeaderExtensionId); |
- |
- // Add extensions. |
- uint16_t total_block_length = 0; |
- |
- RTPExtensionType type = rtp_header_extension_map_.First(); |
- while (type != kRtpExtensionNone) { |
- uint8_t block_length = 0; |
- uint8_t* extension_data = &data_buffer[kHeaderLength + total_block_length]; |
- switch (type) { |
- case kRtpExtensionTransmissionTimeOffset: |
- block_length = BuildTransmissionTimeOffsetExtension(extension_data); |
- break; |
- case kRtpExtensionAudioLevel: |
- block_length = BuildAudioLevelExtension(extension_data); |
- break; |
- case kRtpExtensionAbsoluteSendTime: |
- block_length = BuildAbsoluteSendTimeExtension(extension_data); |
- break; |
- case kRtpExtensionVideoRotation: |
- block_length = BuildVideoRotationExtension(extension_data); |
- break; |
- case kRtpExtensionTransportSequenceNumber: |
- block_length = BuildTransportSequenceNumberExtension( |
- extension_data, transport_sequence_number_); |
- break; |
- case kRtpExtensionPlayoutDelay: |
- block_length = BuildPlayoutDelayExtension( |
- extension_data, playout_delay_oracle_.min_playout_delay_ms(), |
- playout_delay_oracle_.max_playout_delay_ms()); |
- break; |
- default: |
- assert(false); |
- } |
- total_block_length += block_length; |
- type = rtp_header_extension_map_.Next(type); |
- } |
- if (total_block_length == 0) { |
- // No extension added. |
- return 0; |
- } |
- // Add padding elements until we've filled a 32 bit block. |
- size_t padding_bytes = |
- RtpUtility::Word32Align(total_block_length) - total_block_length; |
- if (padding_bytes > 0) { |
- memset(&data_buffer[kHeaderLength + total_block_length], 0, padding_bytes); |
- total_block_length += padding_bytes; |
- } |
- // Set header length (in number of Word32, header excluded). |
- ByteWriter<uint16_t>::WriteBigEndian(data_buffer + kPosLength, |
- total_block_length / 4); |
- // Total added length. |
- return kHeaderLength + total_block_length; |
-} |
- |
-uint8_t RTPSender::BuildTransmissionTimeOffsetExtension( |
- uint8_t* data_buffer) const { |
- // From RFC 5450: Transmission Time Offsets in RTP Streams. |
- // |
- // The transmission time is signaled to the receiver in-band using the |
- // general mechanism for RTP header extensions [RFC5285]. The payload |
- // of this extension (the transmitted value) is a 24-bit signed integer. |
- // When added to the RTP timestamp of the packet, it represents the |
- // "effective" RTP transmission time of the packet, on the RTP |
- // timescale. |
- // |
- // The form of the transmission offset extension block: |
- // |
- // 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 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- // | ID | len=2 | transmission offset | |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- |
- // Get id defined by user. |
- uint8_t id; |
- if (rtp_header_extension_map_.GetId(kRtpExtensionTransmissionTimeOffset, |
- &id) != 0) { |
- // Not registered. |
- return 0; |
- } |
- size_t pos = 0; |
- const uint8_t len = 2; |
- data_buffer[pos++] = (id << 4) + len; |
- ByteWriter<int32_t, 3>::WriteBigEndian(data_buffer + pos, |
- transmission_time_offset_); |
- pos += 3; |
- assert(pos == kTransmissionTimeOffsetLength); |
- return kTransmissionTimeOffsetLength; |
-} |
- |
-uint8_t RTPSender::BuildAudioLevelExtension(uint8_t* data_buffer) const { |
- // An RTP Header Extension for Client-to-Mixer Audio Level Indication |
- // |
- // https://datatracker.ietf.org/doc/draft-lennox-avt-rtp-audio-level-exthdr/ |
- // |
- // The form of the audio level extension block: |
- // |
- // 0 1 |
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- // | ID | len=0 |V| level | |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- // |
- |
- // Get id defined by user. |
- uint8_t id; |
- if (rtp_header_extension_map_.GetId(kRtpExtensionAudioLevel, &id) != 0) { |
- // Not registered. |
- return 0; |
- } |
- size_t pos = 0; |
- const uint8_t len = 0; |
- data_buffer[pos++] = (id << 4) + len; |
- data_buffer[pos++] = (1 << 7) + 0; // Voice, 0 dBov. |
- assert(pos == kAudioLevelLength); |
- return kAudioLevelLength; |
-} |
- |
-uint8_t RTPSender::BuildAbsoluteSendTimeExtension(uint8_t* data_buffer) const { |
- // Absolute send time in RTP streams. |
- // |
- // The absolute send time is signaled to the receiver in-band using the |
- // general mechanism for RTP header extensions [RFC5285]. The payload |
- // of this extension (the transmitted value) is a 24-bit unsigned integer |
- // containing the sender's current time in seconds as a fixed point number |
- // with 18 bits fractional part. |
- // |
- // The form of the absolute send time extension block: |
- // |
- // 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 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- // | ID | len=2 | absolute send time | |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- |
- // Get id defined by user. |
- uint8_t id; |
- if (rtp_header_extension_map_.GetId(kRtpExtensionAbsoluteSendTime, |
- &id) != 0) { |
- // Not registered. |
- return 0; |
- } |
- size_t pos = 0; |
- const uint8_t len = 2; |
- data_buffer[pos++] = (id << 4) + len; |
- ByteWriter<uint32_t, 3>::WriteBigEndian(data_buffer + pos, |
- absolute_send_time_); |
- pos += 3; |
- assert(pos == kAbsoluteSendTimeLength); |
- return kAbsoluteSendTimeLength; |
-} |
- |
-uint8_t RTPSender::BuildVideoRotationExtension(uint8_t* data_buffer) const { |
- // Coordination of Video Orientation in RTP streams. |
- // |
- // Coordination of Video Orientation consists in signaling of the current |
- // orientation of the image captured on the sender side to the receiver for |
- // appropriate rendering and displaying. |
- // |
- // 0 1 |
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- // | ID | len=0 |0 0 0 0 C F R R| |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- // |
- |
- // Get id defined by user. |
- uint8_t id; |
- if (rtp_header_extension_map_.GetId(kRtpExtensionVideoRotation, &id) != 0) { |
- // Not registered. |
- return 0; |
- } |
- size_t pos = 0; |
- const uint8_t len = 0; |
- data_buffer[pos++] = (id << 4) + len; |
- data_buffer[pos++] = ConvertVideoRotationToCVOByte(rotation_); |
- assert(pos == kVideoRotationLength); |
- return kVideoRotationLength; |
+ packet->SetSequenceNumber(sequence_number); |
+ packet->SetTimestamp(timestamp_); |
+ return true; |
} |
-uint8_t RTPSender::BuildTransportSequenceNumberExtension( |
- uint8_t* data_buffer, |
- uint16_t sequence_number) const { |
- // 0 1 2 |
- // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- // | ID | L=1 |transport wide sequence number | |
- // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
- |
- // Get id defined by user. |
- uint8_t id; |
- if (rtp_header_extension_map_.GetId(kRtpExtensionTransportSequenceNumber, |
- &id) != 0) { |
- // Not registered. |
- return 0; |
- } |
- size_t pos = 0; |
- const uint8_t len = 1; |
- data_buffer[pos++] = (id << 4) + len; |
- ByteWriter<uint16_t>::WriteBigEndian(data_buffer + pos, sequence_number); |
- pos += 2; |
- assert(pos == kTransportSequenceNumberLength); |
- return kTransportSequenceNumberLength; |
-} |
+uint32_t RTPSender::TimestampOffset(uint32_t capture_timestamp) const { |
+ rtc::CritScope lock(&send_critsect_); |
+ return start_timestamp_ + capture_timestamp - timestamp_; |
+} |
+/* |
uint8_t RTPSender::BuildPlayoutDelayExtension( |
uint8_t* data_buffer, |
uint16_t min_playout_delay_ms, |
@@ -1363,121 +1050,7 @@ uint8_t RTPSender::BuildPlayoutDelayExtension( |
assert(pos == kPlayoutDelayLength); |
return kPlayoutDelayLength; |
} |
- |
-bool RTPSender::FindHeaderExtensionPosition(RTPExtensionType type, |
- const uint8_t* rtp_packet, |
- size_t rtp_packet_length, |
- const RTPHeader& rtp_header, |
- size_t* position) const { |
- // Get length until start of header extension block. |
- int extension_block_pos = |
- rtp_header_extension_map_.GetLengthUntilBlockStartInBytes(type); |
- if (extension_block_pos < 0) { |
- LOG(LS_WARNING) << "Failed to find extension position for " << type |
- << " as it is not registered."; |
- return false; |
- } |
- |
- HeaderExtension header_extension(type); |
- |
- size_t extension_pos = |
- kRtpHeaderLength + rtp_header.numCSRCs * sizeof(uint32_t); |
- size_t block_pos = extension_pos + extension_block_pos; |
- if (rtp_packet_length < block_pos + header_extension.length || |
- rtp_header.headerLength < block_pos + header_extension.length) { |
- LOG(LS_WARNING) << "Failed to find extension position for " << type |
- << " as the length is invalid."; |
- return false; |
- } |
- |
- // Verify that header contains extension. |
- if (!(rtp_packet[extension_pos] == 0xBE && |
- rtp_packet[extension_pos + 1] == 0xDE)) { |
- LOG(LS_WARNING) << "Failed to find extension position for " << type |
- << "as hdr extension not found."; |
- return false; |
- } |
- |
- *position = block_pos; |
- return true; |
-} |
- |
-RTPSender::ExtensionStatus RTPSender::VerifyExtension( |
- RTPExtensionType extension_type, |
- uint8_t* rtp_packet, |
- size_t rtp_packet_length, |
- const RTPHeader& rtp_header, |
- size_t extension_length_bytes, |
- size_t* extension_offset) const { |
- // Get id. |
- uint8_t id = 0; |
- if (rtp_header_extension_map_.GetId(extension_type, &id) != 0) |
- return ExtensionStatus::kNotRegistered; |
- |
- size_t block_pos = 0; |
- if (!FindHeaderExtensionPosition(extension_type, rtp_packet, |
- rtp_packet_length, rtp_header, &block_pos)) |
- return ExtensionStatus::kError; |
- |
- // Verify first byte in block. |
- const uint8_t first_block_byte = (id << 4) + (extension_length_bytes - 2); |
- if (rtp_packet[block_pos] != first_block_byte) |
- return ExtensionStatus::kError; |
- |
- *extension_offset = block_pos; |
- return ExtensionStatus::kOk; |
-} |
- |
-bool RTPSender::UpdateAudioLevel(uint8_t* rtp_packet, |
- size_t rtp_packet_length, |
- const RTPHeader& rtp_header, |
- bool is_voiced, |
- uint8_t dBov) const { |
- size_t offset; |
- rtc::CritScope lock(&send_critsect_); |
- |
- switch (VerifyExtension(kRtpExtensionAudioLevel, rtp_packet, |
- rtp_packet_length, rtp_header, kAudioLevelLength, |
- &offset)) { |
- case ExtensionStatus::kNotRegistered: |
- return false; |
- case ExtensionStatus::kError: |
- LOG(LS_WARNING) << "Failed to update audio level."; |
- return false; |
- case ExtensionStatus::kOk: |
- break; |
- default: |
- RTC_NOTREACHED(); |
- } |
- |
- rtp_packet[offset + 1] = (is_voiced ? 0x80 : 0x00) + (dBov & 0x7f); |
- return true; |
-} |
- |
-bool RTPSender::UpdateVideoRotation(uint8_t* rtp_packet, |
- size_t rtp_packet_length, |
- const RTPHeader& rtp_header, |
- VideoRotation rotation) const { |
- size_t offset; |
- rtc::CritScope lock(&send_critsect_); |
- |
- switch (VerifyExtension(kRtpExtensionVideoRotation, rtp_packet, |
- rtp_packet_length, rtp_header, kVideoRotationLength, |
- &offset)) { |
- case ExtensionStatus::kNotRegistered: |
- return false; |
- case ExtensionStatus::kError: |
- LOG(LS_WARNING) << "Failed to update CVO."; |
- return false; |
- case ExtensionStatus::kOk: |
- break; |
- default: |
- RTC_NOTREACHED(); |
- } |
- |
- rtp_packet[offset + 1] = ConvertVideoRotationToCVOByte(rotation); |
- return true; |
-} |
+*/ |
bool RTPSender::UpdateTransportSequenceNumber(RtpPacketToSend* packet, |
int* packet_id) const { |