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 016a8469cd6b3404d84d3c909351051dbb71c277..fe0e49f79e6a2df6194a307095fe8c40beb49062 100644 |
--- a/webrtc/modules/rtp_rtcp/source/rtp_sender.cc |
+++ b/webrtc/modules/rtp_rtcp/source/rtp_sender.cc |
@@ -22,6 +22,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/playout_delay_oracle.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" |
@@ -137,12 +138,13 @@ RTPSender::RTPSender( |
transmission_time_offset_(0), |
absolute_send_time_(0), |
rotation_(kVideoRotation_0), |
- cvo_mode_(kCVONone), |
+ video_rotation_active_(false), |
transport_sequence_number_(0), |
// NACK. |
nack_byte_count_times_(), |
nack_byte_count_(), |
nack_bitrate_(clock, bitrates_.retransmit_bitrate_observer()), |
+ playout_delay_active_(false), |
packet_history_(clock), |
// Statistics |
rtp_stats_callback_(NULL), |
@@ -271,11 +273,23 @@ int32_t RTPSender::SetTransportSequenceNumber(uint16_t sequence_number) { |
int32_t RTPSender::RegisterRtpHeaderExtension(RTPExtensionType type, |
uint8_t id) { |
rtc::CritScope lock(&send_critsect_); |
- if (type == kRtpExtensionVideoRotation) { |
- cvo_mode_ = kCVOInactive; |
- return rtp_header_extension_map_.RegisterInactive(type, id); |
+ switch (type) { |
+ case kRtpExtensionVideoRotation: |
+ video_rotation_active_ = false; |
+ return rtp_header_extension_map_.RegisterInactive(type, id); |
+ case kRtpExtensionPlayoutDelay: |
+ playout_delay_active_ = false; |
+ return rtp_header_extension_map_.RegisterInactive(type, id); |
+ case kRtpExtensionTransmissionTimeOffset: |
+ case kRtpExtensionAbsoluteSendTime: |
+ case kRtpExtensionAudioLevel: |
+ case kRtpExtensionTransportSequenceNumber: |
+ return rtp_header_extension_map_.Register(type, id); |
+ case kRtpExtensionNone: |
+ LOG(LS_ERROR) << "Invalid RTP extension type for registration"; |
+ return -1; |
} |
- return rtp_header_extension_map_.Register(type, id); |
+ return -1; |
} |
bool RTPSender::IsRtpHeaderExtensionRegistered(RTPExtensionType type) { |
@@ -288,7 +302,7 @@ int32_t RTPSender::DeregisterRtpHeaderExtension(RTPExtensionType type) { |
return rtp_header_extension_map_.Deregister(type); |
} |
-size_t RTPSender::RtpHeaderExtensionTotalLength() const { |
+size_t RTPSender::RtpHeaderExtensionLength() const { |
rtc::CritScope lock(&send_critsect_); |
return rtp_header_extension_map_.GetTotalLengthInBytes(); |
} |
@@ -386,9 +400,9 @@ size_t RTPSender::MaxDataPayloadLength() const { |
rtx = rtx_; |
} |
if (audio_configured_) { |
- return max_payload_length_ - RTPHeaderLength(); |
+ return max_payload_length_ - RtpHeaderLength(); |
} else { |
- return max_payload_length_ - RTPHeaderLength() // RTP overhead. |
+ return max_payload_length_ - RtpHeaderLength() // RTP overhead. |
- video_->FECPacketOverhead() // FEC/ULP/RED overhead. |
- ((rtx) ? 2 : 0); // RTX overhead. |
} |
@@ -472,14 +486,14 @@ int32_t RTPSender::CheckPayloadType(int8_t payload_type, |
return 0; |
} |
-RTPSenderInterface::CVOMode RTPSender::ActivateCVORtpHeaderExtension() { |
- if (cvo_mode_ == kCVOInactive) { |
+bool RTPSender::ActivateCVORtpHeaderExtension() { |
+ if (!video_rotation_active_) { |
rtc::CritScope lock(&send_critsect_); |
if (rtp_header_extension_map_.SetActive(kRtpExtensionVideoRotation, true)) { |
- cvo_mode_ = kCVOActivated; |
+ video_rotation_active_ = true; |
} |
} |
- return cvo_mode_; |
+ return video_rotation_active_; |
} |
int32_t RTPSender::SendOutgoingData(FrameType frame_type, |
@@ -491,10 +505,12 @@ int32_t RTPSender::SendOutgoingData(FrameType frame_type, |
const RTPFragmentationHeader* fragmentation, |
const RTPVideoHeader* rtp_hdr) { |
uint32_t ssrc; |
+ uint16_t sequence_number; |
{ |
// Drop this packet if we're not sending media packets. |
rtc::CritScope lock(&send_critsect_); |
ssrc = ssrc_; |
+ sequence_number = sequence_number_; |
if (!sending_media_) { |
return 0; |
} |
@@ -523,10 +539,25 @@ int32_t RTPSender::SendOutgoingData(FrameType frame_type, |
if (frame_type == kEmptyFrame) |
return 0; |
- ret_val = |
- video_->SendVideo(video_type, frame_type, payload_type, |
- capture_timestamp, capture_time_ms, payload_data, |
- payload_size, fragmentation, rtp_hdr); |
+ if (rtp_hdr) { |
+ playout_delay_oracle_.UpdateRequest(ssrc, rtp_hdr->playout_delay, |
+ sequence_number); |
+ } |
+ |
+ // Update the active/inactive status of playout delay extension based |
+ // on what the oracle indicates. |
+ { |
+ rtc::CritScope lock(&send_critsect_); |
+ if (playout_delay_active_ != playout_delay_oracle_.send_playout_delay()) { |
+ playout_delay_active_ = playout_delay_oracle_.send_playout_delay(); |
+ rtp_header_extension_map_.SetActive(kRtpExtensionPlayoutDelay, |
+ playout_delay_active_); |
+ } |
+ } |
+ |
+ ret_val = video_->SendVideo( |
+ video_type, frame_type, payload_type, capture_timestamp, |
+ capture_time_ms, payload_data, payload_size, fragmentation, rtp_hdr); |
} |
rtc::CritScope cs(&statistics_crit_); |
@@ -833,6 +864,11 @@ void RTPSender::OnReceivedNACK(const std::list<uint16_t>& nack_sequence_numbers, |
} |
} |
+void RTPSender::OnReceivedRtcpReportBlocks( |
+ const ReportBlockList& report_blocks) { |
+ playout_delay_oracle_.OnReceivedRtcpReportBlocks(report_blocks); |
+} |
+ |
bool RTPSender::ProcessNACKBitRate(uint32_t now) { |
uint32_t num = 0; |
size_t byte_count = 0; |
@@ -1152,11 +1188,11 @@ void RTPSender::ProcessBitrate() { |
video_->ProcessBitrate(); |
} |
-size_t RTPSender::RTPHeaderLength() const { |
+size_t RTPSender::RtpHeaderLength() const { |
rtc::CritScope lock(&send_critsect_); |
size_t rtp_header_length = kRtpHeaderLength; |
rtp_header_length += sizeof(uint32_t) * csrcs_.size(); |
- rtp_header_length += RtpHeaderExtensionTotalLength(); |
+ rtp_header_length += RtpHeaderExtensionLength(); |
return rtp_header_length; |
} |
@@ -1283,6 +1319,11 @@ uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer, |
block_length = BuildTransportSequenceNumberExtension( |
extension_data, transport_sequence_number_); |
break; |
+ case kRtpExtensionPlayoutDelay: |
+ block_length = BuildPlayoutDelayExtension( |
+ extension_data, playout_delay_oracle_.min_playout_delay_ms(), |
+ playout_delay_oracle_.max_playout_delay_ms()); |
+ break; |
default: |
assert(false); |
} |
@@ -1458,6 +1499,37 @@ uint8_t RTPSender::BuildTransportSequenceNumberExtension( |
return kTransportSequenceNumberLength; |
} |
+uint8_t RTPSender::BuildPlayoutDelayExtension( |
+ uint8_t* data_buffer, |
+ uint16_t min_playout_delay_ms, |
+ uint16_t max_playout_delay_ms) const { |
+ RTC_DCHECK_LE(min_playout_delay_ms, kPlayoutDelayMaxMs); |
+ RTC_DCHECK_LE(max_playout_delay_ms, kPlayoutDelayMaxMs); |
+ RTC_DCHECK_LE(min_playout_delay_ms, max_playout_delay_ms); |
+ // 0 1 2 3 |
+ // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+ // | ID | len=2 | MIN delay | MAX delay | |
+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |
+ uint8_t id; |
+ if (rtp_header_extension_map_.GetId(kRtpExtensionPlayoutDelay, &id) != 0) { |
+ // Not registered. |
+ return 0; |
+ } |
+ size_t pos = 0; |
+ const uint8_t len = 2; |
+ // Convert MS to value to be sent on extension header. |
+ uint16_t min_playout = min_playout_delay_ms / kPlayoutDelayGranularityMs; |
+ uint16_t max_playout = max_playout_delay_ms / kPlayoutDelayGranularityMs; |
+ |
+ data_buffer[pos++] = (id << 4) + len; |
+ data_buffer[pos++] = min_playout >> 4; |
+ data_buffer[pos++] = ((min_playout & 0xf) << 4) | (max_playout >> 8); |
+ data_buffer[pos++] = max_playout & 0xff; |
+ assert(pos == kPlayoutDelayLength); |
+ return kPlayoutDelayLength; |
+} |
+ |
bool RTPSender::FindHeaderExtensionPosition(RTPExtensionType type, |
const uint8_t* rtp_packet, |
size_t rtp_packet_length, |