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 f7b72b875c785358d42179f333ff2173075c0e99..500353f50497c8f2b6606017dbd1e7dfd110277e 100644 |
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc |
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc |
@@ -21,6 +21,7 @@ |
#include "webrtc/call/rtc_event_log.h" |
#include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h" |
#include "webrtc/modules/rtp_rtcp/source/byte_io.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" |
@@ -31,7 +32,6 @@ 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; |
namespace { |
@@ -49,17 +49,6 @@ 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; |
-} |
} // namespace |
RTPSender::BitrateAggregator::BitrateAggregator( |
@@ -115,10 +104,6 @@ RTPSender::RTPSender( |
SendSideDelayObserver* send_side_delay_observer, |
RtcEventLog* event_log) |
: clock_(clock), |
- // TODO(holmer): Remove this conversion when we remove the use of |
- // TickTime. |
- clock_delta_ms_(clock_->TimeInMilliseconds() - |
- TickTime::MillisecondTimestamp()), |
random_(clock_->TimeInMicroseconds()), |
bitrates_(bitrate_callback), |
total_bitrate_sent_(clock, bitrates_.total_bitrate_observer()), |
@@ -180,6 +165,8 @@ RTPSender::RTPSender( |
// Random start, 16 bits. Can't be 0. |
sequence_number_rtx_ = random_.Rand(1, kMaxInitRtpSeqNumber); |
sequence_number_ = random_.Rand(1, kMaxInitRtpSeqNumber); |
+ encoder_thread_.DetachFromThread(); |
+ network_thread_.DetachFromThread(); |
} |
RTPSender::~RTPSender() { |
@@ -187,6 +174,7 @@ RTPSender::~RTPSender() { |
// deleted on the same thread. At the moment this isn't possible due to |
// voe::ChannelOwner in voice engine. To reproduce, run: |
// voe_auto_test --automated --gtest_filter=*MixManyChannelsForStressOpus |
+ // RTC_DCHECK(configuration_thread_.CalledOnValidThread()); |
// TODO(tommi,holmer): We don't grab locks in the dtor before accessing member |
// variables but we grab them in all other methods. (what's the design?) |
@@ -270,7 +258,29 @@ int32_t RTPSender::SetTransportSequenceNumber(uint16_t sequence_number) { |
int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type, |
uint8_t id) { |
+ RTC_DCHECK(configuration_thread_.CalledOnValidThread()); |
rtc::CritScope lock(&send_critsect_); |
+ // Register in rtp_manager_ |
+ switch (type) { |
+ case kRtpExtensionNone: |
+ RTC_NOTREACHED(); |
+ case kRtpExtensionVideoRotation: |
+ rtp_manager_.Register<VideoOrientation>(id); |
+ break; |
+ case kRtpExtensionTransmissionTimeOffset: |
+ rtp_manager_.Register<TransmissionOffset>(id); |
+ break; |
+ case kRtpExtensionAudioLevel: |
+ rtp_manager_.Register<AudioLevel>(id); |
+ break; |
+ case kRtpExtensionAbsoluteSendTime: |
+ rtp_manager_.Register<AbsoluteSendTime>(id); |
+ break; |
+ case kRtpExtensionTransportSequenceNumber: |
+ rtp_manager_.Register<TransportSequenceNumber>(id); |
+ break; |
+ } |
+ // Register in older rtp_extension_header_map_ |
if (type == kRtpExtensionVideoRotation) { |
cvo_mode_ = kCVOInactive; |
return rtp_header_extension_map_.RegisterInactive(type, id); |
@@ -279,11 +289,13 @@ int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type, |
} |
bool RTPSender::IsRtpHeaderExtensionRegistered(RTPExtensionType type) { |
+ RTC_DCHECK(network_thread_.CalledOnValidThread()); |
rtc::CritScope lock(&send_critsect_); |
return rtp_header_extension_map_.IsRegistered(type); |
} |
int32_t RTPSender::DeregisterRtpHeaderExtension(RTPExtensionType type) { |
+ RTC_DCHECK(configuration_thread_.CalledOnValidThread()); |
rtc::CritScope lock(&send_critsect_); |
return rtp_header_extension_map_.Deregister(type); |
} |
@@ -293,12 +305,41 @@ size_t RTPSender::RtpHeaderExtensionTotalLength() const { |
return rtp_header_extension_map_.GetTotalLengthInBytes(); |
} |
+std::unique_ptr<RtpPacketToSend> RTPSender::CreatePacket() const { |
+ RtpPacketToSend* packet = |
+ new RtpPacketToSend(&rtp_manager_, max_payload_length_); |
+ packet->set_capture_time_ms(clock_->TimeInMilliseconds()); |
+ return std::unique_ptr<RtpPacketToSend>(packet); |
+} |
+ |
+void RTPSender::BuildRtpHeader(RtpPacketToSend* packet, |
+ uint32_t capture_timestamp, |
+ bool reserve_extensions) { |
+ rtc::CritScope lock(&send_critsect_); |
+ |
+ timestamp_ = start_timestamp_ + capture_timestamp; |
+ last_timestamp_time_ms_ = clock_->TimeInMilliseconds(); |
+ |
+ packet->SetSsrc(ssrc_); |
+ packet->SetSequenceNumber(sequence_number_++); |
+ packet->SetTimestamp(timestamp_); |
+ if (reserve_extensions) { |
+ packet->SetCsrcs(csrcs_); |
+ // If extension wasn't registered, it will not be reserved. |
+ // Reserve only those extensions RTPSender set values itself. |
+ packet->ReserveExtension<TransmissionOffset>(); |
+ packet->ReserveExtension<AbsoluteSendTime>(); |
+ packet->ReserveExtension<TransportSequenceNumber>(); |
+ } |
+} |
+ |
int32_t RTPSender::RegisterPayload( |
const char payload_name[RTP_PAYLOAD_NAME_SIZE], |
int8_t payload_number, |
uint32_t frequency, |
size_t channels, |
uint32_t rate) { |
+ RTC_DCHECK(configuration_thread_.CalledOnValidThread()); |
RTC_DCHECK_LT(strlen(payload_name), RTP_PAYLOAD_NAME_SIZE); |
rtc::CritScope lock(&send_critsect_); |
@@ -490,6 +531,7 @@ int32_t RTPSender::SendOutgoingData(FrameType frame_type, |
size_t payload_size, |
const RTPFragmentationHeader* fragmentation, |
const RTPVideoHeader* rtp_hdr) { |
+ RTC_DCHECK(encoder_thread_.CalledOnValidThread()); |
uint32_t ssrc; |
{ |
// Drop this packet if we're not sending media packets. |
@@ -544,6 +586,7 @@ int32_t RTPSender::SendOutgoingData(FrameType frame_type, |
} |
size_t RTPSender::TrySendRedundantPayloads(size_t bytes_to_send) { |
+ RTC_DCHECK(network_thread_.CalledOnValidThread()); |
{ |
rtc::CritScope lock(&send_critsect_); |
if (!sending_media_) |
@@ -552,21 +595,15 @@ 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)) { |
+ auto packet = packet_history_.GetBestFittingPacket(bytes_left); |
+ if (!packet) { |
break; |
} |
- if (!PrepareAndSendPacket(buffer, length, capture_time_ms, true, false)) |
+ if (!PrepareAndSendPacket(packet, true, false)) |
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 -= static_cast<int>(packet->payload_size()); |
} |
return bytes_to_send - bytes_left; |
} |
@@ -574,6 +611,7 @@ size_t RTPSender::TrySendRedundantPayloads(size_t bytes_to_send) { |
void RTPSender::BuildPaddingPacket(uint8_t* packet, |
size_t header_length, |
size_t padding_length) { |
+ RTC_DCHECK(network_thread_.CalledOnValidThread()); |
packet[0] |= 0x20; // Set padding bit. |
int32_t* data = reinterpret_cast<int32_t*>(&(packet[header_length])); |
@@ -597,9 +635,9 @@ size_t RTPSender::SendPadData(size_t bytes, |
size_t padding_bytes_in_packet = |
std::min(MaxDataPayloadLength(), kMaxPaddingLength); |
size_t bytes_sent = 0; |
- bool using_transport_seq = rtp_header_extension_map_.IsRegistered( |
- kRtpExtensionTransportSequenceNumber) && |
- transport_sequence_number_allocator_; |
+ bool using_transport_seq = |
+ transport_sequence_number_allocator_ && |
+ rtp_manager_.IsRegistered<TransportSequenceNumber>(); |
for (; bytes > 0; bytes -= padding_bytes_in_packet) { |
if (bytes < padding_bytes_in_packet) |
bytes = padding_bytes_in_packet; |
@@ -651,109 +689,96 @@ size_t RTPSender::SendPadData(size_t bytes, |
over_rtx = true; |
} |
} |
+ RtpPacketToSend padding_packet(&rtp_manager_); |
+ padding_packet.SetPayloadType(payload_type); |
+ padding_packet.SetSsrc(ssrc); |
+ padding_packet.SetTimestamp(timestamp); |
+ padding_packet.SetSequenceNumber(sequence_number); |
- uint8_t padding_packet[IP_PACKET_SIZE]; |
- size_t 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(); |
- |
- RtpUtility::RtpHeaderParser rtp_parser(padding_packet, length); |
- RTPHeader rtp_header; |
- rtp_parser.Parse(&rtp_header); |
- |
+ padding_packet.ReserveExtension<TransmissionOffset>(); |
if (capture_time_ms > 0) { |
- UpdateTransmissionTimeOffset( |
- padding_packet, length, rtp_header, now_ms - capture_time_ms); |
- } |
- |
- UpdateAbsoluteSendTime(padding_packet, length, rtp_header, now_ms); |
- |
- PacketOptions options; |
- if (using_transport_seq) { |
- options.packet_id = |
- UpdateTransportSequenceNumber(padding_packet, length, rtp_header); |
- } |
- |
- if (using_transport_seq && transport_feedback_observer_) { |
- transport_feedback_observer_->AddPacket(options.packet_id, length, true); |
+ int64_t offset_rtp = (now_ms - capture_time_ms) * 90; |
+ padding_packet.SetExtension<TransmissionOffset>(offset_rtp); |
} |
- |
- if (!SendPacketToNetwork(padding_packet, length, options)) |
+ padding_packet.SetExtension<AbsoluteSendTime>(now_ms); |
+ padding_packet.ReserveExtension<TransportSequenceNumber>(); |
+ padding_packet.SetPadding(padding_bytes_in_packet, &random_); |
+ if (!SendPacketToNetwork(&padding_packet)) |
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; |
} |
-void RTPSender::SetStorePacketsStatus(bool enable, uint16_t number_to_store) { |
- packet_history_.SetStorePacketsStatus(enable, number_to_store); |
-} |
- |
-bool RTPSender::StorePackets() const { |
- return packet_history_.StorePackets(); |
+void RTPSender::SetStorePacketsSize(uint16_t number_to_store) { |
+ packet_history_.SetStoreSize(number_to_store); |
} |
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)) { |
- // Packet not found. |
+ RTC_DCHECK(network_thread_.CalledOnValidThread()); |
+ RtpPacketToSend* packet = |
+ packet_history_.GetPacket(packet_id, min_resend_time, true); |
+ if (!packet) |
return 0; |
- } |
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); |
+ paced_sender_->InsertPacket(RtpPacketSender::kNormalPriority, |
+ packet->Ssrc(), packet->SequenceNumber(), |
+ packet->capture_time_ms(), |
+ packet->payload_size(), true); |
- return length; |
+ return packet->size(); |
} |
int rtx = kRtxOff; |
{ |
rtc::CritScope lock(&send_critsect_); |
rtx = rtx_; |
} |
- if (!PrepareAndSendPacket(data_buffer, length, capture_time_ms, |
- (rtx & kRtxRetransmitted) > 0, true)) { |
+ if (!PrepareAndSendPacket(packet, (rtx & kRtxRetransmitted) > 0, true)) { |
return -1; |
} |
- return static_cast<int32_t>(length); |
+ return static_cast<int32_t>(packet->size()); |
} |
-bool RTPSender::SendPacketToNetwork(const uint8_t* packet, |
- size_t size, |
- const PacketOptions& options) { |
+bool RTPSender::SendPacketToNetwork(RtpPacketToSend* packet) { |
+ RTC_DCHECK(network_thread_.CalledOnValidThread()); |
+ { |
+ rtc::CritScope lock(&send_critsect_); |
+ last_packet_marker_bit_ = packet->Marker(); |
+ last_capture_time_ms_sent_ = packet->capture_time_ms(); |
+ } |
+ |
+ PacketOptions options; |
+ |
+ bool using_transport_seq = |
+ transport_sequence_number_allocator_ && |
+ rtp_manager_.IsRegistered<TransportSequenceNumber>(); |
+ if (using_transport_seq) { |
+ options.packet_id = UpdateTransportSequenceNumber(packet); |
+ |
+ if (transport_feedback_observer_) { |
+ transport_feedback_observer_->AddPacket(options.packet_id, packet->size(), |
+ true); |
+ } |
+ } |
+ |
int bytes_sent = -1; |
if (transport_) { |
- bytes_sent = transport_->SendRtp(packet, size, options) |
- ? static_cast<int>(size) |
- : -1; |
+ if (transport_->SendRtp(packet->data(), packet->size(), options)) { |
+ bytes_sent = static_cast<int>(packet->size()); |
+ } |
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"; |
@@ -870,16 +895,9 @@ void RTPSender::UpdateNACKBitRate(uint32_t bytes, int64_t now) { |
bool RTPSender::TimeToSendPacket(uint16_t sequence_number, |
int64_t capture_time_ms, |
bool retransmission) { |
- 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)) { |
+ RTC_DCHECK(network_thread_.CalledOnValidThread()); |
+ auto packet = packet_history_.GetPacket(sequence_number, 0, retransmission); |
+ if (!packet) { |
// Packet cannot be found. Allow sending to continue. |
return true; |
} |
@@ -891,72 +909,54 @@ bool RTPSender::TimeToSendPacket(uint16_t sequence_number, |
rtc::CritScope lock(&send_critsect_); |
rtx = rtx_; |
} |
- return PrepareAndSendPacket(data_buffer, |
- length, |
- capture_time_ms, |
- retransmission && (rtx & kRtxRetransmitted) > 0, |
- retransmission); |
+ return PrepareAndSendPacket( |
+ packet, retransmission && (rtx & kRtxRetransmitted) > 0, retransmission); |
} |
-bool RTPSender::PrepareAndSendPacket(uint8_t* buffer, |
- size_t length, |
- int64_t capture_time_ms, |
+bool RTPSender::PrepareAndSendPacket(RtpPacketToSend* packet, |
bool send_over_rtx, |
bool is_retransmit) { |
- uint8_t* buffer_to_send_ptr = buffer; |
+ RtpPacketToSend* packet_to_send = packet; |
- 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); |
+ packet->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) { |
- BuildRtxPacket(buffer, &length, data_buffer_rtx); |
- buffer_to_send_ptr = data_buffer_rtx; |
+ packet_rtx = BuildRtxPacket(*packet); |
+ 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); |
- |
- // TODO(sprang): Potentially too much overhead in IsRegistered()? |
- bool using_transport_seq = rtp_header_extension_map_.IsRegistered( |
- kRtpExtensionTransportSequenceNumber) && |
- transport_sequence_number_allocator_; |
- |
- PacketOptions options; |
- if (using_transport_seq) { |
- options.packet_id = |
- UpdateTransportSequenceNumber(buffer_to_send_ptr, length, rtp_header); |
- } |
+ int64_t diff_rtp = (now_ms - packet->capture_time_ms()) * 90; |
+ packet_to_send->SetExtension<TransmissionOffset>(diff_rtp); |
+ packet_to_send->SetExtension<AbsoluteSendTime>(now_ms); |
- if (using_transport_seq && transport_feedback_observer_) { |
- transport_feedback_observer_->AddPacket(options.packet_id, length, true); |
- } |
- |
- bool ret = SendPacketToNetwork(buffer_to_send_ptr, length, options); |
+ bool ret = SendPacketToNetwork(packet_to_send); |
+ // Update original packet even in case of retransmit. |
+ packet->set_send_time_ms(clock_->TimeInMilliseconds()); |
if (ret) { |
rtc::CritScope lock(&send_critsect_); |
media_has_been_sent_ = true; |
} |
- UpdateRtpStats(buffer_to_send_ptr, length, rtp_header, send_over_rtx, |
- is_retransmit); |
+ UpdateRtpStats(*packet_to_send, send_over_rtx, is_retransmit); |
return ret; |
} |
-void RTPSender::UpdateRtpStats(const uint8_t* buffer, |
- size_t packet_length, |
- const RTPHeader& header, |
+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(); |
+} |
+ |
+void RTPSender::UpdateRtpStats(const RtpPacketToSend& packet, |
bool is_rtx, |
bool is_retransmit) { |
StreamDataCounters* counters; |
@@ -970,26 +970,25 @@ void RTPSender::UpdateRtpStats(const uint8_t* buffer, |
counters = &rtp_stats_; |
} |
- total_bitrate_sent_.Update(packet_length); |
+ total_bitrate_sent_.Update(packet.size()); |
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); |
+ CountPacket(&counters->retransmitted, packet); |
} |
- counters->transmitted.AddPacket(packet_length, header); |
+ CountPacket(&counters->transmitted, packet); |
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; |
} |
@@ -997,9 +996,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) { |
@@ -1007,22 +1005,19 @@ size_t RTPSender::TimeToSendPadding(size_t bytes) { |
return 0; |
size_t bytes_sent = TrySendRedundantPayloads(bytes); |
if (bytes_sent < bytes) |
- bytes_sent += SendPadData(bytes - bytes_sent, false, 0, 0); |
+ bytes_sent += |
+ SendPadData(bytes - bytes_sent, false, 0, last_capture_time_ms_sent_); |
return bytes_sent; |
} |
-// TODO(pwestin): send in the RtpHeaderParser to avoid parsing it again. |
-int32_t RTPSender::SendToNetwork(uint8_t* buffer, |
+int32_t RTPSender::SendToNetwork(std::unique_ptr<RtpPacketToSend> packet_ptr, |
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; |
- RtpUtility::RtpHeaderParser rtp_parser(buffer, length); |
- |
- RTPHeader rtp_header; |
- rtp_parser.Parse(&rtp_header); |
+ RTC_DCHECK(packet_ptr); |
+ // Real payload_length might be less than PayloadSize() because of RED/FEC. |
+ RTC_DCHECK_GE(packet_ptr->payload_size(), payload_length); |
int64_t now_ms = clock_->TimeInMilliseconds(); |
@@ -1030,31 +1025,25 @@ int32_t RTPSender::SendToNetwork(uint8_t* buffer, |
// 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); |
+ uint32_t rtp_offset = (now_ms - capture_time_ms) * 90; |
+ packet_ptr->SetExtension<TransmissionOffset>(rtp_offset); |
} |
- UpdateAbsoluteSendTime(buffer, length, rtp_header, now_ms); |
+ packet_ptr->SetExtension<AbsoluteSendTime>(now_ms); |
+ packet_ptr->set_capture_time_ms(capture_time_ms); |
// Used for NACK and to spread out the transmission of packets. |
- if (packet_history_.PutRTPPacket(buffer, length, capture_time_ms, storage) != |
- 0) { |
- return -1; |
- } |
+ RtpPacketToSend* packet = packet_history_.PutRtpPacket(&packet_ptr, storage); |
if (paced_sender_) { |
- // 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, |
+ paced_sender_->InsertPacket(priority, packet->Ssrc(), |
+ packet->SequenceNumber(), capture_time_ms, |
payload_length, false); |
- if (last_capture_time_ms_sent_ == 0 || |
- corrected_time_ms > last_capture_time_ms_sent_) { |
- last_capture_time_ms_sent_ = corrected_time_ms; |
+ if (capture_time_ms > last_capture_time_ms_sent_) { |
+ last_capture_time_ms_sent_ = capture_time_ms; |
TRACE_EVENT_ASYNC_BEGIN1(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"), |
- "PacedSend", corrected_time_ms, |
- "capture_time_ms", corrected_time_ms); |
+ "PacedSend", capture_time_ms, "capture_time_ms", |
+ capture_time_ms); |
} |
return 0; |
} |
@@ -1062,26 +1051,11 @@ int32_t RTPSender::SendToNetwork(uint8_t* buffer, |
UpdateDelayStatistics(capture_time_ms, now_ms); |
} |
- // TODO(sprang): Potentially too much overhead in IsRegistered()? |
- bool using_transport_seq = rtp_header_extension_map_.IsRegistered( |
- kRtpExtensionTransportSequenceNumber) && |
- transport_sequence_number_allocator_; |
- |
- PacketOptions options; |
- if (using_transport_seq) { |
- options.packet_id = |
- UpdateTransportSequenceNumber(buffer, length, rtp_header); |
- if (transport_feedback_observer_) { |
- transport_feedback_observer_->AddPacket(options.packet_id, length, true); |
- } |
- } |
- |
- bool sent = SendPacketToNetwork(buffer, length, options); |
- |
+ bool sent = SendPacketToNetwork(packet); |
// 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); |
+ packet->set_send_time_ms(clock_->TimeInMilliseconds()); |
if (!sent) |
return -1; |
@@ -1090,7 +1064,7 @@ int32_t RTPSender::SendToNetwork(uint8_t* buffer, |
rtc::CritScope lock(&send_critsect_); |
media_has_been_sent_ = true; |
} |
- UpdateRtpStats(buffer, length, rtp_header, false, false); |
+ UpdateRtpStats(*packet, false, false); |
return 0; |
} |
@@ -1583,56 +1557,12 @@ 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; |
- 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)); |
-} |
- |
uint16_t RTPSender::UpdateTransportSequenceNumber( |
- uint8_t* rtp_packet, |
- size_t rtp_packet_length, |
- const RTPHeader& rtp_header) const { |
- size_t offset; |
+ RtpPacketToSend* packet) const { |
rtc::CritScope lock(&send_critsect_); |
- switch (VerifyExtension(kRtpExtensionTransportSequenceNumber, rtp_packet, |
- rtp_packet_length, rtp_header, |
- kTransportSequenceNumberLength, &offset)) { |
- case ExtensionStatus::kNotRegistered: |
- return 0; |
- case ExtensionStatus::kError: |
- LOG(LS_WARNING) << "Failed to update transport sequence number"; |
- return 0; |
- case ExtensionStatus::kOk: |
- break; |
- default: |
- RTC_NOTREACHED(); |
- } |
- |
uint16_t seq = transport_sequence_number_allocator_->AllocateSequenceNumber(); |
- BuildTransportSequenceNumberExtension(rtp_packet + offset, seq); |
+ RTC_CHECK(packet->SetExtension<TransportSequenceNumber>(seq)); |
return seq; |
} |
@@ -1808,49 +1738,35 @@ int32_t RTPSender::SetFecParameters( |
return 0; |
} |
-void RTPSender::BuildRtxPacket(uint8_t* buffer, size_t* length, |
- uint8_t* buffer_rtx) { |
- rtc::CritScope lock(&send_critsect_); |
- uint8_t* data_buffer_rtx = buffer_rtx; |
- // Add RTX header. |
- RtpUtility::RtpHeaderParser rtp_parser( |
- reinterpret_cast<const uint8_t*>(buffer), *length); |
- |
- RTPHeader rtp_header; |
- rtp_parser.Parse(&rtp_header); |
- |
- // 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_); |
+std::unique_ptr<RtpPacketToSend> RTPSender::BuildRtxPacket( |
+ const RtpPacketToSend& packet) { |
+ std::unique_ptr<RtpPacketToSend> packet_rtx = CreatePacket(); |
+ // Copy original RTP header. |
+ packet_rtx->CopyHeader(packet); |
+ { |
+ rtc::CritScope lock(&send_critsect_); |
+ // Replace payload type, if a specific type is set for RTX. |
+ auto kv = rtx_payload_type_map_.find(packet.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()) |
+ packet_rtx->SetPayloadType(kv->second); |
+ |
+ // Replace sequence number. |
+ packet_rtx->SetSequenceNumber(sequence_number_rtx_++); |
+ packet_rtx->SetSsrc(ssrc_rtx_); |
+ } |
+ uint8_t* data = packet_rtx->AllocatePayload(packet.payload_size() + 2); |
// 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(data, packet.SequenceNumber()); |
// Add original payload data. |
- memcpy(ptr, buffer + rtp_header.headerLength, |
- *length - rtp_header.headerLength); |
- *length += 2; |
+ memcpy(&data[2], packet.payload(), packet.payload_size()); |
+ return packet_rtx; |
} |
void RTPSender::RegisterRtpStatisticsCallback( |