Make RTCP report interval configurable
Bug: webrtc:8789 Change-Id: I79c9132123c946b030ed79c647b4329e81d6e6ae Reviewed-on: https://webrtc-review.googlesource.com/43201 Reviewed-by: Stefan Holmer <stefan@webrtc.org> Commit-Queue: Stefan Holmer <stefan@webrtc.org> Cr-Commit-Position: refs/heads/master@{#21837}
This commit is contained in:
@ -71,6 +71,7 @@ std::string VideoSendStream::Config::ToString() const {
|
|||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
ss << "{encoder_settings: " << encoder_settings.ToString();
|
ss << "{encoder_settings: " << encoder_settings.ToString();
|
||||||
ss << ", rtp: " << rtp.ToString();
|
ss << ", rtp: " << rtp.ToString();
|
||||||
|
ss << ", rtcp: " << rtcp.ToString();
|
||||||
ss << ", pre_encode_callback: "
|
ss << ", pre_encode_callback: "
|
||||||
<< (pre_encode_callback ? "(VideoSinkInterface)" : "nullptr");
|
<< (pre_encode_callback ? "(VideoSinkInterface)" : "nullptr");
|
||||||
ss << ", post_encode_callback: "
|
ss << ", post_encode_callback: "
|
||||||
@ -159,4 +160,16 @@ std::string VideoSendStream::Config::Rtp::Rtx::ToString() const {
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VideoSendStream::Config::Rtcp::Rtcp() = default;
|
||||||
|
VideoSendStream::Config::Rtcp::Rtcp(const Rtcp&) = default;
|
||||||
|
VideoSendStream::Config::Rtcp::~Rtcp() = default;
|
||||||
|
|
||||||
|
std::string VideoSendStream::Config::Rtcp::ToString() const {
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << "{video_report_interval_ms: " << video_report_interval_ms;
|
||||||
|
ss << ", audio_report_interval_ms: " << audio_report_interval_ms;
|
||||||
|
ss << '}';
|
||||||
|
return ss.str();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -201,6 +201,18 @@ class VideoSendStream {
|
|||||||
std::string c_name;
|
std::string c_name;
|
||||||
} rtp;
|
} rtp;
|
||||||
|
|
||||||
|
struct Rtcp {
|
||||||
|
Rtcp();
|
||||||
|
Rtcp(const Rtcp&);
|
||||||
|
~Rtcp();
|
||||||
|
std::string ToString() const;
|
||||||
|
|
||||||
|
// Time interval between RTCP report for video
|
||||||
|
int64_t video_report_interval_ms = 1000;
|
||||||
|
// Time interval between RTCP report for audio
|
||||||
|
int64_t audio_report_interval_ms = 5000;
|
||||||
|
} rtcp;
|
||||||
|
|
||||||
// Transport for outgoing packets.
|
// Transport for outgoing packets.
|
||||||
Transport* send_transport = nullptr;
|
Transport* send_transport = nullptr;
|
||||||
|
|
||||||
|
@ -94,6 +94,7 @@ class RtpRtcp : public Module, public RtcpFeedbackSenderInterface {
|
|||||||
RateLimiter* retransmission_rate_limiter = nullptr;
|
RateLimiter* retransmission_rate_limiter = nullptr;
|
||||||
OverheadObserver* overhead_observer = nullptr;
|
OverheadObserver* overhead_observer = nullptr;
|
||||||
RtpKeepAliveConfig keepalive_config;
|
RtpKeepAliveConfig keepalive_config;
|
||||||
|
RtcpIntervalConfig rtcp_interval_config;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
RTC_DISALLOW_COPY_AND_ASSIGN(Configuration);
|
RTC_DISALLOW_COPY_AND_ASSIGN(Configuration);
|
||||||
|
@ -41,6 +41,15 @@ const int kBogusRtpRateForAudioRtcp = 8000;
|
|||||||
// Minimum RTP header size in bytes.
|
// Minimum RTP header size in bytes.
|
||||||
const uint8_t kRtpHeaderSize = 12;
|
const uint8_t kRtpHeaderSize = 12;
|
||||||
|
|
||||||
|
struct RtcpIntervalConfig final {
|
||||||
|
RtcpIntervalConfig() = default;
|
||||||
|
RtcpIntervalConfig(int64_t video_interval_ms, int64_t audio_interval_ms)
|
||||||
|
: video_interval_ms(video_interval_ms),
|
||||||
|
audio_interval_ms(audio_interval_ms) {}
|
||||||
|
int64_t video_interval_ms = 1000;
|
||||||
|
int64_t audio_interval_ms = 5000;
|
||||||
|
};
|
||||||
|
|
||||||
struct AudioPayload {
|
struct AudioPayload {
|
||||||
SdpAudioFormat format;
|
SdpAudioFormat format;
|
||||||
uint32_t rate;
|
uint32_t rate;
|
||||||
|
@ -52,6 +52,8 @@ using rtcp::ReportBlock;
|
|||||||
// The number of RTCP time intervals needed to trigger a timeout.
|
// The number of RTCP time intervals needed to trigger a timeout.
|
||||||
const int kRrTimeoutIntervals = 3;
|
const int kRrTimeoutIntervals = 3;
|
||||||
|
|
||||||
|
const int64_t kTmmbrTimeoutIntervalMs = 5 * 5000;
|
||||||
|
|
||||||
const int64_t kMaxWarningLogIntervalMs = 10000;
|
const int64_t kMaxWarningLogIntervalMs = 10000;
|
||||||
const int64_t kRtcpMinFrameLengthMs = 17;
|
const int64_t kRtcpMinFrameLengthMs = 17;
|
||||||
|
|
||||||
@ -567,8 +569,7 @@ bool RTCPReceiver::UpdateTmmbrTimers() {
|
|||||||
rtc::CritScope lock(&rtcp_receiver_lock_);
|
rtc::CritScope lock(&rtcp_receiver_lock_);
|
||||||
|
|
||||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||||
// Use audio define since we don't know what interval the remote peer use.
|
int64_t timeout_ms = now_ms - kTmmbrTimeoutIntervalMs;
|
||||||
int64_t timeout_ms = now_ms - 5 * RTCP_INTERVAL_AUDIO_MS;
|
|
||||||
|
|
||||||
if (oldest_tmmbr_info_ms_ >= timeout_ms)
|
if (oldest_tmmbr_info_ms_ >= timeout_ms)
|
||||||
return false;
|
return false;
|
||||||
@ -1032,8 +1033,7 @@ std::vector<rtcp::TmmbItem> RTCPReceiver::TmmbrReceived() {
|
|||||||
std::vector<rtcp::TmmbItem> candidates;
|
std::vector<rtcp::TmmbItem> candidates;
|
||||||
|
|
||||||
int64_t now_ms = clock_->TimeInMilliseconds();
|
int64_t now_ms = clock_->TimeInMilliseconds();
|
||||||
// Use audio define since we don't know what interval the remote peer use.
|
int64_t timeout_ms = now_ms - kTmmbrTimeoutIntervalMs;
|
||||||
int64_t timeout_ms = now_ms - 5 * RTCP_INTERVAL_AUDIO_MS;
|
|
||||||
|
|
||||||
for (auto& kv : tmmbr_infos_) {
|
for (auto& kv : tmmbr_infos_) {
|
||||||
for (auto it = kv.second.tmmbr.begin(); it != kv.second.tmmbr.end();) {
|
for (auto it = kv.second.tmmbr.begin(); it != kv.second.tmmbr.end();) {
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#include "rtc_base/checks.h"
|
#include "rtc_base/checks.h"
|
||||||
#include "rtc_base/constructormagic.h"
|
#include "rtc_base/constructormagic.h"
|
||||||
#include "rtc_base/logging.h"
|
#include "rtc_base/logging.h"
|
||||||
|
#include "rtc_base/numerics/safe_conversions.h"
|
||||||
#include "rtc_base/ptr_util.h"
|
#include "rtc_base/ptr_util.h"
|
||||||
#include "rtc_base/trace_event.h"
|
#include "rtc_base/trace_event.h"
|
||||||
|
|
||||||
@ -139,13 +140,15 @@ RTCPSender::RTCPSender(
|
|||||||
ReceiveStatisticsProvider* receive_statistics,
|
ReceiveStatisticsProvider* receive_statistics,
|
||||||
RtcpPacketTypeCounterObserver* packet_type_counter_observer,
|
RtcpPacketTypeCounterObserver* packet_type_counter_observer,
|
||||||
RtcEventLog* event_log,
|
RtcEventLog* event_log,
|
||||||
Transport* outgoing_transport)
|
Transport* outgoing_transport,
|
||||||
|
RtcpIntervalConfig interval_config)
|
||||||
: audio_(audio),
|
: audio_(audio),
|
||||||
clock_(clock),
|
clock_(clock),
|
||||||
random_(clock_->TimeInMicroseconds()),
|
random_(clock_->TimeInMicroseconds()),
|
||||||
method_(RtcpMode::kOff),
|
method_(RtcpMode::kOff),
|
||||||
event_log_(event_log),
|
event_log_(event_log),
|
||||||
transport_(outgoing_transport),
|
transport_(outgoing_transport),
|
||||||
|
interval_config_(interval_config),
|
||||||
using_nack_(false),
|
using_nack_(false),
|
||||||
sending_(false),
|
sending_(false),
|
||||||
next_time_to_send_rtcp_(0),
|
next_time_to_send_rtcp_(0),
|
||||||
@ -199,9 +202,9 @@ void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
|
|||||||
|
|
||||||
if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
|
if (method_ == RtcpMode::kOff && new_method != RtcpMode::kOff) {
|
||||||
// When switching on, reschedule the next packet
|
// When switching on, reschedule the next packet
|
||||||
next_time_to_send_rtcp_ =
|
int64_t interval_ms = audio_ ? interval_config_.audio_interval_ms
|
||||||
clock_->TimeInMilliseconds() +
|
: interval_config_.video_interval_ms;
|
||||||
(audio_ ? RTCP_INTERVAL_AUDIO_MS / 2 : RTCP_INTERVAL_VIDEO_MS / 2);
|
next_time_to_send_rtcp_ = clock_->TimeInMilliseconds() + (interval_ms / 2);
|
||||||
}
|
}
|
||||||
method_ = new_method;
|
method_ = new_method;
|
||||||
}
|
}
|
||||||
@ -343,11 +346,11 @@ int32_t RTCPSender::RemoveMixedCNAME(uint32_t SSRC) {
|
|||||||
|
|
||||||
bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
|
bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
|
||||||
/*
|
/*
|
||||||
For audio we use a fix 5 sec interval
|
For audio we use a configurable interval (default: 5 seconds)
|
||||||
|
|
||||||
For video we use 1 sec interval fo a BW smaller than 360 kbit/s,
|
For video we use a configurable interval (default: 1 second) for a BW
|
||||||
technicaly we break the max 5% RTCP BW for video below 10 kbit/s but
|
smaller than 360 kbit/s, technicaly we break the max 5% RTCP BW for
|
||||||
that should be extremely rare
|
video below 10 kbit/s but that should be extremely rare
|
||||||
|
|
||||||
|
|
||||||
From RFC 3550
|
From RFC 3550
|
||||||
@ -361,8 +364,8 @@ bool RTCPSender::TimeToSendRTCPReport(bool sendKeyframeBeforeRTP) const {
|
|||||||
is smaller than 5 seconds for bandwidths greater than 72 kb/s.
|
is smaller than 5 seconds for bandwidths greater than 72 kb/s.
|
||||||
|
|
||||||
If the participant has not yet sent an RTCP packet (the variable
|
If the participant has not yet sent an RTCP packet (the variable
|
||||||
initial is true), the constant Tmin is set to 2.5 seconds, else it
|
initial is true), the constant Tmin is set to half of the configured
|
||||||
is set to 5 seconds.
|
interval.
|
||||||
|
|
||||||
The interval between RTCP packets is varied randomly over the
|
The interval between RTCP packets is varied randomly over the
|
||||||
range [0.5,1.5] times the calculated interval to avoid unintended
|
range [0.5,1.5] times the calculated interval to avoid unintended
|
||||||
@ -793,7 +796,8 @@ void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// generate next time to send an RTCP report
|
// generate next time to send an RTCP report
|
||||||
uint32_t minIntervalMs = RTCP_INTERVAL_AUDIO_MS;
|
uint32_t minIntervalMs =
|
||||||
|
rtc::dchecked_cast<uint32_t>(interval_config_.audio_interval_ms);
|
||||||
|
|
||||||
if (!audio_) {
|
if (!audio_) {
|
||||||
if (sending_) {
|
if (sending_) {
|
||||||
@ -802,9 +806,13 @@ void RTCPSender::PrepareReport(const FeedbackState& feedback_state) {
|
|||||||
if (send_bitrate_kbit != 0)
|
if (send_bitrate_kbit != 0)
|
||||||
minIntervalMs = 360000 / send_bitrate_kbit;
|
minIntervalMs = 360000 / send_bitrate_kbit;
|
||||||
}
|
}
|
||||||
if (minIntervalMs > RTCP_INTERVAL_VIDEO_MS)
|
if (minIntervalMs >
|
||||||
minIntervalMs = RTCP_INTERVAL_VIDEO_MS;
|
rtc::dchecked_cast<uint32_t>(interval_config_.video_interval_ms)) {
|
||||||
|
minIntervalMs =
|
||||||
|
rtc::dchecked_cast<uint32_t>(interval_config_.video_interval_ms);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The interval between RTCP packets is varied randomly over the
|
// The interval between RTCP packets is varied randomly over the
|
||||||
// range [1/2,3/2] times the calculated interval.
|
// range [1/2,3/2] times the calculated interval.
|
||||||
uint32_t timeToNext =
|
uint32_t timeToNext =
|
||||||
@ -962,4 +970,12 @@ bool RTCPSender::SendFeedbackPacket(const rtcp::TransportFeedback& packet) {
|
|||||||
return packet.Build(max_packet_size, callback) && !send_failure;
|
return packet.Build(max_packet_size, callback) && !send_failure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t RTCPSender::RtcpAudioReportInverval() const {
|
||||||
|
return interval_config_.audio_interval_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t RTCPSender::RtcpVideoReportInverval() const {
|
||||||
|
return interval_config_.video_interval_ms;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -80,7 +80,8 @@ class RTCPSender {
|
|||||||
ReceiveStatisticsProvider* receive_statistics,
|
ReceiveStatisticsProvider* receive_statistics,
|
||||||
RtcpPacketTypeCounterObserver* packet_type_counter_observer,
|
RtcpPacketTypeCounterObserver* packet_type_counter_observer,
|
||||||
RtcEventLog* event_log,
|
RtcEventLog* event_log,
|
||||||
Transport* outgoing_transport);
|
Transport* outgoing_transport,
|
||||||
|
RtcpIntervalConfig interval_config);
|
||||||
virtual ~RTCPSender();
|
virtual ~RTCPSender();
|
||||||
|
|
||||||
RtcpMode Status() const;
|
RtcpMode Status() const;
|
||||||
@ -148,6 +149,9 @@ class RTCPSender {
|
|||||||
void SetVideoBitrateAllocation(const BitrateAllocation& bitrate);
|
void SetVideoBitrateAllocation(const BitrateAllocation& bitrate);
|
||||||
bool SendFeedbackPacket(const rtcp::TransportFeedback& packet);
|
bool SendFeedbackPacket(const rtcp::TransportFeedback& packet);
|
||||||
|
|
||||||
|
int64_t RtcpAudioReportInverval() const;
|
||||||
|
int64_t RtcpVideoReportInverval() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class RtcpContext;
|
class RtcpContext;
|
||||||
|
|
||||||
@ -194,6 +198,8 @@ class RTCPSender {
|
|||||||
RtcEventLog* const event_log_;
|
RtcEventLog* const event_log_;
|
||||||
Transport* const transport_;
|
Transport* const transport_;
|
||||||
|
|
||||||
|
const RtcpIntervalConfig interval_config_;
|
||||||
|
|
||||||
rtc::CriticalSection critical_section_rtcp_sender_;
|
rtc::CriticalSection critical_section_rtcp_sender_;
|
||||||
bool using_nack_ RTC_GUARDED_BY(critical_section_rtcp_sender_);
|
bool using_nack_ RTC_GUARDED_BY(critical_section_rtcp_sender_);
|
||||||
bool sending_ RTC_GUARDED_BY(critical_section_rtcp_sender_);
|
bool sending_ RTC_GUARDED_BY(critical_section_rtcp_sender_);
|
||||||
|
@ -239,7 +239,8 @@ class RtcpSenderTest : public ::testing::Test {
|
|||||||
|
|
||||||
rtp_rtcp_impl_.reset(new ModuleRtpRtcpImpl(configuration));
|
rtp_rtcp_impl_.reset(new ModuleRtpRtcpImpl(configuration));
|
||||||
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
||||||
nullptr, nullptr, &test_transport_));
|
nullptr, nullptr, &test_transport_,
|
||||||
|
configuration.rtcp_interval_config));
|
||||||
rtcp_sender_->SetSSRC(kSenderSsrc);
|
rtcp_sender_->SetSSRC(kSenderSsrc);
|
||||||
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
||||||
rtcp_sender_->SetTimestampOffset(kStartRtpTimestamp);
|
rtcp_sender_->SetTimestampOffset(kStartRtpTimestamp);
|
||||||
@ -309,7 +310,8 @@ TEST_F(RtcpSenderTest, SendSr) {
|
|||||||
|
|
||||||
TEST_F(RtcpSenderTest, DoNotSendSrBeforeRtp) {
|
TEST_F(RtcpSenderTest, DoNotSendSrBeforeRtp) {
|
||||||
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
||||||
nullptr, nullptr, &test_transport_));
|
nullptr, nullptr, &test_transport_,
|
||||||
|
RtcpIntervalConfig{}));
|
||||||
rtcp_sender_->SetSSRC(kSenderSsrc);
|
rtcp_sender_->SetSSRC(kSenderSsrc);
|
||||||
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
||||||
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
||||||
@ -327,7 +329,8 @@ TEST_F(RtcpSenderTest, DoNotSendSrBeforeRtp) {
|
|||||||
|
|
||||||
TEST_F(RtcpSenderTest, DoNotSendCompundBeforeRtp) {
|
TEST_F(RtcpSenderTest, DoNotSendCompundBeforeRtp) {
|
||||||
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
||||||
nullptr, nullptr, &test_transport_));
|
nullptr, nullptr, &test_transport_,
|
||||||
|
RtcpIntervalConfig{}));
|
||||||
rtcp_sender_->SetSSRC(kSenderSsrc);
|
rtcp_sender_->SetSSRC(kSenderSsrc);
|
||||||
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
||||||
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kCompound);
|
||||||
@ -654,7 +657,8 @@ TEST_F(RtcpSenderTest, TestNoXrRrtrSentIfNotEnabled) {
|
|||||||
TEST_F(RtcpSenderTest, TestRegisterRtcpPacketTypeObserver) {
|
TEST_F(RtcpSenderTest, TestRegisterRtcpPacketTypeObserver) {
|
||||||
RtcpPacketTypeCounterObserverImpl observer;
|
RtcpPacketTypeCounterObserverImpl observer;
|
||||||
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
||||||
&observer, nullptr, &test_transport_));
|
&observer, nullptr, &test_transport_,
|
||||||
|
RtcpIntervalConfig{}));
|
||||||
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
||||||
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
rtcp_sender_->SetRTCPStatus(RtcpMode::kReducedSize);
|
||||||
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpPli));
|
EXPECT_EQ(0, rtcp_sender_->SendRTCP(feedback_state(), kRtcpPli));
|
||||||
@ -775,7 +779,8 @@ TEST_F(RtcpSenderTest, ByeMustBeLast) {
|
|||||||
|
|
||||||
// Re-configure rtcp_sender_ with mock_transport_
|
// Re-configure rtcp_sender_ with mock_transport_
|
||||||
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
rtcp_sender_.reset(new RTCPSender(false, &clock_, receive_statistics_.get(),
|
||||||
nullptr, nullptr, &mock_transport));
|
nullptr, nullptr, &mock_transport,
|
||||||
|
RtcpIntervalConfig{}));
|
||||||
rtcp_sender_->SetSSRC(kSenderSsrc);
|
rtcp_sender_->SetSSRC(kSenderSsrc);
|
||||||
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
rtcp_sender_->SetRemoteSSRC(kRemoteSsrc);
|
||||||
rtcp_sender_->SetTimestampOffset(kStartRtpTimestamp);
|
rtcp_sender_->SetTimestampOffset(kStartRtpTimestamp);
|
||||||
|
@ -19,8 +19,6 @@ enum { kSendSideNackListSizeSanity = 20000 };
|
|||||||
enum { kDefaultMaxReorderingThreshold = 50 }; // In sequence numbers.
|
enum { kDefaultMaxReorderingThreshold = 50 }; // In sequence numbers.
|
||||||
enum { kRtcpMaxNackFields = 253 };
|
enum { kRtcpMaxNackFields = 253 };
|
||||||
|
|
||||||
enum { RTCP_INTERVAL_VIDEO_MS = 1000 };
|
|
||||||
enum { RTCP_INTERVAL_AUDIO_MS = 5000 };
|
|
||||||
enum { RTCP_SEND_BEFORE_KEY_FRAME_MS = 100 };
|
enum { RTCP_SEND_BEFORE_KEY_FRAME_MS = 100 };
|
||||||
enum { RTCP_MAX_REPORT_BLOCKS = 31 }; // RFC 3550 page 37
|
enum { RTCP_MAX_REPORT_BLOCKS = 31 }; // RFC 3550 page 37
|
||||||
enum {
|
enum {
|
||||||
|
@ -84,7 +84,8 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
|
|||||||
configuration.receive_statistics,
|
configuration.receive_statistics,
|
||||||
configuration.rtcp_packet_type_counter_observer,
|
configuration.rtcp_packet_type_counter_observer,
|
||||||
configuration.event_log,
|
configuration.event_log,
|
||||||
configuration.outgoing_transport),
|
configuration.outgoing_transport,
|
||||||
|
configuration.rtcp_interval_config),
|
||||||
rtcp_receiver_(configuration.clock,
|
rtcp_receiver_(configuration.clock,
|
||||||
configuration.receiver_only,
|
configuration.receiver_only,
|
||||||
configuration.rtcp_packet_type_counter_observer,
|
configuration.rtcp_packet_type_counter_observer,
|
||||||
@ -884,9 +885,9 @@ std::vector<rtcp::TmmbItem> ModuleRtpRtcpImpl::BoundingSet(bool* tmmbr_owner) {
|
|||||||
|
|
||||||
int64_t ModuleRtpRtcpImpl::RtcpReportInterval() {
|
int64_t ModuleRtpRtcpImpl::RtcpReportInterval() {
|
||||||
if (audio_)
|
if (audio_)
|
||||||
return RTCP_INTERVAL_AUDIO_MS;
|
return rtcp_sender_.RtcpAudioReportInverval();
|
||||||
else
|
else
|
||||||
return RTCP_INTERVAL_VIDEO_MS;
|
return rtcp_sender_.RtcpVideoReportInverval();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleRtpRtcpImpl::SetRtcpReceiverSsrcs(uint32_t main_ssrc) {
|
void ModuleRtpRtcpImpl::SetRtcpReceiverSsrcs(uint32_t main_ssrc) {
|
||||||
|
@ -57,6 +57,7 @@ class SendTransport : public Transport,
|
|||||||
clock_(nullptr),
|
clock_(nullptr),
|
||||||
delay_ms_(0),
|
delay_ms_(0),
|
||||||
rtp_packets_sent_(0),
|
rtp_packets_sent_(0),
|
||||||
|
rtcp_packets_sent_(0),
|
||||||
keepalive_payload_type_(0),
|
keepalive_payload_type_(0),
|
||||||
num_keepalive_sent_(0) {}
|
num_keepalive_sent_(0) {}
|
||||||
|
|
||||||
@ -89,6 +90,7 @@ class SendTransport : public Transport,
|
|||||||
}
|
}
|
||||||
EXPECT_TRUE(receiver_);
|
EXPECT_TRUE(receiver_);
|
||||||
receiver_->IncomingRtcpPacket(data, len);
|
receiver_->IncomingRtcpPacket(data, len);
|
||||||
|
++rtcp_packets_sent_;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
int32_t OnReceivedPayloadData(const uint8_t* payload_data,
|
int32_t OnReceivedPayloadData(const uint8_t* payload_data,
|
||||||
@ -100,10 +102,12 @@ class SendTransport : public Transport,
|
|||||||
keepalive_payload_type_ = payload_type;
|
keepalive_payload_type_ = payload_type;
|
||||||
}
|
}
|
||||||
size_t NumKeepaliveSent() { return num_keepalive_sent_; }
|
size_t NumKeepaliveSent() { return num_keepalive_sent_; }
|
||||||
|
size_t NumRtcpSent() { return rtcp_packets_sent_; }
|
||||||
ModuleRtpRtcpImpl* receiver_;
|
ModuleRtpRtcpImpl* receiver_;
|
||||||
SimulatedClock* clock_;
|
SimulatedClock* clock_;
|
||||||
int64_t delay_ms_;
|
int64_t delay_ms_;
|
||||||
int rtp_packets_sent_;
|
int rtp_packets_sent_;
|
||||||
|
size_t rtcp_packets_sent_;
|
||||||
RTPHeader last_rtp_header_;
|
RTPHeader last_rtp_header_;
|
||||||
std::vector<uint16_t> last_nack_list_;
|
std::vector<uint16_t> last_nack_list_;
|
||||||
uint8_t keepalive_payload_type_;
|
uint8_t keepalive_payload_type_;
|
||||||
@ -130,6 +134,7 @@ class RtpRtcpModule : public RtcpPacketTypeCounterObserver {
|
|||||||
uint32_t remote_ssrc_;
|
uint32_t remote_ssrc_;
|
||||||
RateLimiter retransmission_rate_limiter_;
|
RateLimiter retransmission_rate_limiter_;
|
||||||
RtpKeepAliveConfig keepalive_config_;
|
RtpKeepAliveConfig keepalive_config_;
|
||||||
|
RtcpIntervalConfig rtcp_interval_config_;
|
||||||
|
|
||||||
void SetRemoteSsrc(uint32_t ssrc) {
|
void SetRemoteSsrc(uint32_t ssrc) {
|
||||||
remote_ssrc_ = ssrc;
|
remote_ssrc_ = ssrc;
|
||||||
@ -166,6 +171,10 @@ class RtpRtcpModule : public RtcpPacketTypeCounterObserver {
|
|||||||
CreateModuleImpl();
|
CreateModuleImpl();
|
||||||
transport_.SetKeepalivePayloadType(config.payload_type);
|
transport_.SetKeepalivePayloadType(config.payload_type);
|
||||||
}
|
}
|
||||||
|
void SetRtcpIntervalConfigAndReset(const RtcpIntervalConfig& config) {
|
||||||
|
rtcp_interval_config_ = config;
|
||||||
|
CreateModuleImpl();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void CreateModuleImpl() {
|
void CreateModuleImpl() {
|
||||||
@ -178,6 +187,7 @@ class RtpRtcpModule : public RtcpPacketTypeCounterObserver {
|
|||||||
config.rtt_stats = &rtt_stats_;
|
config.rtt_stats = &rtt_stats_;
|
||||||
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
|
||||||
config.keepalive_config = keepalive_config_;
|
config.keepalive_config = keepalive_config_;
|
||||||
|
config.rtcp_interval_config = rtcp_interval_config_;
|
||||||
|
|
||||||
impl_.reset(new ModuleRtpRtcpImpl(config));
|
impl_.reset(new ModuleRtpRtcpImpl(config));
|
||||||
impl_->SetRTCPStatus(RtcpMode::kCompound);
|
impl_->SetRTCPStatus(RtcpMode::kCompound);
|
||||||
@ -643,4 +653,56 @@ TEST_F(RtpRtcpImplTest, SendsKeepaliveAfterTimout) {
|
|||||||
sender_.impl_->Process();
|
sender_.impl_->Process();
|
||||||
EXPECT_EQ(3U, sender_.transport_.NumKeepaliveSent());
|
EXPECT_EQ(3U, sender_.transport_.NumKeepaliveSent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(RtpRtcpImplTest, ConfigurableRtcpReportInterval) {
|
||||||
|
const int kVideoReportInterval = 3000;
|
||||||
|
|
||||||
|
RtcpIntervalConfig config;
|
||||||
|
config.video_interval_ms = kVideoReportInterval;
|
||||||
|
|
||||||
|
// Recreate sender impl with new configuration, and redo setup.
|
||||||
|
sender_.SetRtcpIntervalConfigAndReset(config);
|
||||||
|
SetUp();
|
||||||
|
|
||||||
|
SendFrame(&sender_, kBaseLayerTid);
|
||||||
|
|
||||||
|
// Initial state
|
||||||
|
sender_.impl_->Process();
|
||||||
|
EXPECT_EQ(sender_.RtcpSent().first_packet_time_ms, -1);
|
||||||
|
EXPECT_EQ(0u, sender_.transport_.NumRtcpSent());
|
||||||
|
|
||||||
|
// Move ahead to the last ms before a rtcp is expected, no action.
|
||||||
|
clock_.AdvanceTimeMilliseconds(kVideoReportInterval / 2 - 1);
|
||||||
|
sender_.impl_->Process();
|
||||||
|
EXPECT_EQ(sender_.RtcpSent().first_packet_time_ms, -1);
|
||||||
|
EXPECT_EQ(sender_.transport_.NumRtcpSent(), 0u);
|
||||||
|
|
||||||
|
// Move ahead to the first rtcp. Send RTCP.
|
||||||
|
clock_.AdvanceTimeMilliseconds(1);
|
||||||
|
sender_.impl_->Process();
|
||||||
|
EXPECT_GT(sender_.RtcpSent().first_packet_time_ms, -1);
|
||||||
|
EXPECT_EQ(sender_.transport_.NumRtcpSent(), 1u);
|
||||||
|
|
||||||
|
SendFrame(&sender_, kBaseLayerTid);
|
||||||
|
|
||||||
|
// Move ahead to the last possible second before second rtcp is expected.
|
||||||
|
clock_.AdvanceTimeMilliseconds(kVideoReportInterval * 1 / 2 - 1);
|
||||||
|
sender_.impl_->Process();
|
||||||
|
EXPECT_EQ(sender_.transport_.NumRtcpSent(), 1u);
|
||||||
|
|
||||||
|
// Move ahead into the range of second rtcp, the second rtcp may be sent.
|
||||||
|
clock_.AdvanceTimeMilliseconds(1);
|
||||||
|
sender_.impl_->Process();
|
||||||
|
EXPECT_GE(sender_.transport_.NumRtcpSent(), 1u);
|
||||||
|
|
||||||
|
clock_.AdvanceTimeMilliseconds(kVideoReportInterval / 2);
|
||||||
|
sender_.impl_->Process();
|
||||||
|
EXPECT_GE(sender_.transport_.NumRtcpSent(), 1u);
|
||||||
|
|
||||||
|
// Move out the range of second rtcp, the second rtcp must have been sent.
|
||||||
|
clock_.AdvanceTimeMilliseconds(kVideoReportInterval / 2);
|
||||||
|
sender_.impl_->Process();
|
||||||
|
EXPECT_EQ(sender_.transport_.NumRtcpSent(), 2u);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -63,7 +63,8 @@ std::vector<RtpRtcp*> CreateRtpRtcpModules(
|
|||||||
RateLimiter* retransmission_rate_limiter,
|
RateLimiter* retransmission_rate_limiter,
|
||||||
OverheadObserver* overhead_observer,
|
OverheadObserver* overhead_observer,
|
||||||
size_t num_modules,
|
size_t num_modules,
|
||||||
RtpKeepAliveConfig keepalive_config) {
|
RtpKeepAliveConfig keepalive_config,
|
||||||
|
RtcpIntervalConfig rtc_interval_config) {
|
||||||
RTC_DCHECK_GT(num_modules, 0);
|
RTC_DCHECK_GT(num_modules, 0);
|
||||||
RtpRtcp::Configuration configuration;
|
RtpRtcp::Configuration configuration;
|
||||||
configuration.audio = false;
|
configuration.audio = false;
|
||||||
@ -763,7 +764,9 @@ VideoSendStreamImpl::VideoSendStreamImpl(
|
|||||||
transport->send_side_cc()->GetRetransmissionRateLimiter(),
|
transport->send_side_cc()->GetRetransmissionRateLimiter(),
|
||||||
this,
|
this,
|
||||||
config_->rtp.ssrcs.size(),
|
config_->rtp.ssrcs.size(),
|
||||||
transport->keepalive_config())),
|
transport->keepalive_config(),
|
||||||
|
RtcpIntervalConfig{config_->rtcp.video_report_interval_ms,
|
||||||
|
config_->rtcp.audio_report_interval_ms})),
|
||||||
payload_router_(rtp_rtcp_modules_,
|
payload_router_(rtp_rtcp_modules_,
|
||||||
config_->rtp.ssrcs,
|
config_->rtp.ssrcs,
|
||||||
config_->encoder_settings.payload_type,
|
config_->encoder_settings.payload_type,
|
||||||
|
@ -798,7 +798,8 @@ void VideoSendStreamTest::TestNackRetransmission(
|
|||||||
uint16_t nack_sequence_number = header.sequenceNumber - 1;
|
uint16_t nack_sequence_number = header.sequenceNumber - 1;
|
||||||
nacked_sequence_number_ = nack_sequence_number;
|
nacked_sequence_number_ = nack_sequence_number;
|
||||||
RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), nullptr,
|
RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(), nullptr,
|
||||||
nullptr, nullptr, transport_adapter_.get());
|
nullptr, nullptr, transport_adapter_.get(),
|
||||||
|
RtcpIntervalConfig{});
|
||||||
|
|
||||||
rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
|
rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
|
||||||
rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
|
rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
|
||||||
@ -990,7 +991,7 @@ void VideoSendStreamTest::TestPacketFragmentationSize(VideoFormat format,
|
|||||||
static_cast<uint8_t>((255 * kLossPercent) / 100)); // Loss percent.
|
static_cast<uint8_t>((255 * kLossPercent) / 100)); // Loss percent.
|
||||||
RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
|
RTCPSender rtcp_sender(false, Clock::GetRealTimeClock(),
|
||||||
&lossy_receive_stats, nullptr, nullptr,
|
&lossy_receive_stats, nullptr, nullptr,
|
||||||
transport_adapter_.get());
|
transport_adapter_.get(), RtcpIntervalConfig{});
|
||||||
|
|
||||||
rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
|
rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
|
||||||
rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
|
rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
|
||||||
@ -1247,7 +1248,7 @@ TEST_F(VideoSendStreamTest, SuspendBelowMinBitrate) {
|
|||||||
FakeReceiveStatistics receive_stats(kVideoSendSsrcs[0],
|
FakeReceiveStatistics receive_stats(kVideoSendSsrcs[0],
|
||||||
last_sequence_number_, rtp_count_, 0);
|
last_sequence_number_, rtp_count_, 0);
|
||||||
RTCPSender rtcp_sender(false, clock_, &receive_stats, nullptr, nullptr,
|
RTCPSender rtcp_sender(false, clock_, &receive_stats, nullptr, nullptr,
|
||||||
transport_adapter_.get());
|
transport_adapter_.get(), RtcpIntervalConfig{});
|
||||||
|
|
||||||
rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
|
rtcp_sender.SetRTCPStatus(RtcpMode::kReducedSize);
|
||||||
rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
|
rtcp_sender.SetRemoteSSRC(kVideoSendSsrcs[0]);
|
||||||
|
Reference in New Issue
Block a user