Chromium Code Reviews| 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..9635e92bb85061b00a6f23d97b3a83240e915d27 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" |
| @@ -288,7 +289,7 @@ int32_t RTPSender::DeregisterRtpHeaderExtension(RTPExtensionType type) { |
| return rtp_header_extension_map_.Deregister(type); |
| } |
| -size_t RTPSender::RtpHeaderExtensionTotalLength() const { |
| +size_t RTPSender::RtpHeaderExtensionMaxLength() const { |
| rtc::CritScope lock(&send_critsect_); |
| return rtp_header_extension_map_.GetTotalLengthInBytes(); |
| } |
| @@ -386,11 +387,11 @@ size_t RTPSender::MaxDataPayloadLength() const { |
| rtx = rtx_; |
| } |
| if (audio_configured_) { |
| - return max_payload_length_ - RTPHeaderLength(); |
| + return max_payload_length_ - RtpHeaderMaxLength(); |
| } else { |
| - return max_payload_length_ - RTPHeaderLength() // RTP overhead. |
| - - video_->FECPacketOverhead() // FEC/ULP/RED overhead. |
| - - ((rtx) ? 2 : 0); // RTX overhead. |
| + return max_payload_length_ - RtpHeaderMaxLength() // RTP overhead. |
| + - video_->FECPacketOverhead() // FEC/ULP/RED overhead. |
| + - ((rtx) ? 2 : 0); // RTX overhead. |
| } |
| } |
| @@ -491,10 +492,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 +526,14 @@ 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); |
| + } |
| + |
| + 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 +828,11 @@ void RTPSender::OnReceivedNACK(const std::list<uint16_t>& nack_sequence_numbers, |
| } |
| } |
| +void RTPSender::OnReceivedRtcpReceiverReport( |
| + const ReportBlockList& report_blocks) { |
| + playout_delay_oracle_.OnReceivedRtcpReceiverReport(report_blocks); |
| +} |
| + |
| bool RTPSender::ProcessNACKBitRate(uint32_t now) { |
| uint32_t num = 0; |
| size_t byte_count = 0; |
| @@ -1139,11 +1151,19 @@ void RTPSender::ProcessBitrate() { |
| video_->ProcessBitrate(); |
| } |
| -size_t RTPSender::RTPHeaderLength() const { |
| +size_t RTPSender::RtpHeaderCurrentLength() 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 += RtpHeaderExtensionCurrentLength(); |
| + return rtp_header_length; |
| +} |
| + |
| +size_t RTPSender::RtpHeaderMaxLength() const { |
| + rtc::CritScope lock(&send_critsect_); |
| + size_t rtp_header_length = kRtpHeaderLength; |
| + rtp_header_length += sizeof(uint32_t) * csrcs_.size(); |
| + rtp_header_length += RtpHeaderExtensionMaxLength(); |
| return rtp_header_length; |
| } |
| @@ -1270,6 +1290,13 @@ uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer, |
| block_length = BuildTransportSequenceNumberExtension( |
| extension_data, transport_sequence_number_); |
| break; |
| + case kRtpExtensionPlayoutDelay: |
| + if (playout_delay_oracle_.send_playout_delay()) { |
| + block_length = BuildPlayoutDelayExtension( |
| + extension_data, playout_delay_oracle_.min_playout_delay_ms(), |
| + playout_delay_oracle_.max_playout_delay_ms()); |
| + } |
| + break; |
| default: |
| assert(false); |
| } |
| @@ -1294,6 +1321,69 @@ uint16_t RTPSender::BuildRTPHeaderExtension(uint8_t* data_buffer, |
| return kHeaderLength + total_block_length; |
| } |
| +size_t RTPSender::RtpHeaderExtensionCurrentLength() const { |
|
danilchap
2016/06/02 12:12:34
this function sums size of all extensions, includi
Irfan
2016/06/02 18:15:53
I did not realize TotalLength was already taking i
|
| + if (rtp_header_extension_map_.Size() <= 0) |
| + return 0; |
| + |
| + int header_length = 0; |
| + uint8_t id; |
| + |
| + RTPExtensionType type = rtp_header_extension_map_.First(); |
| + while (type != kRtpExtensionNone) { |
| + switch (type) { |
| + case kRtpExtensionTransmissionTimeOffset: |
| + if (rtp_header_extension_map_.GetId(kRtpExtensionTransmissionTimeOffset, |
|
Stefan
2016/06/02 08:07:09
Would have been nice with a method which simply ch
danilchap
2016/06/02 12:12:34
rtp_header_extension_map_ has method IsRegistered
Irfan
2016/06/02 18:15:53
This is now removed in favour of just treating pla
|
| + &id) == 0) { |
| + header_length += kTransmissionTimeOffsetLength; |
| + } |
| + break; |
| + case kRtpExtensionAudioLevel: |
| + if (rtp_header_extension_map_.GetId(kRtpExtensionAudioLevel, &id) == |
| + 0) { |
| + header_length += kAudioLevelLength; |
| + } |
| + break; |
| + case kRtpExtensionAbsoluteSendTime: |
| + if (rtp_header_extension_map_.GetId(kRtpExtensionAbsoluteSendTime, |
| + &id) == 0) { |
| + header_length += kAbsoluteSendTimeLength; |
| + } |
| + break; |
| + case kRtpExtensionVideoRotation: |
| + if (rtp_header_extension_map_.GetId(kRtpExtensionVideoRotation, &id) == |
|
danilchap
2016/06/02 12:12:34
this means video rotation extension would be count
Irfan
2016/06/02 18:15:53
see above
|
| + 0) { |
| + header_length += kVideoRotationLength; |
| + } |
| + break; |
| + case kRtpExtensionTransportSequenceNumber: |
| + if (rtp_header_extension_map_.GetId( |
| + kRtpExtensionTransportSequenceNumber, &id) == 0) { |
| + header_length += kTransportSequenceNumberLength; |
| + } |
| + break; |
| + case kRtpExtensionPlayoutDelay: |
| + if (playout_delay_oracle_.send_playout_delay()) { |
| + if (rtp_header_extension_map_.GetId(kRtpExtensionPlayoutDelay, &id) == |
| + 0) { |
| + header_length += kPlayoutDelayLength; |
| + } |
| + } |
| + break; |
| + default: |
|
danilchap
2016/06/02 12:12:34
do not use default, this way compiler would warn w
Irfan
2016/06/02 18:15:52
removed
|
| + assert(false); |
| + } |
| + type = rtp_header_extension_map_.Next(type); |
| + } |
| + if (header_length == 0) |
| + return 0; |
| + // Add padding to fill a 32 bit block. |
| + size_t padding_bytes = RtpUtility::Word32Align(header_length) - header_length; |
|
danilchap
2016/06/02 12:12:34
this three lines could be replaced with header_len
Irfan
2016/06/02 18:15:53
removed
|
| + if (padding_bytes > 0) |
| + header_length += padding_bytes; |
| + |
| + return header_length + kRtpOneByteHeaderLength; |
| +} |
| + |
| uint8_t RTPSender::BuildTransmissionTimeOffsetExtension( |
| uint8_t* data_buffer) const { |
| // From RFC 5450: Transmission Time Offsets in RTP Streams. |
| @@ -1445,6 +1535,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, |