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