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 58dbc3ebffb983e84f17c94ba2dbb599fd13e169..b918a908a7d03d0420b1a4e0e08201f1834e4c91 100644 |
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc |
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc |
@@ -10,7 +10,6 @@ |
#include "webrtc/modules/rtp_rtcp/source/rtp_sender.h" |
-#include <stdlib.h> // srand |
#include <algorithm> |
#include <utility> |
@@ -24,22 +23,22 @@ |
#include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h" |
#include "webrtc/modules/rtp_rtcp/source/byte_io.h" |
#include "webrtc/modules/rtp_rtcp/source/playout_delay_oracle.h" |
+#include "webrtc/modules/rtp_rtcp/source/rtp_header_extensions.h" |
+#include "webrtc/modules/rtp_rtcp/source/rtp_packet_to_send.h" |
#include "webrtc/modules/rtp_rtcp/source/rtp_sender_audio.h" |
#include "webrtc/modules/rtp_rtcp/source/rtp_sender_video.h" |
#include "webrtc/modules/rtp_rtcp/source/time_util.h" |
namespace webrtc { |
-// Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP. |
-static const size_t kMaxPaddingLength = 224; |
-static const int kSendSideDelayWindowMs = 1000; |
-static const uint32_t kAbsSendTimeFraction = 18; |
-static const int kBitrateStatisticsWindowMs = 1000; |
- |
namespace { |
- |
-const size_t kRtpHeaderLength = 12; |
-const uint16_t kMaxInitRtpSeqNumber = 32767; // 2^15 -1. |
+// Max in the RFC 3550 is 255 bytes, we limit it to be modulus 32 for SRTP. |
+constexpr size_t kMaxPaddingLength = 224; |
+constexpr int kSendSideDelayWindowMs = 1000; |
+constexpr size_t kRtpHeaderLength = 12; |
+constexpr uint16_t kMaxInitRtpSeqNumber = 32767; // 2^15 -1. |
+constexpr uint32_t kTimestampTicksPerMs = 90; |
+constexpr int kBitrateStatisticsWindowMs = 1000; |
const char* FrameTypeToString(FrameType frame_type) { |
switch (frame_type) { |
@@ -53,16 +52,13 @@ const char* FrameTypeToString(FrameType frame_type) { |
return ""; |
} |
-// TODO(holmer): Merge this with the implementation in |
-// remote_bitrate_estimator_abs_send_time.cc. |
-uint32_t ConvertMsTo24Bits(int64_t time_ms) { |
- uint32_t time_24_bits = |
- static_cast<uint32_t>( |
- ((static_cast<uint64_t>(time_ms) << kAbsSendTimeFraction) + 500) / |
- 1000) & |
- 0x00FFFFFF; |
- return time_24_bits; |
+void CountPacket(RtpPacketCounter* counter, const RtpPacketToSend& packet) { |
+ ++counter->packets; |
+ counter->header_bytes += packet.headers_size(); |
+ counter->padding_bytes += packet.padding_size(); |
+ counter->payload_bytes += packet.payload_size(); |
} |
+ |
} // namespace |
RTPSender::RTPSender( |
@@ -127,10 +123,6 @@ RTPSender::RTPSender( |
csrcs_(), |
rtx_(kRtxOff), |
retransmission_rate_limiter_(retransmission_rate_limiter) { |
- // We need to seed the random generator for BuildPaddingPacket() below. |
- // TODO(holmer,tommi): Note that TimeInMilliseconds might return 0 on Mac |
- // early on in the process. |
- srand(static_cast<uint32_t>(clock_->TimeInMilliseconds())); |
ssrc_ = ssrc_db_->CreateSSRC(); |
RTC_DCHECK(ssrc_ != 0); |
ssrc_rtx_ = ssrc_db_->CreateSSRC(); |
@@ -346,17 +338,12 @@ void RTPSender::SetMaxPayloadLength(size_t max_payload_length) { |
} |
size_t RTPSender::MaxDataPayloadLength() const { |
- int rtx; |
- { |
- rtc::CritScope lock(&send_critsect_); |
- rtx = rtx_; |
- } |
if (audio_configured_) { |
return max_payload_length_ - RtpHeaderLength(); |
} else { |
return max_payload_length_ - RtpHeaderLength() // RTP overhead. |
- video_->FECPacketOverhead() // FEC/ULP/RED overhead. |
- - ((rtx) ? 2 : 0); // RTX overhead. |
+ - (RtxStatus() ? kRtxHeaderSize : 0); // RTX overhead. |
} |
} |
@@ -543,41 +530,20 @@ size_t RTPSender::TrySendRedundantPayloads(size_t bytes_to_send, |
return 0; |
} |
- uint8_t buffer[IP_PACKET_SIZE]; |
int bytes_left = static_cast<int>(bytes_to_send); |
while (bytes_left > 0) { |
- size_t length = bytes_left; |
- int64_t capture_time_ms; |
- if (!packet_history_.GetBestFittingPacket(buffer, &length, |
- &capture_time_ms)) { |
+ std::unique_ptr<RtpPacketToSend> packet = |
+ packet_history_.GetBestFittingPacket(bytes_left); |
+ if (!packet) |
break; |
- } |
- if (!PrepareAndSendPacket(buffer, length, capture_time_ms, true, false, |
- probe_cluster_id)) |
+ size_t payload_size = packet->payload_size(); |
+ if (!PrepareAndSendPacket(std::move(packet), true, false, probe_cluster_id)) |
break; |
- RtpUtility::RtpHeaderParser rtp_parser(buffer, length); |
- RTPHeader rtp_header; |
- rtp_parser.Parse(&rtp_header); |
- bytes_left -= static_cast<int>(length - rtp_header.headerLength); |
+ bytes_left -= payload_size; |
} |
return bytes_to_send - bytes_left; |
} |
-void RTPSender::BuildPaddingPacket(uint8_t* packet, |
- size_t header_length, |
- size_t padding_length) { |
- packet[0] |= 0x20; // Set padding bit. |
- int32_t* data = reinterpret_cast<int32_t*>(&(packet[header_length])); |
- |
- // Fill data buffer with random data. |
- for (size_t j = 0; j < (padding_length >> 2); ++j) { |
- data[j] = rand(); // NOLINT |
- } |
- // Set number of padding bytes in the last byte of the packet. |
- packet[header_length + padding_length - 1] = |
- static_cast<uint8_t>(padding_length); |
-} |
- |
size_t RTPSender::SendPadData(size_t bytes, |
bool timestamp_provided, |
uint32_t timestamp, |
@@ -653,42 +619,36 @@ size_t RTPSender::SendPadData(size_t bytes, |
} |
} |
- uint8_t padding_packet[IP_PACKET_SIZE]; |
- size_t header_length = 0; |
- { |
- rtc::CritScope lock(&send_critsect_); |
- header_length = |
- CreateRtpHeader(padding_packet, payload_type, ssrc, false, timestamp, |
- sequence_number, std::vector<uint32_t>()); |
- } |
- BuildPaddingPacket(padding_packet, header_length, padding_bytes_in_packet); |
- size_t length = padding_bytes_in_packet + header_length; |
- int64_t now_ms = clock_->TimeInMilliseconds(); |
+ RtpPacketToSend padding_packet(&rtp_header_extension_map_, IP_PACKET_SIZE); |
+ padding_packet.SetPayloadType(payload_type); |
+ padding_packet.SetMarker(false); |
+ padding_packet.SetSequenceNumber(sequence_number); |
+ padding_packet.SetTimestamp(timestamp); |
+ padding_packet.SetSsrc(ssrc); |
- RtpUtility::RtpHeaderParser rtp_parser(padding_packet, length); |
- RTPHeader rtp_header; |
- rtp_parser.Parse(&rtp_header); |
+ int64_t now_ms = clock_->TimeInMilliseconds(); |
if (capture_time_ms > 0) { |
- UpdateTransmissionTimeOffset( |
- padding_packet, length, rtp_header, now_ms - capture_time_ms); |
+ padding_packet.SetExtension<TransmissionOffset>( |
+ kTimestampTicksPerMs * (now_ms - capture_time_ms)); |
} |
- |
- UpdateAbsoluteSendTime(padding_packet, length, rtp_header, now_ms); |
+ padding_packet.SetExtension<AbsoluteSendTime>(now_ms); |
PacketOptions options; |
- if (UpdateTransportSequenceNumber(padding_packet, length, rtp_header, |
- &options.packet_id)) { |
- if (transport_feedback_observer_) |
- transport_feedback_observer_->AddPacket(options.packet_id, length, |
- probe_cluster_id); |
- } |
+ bool has_transport_seq_no = |
+ UpdateTransportSequenceNumber(&padding_packet, &options.packet_id); |
- if (!SendPacketToNetwork(padding_packet, length, options)) |
+ padding_packet.SetPadding(padding_bytes_in_packet, &random_); |
+ |
+ if (has_transport_seq_no && transport_feedback_observer_) |
+ transport_feedback_observer_->AddPacket( |
+ options.packet_id, padding_packet.size(), probe_cluster_id); |
+ |
+ if (!SendPacketToNetwork(padding_packet, options)) |
break; |
bytes_sent += padding_bytes_in_packet; |
- UpdateRtpStats(padding_packet, length, rtp_header, over_rtx, false); |
+ UpdateRtpStats(padding_packet, over_rtx, false); |
} |
return bytes_sent; |
@@ -703,13 +663,9 @@ bool RTPSender::StorePackets() const { |
} |
int32_t RTPSender::ReSendPacket(uint16_t packet_id, int64_t min_resend_time) { |
- size_t length = IP_PACKET_SIZE; |
- uint8_t data_buffer[IP_PACKET_SIZE]; |
- int64_t capture_time_ms; |
- |
- if (!packet_history_.GetPacketAndSetSendTime(packet_id, min_resend_time, true, |
- data_buffer, &length, |
- &capture_time_ms)) { |
+ std::unique_ptr<RtpPacketToSend> packet = |
+ packet_history_.GetPacketAndSetSendTime(packet_id, min_resend_time, true); |
+ if (!packet) { |
// Packet not found. |
return 0; |
} |
@@ -717,53 +673,44 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, int64_t min_resend_time) { |
// Check if we're overusing retransmission bitrate. |
// TODO(sprang): Add histograms for nack success or failure reasons. |
RTC_DCHECK(retransmission_rate_limiter_); |
- if (!retransmission_rate_limiter_->TryUseRate(length)) |
+ if (!retransmission_rate_limiter_->TryUseRate(packet->size())) |
return -1; |
if (paced_sender_) { |
- RtpUtility::RtpHeaderParser rtp_parser(data_buffer, length); |
- RTPHeader header; |
- if (!rtp_parser.Parse(&header)) { |
- assert(false); |
- return -1; |
- } |
// Convert from TickTime to Clock since capture_time_ms is based on |
// TickTime. |
- int64_t corrected_capture_tims_ms = capture_time_ms + clock_delta_ms_; |
- paced_sender_->InsertPacket( |
- RtpPacketSender::kNormalPriority, header.ssrc, header.sequenceNumber, |
- corrected_capture_tims_ms, length - header.headerLength, true); |
- |
- return length; |
- } |
- int rtx = kRtxOff; |
- { |
- rtc::CritScope lock(&send_critsect_); |
- rtx = rtx_; |
- } |
- if (!PrepareAndSendPacket(data_buffer, length, capture_time_ms, |
- (rtx & kRtxRetransmitted) > 0, true, |
- PacketInfo::kNotAProbe)) { |
+ int64_t corrected_capture_tims_ms = |
+ packet->capture_time_ms() + clock_delta_ms_; |
+ paced_sender_->InsertPacket(RtpPacketSender::kNormalPriority, |
+ packet->Ssrc(), packet->SequenceNumber(), |
+ corrected_capture_tims_ms, |
+ packet->payload_size(), true); |
+ |
+ return packet->size(); |
+ } |
+ bool rtx = (RtxStatus() & kRtxRetransmitted) > 0; |
+ int32_t packet_size = static_cast<int32_t>(packet->size()); |
+ if (!PrepareAndSendPacket(std::move(packet), rtx, true, |
+ PacketInfo::kNotAProbe)) |
return -1; |
- } |
- return static_cast<int32_t>(length); |
+ return packet_size; |
} |
-bool RTPSender::SendPacketToNetwork(const uint8_t* packet, |
- size_t size, |
+bool RTPSender::SendPacketToNetwork(const RtpPacketToSend& packet, |
const PacketOptions& options) { |
int bytes_sent = -1; |
if (transport_) { |
- bytes_sent = transport_->SendRtp(packet, size, options) |
- ? static_cast<int>(size) |
+ bytes_sent = transport_->SendRtp(packet.data(), packet.size(), options) |
+ ? static_cast<int>(packet.size()) |
: -1; |
if (event_log_ && bytes_sent > 0) { |
- event_log_->LogRtpHeader(kOutgoingPacket, MediaType::ANY, packet, size); |
+ event_log_->LogRtpHeader(kOutgoingPacket, MediaType::ANY, packet.data(), |
+ packet.size()); |
} |
} |
TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
- "RTPSender::SendPacketToNetwork", "size", size, "sent", |
- bytes_sent); |
+ "RTPSender::SendPacketToNetwork", "size", packet.size(), |
+ "sent", bytes_sent); |
// TODO(pwestin): Add a separate bitrate for sent bitrate after pacer. |
if (bytes_sent <= 0) { |
LOG(LS_WARNING) << "Transport failed to send packet"; |
@@ -811,89 +758,75 @@ bool RTPSender::TimeToSendPacket(uint16_t sequence_number, |
int64_t capture_time_ms, |
bool retransmission, |
int probe_cluster_id) { |
- size_t length = IP_PACKET_SIZE; |
- uint8_t data_buffer[IP_PACKET_SIZE]; |
- int64_t stored_time_ms; |
- |
- if (!packet_history_.GetPacketAndSetSendTime(sequence_number, |
- 0, |
- retransmission, |
- data_buffer, |
- &length, |
- &stored_time_ms)) { |
+ std::unique_ptr<RtpPacketToSend> packet = |
+ packet_history_.GetPacketAndSetSendTime(sequence_number, 0, |
+ retransmission); |
+ if (!packet) |
// Packet cannot be found. Allow sending to continue. |
return true; |
- } |
- int rtx; |
- { |
- rtc::CritScope lock(&send_critsect_); |
- rtx = rtx_; |
- } |
- return PrepareAndSendPacket(data_buffer, length, capture_time_ms, |
- retransmission && (rtx & kRtxRetransmitted) > 0, |
- retransmission, probe_cluster_id); |
+ return PrepareAndSendPacket( |
+ std::move(packet), |
+ retransmission && (RtxStatus() & kRtxRetransmitted) > 0, retransmission, |
+ probe_cluster_id); |
} |
-bool RTPSender::PrepareAndSendPacket(uint8_t* buffer, |
- size_t length, |
- int64_t capture_time_ms, |
+bool RTPSender::PrepareAndSendPacket(std::unique_ptr<RtpPacketToSend> packet, |
bool send_over_rtx, |
bool is_retransmit, |
int probe_cluster_id) { |
- uint8_t* buffer_to_send_ptr = buffer; |
+ RTC_DCHECK(packet); |
+ int64_t capture_time_ms = packet->capture_time_ms(); |
+ RtpPacketToSend* packet_to_send = packet.get(); |
- RtpUtility::RtpHeaderParser rtp_parser(buffer, length); |
- RTPHeader rtp_header; |
- rtp_parser.Parse(&rtp_header); |
- if (!is_retransmit && rtp_header.markerBit) { |
+ if (!is_retransmit && packet->Marker()) { |
TRACE_EVENT_ASYNC_END0(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PacedSend", |
capture_time_ms); |
} |
- TRACE_EVENT_INSTANT2( |
- TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), "PrepareAndSendPacket", |
- "timestamp", rtp_header.timestamp, "seqnum", rtp_header.sequenceNumber); |
+ TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
+ "PrepareAndSendPacket", "timestamp", packet->Timestamp(), |
+ "seqnum", packet->SequenceNumber()); |
- uint8_t data_buffer_rtx[IP_PACKET_SIZE]; |
+ std::unique_ptr<RtpPacketToSend> packet_rtx; |
if (send_over_rtx) { |
- if (!BuildRtxPacket(buffer, &length, data_buffer_rtx)) |
+ packet_rtx = BuildRtxPacket(*packet); |
+ if (!packet_rtx) |
return false; |
- buffer_to_send_ptr = data_buffer_rtx; |
+ packet_to_send = packet_rtx.get(); |
} |
int64_t now_ms = clock_->TimeInMilliseconds(); |
int64_t diff_ms = now_ms - capture_time_ms; |
- UpdateTransmissionTimeOffset(buffer_to_send_ptr, length, rtp_header, |
- diff_ms); |
- UpdateAbsoluteSendTime(buffer_to_send_ptr, length, rtp_header, now_ms); |
+ packet_to_send->SetExtension<TransmissionOffset>(kTimestampTicksPerMs * |
+ diff_ms); |
+ packet_to_send->SetExtension<AbsoluteSendTime>(now_ms); |
PacketOptions options; |
- if (UpdateTransportSequenceNumber(buffer_to_send_ptr, length, rtp_header, |
- &options.packet_id)) { |
- if (transport_feedback_observer_) |
- transport_feedback_observer_->AddPacket(options.packet_id, length, |
- probe_cluster_id); |
+ if (UpdateTransportSequenceNumber(packet_to_send, &options.packet_id) && |
+ transport_feedback_observer_) { |
+ transport_feedback_observer_->AddPacket( |
+ options.packet_id, packet_to_send->size(), probe_cluster_id); |
} |
if (!is_retransmit && !send_over_rtx) { |
- UpdateDelayStatistics(capture_time_ms, now_ms); |
- UpdateOnSendPacket(options.packet_id, capture_time_ms, rtp_header.ssrc); |
+ UpdateDelayStatistics(packet->capture_time_ms(), now_ms); |
+ UpdateOnSendPacket(options.packet_id, packet->capture_time_ms(), |
+ packet->Ssrc()); |
} |
- bool ret = SendPacketToNetwork(buffer_to_send_ptr, length, options); |
- if (ret) { |
+ if (!SendPacketToNetwork(*packet_to_send, options)) |
+ return false; |
+ |
+ { |
rtc::CritScope lock(&send_critsect_); |
media_has_been_sent_ = true; |
} |
- UpdateRtpStats(buffer_to_send_ptr, length, rtp_header, send_over_rtx, |
- is_retransmit); |
- return ret; |
+ UpdateRtpStats(*packet_to_send, send_over_rtx, is_retransmit); |
+ return true; |
} |
-void RTPSender::UpdateRtpStats(const uint8_t* buffer, |
- size_t packet_length, |
- const RTPHeader& header, |
+void RTPSender::UpdateRtpStats(const RtpPacketToSend& packet, |
bool is_rtx, |
bool is_retransmit) { |
StreamDataCounters* counters; |
@@ -908,27 +841,26 @@ void RTPSender::UpdateRtpStats(const uint8_t* buffer, |
counters = &rtp_stats_; |
} |
- total_bitrate_sent_.Update(packet_length, now_ms); |
+ total_bitrate_sent_.Update(packet.size(), now_ms); |
- if (counters->first_packet_time_ms == -1) |
+ if (counters->first_packet_time_ms == -1) { |
counters->first_packet_time_ms = clock_->TimeInMilliseconds(); |
- |
- if (IsFecPacket(buffer, header)) |
- counters->fec.AddPacket(packet_length, header); |
- |
+ } |
+ if (IsFecPacket(packet)) { |
+ CountPacket(&counters->fec, packet); |
+ } |
if (is_retransmit) { |
- counters->retransmitted.AddPacket(packet_length, header); |
- nack_bitrate_sent_.Update(packet_length, now_ms); |
+ CountPacket(&counters->retransmitted, packet); |
+ nack_bitrate_sent_.Update(packet.size(), now_ms); |
} |
+ CountPacket(&counters->transmitted, packet); |
- counters->transmitted.AddPacket(packet_length, header); |
- |
- if (rtp_stats_callback_) |
+ if (rtp_stats_callback_) { |
rtp_stats_callback_->DataCountersUpdated(*counters, ssrc); |
+ } |
} |
-bool RTPSender::IsFecPacket(const uint8_t* buffer, |
- const RTPHeader& header) const { |
+bool RTPSender::IsFecPacket(const RtpPacketToSend& packet) const { |
if (!video_) { |
return false; |
} |
@@ -936,9 +868,8 @@ bool RTPSender::IsFecPacket(const uint8_t* buffer, |
uint8_t pt_red; |
uint8_t pt_fec; |
video_->GenericFECStatus(&fec_enabled, &pt_red, &pt_fec); |
- return fec_enabled && |
- header.payloadType == pt_red && |
- buffer[header.headerLength] == pt_fec; |
+ return fec_enabled && packet.PayloadType() == pt_red && |
+ packet.payload()[0] == pt_fec; |
} |
size_t RTPSender::TimeToSendPadding(size_t bytes, int probe_cluster_id) { |
@@ -951,7 +882,6 @@ size_t RTPSender::TimeToSendPadding(size_t bytes, int probe_cluster_id) { |
return bytes_sent; |
} |
-// TODO(pwestin): send in the RtpHeaderParser to avoid parsing it again. |
bool RTPSender::SendToNetwork(uint8_t* buffer, |
size_t payload_length, |
size_t rtp_header_length, |
@@ -959,35 +889,38 @@ bool RTPSender::SendToNetwork(uint8_t* buffer, |
StorageType storage, |
RtpPacketSender::Priority priority) { |
size_t length = payload_length + rtp_header_length; |
- RtpUtility::RtpHeaderParser rtp_parser(buffer, length); |
- |
- RTPHeader rtp_header; |
- rtp_parser.Parse(&rtp_header); |
+ 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) { |
+ RTC_DCHECK(packet); |
int64_t now_ms = clock_->TimeInMilliseconds(); |
// |capture_time_ms| <= 0 is considered invalid. |
// TODO(holmer): This should be changed all over Video Engine so that negative |
// time is consider invalid, while 0 is considered a valid time. |
- if (capture_time_ms > 0) { |
- UpdateTransmissionTimeOffset(buffer, length, rtp_header, |
- now_ms - capture_time_ms); |
- } |
- |
- UpdateAbsoluteSendTime(buffer, length, rtp_header, now_ms); |
- |
- // Used for NACK and to spread out the transmission of packets. |
- if (packet_history_.PutRTPPacket(buffer, length, capture_time_ms, storage) != |
- 0) { |
- return false; |
+ if (packet->capture_time_ms() > 0) { |
+ packet->SetExtension<TransmissionOffset>( |
+ kTimestampTicksPerMs * (now_ms - packet->capture_time_ms())); |
} |
+ packet->SetExtension<AbsoluteSendTime>(now_ms); |
if (paced_sender_) { |
+ uint16_t seq_no = packet->SequenceNumber(); |
+ uint32_t ssrc = packet->Ssrc(); |
// Correct offset between implementations of millisecond time stamps in |
// TickTime and Clock. |
- int64_t corrected_time_ms = capture_time_ms + clock_delta_ms_; |
- paced_sender_->InsertPacket(priority, rtp_header.ssrc, |
- rtp_header.sequenceNumber, corrected_time_ms, |
+ int64_t corrected_time_ms = packet->capture_time_ms() + clock_delta_ms_; |
+ size_t payload_length = packet->payload_size(); |
+ packet_history_.PutRtpPacket(std::move(packet), storage, false); |
+ |
+ paced_sender_->InsertPacket(priority, ssrc, seq_no, corrected_time_ms, |
payload_length, false); |
if (last_capture_time_ms_sent_ == 0 || |
corrected_time_ms > last_capture_time_ms_sent_) { |
@@ -1000,31 +933,32 @@ bool RTPSender::SendToNetwork(uint8_t* buffer, |
} |
PacketOptions options; |
- if (UpdateTransportSequenceNumber(buffer, length, rtp_header, |
- &options.packet_id)) { |
- if (transport_feedback_observer_) |
- transport_feedback_observer_->AddPacket(options.packet_id, length, |
- PacketInfo::kNotAProbe); |
+ if (UpdateTransportSequenceNumber(packet.get(), &options.packet_id) && |
+ transport_feedback_observer_) { |
+ transport_feedback_observer_->AddPacket(options.packet_id, packet->size(), |
+ PacketInfo::kNotAProbe); |
} |
- UpdateDelayStatistics(capture_time_ms, now_ms); |
- UpdateOnSendPacket(options.packet_id, capture_time_ms, rtp_header.ssrc); |
- bool sent = SendPacketToNetwork(buffer, length, options); |
+ UpdateDelayStatistics(packet->capture_time_ms(), now_ms); |
+ UpdateOnSendPacket(options.packet_id, packet->capture_time_ms(), |
+ packet->Ssrc()); |
+ |
+ bool sent = SendPacketToNetwork(*packet, options); |
+ |
+ if (sent) { |
+ { |
+ rtc::CritScope lock(&send_critsect_); |
+ media_has_been_sent_ = true; |
+ } |
+ UpdateRtpStats(*packet, false, false); |
+ } |
// Mark the packet as sent in the history even if send failed. Dropping a |
// packet here should be treated as any other packet drop so we should be |
// ready for a retransmission. |
- packet_history_.SetSent(rtp_header.sequenceNumber); |
- |
- if (!sent) |
- return false; |
+ packet_history_.PutRtpPacket(std::move(packet), storage, true); |
- { |
- rtc::CritScope lock(&send_critsect_); |
- media_has_been_sent_ = true; |
- } |
- UpdateRtpStats(buffer, length, rtp_header, false, false); |
- return true; |
+ return sent; |
} |
void RTPSender::UpdateDelayStatistics(int64_t capture_time_ms, int64_t now_ms) { |
@@ -1494,31 +1428,6 @@ RTPSender::ExtensionStatus RTPSender::VerifyExtension( |
return ExtensionStatus::kOk; |
} |
-void RTPSender::UpdateTransmissionTimeOffset(uint8_t* rtp_packet, |
- size_t rtp_packet_length, |
- const RTPHeader& rtp_header, |
- int64_t time_diff_ms) const { |
- size_t offset; |
- rtc::CritScope lock(&send_critsect_); |
- switch (VerifyExtension(kRtpExtensionTransmissionTimeOffset, rtp_packet, |
- rtp_packet_length, rtp_header, |
- kTransmissionTimeOffsetLength, &offset)) { |
- case ExtensionStatus::kNotRegistered: |
- return; |
- case ExtensionStatus::kError: |
- LOG(LS_WARNING) << "Failed to update transmission time offset."; |
- return; |
- case ExtensionStatus::kOk: |
- break; |
- default: |
- RTC_NOTREACHED(); |
- } |
- |
- // Update transmission offset field (converting to a 90 kHz timestamp). |
- ByteWriter<int32_t, 3>::WriteBigEndian(rtp_packet + offset + 1, |
- time_diff_ms * 90); // RTP timestamp. |
-} |
- |
bool RTPSender::UpdateAudioLevel(uint8_t* rtp_packet, |
size_t rtp_packet_length, |
const RTPHeader& rtp_header, |
@@ -1570,67 +1479,22 @@ bool RTPSender::UpdateVideoRotation(uint8_t* rtp_packet, |
return true; |
} |
-void RTPSender::UpdateAbsoluteSendTime(uint8_t* rtp_packet, |
- size_t rtp_packet_length, |
- const RTPHeader& rtp_header, |
- int64_t now_ms) const { |
- size_t offset; |
+bool RTPSender::UpdateTransportSequenceNumber(RtpPacketToSend* packet, |
+ int* packet_id) const { |
+ RTC_DCHECK(packet); |
+ RTC_DCHECK(packet_id); |
rtc::CritScope lock(&send_critsect_); |
- |
- switch (VerifyExtension(kRtpExtensionAbsoluteSendTime, rtp_packet, |
- rtp_packet_length, rtp_header, |
- kAbsoluteSendTimeLength, &offset)) { |
- case ExtensionStatus::kNotRegistered: |
- return; |
- case ExtensionStatus::kError: |
- LOG(LS_WARNING) << "Failed to update absolute send time"; |
- return; |
- case ExtensionStatus::kOk: |
- break; |
- default: |
- RTC_NOTREACHED(); |
- } |
- |
- // Update absolute send time field (convert ms to 24-bit unsigned with 18 bit |
- // fractional part). |
- ByteWriter<uint32_t, 3>::WriteBigEndian(rtp_packet + offset + 1, |
- ConvertMsTo24Bits(now_ms)); |
-} |
- |
-bool RTPSender::UpdateTransportSequenceNumber(uint8_t* rtp_packet, |
- size_t rtp_packet_length, |
- const RTPHeader& rtp_header, |
- int* sequence_number) const { |
- RTC_DCHECK(sequence_number); |
- size_t offset; |
- rtc::CritScope lock(&send_critsect_); |
- |
- switch (VerifyExtension(kRtpExtensionTransportSequenceNumber, rtp_packet, |
- rtp_packet_length, rtp_header, |
- kTransportSequenceNumberLength, &offset)) { |
- case ExtensionStatus::kNotRegistered: |
- return false; |
- case ExtensionStatus::kError: |
- LOG(LS_WARNING) << "Failed to update transport sequence number"; |
- return false; |
- case ExtensionStatus::kOk: |
- break; |
- default: |
- RTC_NOTREACHED(); |
- } |
- |
- if (!AllocateTransportSequenceNumber(sequence_number)) |
+ if (!rtp_header_extension_map_.IsRegistered(TransportSequenceNumber::kId)) |
return false; |
- BuildTransportSequenceNumberExtension(rtp_packet + offset, *sequence_number); |
- return true; |
-} |
- |
-bool RTPSender::AllocateTransportSequenceNumber(int* packet_id) const { |
if (!transport_sequence_number_allocator_) |
return false; |
*packet_id = transport_sequence_number_allocator_->AllocateSequenceNumber(); |
+ |
+ if (!packet->SetExtension<TransportSequenceNumber>(*packet_id)) |
+ return false; |
+ |
return true; |
} |
@@ -1803,53 +1667,46 @@ int32_t RTPSender::SetFecParameters( |
return 0; |
} |
-bool RTPSender::BuildRtxPacket(uint8_t* buffer, |
- size_t* length, |
- uint8_t* buffer_rtx) { |
- rtc::CritScope lock(&send_critsect_); |
- if (!sending_media_) |
- return false; |
- uint8_t* data_buffer_rtx = buffer_rtx; |
- // Add RTX header. |
- RtpUtility::RtpHeaderParser rtp_parser( |
- reinterpret_cast<const uint8_t*>(buffer), *length); |
+std::unique_ptr<RtpPacketToSend> RTPSender::BuildRtxPacket( |
+ const RtpPacketToSend& packet) { |
+ // TODO(danilchap): Create rtx packet with extra capacity for SRTP |
+ // when transport interface would be updated to take buffer class. |
+ std::unique_ptr<RtpPacketToSend> rtx_packet(new RtpPacketToSend( |
+ &rtp_header_extension_map_, packet.size() + kRtxHeaderSize)); |
+ // Add original RTP header. |
+ rtx_packet->CopyHeaderFrom(packet); |
+ { |
+ rtc::CritScope lock(&send_critsect_); |
+ if (!sending_media_) |
+ return nullptr; |
+ // Replace payload type, if a specific type is set for RTX. |
+ auto kv = rtx_payload_type_map_.find(packet.PayloadType()); |
- RTPHeader rtp_header; |
- rtp_parser.Parse(&rtp_header); |
+ // Use rtx mapping associated with media codec if we can't find one, |
+ // assume it's red. |
+ // TODO(holmer): Remove once old Chrome versions don't rely on this. |
+ if (kv == rtx_payload_type_map_.end()) |
+ kv = rtx_payload_type_map_.find(payload_type_); |
+ if (kv != rtx_payload_type_map_.end()) |
+ rtx_packet->SetPayloadType(kv->second); |
- // Add original RTP header. |
- memcpy(data_buffer_rtx, buffer, rtp_header.headerLength); |
- |
- // Replace payload type, if a specific type is set for RTX. |
- auto kv = rtx_payload_type_map_.find(rtp_header.payloadType); |
- // Use rtx mapping associated with media codec if we can't find one, assuming |
- // it's red. |
- // TODO(holmer): Remove once old Chrome versions don't rely on this. |
- if (kv == rtx_payload_type_map_.end()) |
- kv = rtx_payload_type_map_.find(payload_type_); |
- if (kv != rtx_payload_type_map_.end()) |
- data_buffer_rtx[1] = kv->second; |
- if (rtp_header.markerBit) |
- data_buffer_rtx[1] |= kRtpMarkerBitMask; |
- |
- // Replace sequence number. |
- uint8_t* ptr = data_buffer_rtx + 2; |
- ByteWriter<uint16_t>::WriteBigEndian(ptr, sequence_number_rtx_++); |
- |
- // Replace SSRC. |
- ptr += 6; |
- ByteWriter<uint32_t>::WriteBigEndian(ptr, ssrc_rtx_); |
+ // Replace sequence number. |
+ rtx_packet->SetSequenceNumber(sequence_number_rtx_++); |
+ // Replace SSRC. |
+ rtx_packet->SetSsrc(ssrc_rtx_); |
+ } |
+ |
+ uint8_t* rtx_payload = |
+ rtx_packet->AllocatePayload(packet.payload_size() + kRtxHeaderSize); |
+ RTC_DCHECK(rtx_payload); |
// Add OSN (original sequence number). |
- ptr = data_buffer_rtx + rtp_header.headerLength; |
- ByteWriter<uint16_t>::WriteBigEndian(ptr, rtp_header.sequenceNumber); |
- ptr += 2; |
+ ByteWriter<uint16_t>::WriteBigEndian(rtx_payload, packet.SequenceNumber()); |
// Add original payload data. |
- memcpy(ptr, buffer + rtp_header.headerLength, |
- *length - rtp_header.headerLength); |
- *length += 2; |
- return true; |
+ memcpy(rtx_payload + kRtxHeaderSize, packet.payload(), packet.payload_size()); |
+ |
+ return rtx_packet; |
} |
void RTPSender::RegisterRtpStatisticsCallback( |