| 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(
|
|
|