Reland of actor NACK bitrate allocation (patchset #1 id:1 of https://codereview.webrtc.org/2131913003/ )

Reason for revert:
Upstream fixes in place, should be OK now.

Original issue's description:
> Revert of Refactor NACK bitrate allocation (patchset #16 id:300001 of https://codereview.webrtc.org/2061423003/ )
>
> Reason for revert:
> Breaks upstream code.
>
> Original issue's description:
> > Refactor NACK bitrate allocation
> >
> > Nack bitrate allocation should not be done on a per-rtp-module basis,
> > but rather shared bitrate pool per call. This CL moves allocation to the
> > pacer and cleans up a bunch if bitrate stats handling.
> >
> > BUG=
> > R=danilchap@webrtc.org, stefan@webrtc.org, tommi@webrtc.org
> >
> > Committed: 5fc59e810b
>
> TBR=tommi@webrtc.org,danilchap@webrtc.org,stefan@webrtc.org
> # Skipping CQ checks because original CL landed less than 1 days ago.
> NOPRESUBMIT=true
> NOTREECHECKS=true
> NOTRY=true
> BUG=
>
> Committed: https://crrev.com/e5dd44101eca485f5ad12e5f7ce6f6b0d204116b
> Cr-Commit-Position: refs/heads/master@{#13417}

TBR=tommi@webrtc.org,danilchap@webrtc.org,stefan@webrtc.org
# Not skipping CQ checks because original CL landed more than 1 days ago.
BUG=

Review-Url: https://codereview.webrtc.org/2146013002
Cr-Commit-Position: refs/heads/master@{#13465}
This commit is contained in:
sprang
2016-07-13 09:11:28 -07:00
committed by Commit bot
parent ac09501381
commit cd349d9743
40 changed files with 603 additions and 620 deletions

View File

@ -1,121 +0,0 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
namespace webrtc {
Bitrate::Bitrate(Clock* clock, Observer* observer)
: clock_(clock),
packet_rate_(0),
bitrate_(0),
bitrate_next_idx_(0),
time_last_rate_update_(0),
bytes_count_(0),
packet_count_(0),
observer_(observer) {
memset(packet_rate_array_, 0, sizeof(packet_rate_array_));
memset(bitrate_diff_ms_, 0, sizeof(bitrate_diff_ms_));
memset(bitrate_array_, 0, sizeof(bitrate_array_));
}
Bitrate::~Bitrate() {}
void Bitrate::Update(const size_t bytes) {
rtc::CritScope cs(&crit_);
bytes_count_ += bytes;
packet_count_++;
}
uint32_t Bitrate::PacketRate() const {
rtc::CritScope cs(&crit_);
return packet_rate_;
}
uint32_t Bitrate::BitrateLast() const {
rtc::CritScope cs(&crit_);
return bitrate_;
}
uint32_t Bitrate::BitrateNow() const {
rtc::CritScope cs(&crit_);
int64_t now = clock_->TimeInMilliseconds();
int64_t diff_ms = now - time_last_rate_update_;
if (diff_ms > 10000) { // 10 seconds.
// Too high difference, ignore.
return bitrate_;
}
int64_t bits_since_last_rate_update = 8 * bytes_count_ * 1000;
// We have to consider the time when the measurement was done:
// ((bits/sec * sec) + (bits)) / sec.
int64_t bitrate = (static_cast<uint64_t>(bitrate_) * 1000 +
bits_since_last_rate_update) / (1000 + diff_ms);
return static_cast<uint32_t>(bitrate);
}
int64_t Bitrate::time_last_rate_update() const {
rtc::CritScope cs(&crit_);
return time_last_rate_update_;
}
// Triggered by timer.
void Bitrate::Process() {
BitrateStatistics stats;
{
rtc::CritScope cs(&crit_);
int64_t now = clock_->CurrentNtpInMilliseconds();
int64_t diff_ms = now - time_last_rate_update_;
if (diff_ms < 100) {
// Not enough data, wait...
return;
}
if (diff_ms > 10000) { // 10 seconds.
// Too high difference, ignore.
time_last_rate_update_ = now;
bytes_count_ = 0;
packet_count_ = 0;
return;
}
packet_rate_array_[bitrate_next_idx_] = (packet_count_ * 1000) / diff_ms;
bitrate_array_[bitrate_next_idx_] = 8 * ((bytes_count_ * 1000) / diff_ms);
bitrate_diff_ms_[bitrate_next_idx_] = diff_ms;
bitrate_next_idx_++;
if (bitrate_next_idx_ >= 10) {
bitrate_next_idx_ = 0;
}
int64_t sum_diffMS = 0;
int64_t sum_bitrateMS = 0;
int64_t sum_packetrateMS = 0;
for (int i = 0; i < 10; i++) {
sum_diffMS += bitrate_diff_ms_[i];
sum_bitrateMS += bitrate_array_[i] * bitrate_diff_ms_[i];
sum_packetrateMS += packet_rate_array_[i] * bitrate_diff_ms_[i];
}
time_last_rate_update_ = now;
bytes_count_ = 0;
packet_count_ = 0;
packet_rate_ = static_cast<uint32_t>(sum_packetrateMS / sum_diffMS);
bitrate_ = static_cast<uint32_t>(sum_bitrateMS / sum_diffMS);
stats.bitrate_bps = bitrate_;
stats.packet_rate = packet_rate_;
stats.timestamp_ms = now;
}
if (observer_)
observer_->BitrateUpdated(stats);
}
} // namespace webrtc

View File

@ -1,77 +0,0 @@
/*
* Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license
* that can be found in the LICENSE file in the root of the source
* tree. An additional intellectual property rights grant can be found
* in the file PATENTS. All contributing project authors may
* be found in the AUTHORS file in the root of the source tree.
*/
#ifndef WEBRTC_MODULES_RTP_RTCP_SOURCE_BITRATE_H_
#define WEBRTC_MODULES_RTP_RTCP_SOURCE_BITRATE_H_
#include <stdio.h>
#include <list>
#include "webrtc/base/criticalsection.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h"
#include "webrtc/typedefs.h"
namespace webrtc {
class Clock;
class Bitrate {
public:
class Observer;
Bitrate(Clock* clock, Observer* observer);
virtual ~Bitrate();
// Calculates rates.
void Process();
// Update with a packet.
void Update(const size_t bytes);
// Packet rate last second, updated roughly every 100 ms.
uint32_t PacketRate() const;
// Bitrate last second, updated roughly every 100 ms.
uint32_t BitrateLast() const;
// Bitrate last second, updated now.
uint32_t BitrateNow() const;
int64_t time_last_rate_update() const;
class Observer {
public:
Observer() {}
virtual ~Observer() {}
virtual void BitrateUpdated(const BitrateStatistics& stats) = 0;
};
protected:
Clock* clock_;
private:
rtc::CriticalSection crit_;
uint32_t packet_rate_;
uint32_t bitrate_;
uint8_t bitrate_next_idx_;
int64_t packet_rate_array_[10];
int64_t bitrate_array_[10];
int64_t bitrate_diff_ms_[10];
int64_t time_last_rate_update_;
size_t bytes_count_;
uint32_t packet_count_;
Observer* const observer_;
};
} // namespace webrtc
#endif // WEBRTC_MODULES_RTP_RTCP_SOURCE_BITRATE_H_

View File

@ -15,6 +15,7 @@
#include <set>
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/rate_limiter.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
@ -34,6 +35,7 @@ const int kTestNumberOfRtxPackets = 149;
const int kNumFrames = 30;
const int kPayloadType = 123;
const int kRtxPayloadType = 98;
const int64_t kMaxRttMs = 1000;
class VerifyingRtxReceiver : public NullRtpData {
public:
@ -168,11 +170,12 @@ class RtpRtcpRtxNackTest : public ::testing::Test {
protected:
RtpRtcpRtxNackTest()
: rtp_payload_registry_(RTPPayloadStrategy::CreateStrategy(false)),
rtp_rtcp_module_(NULL),
rtp_rtcp_module_(nullptr),
transport_(kTestSsrc + 1),
receiver_(),
payload_data_length(sizeof(payload_data)),
fake_clock(123456) {}
fake_clock(123456),
retranmission_rate_limiter_(&fake_clock, kMaxRttMs) {}
~RtpRtcpRtxNackTest() {}
void SetUp() override {
@ -182,6 +185,7 @@ class RtpRtcpRtxNackTest : public ::testing::Test {
receive_statistics_.reset(ReceiveStatistics::Create(&fake_clock));
configuration.receive_statistics = receive_statistics_.get();
configuration.outgoing_transport = &transport_;
configuration.retransmission_rate_limiter = &retranmission_rate_limiter_;
rtp_rtcp_module_ = RtpRtcp::CreateRtpRtcp(configuration);
rtp_feedback_.reset(new TestRtpFeedback(rtp_rtcp_module_));
@ -288,6 +292,7 @@ class RtpRtcpRtxNackTest : public ::testing::Test {
uint8_t payload_data[65000];
size_t payload_data_length;
SimulatedClock fake_clock;
RateLimiter retranmission_rate_limiter_;
};
TEST_F(RtpRtcpRtxNackTest, LongNackList) {

View File

@ -14,7 +14,7 @@
#include <cstdlib>
#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h"
#include "webrtc/modules/rtp_rtcp/source/time_util.h"
namespace webrtc {
@ -29,7 +29,8 @@ StreamStatisticianImpl::StreamStatisticianImpl(
RtcpStatisticsCallback* rtcp_callback,
StreamDataCountersCallback* rtp_callback)
: clock_(clock),
incoming_bitrate_(clock, NULL),
incoming_bitrate_(kStatisticsProcessIntervalMs,
RateStatistics::kBpsScale),
ssrc_(0),
max_reordering_threshold_(kDefaultMaxReorderingThreshold),
jitter_q4_(0),
@ -61,7 +62,7 @@ void StreamStatisticianImpl::UpdateCounters(const RTPHeader& header,
rtc::CritScope cs(&stream_lock_);
bool in_order = InOrderPacketInternal(header.sequenceNumber);
ssrc_ = header.ssrc;
incoming_bitrate_.Update(packet_length);
incoming_bitrate_.Update(packet_length, clock_->TimeInMilliseconds());
receive_counters_.transmitted.AddPacket(packet_length, header);
if (!in_order && retransmitted) {
receive_counters_.retransmitted.AddPacket(packet_length, header);
@ -300,12 +301,7 @@ void StreamStatisticianImpl::GetReceiveStreamDataCounters(
uint32_t StreamStatisticianImpl::BitrateReceived() const {
rtc::CritScope cs(&stream_lock_);
return incoming_bitrate_.BitrateNow();
}
void StreamStatisticianImpl::ProcessBitrate() {
rtc::CritScope cs(&stream_lock_);
incoming_bitrate_.Process();
return incoming_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
}
void StreamStatisticianImpl::LastReceiveTimeNtp(uint32_t* secs,
@ -376,7 +372,6 @@ ReceiveStatistics* ReceiveStatistics::Create(Clock* clock) {
ReceiveStatisticsImpl::ReceiveStatisticsImpl(Clock* clock)
: clock_(clock),
last_rate_update_ms_(0),
rtcp_stats_callback_(NULL),
rtp_stats_callback_(NULL) {}
@ -452,23 +447,6 @@ void ReceiveStatisticsImpl::SetMaxReorderingThreshold(
}
}
void ReceiveStatisticsImpl::Process() {
rtc::CritScope cs(&receive_statistics_lock_);
for (StatisticianImplMap::iterator it = statisticians_.begin();
it != statisticians_.end(); ++it) {
it->second->ProcessBitrate();
}
last_rate_update_ms_ = clock_->TimeInMilliseconds();
}
int64_t ReceiveStatisticsImpl::TimeUntilNextProcess() {
rtc::CritScope cs(&receive_statistics_lock_);
int64_t time_since_last_update = clock_->TimeInMilliseconds() -
last_rate_update_ms_;
return std::max<int64_t>(
kStatisticsProcessIntervalMs - time_since_last_update, 0);
}
void ReceiveStatisticsImpl::RegisterRtcpStatisticsCallback(
RtcpStatisticsCallback* callback) {
rtc::CritScope cs(&receive_statistics_lock_);
@ -525,10 +503,6 @@ StreamStatistician* NullReceiveStatistics::GetStatistician(
void NullReceiveStatistics::SetMaxReorderingThreshold(
int max_reordering_threshold) {}
int64_t NullReceiveStatistics::TimeUntilNextProcess() { return 0; }
void NullReceiveStatistics::Process() {}
void NullReceiveStatistics::RegisterRtcpStatisticsCallback(
RtcpStatisticsCallback* callback) {}

View File

@ -17,7 +17,7 @@
#include <map>
#include "webrtc/base/criticalsection.h"
#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
#include "webrtc/base/rate_statistics.h"
#include "webrtc/system_wrappers/include/ntp_time.h"
namespace webrtc {
@ -44,7 +44,6 @@ class StreamStatisticianImpl : public StreamStatistician {
bool retransmitted);
void FecPacketReceived(const RTPHeader& header, size_t packet_length);
void SetMaxReorderingThreshold(int max_reordering_threshold);
void ProcessBitrate();
virtual void LastReceiveTimeNtp(uint32_t* secs, uint32_t* frac) const;
private:
@ -57,9 +56,9 @@ class StreamStatisticianImpl : public StreamStatistician {
void NotifyRtpCallback() LOCKS_EXCLUDED(stream_lock_);
void NotifyRtcpCallback() LOCKS_EXCLUDED(stream_lock_);
Clock* clock_;
Clock* const clock_;
rtc::CriticalSection stream_lock_;
Bitrate incoming_bitrate_;
RateStatistics incoming_bitrate_;
uint32_t ssrc_;
int max_reordering_threshold_; // In number of packets or sequence numbers.
@ -108,10 +107,6 @@ class ReceiveStatisticsImpl : public ReceiveStatistics,
StreamStatistician* GetStatistician(uint32_t ssrc) const override;
void SetMaxReorderingThreshold(int max_reordering_threshold) override;
// Implement Module.
void Process() override;
int64_t TimeUntilNextProcess() override;
void RegisterRtcpStatisticsCallback(
RtcpStatisticsCallback* callback) override;
@ -127,9 +122,8 @@ class ReceiveStatisticsImpl : public ReceiveStatistics,
typedef std::map<uint32_t, StreamStatisticianImpl*> StatisticianImplMap;
Clock* clock_;
Clock* const clock_;
rtc::CriticalSection receive_statistics_lock_;
int64_t last_rate_update_ms_;
StatisticianImplMap statisticians_;
RtcpStatisticsCallback* rtcp_stats_callback_;

View File

@ -13,7 +13,6 @@
#include "webrtc/base/onetimeevent.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h"
#include "webrtc/typedefs.h"

View File

@ -63,7 +63,8 @@ RtpRtcp::Configuration::Configuration()
send_frame_count_observer(nullptr),
send_side_delay_observer(nullptr),
event_log(nullptr),
send_packet_observer(nullptr) {}
send_packet_observer(nullptr),
retransmission_rate_limiter(nullptr) {}
RtpRtcp* RtpRtcp::CreateRtpRtcp(const RtpRtcp::Configuration& configuration) {
if (configuration.clock) {
@ -89,7 +90,8 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
configuration.send_frame_count_observer,
configuration.send_side_delay_observer,
configuration.event_log,
configuration.send_packet_observer),
configuration.send_packet_observer,
configuration.retransmission_rate_limiter),
rtcp_sender_(configuration.audio,
configuration.clock,
configuration.receive_statistics,
@ -820,10 +822,6 @@ int32_t ModuleRtpRtcpImpl::SendREDPayloadType(int8_t* payload_type) const {
return rtp_sender_.RED(payload_type);
}
void ModuleRtpRtcpImpl::SetTargetSendBitrate(uint32_t bitrate_bps) {
rtp_sender_.SetTargetBitrate(bitrate_bps);
}
int32_t ModuleRtpRtcpImpl::SetKeyFrameRequestMethod(
const KeyFrameRequestMethod method) {
key_frame_req_method_ = method;

View File

@ -285,8 +285,6 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
// Send a request for a keyframe.
int32_t RequestKeyFrame() override;
void SetTargetSendBitrate(uint32_t bitrate_bps) override;
void SetGenericFECStatus(bool enable,
uint8_t payload_type_red,
uint8_t payload_type_fec) override;

View File

@ -15,6 +15,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/rate_limiter.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
@ -37,6 +38,7 @@ const int64_t kOneWayNetworkDelayMs = 100;
const uint8_t kBaseLayerTid = 0;
const uint8_t kHigherLayerTid = 1;
const uint16_t kSequenceNumber = 100;
const int64_t kMaxRttMs = 1000;
class RtcpRttStatsTestImpl : public RtcpRttStats {
public:
@ -99,7 +101,9 @@ class SendTransport : public Transport,
class RtpRtcpModule : public RtcpPacketTypeCounterObserver {
public:
explicit RtpRtcpModule(SimulatedClock* clock)
: receive_statistics_(ReceiveStatistics::Create(clock)) {
: receive_statistics_(ReceiveStatistics::Create(clock)),
remote_ssrc_(0),
retransmission_rate_limiter_(clock, kMaxRttMs) {
RtpRtcp::Configuration config;
config.audio = false;
config.clock = clock;
@ -107,6 +111,7 @@ class RtpRtcpModule : public RtcpPacketTypeCounterObserver {
config.receive_statistics = receive_statistics_.get();
config.rtcp_packet_type_counter_observer = this;
config.rtt_stats = &rtt_stats_;
config.retransmission_rate_limiter = &retransmission_rate_limiter_;
impl_.reset(new ModuleRtpRtcpImpl(config));
impl_->SetRTCPStatus(RtcpMode::kCompound);
@ -121,6 +126,7 @@ class RtpRtcpModule : public RtcpPacketTypeCounterObserver {
RtcpRttStatsTestImpl rtt_stats_;
std::unique_ptr<ModuleRtpRtcpImpl> impl_;
uint32_t remote_ssrc_;
RateLimiter retransmission_rate_limiter_;
void SetRemoteSsrc(uint32_t ssrc) {
remote_ssrc_ = ssrc;

View File

@ -16,6 +16,7 @@
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
#include "webrtc/base/rate_limiter.h"
#include "webrtc/base/trace_event.h"
#include "webrtc/base/timeutils.h"
#include "webrtc/call.h"
@ -33,6 +34,7 @@ namespace webrtc {
static const size_t kMaxPaddingLength = 224;
static const int kSendSideDelayWindowMs = 1000;
static const uint32_t kAbsSendTimeFraction = 18;
static const int kBitrateStatisticsWindowMs = 1000;
namespace {
@ -63,47 +65,6 @@ uint32_t ConvertMsTo24Bits(int64_t time_ms) {
}
} // namespace
RTPSender::BitrateAggregator::BitrateAggregator(
BitrateStatisticsObserver* bitrate_callback)
: callback_(bitrate_callback),
total_bitrate_observer_(*this),
retransmit_bitrate_observer_(*this),
ssrc_(0) {}
void RTPSender::BitrateAggregator::OnStatsUpdated() const {
if (callback_) {
callback_->Notify(total_bitrate_observer_.statistics(),
retransmit_bitrate_observer_.statistics(), ssrc_);
}
}
Bitrate::Observer* RTPSender::BitrateAggregator::total_bitrate_observer() {
return &total_bitrate_observer_;
}
Bitrate::Observer* RTPSender::BitrateAggregator::retransmit_bitrate_observer() {
return &retransmit_bitrate_observer_;
}
void RTPSender::BitrateAggregator::set_ssrc(uint32_t ssrc) {
ssrc_ = ssrc;
}
RTPSender::BitrateAggregator::BitrateObserver::BitrateObserver(
const BitrateAggregator& aggregator)
: aggregator_(aggregator) {}
// Implements Bitrate::Observer.
void RTPSender::BitrateAggregator::BitrateObserver::BitrateUpdated(
const BitrateStatistics& stats) {
statistics_ = stats;
aggregator_.OnStatsUpdated();
}
const BitrateStatistics&
RTPSender::BitrateAggregator::BitrateObserver::statistics() const {
return statistics_;
}
RTPSender::RTPSender(
bool audio,
Clock* clock,
@ -115,13 +76,12 @@ RTPSender::RTPSender(
FrameCountObserver* frame_count_observer,
SendSideDelayObserver* send_side_delay_observer,
RtcEventLog* event_log,
SendPacketObserver* send_packet_observer)
SendPacketObserver* send_packet_observer,
RateLimiter* retransmission_rate_limiter)
: clock_(clock),
// TODO(holmer): Remove this conversion?
clock_delta_ms_(clock_->TimeInMilliseconds() - rtc::TimeMillis()),
random_(clock_->TimeInMicroseconds()),
bitrates_(bitrate_callback),
total_bitrate_sent_(clock, bitrates_.total_bitrate_observer()),
audio_configured_(audio),
audio_(audio ? new RTPSenderAudio(clock, this) : nullptr),
video_(audio ? nullptr : new RTPSenderVideo(clock, this)),
@ -140,18 +100,18 @@ RTPSender::RTPSender(
rotation_(kVideoRotation_0),
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),
rtp_stats_callback_(nullptr),
total_bitrate_sent_(kBitrateStatisticsWindowMs,
RateStatistics::kBpsScale),
nack_bitrate_sent_(kBitrateStatisticsWindowMs, RateStatistics::kBpsScale),
frame_count_observer_(frame_count_observer),
send_side_delay_observer_(send_side_delay_observer),
event_log_(event_log),
send_packet_observer_(send_packet_observer),
bitrate_callback_(bitrate_callback),
// RTP variables
start_timestamp_forced_(false),
start_timestamp_(0),
@ -166,9 +126,7 @@ RTPSender::RTPSender(
last_packet_marker_bit_(false),
csrcs_(),
rtx_(kRtxOff),
target_bitrate_(0) {
memset(nack_byte_count_times_, 0, sizeof(nack_byte_count_times_));
memset(nack_byte_count_, 0, sizeof(nack_byte_count_));
retransmission_rate_limiter_(retransmission_rate_limiter) {
// We need to seed the random generator for BuildPaddingPacket() below.
// TODO(holmer,tommi): Note that TimeInMilliseconds might return 0 on Mac
// early on in the process.
@ -178,7 +136,6 @@ RTPSender::RTPSender(
ssrc_rtx_ = ssrc_db_->CreateSSRC();
RTC_DCHECK(ssrc_rtx_ != 0);
bitrates_.set_ssrc(ssrc_);
// Random start, 16 bits. Can't be 0.
sequence_number_rtx_ = random_.Rand(1, kMaxInitRtpSeqNumber);
sequence_number_ = random_.Rand(1, kMaxInitRtpSeqNumber);
@ -208,18 +165,11 @@ RTPSender::~RTPSender() {
}
}
void RTPSender::SetTargetBitrate(uint32_t bitrate) {
rtc::CritScope cs(&target_bitrate_critsect_);
target_bitrate_ = bitrate;
}
uint32_t RTPSender::GetTargetBitrate() {
rtc::CritScope cs(&target_bitrate_critsect_);
return target_bitrate_;
}
uint16_t RTPSender::ActualSendBitrateKbit() const {
return (uint16_t)(total_bitrate_sent_.BitrateNow() / 1000);
rtc::CritScope cs(&statistics_crit_);
return static_cast<uint16_t>(
total_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0) /
1000);
}
uint32_t RTPSender::VideoBitrateSent() const {
@ -237,7 +187,8 @@ uint32_t RTPSender::FecOverheadRate() const {
}
uint32_t RTPSender::NackOverheadRate() const {
return nack_bitrate_.BitrateLast();
rtc::CritScope cs(&statistics_crit_);
return nack_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0);
}
int32_t RTPSender::SetTransmissionTimeOffset(int32_t transmission_time_offset) {
@ -754,6 +705,12 @@ int32_t RTPSender::ReSendPacket(uint16_t packet_id, int64_t min_resend_time) {
return 0;
}
// Check if we're overusing retransmission bitrate.
// TODO(sprang): Add histograms for nack success or failure reasons.
RTC_DCHECK(retransmission_rate_limiter_);
if (!retransmission_rate_limiter_->TryUseRate(length))
return -1;
if (paced_sender_) {
RtpUtility::RtpHeaderParser rtp_parser(data_buffer, length);
RTPHeader header;
@ -824,44 +781,14 @@ void RTPSender::OnReceivedNACK(const std::list<uint16_t>& nack_sequence_numbers,
TRACE_EVENT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
"RTPSender::OnReceivedNACK", "num_seqnum",
nack_sequence_numbers.size(), "avg_rtt", avg_rtt);
const int64_t now = clock_->TimeInMilliseconds();
uint32_t bytes_re_sent = 0;
uint32_t target_bitrate = GetTargetBitrate();
// Enough bandwidth to send NACK?
if (!ProcessNACKBitRate(now)) {
LOG(LS_INFO) << "NACK bitrate reached. Skip sending NACK response. Target "
<< target_bitrate;
return;
}
for (std::list<uint16_t>::const_iterator it = nack_sequence_numbers.begin();
it != nack_sequence_numbers.end(); ++it) {
const int32_t bytes_sent = ReSendPacket(*it, 5 + avg_rtt);
if (bytes_sent > 0) {
bytes_re_sent += bytes_sent;
} else if (bytes_sent == 0) {
// The packet has previously been resent.
// Try resending next packet in the list.
continue;
} else {
for (uint16_t seq_no : nack_sequence_numbers) {
const int32_t bytes_sent = ReSendPacket(seq_no, 5 + avg_rtt);
if (bytes_sent < 0) {
// Failed to send one Sequence number. Give up the rest in this nack.
LOG(LS_WARNING) << "Failed resending RTP packet " << *it
LOG(LS_WARNING) << "Failed resending RTP packet " << seq_no
<< ", Discard rest of packets";
break;
}
// Delay bandwidth estimate (RTT * BW).
if (target_bitrate != 0 && avg_rtt) {
// kbits/s * ms = bits => bits/8 = bytes
size_t target_bytes =
(static_cast<size_t>(target_bitrate / 1000) * avg_rtt) >> 3;
if (bytes_re_sent > target_bytes) {
break; // Ignore the rest of the packets in the list.
}
}
}
if (bytes_re_sent > 0) {
UpdateNACKBitRate(bytes_re_sent, now);
}
}
@ -870,51 +797,6 @@ void RTPSender::OnReceivedRtcpReportBlocks(
playout_delay_oracle_.OnReceivedRtcpReportBlocks(report_blocks);
}
bool RTPSender::ProcessNACKBitRate(uint32_t now) {
uint32_t num = 0;
size_t byte_count = 0;
const uint32_t kAvgIntervalMs = 1000;
uint32_t target_bitrate = GetTargetBitrate();
rtc::CritScope lock(&send_critsect_);
if (target_bitrate == 0) {
return true;
}
for (num = 0; num < NACK_BYTECOUNT_SIZE; ++num) {
if ((now - nack_byte_count_times_[num]) > kAvgIntervalMs) {
// Don't use data older than 1sec.
break;
} else {
byte_count += nack_byte_count_[num];
}
}
uint32_t time_interval = kAvgIntervalMs;
if (num == NACK_BYTECOUNT_SIZE) {
// More than NACK_BYTECOUNT_SIZE nack messages has been received
// during the last msg_interval.
if (nack_byte_count_times_[num - 1] <= now) {
time_interval = now - nack_byte_count_times_[num - 1];
}
}
return (byte_count * 8) < (target_bitrate / 1000 * time_interval);
}
void RTPSender::UpdateNACKBitRate(uint32_t bytes, int64_t now) {
rtc::CritScope lock(&send_critsect_);
if (bytes == 0)
return;
nack_bitrate_.Update(bytes);
// Save bitrate statistics.
// Shift all but first time.
for (int i = NACK_BYTECOUNT_SIZE - 2; i >= 0; i--) {
nack_byte_count_[i + 1] = nack_byte_count_[i];
nack_byte_count_times_[i + 1] = nack_byte_count_times_[i];
}
nack_byte_count_[0] = bytes;
nack_byte_count_times_[0] = now;
}
// Called from pacer when we can send the packet.
bool RTPSender::TimeToSendPacket(uint16_t sequence_number,
int64_t capture_time_ms,
@ -1009,6 +891,7 @@ void RTPSender::UpdateRtpStats(const uint8_t* buffer,
StreamDataCounters* counters;
// Get ssrc before taking statistics_crit_ to avoid possible deadlock.
uint32_t ssrc = is_rtx ? RtxSsrc() : SSRC();
int64_t now_ms = clock_->TimeInMilliseconds();
rtc::CritScope lock(&statistics_crit_);
if (is_rtx) {
@ -1017,22 +900,23 @@ void RTPSender::UpdateRtpStats(const uint8_t* buffer,
counters = &rtp_stats_;
}
total_bitrate_sent_.Update(packet_length);
total_bitrate_sent_.Update(packet_length, now_ms);
if (counters->first_packet_time_ms == -1) {
if (counters->first_packet_time_ms == -1)
counters->first_packet_time_ms = clock_->TimeInMilliseconds();
}
if (IsFecPacket(buffer, header)) {
if (IsFecPacket(buffer, header))
counters->fec.AddPacket(packet_length, header);
}
if (is_retransmit) {
counters->retransmitted.AddPacket(packet_length, header);
nack_bitrate_sent_.Update(packet_length, now_ms);
}
counters->transmitted.AddPacket(packet_length, header);
if (rtp_stats_callback_) {
if (rtp_stats_callback_)
rtp_stats_callback_->DataCountersUpdated(*counters, ssrc);
}
}
bool RTPSender::IsFecPacket(const uint8_t* buffer,
@ -1180,13 +1064,18 @@ void RTPSender::UpdateOnSendPacket(int packet_id,
}
void RTPSender::ProcessBitrate() {
rtc::CritScope lock(&send_critsect_);
total_bitrate_sent_.Process();
nack_bitrate_.Process();
if (audio_configured_) {
if (!bitrate_callback_)
return;
int64_t now_ms = clock_->TimeInMilliseconds();
uint32_t ssrc;
{
rtc::CritScope lock(&send_critsect_);
ssrc = ssrc_;
}
video_->ProcessBitrate();
rtc::CritScope lock(&statistics_crit_);
bitrate_callback_->Notify(total_bitrate_sent_.Rate(now_ms).value_or(0),
nack_bitrate_sent_.Rate(now_ms).value_or(0), ssrc);
}
size_t RTPSender::RtpHeaderLength() const {
@ -1746,7 +1635,6 @@ void RTPSender::SetSendingStatus(bool enabled) {
ssrc_db_->ReturnSSRC(ssrc_);
ssrc_ = ssrc_db_->CreateSSRC();
RTC_DCHECK(ssrc_ != 0);
bitrates_.set_ssrc(ssrc_);
}
// Don't initialize seq number if SSRC passed externally.
if (!sequence_number_forced_ && !ssrc_forced_) {
@ -1797,7 +1685,6 @@ uint32_t RTPSender::GenerateNewSSRC() {
}
ssrc_ = ssrc_db_->CreateSSRC();
RTC_DCHECK(ssrc_ != 0);
bitrates_.set_ssrc(ssrc_);
return ssrc_;
}
@ -1812,7 +1699,6 @@ void RTPSender::SetSSRC(uint32_t ssrc) {
ssrc_db_->ReturnSSRC(ssrc_);
ssrc_db_->RegisterSSRC(ssrc);
ssrc_ = ssrc;
bitrates_.set_ssrc(ssrc_);
if (!sequence_number_forced_) {
sequence_number_ = random_.Rand(1, kMaxInitRtpSeqNumber);
}
@ -1961,7 +1847,8 @@ StreamDataCountersCallback* RTPSender::GetRtpStatisticsCallback() const {
}
uint32_t RTPSender::BitrateSent() const {
return total_bitrate_sent_.BitrateLast();
rtc::CritScope cs(&statistics_crit_);
return total_bitrate_sent_.Rate(clock_->TimeInMilliseconds()).value_or(0);
}
void RTPSender::SetRtpState(const RtpState& rtp_state) {

View File

@ -20,10 +20,10 @@
#include "webrtc/base/constructormagic.h"
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/random.h"
#include "webrtc/base/rate_statistics.h"
#include "webrtc/base/thread_annotations.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
#include "webrtc/modules/rtp_rtcp/source/playout_delay_oracle.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_header_extension.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_packet_history.h"
@ -34,6 +34,7 @@
namespace webrtc {
class RateLimiter;
class RTPSenderAudio;
class RTPSenderVideo;
class RtcEventLog;
@ -93,7 +94,8 @@ class RTPSender : public RTPSenderInterface {
FrameCountObserver* frame_count_observer,
SendSideDelayObserver* send_side_delay_observer,
RtcEventLog* event_log,
SendPacketObserver* send_packet_observer);
SendPacketObserver* send_packet_observer,
RateLimiter* nack_rate_limiter);
virtual ~RTPSender();
@ -105,9 +107,6 @@ class RTPSender : public RTPSenderInterface {
uint32_t FecOverheadRate() const;
uint32_t NackOverheadRate() const;
void SetTargetBitrate(uint32_t bitrate);
uint32_t GetTargetBitrate();
// Includes size of RTP and FEC headers.
size_t MaxDataPayloadLength() const override;
@ -227,8 +226,6 @@ class RTPSender : public RTPSenderInterface {
int32_t ReSendPacket(uint16_t packet_id, int64_t min_resend_time = 0);
bool ProcessNACKBitRate(uint32_t now);
// Feedback to decide when to stop sending playout delay.
void OnReceivedRtcpReportBlocks(const ReportBlockList& report_blocks);
@ -340,8 +337,6 @@ class RTPSender : public RTPSenderInterface {
uint16_t sequence_number,
const std::vector<uint32_t>& csrcs) const;
void UpdateNACKBitRate(uint32_t bytes, int64_t now);
bool PrepareAndSendPacket(uint8_t* buffer,
size_t length,
int64_t capture_time_ms,
@ -406,45 +401,10 @@ class RTPSender : public RTPSenderInterface {
bool is_retransmit);
bool IsFecPacket(const uint8_t* buffer, const RTPHeader& header) const;
class BitrateAggregator {
public:
explicit BitrateAggregator(BitrateStatisticsObserver* bitrate_callback);
void OnStatsUpdated() const;
Bitrate::Observer* total_bitrate_observer();
Bitrate::Observer* retransmit_bitrate_observer();
void set_ssrc(uint32_t ssrc);
private:
// We assume that these observers are called on the same thread, which is
// true for RtpSender as they are called on the Process thread.
class BitrateObserver : public Bitrate::Observer {
public:
explicit BitrateObserver(const BitrateAggregator& aggregator);
// Implements Bitrate::Observer.
void BitrateUpdated(const BitrateStatistics& stats) override;
const BitrateStatistics& statistics() const;
private:
BitrateStatistics statistics_;
const BitrateAggregator& aggregator_;
};
BitrateStatisticsObserver* const callback_;
BitrateObserver total_bitrate_observer_;
BitrateObserver retransmit_bitrate_observer_;
uint32_t ssrc_;
};
Clock* const clock_;
const int64_t clock_delta_ms_;
Random random_ GUARDED_BY(send_critsect_);
BitrateAggregator bitrates_;
Bitrate total_bitrate_sent_;
const bool audio_configured_;
const std::unique_ptr<RTPSenderAudio> audio_;
const std::unique_ptr<RTPSenderVideo> video_;
@ -470,11 +430,6 @@ class RTPSender : public RTPSenderInterface {
bool video_rotation_active_;
uint16_t transport_sequence_number_;
// NACK
uint32_t nack_byte_count_times_[NACK_BYTECOUNT_SIZE];
size_t nack_byte_count_[NACK_BYTECOUNT_SIZE];
Bitrate nack_bitrate_;
// Tracks the current request for playout delay limits from application
// and decides whether the current RTP frame should include the playout
// delay extension on header.
@ -490,10 +445,13 @@ class RTPSender : public RTPSenderInterface {
StreamDataCounters rtp_stats_ GUARDED_BY(statistics_crit_);
StreamDataCounters rtx_rtp_stats_ GUARDED_BY(statistics_crit_);
StreamDataCountersCallback* rtp_stats_callback_ GUARDED_BY(statistics_crit_);
RateStatistics total_bitrate_sent_ GUARDED_BY(statistics_crit_);
RateStatistics nack_bitrate_sent_ GUARDED_BY(statistics_crit_);
FrameCountObserver* const frame_count_observer_;
SendSideDelayObserver* const send_side_delay_observer_;
RtcEventLog* const event_log_;
SendPacketObserver* const send_packet_observer_;
BitrateStatisticsObserver* const bitrate_callback_;
// RTP variables
bool start_timestamp_forced_ GUARDED_BY(send_critsect_);
@ -516,12 +474,7 @@ class RTPSender : public RTPSenderInterface {
// Mapping rtx_payload_type_map_[associated] = rtx.
std::map<int8_t, int8_t> rtx_payload_type_map_ GUARDED_BY(send_critsect_);
// Note: Don't access this variable directly, always go through
// SetTargetBitrateKbps or GetTargetBitrateKbps. Also remember
// that by the time the function returns there is no guarantee
// that the target bitrate is still valid.
rtc::CriticalSection target_bitrate_critsect_;
uint32_t target_bitrate_ GUARDED_BY(target_bitrate_critsect_);
RateLimiter* const retransmission_rate_limiter_;
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(RTPSender);
};

View File

@ -15,6 +15,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "webrtc/base/buffer.h"
#include "webrtc/base/rate_limiter.h"
#include "webrtc/call/mock/mock_rtc_event_log.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_cvo.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h"
@ -133,11 +134,11 @@ class RtpSenderTest : public ::testing::Test {
: fake_clock_(kStartTime),
mock_rtc_event_log_(),
mock_paced_sender_(),
retransmission_rate_limiter_(&fake_clock_, 1000),
rtp_sender_(),
payload_(kPayload),
transport_(),
kMarkerBit(true) {
}
kMarkerBit(true) {}
void SetUp() override { SetUpRtpSender(true); }
@ -145,7 +146,8 @@ class RtpSenderTest : public ::testing::Test {
rtp_sender_.reset(new RTPSender(
false, &fake_clock_, &transport_, pacer ? &mock_paced_sender_ : nullptr,
&seq_num_allocator_, nullptr, nullptr, nullptr, nullptr,
&mock_rtc_event_log_, &send_packet_observer_));
&mock_rtc_event_log_, &send_packet_observer_,
&retransmission_rate_limiter_));
rtp_sender_->SetSequenceNumber(kSeqNum);
}
@ -154,6 +156,7 @@ class RtpSenderTest : public ::testing::Test {
MockRtpPacketSender mock_paced_sender_;
MockTransportSequenceNumberAllocator seq_num_allocator_;
MockSendPacketObserver send_packet_observer_;
RateLimiter retransmission_rate_limiter_;
std::unique_ptr<RTPSender> rtp_sender_;
int payload_;
LoopbackTransportTest transport_;
@ -743,7 +746,6 @@ TEST_F(RtpSenderTest, TrafficSmoothingWithExtensions) {
EXPECT_EQ(
0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
kAbsoluteSendTimeExtensionId));
rtp_sender_->SetTargetBitrate(300000);
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
int rtp_length_int = rtp_sender_->BuildRTPheader(
packet_, kPayload, kMarkerBit, kTimestamp, capture_time_ms);
@ -797,7 +799,6 @@ TEST_F(RtpSenderTest, TrafficSmoothingRetransmits) {
EXPECT_EQ(
0, rtp_sender_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
kAbsoluteSendTimeExtensionId));
rtp_sender_->SetTargetBitrate(300000);
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
int rtp_length_int = rtp_sender_->BuildRTPheader(
packet_, kPayload, kMarkerBit, kTimestamp, capture_time_ms);
@ -879,7 +880,6 @@ TEST_F(RtpSenderTest, SendPadding) {
kAbsoluteSendTimeExtensionId);
webrtc::RTPHeader rtp_header;
rtp_sender_->SetTargetBitrate(300000);
int64_t capture_time_ms = fake_clock_.TimeInMilliseconds();
int rtp_length_int = rtp_sender_->BuildRTPheader(
packet_, kPayload, kMarkerBit, timestamp, capture_time_ms);
@ -1011,7 +1011,7 @@ TEST_F(RtpSenderTest, OnSendPacketNotUpdatedWithoutSeqNumAllocator) {
rtp_sender_.reset(new RTPSender(
false, &fake_clock_, &transport_, &mock_paced_sender_,
nullptr /* TransportSequenceNumberAllocator */, nullptr, nullptr, nullptr,
nullptr, nullptr, &send_packet_observer_));
nullptr, nullptr, &send_packet_observer_, nullptr));
rtp_sender_->SetSequenceNumber(kSeqNum);
rtp_sender_->SetStorePacketsStatus(true, 10);
@ -1029,7 +1029,7 @@ TEST_F(RtpSenderTest, SendRedundantPayloads) {
MockTransport transport;
rtp_sender_.reset(new RTPSender(
false, &fake_clock_, &transport, &mock_paced_sender_, nullptr, nullptr,
nullptr, nullptr, nullptr, &mock_rtc_event_log_, nullptr));
nullptr, nullptr, nullptr, &mock_rtc_event_log_, nullptr, nullptr));
rtp_sender_->SetSequenceNumber(kSeqNum);
rtp_sender_->SetRtxPayloadType(kRtxPayload, kPayload);
@ -1054,7 +1054,6 @@ TEST_F(RtpSenderTest, SendRedundantPayloads) {
kTransmissionTimeOffsetExtensionId);
rtp_parser->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
kAbsoluteSendTimeExtensionId);
rtp_sender_->SetTargetBitrate(300000);
const size_t kNumPayloadSizes = 10;
const size_t kPayloadSizes[kNumPayloadSizes] = {500, 550, 600, 650, 700,
750, 800, 850, 900, 950};
@ -1176,7 +1175,7 @@ TEST_F(RtpSenderTest, FrameCountCallbacks) {
rtp_sender_.reset(new RTPSender(
false, &fake_clock_, &transport_, &mock_paced_sender_, nullptr, nullptr,
nullptr, &callback, nullptr, nullptr, nullptr));
nullptr, &callback, nullptr, nullptr, nullptr, nullptr));
char payload_name[RTP_PAYLOAD_NAME_SIZE] = "GENERIC";
const uint8_t payload_type = 127;
@ -1213,30 +1212,39 @@ TEST_F(RtpSenderTest, FrameCountCallbacks) {
TEST_F(RtpSenderTest, BitrateCallbacks) {
class TestCallback : public BitrateStatisticsObserver {
public:
TestCallback() : BitrateStatisticsObserver(), num_calls_(0), ssrc_(0) {}
TestCallback()
: BitrateStatisticsObserver(),
num_calls_(0),
ssrc_(0),
total_bitrate_(0),
retransmit_bitrate_(0) {}
virtual ~TestCallback() {}
void Notify(const BitrateStatistics& total_stats,
const BitrateStatistics& retransmit_stats,
void Notify(uint32_t total_bitrate,
uint32_t retransmit_bitrate,
uint32_t ssrc) override {
++num_calls_;
ssrc_ = ssrc;
total_stats_ = total_stats;
retransmit_stats_ = retransmit_stats;
total_bitrate_ = total_bitrate;
retransmit_bitrate_ = retransmit_bitrate;
}
uint32_t num_calls_;
uint32_t ssrc_;
BitrateStatistics total_stats_;
BitrateStatistics retransmit_stats_;
uint32_t total_bitrate_;
uint32_t retransmit_bitrate_;
} callback;
rtp_sender_.reset(new RTPSender(false, &fake_clock_, &transport_, nullptr,
nullptr, nullptr, &callback, nullptr, nullptr,
nullptr, nullptr));
nullptr, nullptr, nullptr));
// Simulate kNumPackets sent with kPacketInterval ms intervals.
const uint32_t kNumPackets = 15;
// Simulate kNumPackets sent with kPacketInterval ms intervals, with the
// number of packets selected so that we fill (but don't overflow) the one
// second averaging window.
const uint32_t kWindowSizeMs = 1000;
const uint32_t kPacketInterval = 20;
const uint32_t kNumPackets =
(kWindowSizeMs - kPacketInterval) / kPacketInterval;
// Overhead = 12 bytes RTP header + 1 byte generic header.
const uint32_t kPacketOverhead = 13;
@ -1250,7 +1258,6 @@ TEST_F(RtpSenderTest, BitrateCallbacks) {
// Initial process call so we get a new time window.
rtp_sender_->ProcessBitrate();
uint64_t start_time = fake_clock_.CurrentNtpInMilliseconds();
// Send a few frames.
for (uint32_t i = 0; i < kNumPackets; ++i) {
@ -1262,17 +1269,18 @@ TEST_F(RtpSenderTest, BitrateCallbacks) {
rtp_sender_->ProcessBitrate();
const uint32_t expected_packet_rate = 1000 / kPacketInterval;
// We get one call for every stats updated, thus two calls since both the
// stream stats and the retransmit stats are updated once.
EXPECT_EQ(2u, callback.num_calls_);
EXPECT_EQ(ssrc, callback.ssrc_);
EXPECT_EQ(start_time + (kNumPackets * kPacketInterval),
callback.total_stats_.timestamp_ms);
EXPECT_EQ(expected_packet_rate, callback.total_stats_.packet_rate);
EXPECT_EQ((kPacketOverhead + sizeof(payload)) * 8 * expected_packet_rate,
callback.total_stats_.bitrate_bps);
const uint32_t kTotalPacketSize = kPacketOverhead + sizeof(payload);
// Bitrate measured over delta between last and first timestamp, plus one.
const uint32_t kExpectedWindowMs = kNumPackets * kPacketInterval + 1;
const uint32_t kExpectedBitsAccumulated = kTotalPacketSize * kNumPackets * 8;
const uint32_t kExpectedRateBps =
(kExpectedBitsAccumulated * 1000 + (kExpectedWindowMs / 2)) /
kExpectedWindowMs;
EXPECT_EQ(kExpectedRateBps, callback.total_bitrate_);
rtp_sender_.reset();
}
@ -1285,7 +1293,7 @@ class RtpSenderAudioTest : public RtpSenderTest {
payload_ = kAudioPayload;
rtp_sender_.reset(new RTPSender(true, &fake_clock_, &transport_, nullptr,
nullptr, nullptr, nullptr, nullptr, nullptr,
nullptr, nullptr));
nullptr, nullptr, nullptr));
rtp_sender_->SetSequenceNumber(kSeqNum);
}
};
@ -1553,9 +1561,9 @@ TEST_F(RtpSenderTestWithoutPacer, RespectsNackBitrateLimit) {
const int32_t kPacketSize = 1400;
const int32_t kNumPackets = 30;
retransmission_rate_limiter_.SetMaxRate(kPacketSize * kNumPackets * 8);
rtp_sender_->SetStorePacketsStatus(true, kNumPackets);
// Set bitrate (in kbps) to fit kNumPackets á kPacketSize bytes in one second.
rtp_sender_->SetTargetBitrate(kNumPackets * kPacketSize * 8);
const uint16_t kStartSequenceNumber = rtp_sender_->SequenceNumber();
std::list<uint16_t> sequence_numbers;
for (int32_t i = 0; i < kNumPackets; ++i) {
@ -1573,6 +1581,9 @@ TEST_F(RtpSenderTestWithoutPacer, RespectsNackBitrateLimit) {
rtp_sender_->OnReceivedNACK(sequence_numbers, 0);
EXPECT_EQ(kNumPackets * 2, transport_.packets_sent_);
// Must be at least 5ms in between retransmission attempts.
fake_clock_.AdvanceTimeMilliseconds(5);
// Resending should not work, bandwidth exceeded.
rtp_sender_->OnReceivedNACK(sequence_numbers, 0);
EXPECT_EQ(kNumPackets * 2, transport_.packets_sent_);

View File

@ -31,6 +31,7 @@ enum { REDForFECHeaderLength = 1 };
RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender)
: _rtpSender(*rtpSender),
clock_(clock),
_videoType(kRtpVideoGeneric),
_retransmissionSettings(kRetransmitBaseLayer),
// Generic FEC
@ -41,8 +42,8 @@ RTPSenderVideo::RTPSenderVideo(Clock* clock, RTPSenderInterface* rtpSender)
delta_fec_params_(),
key_fec_params_(),
producer_fec_(&fec_),
_fecOverheadRate(clock, NULL),
_videoBitrate(clock, NULL) {
fec_bitrate_(1000, RateStatistics::kBpsScale),
video_bitrate_(1000, RateStatistics::kBpsScale) {
memset(&delta_fec_params_, 0, sizeof(delta_fec_params_));
memset(&key_fec_params_, 0, sizeof(key_fec_params_));
delta_fec_params_.max_fec_frames = key_fec_params_.max_fec_frames = 1;
@ -95,7 +96,9 @@ void RTPSenderVideo::SendVideoPacket(uint8_t* data_buffer,
if (_rtpSender.SendToNetwork(data_buffer, payload_length, rtp_header_length,
capture_time_ms, storage,
RtpPacketSender::kLowPriority) == 0) {
_videoBitrate.Update(payload_length + rtp_header_length);
rtc::CritScope cs(&stats_crit_);
video_bitrate_.Update(payload_length + rtp_header_length,
clock_->TimeInMilliseconds());
TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
"Video::PacketNormal", "timestamp", capture_timestamp,
"seqnum", seq_num);
@ -141,7 +144,8 @@ void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer,
red_packet->data(), red_packet->length() - rtp_header_length,
rtp_header_length, capture_time_ms, media_packet_storage,
RtpPacketSender::kLowPriority) == 0) {
_videoBitrate.Update(red_packet->length());
rtc::CritScope cs(&stats_crit_);
video_bitrate_.Update(red_packet->length(), clock_->TimeInMilliseconds());
TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
"Video::PacketRed", "timestamp", capture_timestamp,
"seqnum", media_seq_num);
@ -153,7 +157,8 @@ void RTPSenderVideo::SendVideoPacketAsRed(uint8_t* data_buffer,
fec_packet->data(), fec_packet->length() - rtp_header_length,
rtp_header_length, capture_time_ms, fec_storage,
RtpPacketSender::kLowPriority) == 0) {
_fecOverheadRate.Update(fec_packet->length());
rtc::CritScope cs(&stats_crit_);
fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds());
TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("webrtc_rtp"),
"Video::PacketFec", "timestamp", capture_timestamp,
"seqnum", next_fec_sequence_number);
@ -337,17 +342,14 @@ int32_t RTPSenderVideo::SendVideo(const RtpVideoCodecTypes videoType,
return 0;
}
void RTPSenderVideo::ProcessBitrate() {
_videoBitrate.Process();
_fecOverheadRate.Process();
}
uint32_t RTPSenderVideo::VideoBitrateSent() const {
return _videoBitrate.BitrateLast();
rtc::CritScope cs(&stats_crit_);
return video_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
}
uint32_t RTPSenderVideo::FecOverheadRate() const {
return _fecOverheadRate.BitrateLast();
rtc::CritScope cs(&stats_crit_);
return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
}
int RTPSenderVideo::SelectiveRetransmissions() const {

View File

@ -15,10 +15,10 @@
#include "webrtc/base/criticalsection.h"
#include "webrtc/base/onetimeevent.h"
#include "webrtc/base/rate_statistics.h"
#include "webrtc/base/thread_annotations.h"
#include "webrtc/common_types.h"
#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp_defines.h"
#include "webrtc/modules/rtp_rtcp/source/bitrate.h"
#include "webrtc/modules/rtp_rtcp/source/forward_error_correction.h"
#include "webrtc/modules/rtp_rtcp/source/producer_fec.h"
#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_config.h"
@ -68,8 +68,6 @@ class RTPSenderVideo {
void SetFecParameters(const FecProtectionParams* delta_params,
const FecProtectionParams* key_params);
void ProcessBitrate();
uint32_t VideoBitrateSent() const;
uint32_t FecOverheadRate() const;
@ -95,9 +93,10 @@ class RTPSenderVideo {
bool protect);
RTPSenderInterface& _rtpSender;
Clock* const clock_;
// Should never be held when calling out of this class.
const rtc::CriticalSection crit_;
rtc::CriticalSection crit_;
RtpVideoCodecTypes _videoType;
int32_t _retransmissionSettings GUARDED_BY(crit_);
@ -111,11 +110,12 @@ class RTPSenderVideo {
FecProtectionParams key_fec_params_ GUARDED_BY(crit_);
ProducerFec producer_fec_ GUARDED_BY(crit_);
rtc::CriticalSection stats_crit_;
// Bitrate used for FEC payload, RED headers, RTP headers for FEC packets
// and any padding overhead.
Bitrate _fecOverheadRate;
// Bitrate used for video payload and RTP headers
Bitrate _videoBitrate;
RateStatistics fec_bitrate_ GUARDED_BY(stats_crit_);
// Bitrate used for video payload and RTP headers.
RateStatistics video_bitrate_ GUARDED_BY(stats_crit_);
OneTimeEvent first_frame_sent_;
};
} // namespace webrtc