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 cda776bf22b2cdcef3510233fe94acda11286aa4..c0dbd03954e3672dd038982937042ba163bf9c96 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" |
@@ -523,10 +524,13 @@ 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); |
+ playout_delay_oracle_.Update(ssrc, rtp_hdr->min_playout_delay_ms, |
+ rtp_hdr->max_playout_delay_ms, |
+ sequence_number_); |
danilchap
2016/05/24 13:28:24
sequence_number_ here is 16 bit, i.e. wrapped, but
sprang_webrtc
2016/05/24 14:46:08
Or use SequenceNumberUnwrapper from module_common_
Irfan
2016/05/25 09:32:53
good catch. done.
|
+ |
+ 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_); |
@@ -821,6 +825,12 @@ void RTPSender::OnReceivedNACK(const std::list<uint16_t>& nack_sequence_numbers, |
} |
} |
+void RTPSender::OnReceivedRtcpReceiverReport( |
+ const ReportBlockList& report_blocks) { |
+ rtc::CritScope lock(&send_critsect_); |
+ playout_delay_oracle_.OnReceivedRtcpReceiverReport(report_blocks); |
+} |
+ |
bool RTPSender::ProcessNACKBitRate(uint32_t now) { |
uint32_t num = 0; |
size_t byte_count = 0; |
@@ -1034,6 +1044,12 @@ int32_t RTPSender::SendToNetwork(uint8_t* buffer, |
UpdateAbsoluteSendTime(buffer, length, rtp_header, now_ms); |
+ if (playout_delay_oracle_.ShouldIncludePlayoutDelayExtension(rtp_header.ssrc)) |
+ UpdatePlayoutDelayLimits( |
+ buffer, length, rtp_header, |
+ playout_delay_oracle_.MinPlayoutDelayMs(rtp_header.ssrc), |
+ playout_delay_oracle_.MaxPlayoutDelayMs(rtp_header.ssrc)); |
+ |
// Used for NACK and to spread out the transmission of packets. |
if (packet_history_.PutRTPPacket(buffer, length, capture_time_ms, storage) != |
0) { |
@@ -1191,7 +1207,7 @@ size_t RTPSender::CreateRtpHeader(uint8_t* header, |
} |
uint16_t len = |
- BuildRTPHeaderExtension(header + rtp_header_length, marker_bit); |
+ BuildRTPHeaderExtension(ssrc, header + rtp_header_length, marker_bit); |
if (len > 0) { |
header[0] |= 0x10; // Set extension bit. |
rtp_header_length += len; |
@@ -1225,7 +1241,8 @@ int32_t RTPSender::BuildRTPheader(uint8_t* data_buffer, |
timestamp_, sequence_number, csrcs_); |
} |
-uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer, |
+uint16_t RTPSender::BuildRTPHeaderExtension(uint32_t ssrc, |
+ uint8_t* data_buffer, |
bool marker_bit) const { |
if (rtp_header_extension_map_.Size() <= 0) { |
return 0; |
@@ -1270,6 +1287,13 @@ uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer, |
block_length = BuildTransportSequenceNumberExtension( |
extension_data, transport_sequence_number_); |
break; |
+ case kRtpExtensionPlayoutDelay: |
+ if (playout_delay_oracle_.ShouldIncludePlayoutDelayExtension(ssrc)) { |
+ block_length = BuildPlayoutDelayExtension( |
+ extension_data, playout_delay_oracle_.MinPlayoutDelayMs(ssrc), |
+ playout_delay_oracle_.MaxPlayoutDelayMs(ssrc)); |
+ } |
+ break; |
default: |
assert(false); |
} |
@@ -1445,6 +1469,36 @@ 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); |
+ // 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, |
@@ -1638,6 +1692,34 @@ bool RTPSender::UpdateTransportSequenceNumber( |
return true; |
} |
+void RTPSender::UpdatePlayoutDelayLimits(uint8_t* rtp_packet, |
+ size_t rtp_packet_length, |
+ const RTPHeader& rtp_header, |
+ uint16_t min_playout_delay_ms, |
+ uint16_t max_playout_delay_ms) const { |
+ size_t offset; |
+ rtc::CritScope lock(&send_critsect_); |
+ |
+ switch (VerifyExtension(kRtpExtensionPlayoutDelay, rtp_packet, |
+ rtp_packet_length, rtp_header, kPlayoutDelayLength, |
+ &offset)) { |
+ case ExtensionStatus::kNotRegistered: |
+ return; |
+ case ExtensionStatus::kError: |
+ LOG(LS_WARNING) << "Failed to update playout delay limits"; |
+ return; |
+ case ExtensionStatus::kOk: |
+ break; |
+ default: |
+ RTC_NOTREACHED(); |
+ } |
+ |
+ int length = BuildPlayoutDelayExtension( |
+ rtp_packet + offset, min_playout_delay_ms, max_playout_delay_ms); |
+ RTC_DCHECK(length == kPlayoutDelayLength); |
danilchap
2016/05/24 13:28:24
RTC_DCHECK_EQ
Irfan
2016/05/25 09:32:53
replaced with assert
danilchap
2016/05/25 19:08:48
Acknowledged.
|
+ return; |
+} |
+ |
bool RTPSender::AllocateTransportSequenceNumber(int* packet_id) const { |
if (!transport_sequence_number_allocator_) |
return false; |