| 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 e7306a11bd3f2ca56ffd5d733a7cb278607fc396..cec7e17e4b621fbe7984281633db41d0793e19df 100644
|
| --- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
|
| +++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc
|
| @@ -103,6 +103,8 @@ RTPSender::RTPSender(int32_t id,
|
| Transport* transport,
|
| RtpAudioFeedback* audio_feedback,
|
| PacedSender* paced_sender,
|
| + PacketRouter* packet_router,
|
| + SendTimeObserver* send_time_observer,
|
| BitrateStatisticsObserver* bitrate_callback,
|
| FrameCountObserver* frame_count_observer,
|
| SendSideDelayObserver* send_side_delay_observer)
|
| @@ -119,6 +121,8 @@ RTPSender::RTPSender(int32_t id,
|
| : nullptr),
|
| video_(audio ? nullptr : new RTPSenderVideo(clock, this)),
|
| paced_sender_(paced_sender),
|
| + packet_router_(packet_router),
|
| + send_time_observer_(send_time_observer),
|
| last_capture_time_ms_sent_(0),
|
| send_critsect_(CriticalSectionWrapper::CreateCriticalSection()),
|
| transport_(transport),
|
| @@ -603,6 +607,9 @@ size_t RTPSender::SendPadData(uint32_t timestamp,
|
| size_t bytes) {
|
| size_t padding_bytes_in_packet = 0;
|
| size_t bytes_sent = 0;
|
| + bool using_transport_seq = rtp_header_extension_map_.IsRegistered(
|
| + kRtpExtensionTransportSequenceNumber) &&
|
| + packet_router_;
|
| for (; bytes > 0; bytes -= padding_bytes_in_packet) {
|
| // Always send full padding packets.
|
| if (bytes < kMaxPaddingLength)
|
| @@ -659,8 +666,19 @@ size_t RTPSender::SendPadData(uint32_t timestamp,
|
| }
|
|
|
| UpdateAbsoluteSendTime(padding_packet, length, rtp_header, now_ms);
|
| +
|
| + uint16_t transport_seq = 0;
|
| + if (using_transport_seq) {
|
| + transport_seq =
|
| + UpdateTransportSequenceNumber(padding_packet, length, rtp_header);
|
| + }
|
| +
|
| if (!SendPacketToNetwork(padding_packet, length))
|
| break;
|
| +
|
| + if (using_transport_seq)
|
| + send_time_observer_->OnPacketSent(transport_seq, now_ms);
|
| +
|
| bytes_sent += padding_bytes_in_packet;
|
| UpdateRtpStats(padding_packet, length, rtp_header, over_rtx, false);
|
| }
|
| @@ -710,9 +728,11 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, int64_t min_resend_time) {
|
| CriticalSectionScoped lock(send_critsect_.get());
|
| rtx = rtx_;
|
| }
|
| - return PrepareAndSendPacket(data_buffer, length, capture_time_ms,
|
| - (rtx & kRtxRetransmitted) > 0, true) ?
|
| - static_cast<int32_t>(length) : -1;
|
| + if (!PrepareAndSendPacket(data_buffer, length, capture_time_ms,
|
| + (rtx & kRtxRetransmitted) > 0, true)) {
|
| + return -1;
|
| + }
|
| + return static_cast<int32_t>(length);
|
| }
|
|
|
| bool RTPSender::SendPacketToNetwork(const uint8_t *packet, size_t size) {
|
| @@ -897,11 +917,23 @@ bool RTPSender::PrepareAndSendPacket(uint8_t* buffer,
|
| UpdateTransmissionTimeOffset(buffer_to_send_ptr, length, rtp_header,
|
| diff_ms);
|
| UpdateAbsoluteSendTime(buffer_to_send_ptr, length, rtp_header, now_ms);
|
| +
|
| + uint16_t transport_seq = 0;
|
| + bool using_transport_seq = rtp_header_extension_map_.IsRegistered(
|
| + kRtpExtensionTransportSequenceNumber) &&
|
| + packet_router_;
|
| + if (using_transport_seq) {
|
| + transport_seq =
|
| + UpdateTransportSequenceNumber(buffer_to_send_ptr, length, rtp_header);
|
| + }
|
| +
|
| bool ret = SendPacketToNetwork(buffer_to_send_ptr, length);
|
| if (ret) {
|
| CriticalSectionScoped lock(send_critsect_.get());
|
| media_has_been_sent_ = true;
|
| }
|
| + if (using_transport_seq)
|
| + send_time_observer_->OnPacketSent(transport_seq, now_ms);
|
| UpdateRtpStats(buffer_to_send_ptr, length, rtp_header, send_over_rtx,
|
| is_retransmit);
|
| return ret;
|
| @@ -960,7 +992,8 @@ size_t RTPSender::TimeToSendPadding(size_t bytes) {
|
| return 0;
|
| {
|
| CriticalSectionScoped cs(send_critsect_.get());
|
| - if (!sending_media_) return 0;
|
| + if (!sending_media_)
|
| + return 0;
|
| }
|
| size_t bytes_sent = TrySendRedundantPayloads(bytes);
|
| if (bytes_sent < bytes)
|
| @@ -1212,7 +1245,8 @@ uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer,
|
| block_length = BuildVideoRotationExtension(extension_data);
|
| break;
|
| case kRtpExtensionTransportSequenceNumber:
|
| - block_length = BuildTransportSequenceNumberExtension(extension_data);
|
| + block_length = BuildTransportSequenceNumberExtension(
|
| + extension_data, transport_sequence_number_);
|
| break;
|
| default:
|
| assert(false);
|
| @@ -1365,7 +1399,8 @@ uint8_t RTPSender::BuildVideoRotationExtension(uint8_t* data_buffer) const {
|
| }
|
|
|
| uint8_t RTPSender::BuildTransportSequenceNumberExtension(
|
| - uint8_t* data_buffer) const {
|
| + 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
|
| // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
| @@ -1382,8 +1417,7 @@ uint8_t RTPSender::BuildTransportSequenceNumberExtension(
|
| size_t pos = 0;
|
| const uint8_t len = 1;
|
| data_buffer[pos++] = (id << 4) + len;
|
| - ByteWriter<uint16_t>::WriteBigEndian(data_buffer + pos,
|
| - transport_sequence_number_);
|
| + ByteWriter<uint16_t>::WriteBigEndian(data_buffer + pos, sequence_number);
|
| pos += 2;
|
| assert(pos == kTransportSequenceNumberLength);
|
| return kTransportSequenceNumberLength;
|
| @@ -1426,35 +1460,62 @@ bool RTPSender::FindHeaderExtensionPosition(RTPExtensionType type,
|
| return true;
|
| }
|
|
|
| -void RTPSender::UpdateTransmissionTimeOffset(uint8_t* rtp_packet,
|
| - size_t rtp_packet_length,
|
| - const RTPHeader& rtp_header,
|
| - int64_t time_diff_ms) const {
|
| - CriticalSectionScoped cs(send_critsect_.get());
|
| +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(kRtpExtensionTransmissionTimeOffset,
|
| - &id) != 0) {
|
| - // Not registered.
|
| - return;
|
| - }
|
| + if (rtp_header_extension_map_.GetId(extension_type, &id) != 0)
|
| + return ExtensionStatus::kNotRegistered;
|
|
|
| size_t block_pos = 0;
|
| - if (!FindHeaderExtensionPosition(kRtpExtensionTransmissionTimeOffset,
|
| - rtp_packet, rtp_packet_length, rtp_header,
|
| - &block_pos)) {
|
| - LOG(LS_WARNING) << "Failed to update transmission time offset.";
|
| - return;
|
| + if (!FindHeaderExtensionPosition(extension_type, rtp_packet,
|
| + rtp_packet_length, rtp_header, &block_pos))
|
| + return ExtensionStatus::kError;
|
| +
|
| + // Verify that header contains extension.
|
| + if (!((rtp_packet[kRtpHeaderLength + rtp_header.numCSRCs] == 0xBE) &&
|
| + (rtp_packet[kRtpHeaderLength + rtp_header.numCSRCs + 1] == 0xDE))) {
|
| + LOG(LS_WARNING)
|
| + << "Failed to update absolute send time, hdr extension not found.";
|
| + return ExtensionStatus::kError;
|
| }
|
|
|
| // Verify first byte in block.
|
| - const uint8_t first_block_byte = (id << 4) + 2;
|
| - if (rtp_packet[block_pos] != first_block_byte) {
|
| - LOG(LS_WARNING) << "Failed to update transmission time offset.";
|
| - return;
|
| + 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;
|
| +}
|
| +
|
| +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;
|
| + CriticalSectionScoped cs(send_critsect_.get());
|
| + 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 + block_pos + 1,
|
| + ByteWriter<int32_t, 3>::WriteBigEndian(rtp_packet + offset + 1,
|
| time_diff_ms * 90); // RTP timestamp.
|
| }
|
|
|
| @@ -1463,29 +1524,24 @@ bool RTPSender::UpdateAudioLevel(uint8_t* rtp_packet,
|
| const RTPHeader& rtp_header,
|
| bool is_voiced,
|
| uint8_t dBov) const {
|
| + size_t offset;
|
| CriticalSectionScoped cs(send_critsect_.get());
|
|
|
| - // Get id.
|
| - uint8_t id = 0;
|
| - if (rtp_header_extension_map_.GetId(kRtpExtensionAudioLevel, &id) != 0) {
|
| - // Not registered.
|
| - return false;
|
| - }
|
| -
|
| - size_t block_pos = 0;
|
| - if (!FindHeaderExtensionPosition(kRtpExtensionAudioLevel, rtp_packet,
|
| - rtp_packet_length, rtp_header, &block_pos)) {
|
| - LOG(LS_WARNING) << "Failed to update audio level.";
|
| - return false;
|
| + 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();
|
| }
|
|
|
| - // Verify first byte in block.
|
| - const uint8_t first_block_byte = (id << 4) + 0;
|
| - if (rtp_packet[block_pos] != first_block_byte) {
|
| - LOG(LS_WARNING) << "Failed to update audio level.";
|
| - return false;
|
| - }
|
| - rtp_packet[block_pos + 1] = (is_voiced ? 0x80 : 0x00) + (dBov & 0x7f);
|
| + rtp_packet[offset + 1] = (is_voiced ? 0x80 : 0x00) + (dBov & 0x7f);
|
| return true;
|
| }
|
|
|
| @@ -1493,37 +1549,24 @@ bool RTPSender::UpdateVideoRotation(uint8_t* rtp_packet,
|
| size_t rtp_packet_length,
|
| const RTPHeader& rtp_header,
|
| VideoRotation rotation) const {
|
| + size_t offset;
|
| CriticalSectionScoped cs(send_critsect_.get());
|
|
|
| - // Get id.
|
| - uint8_t id = 0;
|
| - if (rtp_header_extension_map_.GetId(kRtpExtensionVideoRotation, &id) != 0) {
|
| - // Not registered.
|
| - return false;
|
| - }
|
| -
|
| - size_t block_pos = 0;
|
| - if (!FindHeaderExtensionPosition(kRtpExtensionVideoRotation, rtp_packet,
|
| - rtp_packet_length, rtp_header, &block_pos)) {
|
| - LOG(LS_WARNING) << "Failed to update video rotation (CVO).";
|
| - return false;
|
| - }
|
| - // Get length until start of header extension block.
|
| - int extension_block_pos =
|
| - rtp_header_extension_map_.GetLengthUntilBlockStartInBytes(
|
| - kRtpExtensionVideoRotation);
|
| - if (extension_block_pos < 0) {
|
| - // The feature is not enabled.
|
| - return false;
|
| + 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();
|
| }
|
|
|
| - // Verify first byte in block.
|
| - const uint8_t first_block_byte = (id << 4) + 0;
|
| - if (rtp_packet[block_pos] != first_block_byte) {
|
| - LOG(LS_WARNING) << "Failed to update CVO.";
|
| - return false;
|
| - }
|
| - rtp_packet[block_pos + 1] = ConvertVideoRotationToCVOByte(rotation);
|
| + rtp_packet[offset + 1] = ConvertVideoRotationToCVOByte(rotation);
|
| return true;
|
| }
|
|
|
| @@ -1531,49 +1574,55 @@ void RTPSender::UpdateAbsoluteSendTime(uint8_t* rtp_packet,
|
| size_t rtp_packet_length,
|
| const RTPHeader& rtp_header,
|
| int64_t now_ms) const {
|
| + size_t offset;
|
| CriticalSectionScoped cs(send_critsect_.get());
|
|
|
| - // Get id.
|
| - uint8_t id = 0;
|
| - if (rtp_header_extension_map_.GetId(kRtpExtensionAbsoluteSendTime,
|
| - &id) != 0) {
|
| - // Not registered.
|
| - return;
|
| - }
|
| - // Get length until start of header extension block.
|
| - int extension_block_pos =
|
| - rtp_header_extension_map_.GetLengthUntilBlockStartInBytes(
|
| - kRtpExtensionAbsoluteSendTime);
|
| - if (extension_block_pos < 0) {
|
| - // The feature is not enabled.
|
| - return;
|
| - }
|
| - size_t block_pos =
|
| - kRtpHeaderLength + rtp_header.numCSRCs + extension_block_pos;
|
| - if (rtp_packet_length < block_pos + kAbsoluteSendTimeLength ||
|
| - rtp_header.headerLength < block_pos + kAbsoluteSendTimeLength) {
|
| - LOG(LS_WARNING) << "Failed to update absolute send time, invalid length.";
|
| - return;
|
| - }
|
| - // Verify that header contains extension.
|
| - if (!((rtp_packet[kRtpHeaderLength + rtp_header.numCSRCs] == 0xBE) &&
|
| - (rtp_packet[kRtpHeaderLength + rtp_header.numCSRCs + 1] == 0xDE))) {
|
| - LOG(LS_WARNING)
|
| - << "Failed to update absolute send time, hdr extension not found.";
|
| - return;
|
| - }
|
| - // Verify first byte in block.
|
| - const uint8_t first_block_byte = (id << 4) + 2;
|
| - if (rtp_packet[block_pos] != first_block_byte) {
|
| - LOG(LS_WARNING) << "Failed to update absolute send time.";
|
| - return;
|
| + 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 + block_pos + 1,
|
| + ByteWriter<uint32_t, 3>::WriteBigEndian(rtp_packet + offset + 1,
|
| ((now_ms << 18) / 1000) & 0x00ffffff);
|
| }
|
|
|
| +uint16_t RTPSender::UpdateTransportSequenceNumber(
|
| + uint8_t* rtp_packet,
|
| + size_t rtp_packet_length,
|
| + const RTPHeader& rtp_header) const {
|
| + size_t offset;
|
| + CriticalSectionScoped cs(send_critsect_.get());
|
| +
|
| + 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 = packet_router_->AllocateSequenceNumber();
|
| + BuildTransportSequenceNumberExtension(rtp_packet + offset, seq);
|
| + return seq;
|
| +}
|
| +
|
| void RTPSender::SetSendingStatus(bool enabled) {
|
| if (enabled) {
|
| uint32_t frequency_hz = SendPayloadFrequency();
|
|
|