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:
Jiawei Ou
2018-01-31 22:08:26 -08:00
committed by Commit Bot
parent addc380168
commit 3587b8302a
13 changed files with 160 additions and 33 deletions

View File

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

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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();) {

View File

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

View File

@ -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_);

View File

@ -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);

View File

@ -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 {

View File

@ -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) {

View File

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

View File

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

View File

@ -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]);