Break out RemoteBitrateEstimator from RtpRtcp module and make RemoteBitrateEstimator::Process trigger new REMB messages.
Also make sure RTT is computed independently of whether it's time to send RTCP messages or not. BUG=1298 Review URL: https://webrtc-codereview.appspot.com/1060005 git-svn-id: http://webrtc.googlecode.com/svn/trunk@3455 4adac7df-926f-26a2-2b94-8c16560cd09d
This commit is contained in:
parent
46d90dcd74
commit
b586507986
@ -320,6 +320,16 @@ struct FecProtectionParams {
|
|||||||
FecMaskType fec_mask_type;
|
FecMaskType fec_mask_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Interface used by the CallStats class to distribute call statistics.
|
||||||
|
// Callbacks will be triggered as soon as the class has been registered to a
|
||||||
|
// CallStats object using RegisterStatsObserver.
|
||||||
|
class StatsObserver {
|
||||||
|
public:
|
||||||
|
virtual void OnRttUpdate(uint32_t rtt_ms) = 0;
|
||||||
|
|
||||||
|
virtual ~StatsObserver() {}
|
||||||
|
};
|
||||||
|
|
||||||
// class describing a complete, or parts of an encoded frame.
|
// class describing a complete, or parts of an encoded frame.
|
||||||
class EncodedVideoData
|
class EncodedVideoData
|
||||||
{
|
{
|
||||||
|
@ -19,9 +19,9 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
enum BandwidthUsage
|
enum BandwidthUsage
|
||||||
{
|
{
|
||||||
kBwNormal,
|
kBwNormal = 0,
|
||||||
kBwOverusing,
|
kBwUnderusing = 1,
|
||||||
kBwUnderusing
|
kBwOverusing = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum RateControlState
|
enum RateControlState
|
||||||
|
@ -16,11 +16,15 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
#include "typedefs.h"
|
#include "webrtc/modules/interface/module.h"
|
||||||
|
#include "webrtc/modules/interface/module_common_types.h"
|
||||||
|
#include "webrtc/typedefs.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class Clock;
|
||||||
|
|
||||||
// RemoteBitrateObserver is used to signal changes in bitrate estimates for
|
// RemoteBitrateObserver is used to signal changes in bitrate estimates for
|
||||||
// the incoming streams.
|
// the incoming streams.
|
||||||
class RemoteBitrateObserver {
|
class RemoteBitrateObserver {
|
||||||
@ -33,7 +37,7 @@ class RemoteBitrateObserver {
|
|||||||
virtual ~RemoteBitrateObserver() {}
|
virtual ~RemoteBitrateObserver() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class RemoteBitrateEstimator {
|
class RemoteBitrateEstimator : public StatsObserver, public Module {
|
||||||
public:
|
public:
|
||||||
enum EstimationMode {
|
enum EstimationMode {
|
||||||
kMultiStreamEstimation,
|
kMultiStreamEstimation,
|
||||||
@ -42,9 +46,10 @@ class RemoteBitrateEstimator {
|
|||||||
|
|
||||||
virtual ~RemoteBitrateEstimator() {}
|
virtual ~RemoteBitrateEstimator() {}
|
||||||
|
|
||||||
static RemoteBitrateEstimator* Create(RemoteBitrateObserver* observer,
|
static RemoteBitrateEstimator* Create(const OverUseDetectorOptions& options,
|
||||||
const OverUseDetectorOptions& options,
|
EstimationMode mode,
|
||||||
EstimationMode mode);
|
RemoteBitrateObserver* observer,
|
||||||
|
Clock* clock);
|
||||||
|
|
||||||
// Stores an RTCP SR (NTP, RTP timestamp) tuple for a specific SSRC to be used
|
// Stores an RTCP SR (NTP, RTP timestamp) tuple for a specific SSRC to be used
|
||||||
// in future RTP timestamp to NTP time conversions. As soon as any SSRC has
|
// in future RTP timestamp to NTP time conversions. As soon as any SSRC has
|
||||||
@ -61,13 +66,6 @@ class RemoteBitrateEstimator {
|
|||||||
int64_t arrival_time,
|
int64_t arrival_time,
|
||||||
uint32_t rtp_timestamp) = 0;
|
uint32_t rtp_timestamp) = 0;
|
||||||
|
|
||||||
// Triggers a new estimate calculation.
|
|
||||||
virtual void UpdateEstimate(unsigned int ssrc, int64_t time_now) = 0;
|
|
||||||
|
|
||||||
// Set the current round-trip time experienced by the streams going into this
|
|
||||||
// estimator.
|
|
||||||
virtual void SetRtt(unsigned int rtt) = 0;
|
|
||||||
|
|
||||||
// Removes all data for |ssrc|.
|
// Removes all data for |ssrc|.
|
||||||
virtual void RemoveStream(unsigned int ssrc) = 0;
|
virtual void RemoveStream(unsigned int ssrc) = 0;
|
||||||
|
|
||||||
@ -76,6 +74,10 @@ class RemoteBitrateEstimator {
|
|||||||
// currently being received and of which the bitrate estimate is based upon.
|
// currently being received and of which the bitrate estimate is based upon.
|
||||||
virtual bool LatestEstimate(std::vector<unsigned int>* ssrcs,
|
virtual bool LatestEstimate(std::vector<unsigned int>* ssrcs,
|
||||||
unsigned int* bitrate_bps) const = 0;
|
unsigned int* bitrate_bps) const = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
static const int kProcessIntervalMs = 1000;
|
||||||
|
static const int kStreamTimeOutMs = 2000;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -43,7 +43,8 @@ OveruseDetector::OveruseDetector(const OverUseDetectorOptions& options)
|
|||||||
prev_offset_(0.0),
|
prev_offset_(0.0),
|
||||||
time_over_using_(-1),
|
time_over_using_(-1),
|
||||||
over_use_counter_(0),
|
over_use_counter_(0),
|
||||||
hypothesis_(kBwNormal)
|
hypothesis_(kBwNormal),
|
||||||
|
time_of_last_received_packet_(-1)
|
||||||
#ifdef WEBRTC_BWE_MATLAB
|
#ifdef WEBRTC_BWE_MATLAB
|
||||||
, plots_()
|
, plots_()
|
||||||
#endif
|
#endif
|
||||||
@ -80,6 +81,7 @@ void OveruseDetector::Update(uint16_t packet_size,
|
|||||||
int64_t timestamp_ms,
|
int64_t timestamp_ms,
|
||||||
uint32_t timestamp,
|
uint32_t timestamp,
|
||||||
const int64_t now_ms) {
|
const int64_t now_ms) {
|
||||||
|
time_of_last_received_packet_ = now_ms;
|
||||||
#ifdef WEBRTC_BWE_MATLAB
|
#ifdef WEBRTC_BWE_MATLAB
|
||||||
// Create plots
|
// Create plots
|
||||||
const int64_t startTimeMs = nowMS;
|
const int64_t startTimeMs = nowMS;
|
||||||
@ -166,6 +168,10 @@ void OveruseDetector::SetRateControlRegion(RateControlRegion region) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t OveruseDetector::time_of_last_received_packet() const {
|
||||||
|
return time_of_last_received_packet_;
|
||||||
|
}
|
||||||
|
|
||||||
void OveruseDetector::SwitchTimeBase() {
|
void OveruseDetector::SwitchTimeBase() {
|
||||||
current_frame_.size = 0;
|
current_frame_.size = 0;
|
||||||
current_frame_.complete_time_ms = -1;
|
current_frame_.complete_time_ms = -1;
|
||||||
|
@ -23,6 +23,8 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
enum RateControlRegion;
|
enum RateControlRegion;
|
||||||
|
|
||||||
|
// This class is assumed to be protected by the owner if used by multiple
|
||||||
|
// threads.
|
||||||
class OveruseDetector {
|
class OveruseDetector {
|
||||||
public:
|
public:
|
||||||
explicit OveruseDetector(const OverUseDetectorOptions& options);
|
explicit OveruseDetector(const OverUseDetectorOptions& options);
|
||||||
@ -34,6 +36,7 @@ class OveruseDetector {
|
|||||||
BandwidthUsage State() const;
|
BandwidthUsage State() const;
|
||||||
double NoiseVar() const;
|
double NoiseVar() const;
|
||||||
void SetRateControlRegion(RateControlRegion region);
|
void SetRateControlRegion(RateControlRegion region);
|
||||||
|
int64_t time_of_last_received_packet() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct FrameSample {
|
struct FrameSample {
|
||||||
@ -100,6 +103,7 @@ class OveruseDetector {
|
|||||||
double time_over_using_;
|
double time_over_using_;
|
||||||
uint16_t over_use_counter_;
|
uint16_t over_use_counter_;
|
||||||
BandwidthUsage hypothesis_;
|
BandwidthUsage hypothesis_;
|
||||||
|
int64_t time_of_last_received_packet_;
|
||||||
#ifdef WEBRTC_BWE_MATLAB
|
#ifdef WEBRTC_BWE_MATLAB
|
||||||
DebugPlots plots_;
|
DebugPlots plots_;
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,38 +8,43 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.h"
|
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_multi_stream.h"
|
||||||
|
|
||||||
#include "modules/remote_bitrate_estimator/include/rtp_to_ntp.h"
|
#include "webrtc/modules/remote_bitrate_estimator/include/rtp_to_ntp.h"
|
||||||
#include "modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
|
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
|
||||||
#include "system_wrappers/interface/tick_util.h"
|
#include "webrtc/system_wrappers/interface/clock.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/tick_util.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
RemoteBitrateEstimator* RemoteBitrateEstimator::Create(
|
RemoteBitrateEstimator* RemoteBitrateEstimator::Create(
|
||||||
RemoteBitrateObserver* observer,
|
|
||||||
const OverUseDetectorOptions& options,
|
const OverUseDetectorOptions& options,
|
||||||
EstimationMode mode) {
|
EstimationMode mode,
|
||||||
|
RemoteBitrateObserver* observer,
|
||||||
|
Clock* clock) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case kMultiStreamEstimation:
|
case kMultiStreamEstimation:
|
||||||
return new RemoteBitrateEstimatorMultiStream(observer, options);
|
return new RemoteBitrateEstimatorMultiStream(options, observer, clock);
|
||||||
case kSingleStreamEstimation:
|
case kSingleStreamEstimation:
|
||||||
return new RemoteBitrateEstimatorSingleStream(observer, options);
|
return new RemoteBitrateEstimatorSingleStream(options, observer, clock);
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
RemoteBitrateEstimatorMultiStream::RemoteBitrateEstimatorMultiStream(
|
RemoteBitrateEstimatorMultiStream::RemoteBitrateEstimatorMultiStream(
|
||||||
|
const OverUseDetectorOptions& options,
|
||||||
RemoteBitrateObserver* observer,
|
RemoteBitrateObserver* observer,
|
||||||
const OverUseDetectorOptions& options)
|
Clock* clock)
|
||||||
: remote_rate_(),
|
: clock_(clock),
|
||||||
|
remote_rate_(),
|
||||||
overuse_detector_(options),
|
overuse_detector_(options),
|
||||||
incoming_bitrate_(),
|
incoming_bitrate_(),
|
||||||
observer_(observer),
|
observer_(observer),
|
||||||
streams_(),
|
streams_(),
|
||||||
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
initial_ssrc_(0),
|
initial_ssrc_(0),
|
||||||
multi_stream_(false) {
|
multi_stream_(false),
|
||||||
|
last_process_time_(-1) {
|
||||||
assert(observer_);
|
assert(observer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,16 +113,45 @@ void RemoteBitrateEstimatorMultiStream::IncomingPacket(unsigned int ssrc,
|
|||||||
}
|
}
|
||||||
overuse_detector_.Update(payload_size, timestamp_in_ms, rtp_timestamp,
|
overuse_detector_.Update(payload_size, timestamp_in_ms, rtp_timestamp,
|
||||||
arrival_time);
|
arrival_time);
|
||||||
if (prior_state != kBwOverusing &&
|
if (overuse_detector_.State() == kBwOverusing) {
|
||||||
overuse_detector_.State() == kBwOverusing) {
|
unsigned int incoming_bitrate = incoming_bitrate_.BitRate(arrival_time);
|
||||||
// The first overuse should immediately trigger a new estimate.
|
if (prior_state != kBwOverusing ||
|
||||||
UpdateEstimate(1, arrival_time);
|
remote_rate_.TimeToReduceFurther(arrival_time, incoming_bitrate)) {
|
||||||
|
// The first overuse should immediately trigger a new estimate.
|
||||||
|
// We also have to update the estimate immediately if we are overusing
|
||||||
|
// and the target bitrate is too high compared to what we are receiving.
|
||||||
|
UpdateEstimate(arrival_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteBitrateEstimatorMultiStream::UpdateEstimate(unsigned int ssrc,
|
int32_t RemoteBitrateEstimatorMultiStream::Process() {
|
||||||
int64_t time_now) {
|
if (TimeUntilNextProcess() > 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
UpdateEstimate(clock_->TimeInMilliseconds());
|
||||||
|
last_process_time_ = clock_->TimeInMilliseconds();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t RemoteBitrateEstimatorMultiStream::TimeUntilNextProcess() {
|
||||||
|
if (last_process_time_ < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return last_process_time_ + kProcessIntervalMs - clock_->TimeInMilliseconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteBitrateEstimatorMultiStream::UpdateEstimate(int64_t time_now) {
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
CriticalSectionScoped cs(crit_sect_.get());
|
||||||
|
const int64_t time_of_last_received_packet =
|
||||||
|
overuse_detector_.time_of_last_received_packet();
|
||||||
|
if (time_of_last_received_packet >= 0 &&
|
||||||
|
time_now - time_of_last_received_packet > kStreamTimeOutMs) {
|
||||||
|
// This over-use detector hasn't received packets for |kStreamTimeOutMs|
|
||||||
|
// milliseconds and is considered stale.
|
||||||
|
remote_rate_.Reset();
|
||||||
|
return;
|
||||||
|
}
|
||||||
const RateControlInput input(overuse_detector_.State(),
|
const RateControlInput input(overuse_detector_.State(),
|
||||||
incoming_bitrate_.BitRate(time_now),
|
incoming_bitrate_.BitRate(time_now),
|
||||||
overuse_detector_.NoiseVar());
|
overuse_detector_.NoiseVar());
|
||||||
@ -133,7 +167,7 @@ void RemoteBitrateEstimatorMultiStream::UpdateEstimate(unsigned int ssrc,
|
|||||||
overuse_detector_.SetRateControlRegion(region);
|
overuse_detector_.SetRateControlRegion(region);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteBitrateEstimatorMultiStream::SetRtt(unsigned int rtt) {
|
void RemoteBitrateEstimatorMultiStream::OnRttUpdate(uint32_t rtt) {
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
CriticalSectionScoped cs(crit_sect_.get());
|
||||||
remote_rate_.SetRtt(rtt);
|
remote_rate_.SetRtt(rtt);
|
||||||
}
|
}
|
||||||
|
@ -27,10 +27,13 @@
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class Clock;
|
||||||
|
|
||||||
class RemoteBitrateEstimatorMultiStream : public RemoteBitrateEstimator {
|
class RemoteBitrateEstimatorMultiStream : public RemoteBitrateEstimator {
|
||||||
public:
|
public:
|
||||||
RemoteBitrateEstimatorMultiStream(RemoteBitrateObserver* observer,
|
RemoteBitrateEstimatorMultiStream(const OverUseDetectorOptions& options,
|
||||||
const OverUseDetectorOptions& options);
|
RemoteBitrateObserver* observer,
|
||||||
|
Clock* clock);
|
||||||
|
|
||||||
~RemoteBitrateEstimatorMultiStream() {}
|
~RemoteBitrateEstimatorMultiStream() {}
|
||||||
|
|
||||||
@ -52,11 +55,12 @@ class RemoteBitrateEstimatorMultiStream : public RemoteBitrateEstimator {
|
|||||||
uint32_t rtp_timestamp);
|
uint32_t rtp_timestamp);
|
||||||
|
|
||||||
// Triggers a new estimate calculation.
|
// Triggers a new estimate calculation.
|
||||||
void UpdateEstimate(unsigned int ssrc, int64_t time_now);
|
// Implements the Module interface.
|
||||||
|
virtual int32_t Process();
|
||||||
// Set the current round-trip time experienced by the streams going into this
|
virtual int32_t TimeUntilNextProcess();
|
||||||
// estimator.
|
// Set the current round-trip time experienced by the stream.
|
||||||
void SetRtt(unsigned int rtt);
|
// Implements the StatsObserver interface.
|
||||||
|
virtual void OnRttUpdate(uint32_t rtt);
|
||||||
|
|
||||||
// Removes all data for |ssrc|.
|
// Removes all data for |ssrc|.
|
||||||
void RemoveStream(unsigned int ssrc);
|
void RemoveStream(unsigned int ssrc);
|
||||||
@ -70,8 +74,12 @@ class RemoteBitrateEstimatorMultiStream : public RemoteBitrateEstimator {
|
|||||||
private:
|
private:
|
||||||
typedef std::map<unsigned int, synchronization::RtcpList> StreamMap;
|
typedef std::map<unsigned int, synchronization::RtcpList> StreamMap;
|
||||||
|
|
||||||
|
// Triggers a new estimate calculation.
|
||||||
|
void UpdateEstimate(int64_t time_now);
|
||||||
|
|
||||||
void GetSsrcs(std::vector<unsigned int>* ssrcs) const;
|
void GetSsrcs(std::vector<unsigned int>* ssrcs) const;
|
||||||
|
|
||||||
|
Clock* clock_;
|
||||||
RemoteRateControl remote_rate_;
|
RemoteRateControl remote_rate_;
|
||||||
OveruseDetector overuse_detector_;
|
OveruseDetector overuse_detector_;
|
||||||
BitRateStats incoming_bitrate_;
|
BitRateStats incoming_bitrate_;
|
||||||
@ -80,6 +88,7 @@ class RemoteBitrateEstimatorMultiStream : public RemoteBitrateEstimator {
|
|||||||
scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
||||||
unsigned int initial_ssrc_;
|
unsigned int initial_ssrc_;
|
||||||
bool multi_stream_;
|
bool multi_stream_;
|
||||||
|
int32_t last_process_time_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(RemoteBitrateEstimatorMultiStream);
|
DISALLOW_COPY_AND_ASSIGN(RemoteBitrateEstimatorMultiStream);
|
||||||
};
|
};
|
||||||
|
@ -8,17 +8,21 @@
|
|||||||
* be found in the AUTHORS file in the root of the source tree.
|
* be found in the AUTHORS file in the root of the source tree.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
|
#include "webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_single_stream.h"
|
||||||
|
|
||||||
#include "system_wrappers/interface/tick_util.h"
|
#include "webrtc/system_wrappers/interface/clock.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
RemoteBitrateEstimatorSingleStream::RemoteBitrateEstimatorSingleStream(
|
RemoteBitrateEstimatorSingleStream::RemoteBitrateEstimatorSingleStream(
|
||||||
RemoteBitrateObserver* observer, const OverUseDetectorOptions& options)
|
const OverUseDetectorOptions& options,
|
||||||
|
RemoteBitrateObserver* observer,
|
||||||
|
Clock* clock)
|
||||||
: options_(options),
|
: options_(options),
|
||||||
|
clock_(clock),
|
||||||
observer_(observer),
|
observer_(observer),
|
||||||
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()) {
|
crit_sect_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
|
last_process_time_(-1) {
|
||||||
assert(observer_);
|
assert(observer_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,37 +49,80 @@ void RemoteBitrateEstimatorSingleStream::IncomingPacket(
|
|||||||
incoming_bitrate_.Update(payload_size, arrival_time);
|
incoming_bitrate_.Update(payload_size, arrival_time);
|
||||||
const BandwidthUsage prior_state = overuse_detector->State();
|
const BandwidthUsage prior_state = overuse_detector->State();
|
||||||
overuse_detector->Update(payload_size, -1, rtp_timestamp, arrival_time);
|
overuse_detector->Update(payload_size, -1, rtp_timestamp, arrival_time);
|
||||||
if (prior_state != overuse_detector->State() &&
|
if (overuse_detector->State() == kBwOverusing) {
|
||||||
overuse_detector->State() == kBwOverusing) {
|
unsigned int incoming_bitrate = incoming_bitrate_.BitRate(arrival_time);
|
||||||
// The first overuse should immediately trigger a new estimate.
|
if (prior_state != kBwOverusing ||
|
||||||
UpdateEstimate(ssrc, arrival_time);
|
remote_rate_.TimeToReduceFurther(arrival_time, incoming_bitrate)) {
|
||||||
|
// The first overuse should immediately trigger a new estimate.
|
||||||
|
// We also have to update the estimate immediately if we are overusing
|
||||||
|
// and the target bitrate is too high compared to what we are receiving.
|
||||||
|
UpdateEstimate(arrival_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteBitrateEstimatorSingleStream::UpdateEstimate(unsigned int ssrc,
|
int32_t RemoteBitrateEstimatorSingleStream::Process() {
|
||||||
int64_t time_now) {
|
if (TimeUntilNextProcess() > 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
UpdateEstimate(clock_->TimeInMilliseconds());
|
||||||
|
last_process_time_ = clock_->TimeInMilliseconds();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t RemoteBitrateEstimatorSingleStream::TimeUntilNextProcess() {
|
||||||
|
if (last_process_time_ < 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return last_process_time_ + kProcessIntervalMs - clock_->TimeInMilliseconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RemoteBitrateEstimatorSingleStream::UpdateEstimate(int64_t time_now) {
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
CriticalSectionScoped cs(crit_sect_.get());
|
||||||
SsrcOveruseDetectorMap::iterator it = overuse_detectors_.find(ssrc);
|
BandwidthUsage bw_state = kBwNormal;
|
||||||
if (it == overuse_detectors_.end()) {
|
double sum_noise_var = 0.0;
|
||||||
|
SsrcOveruseDetectorMap::iterator it = overuse_detectors_.begin();
|
||||||
|
while (it != overuse_detectors_.end()) {
|
||||||
|
const int64_t time_of_last_received_packet =
|
||||||
|
it->second.time_of_last_received_packet();
|
||||||
|
if (time_of_last_received_packet >= 0 &&
|
||||||
|
time_now - time_of_last_received_packet > kStreamTimeOutMs) {
|
||||||
|
// This over-use detector hasn't received packets for |kStreamTimeOutMs|
|
||||||
|
// milliseconds and is considered stale.
|
||||||
|
overuse_detectors_.erase(it++);
|
||||||
|
} else {
|
||||||
|
sum_noise_var += it->second.NoiseVar();
|
||||||
|
// Make sure that we trigger an over-use if any of the over-use detectors
|
||||||
|
// is detecting over-use.
|
||||||
|
if (it->second.State() > bw_state) {
|
||||||
|
bw_state = it->second.State();
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We can't update the estimate if we don't have any active streams.
|
||||||
|
if (overuse_detectors_.empty()) {
|
||||||
|
remote_rate_.Reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
OveruseDetector* overuse_detector = &it->second;
|
double mean_noise_var = sum_noise_var /
|
||||||
const RateControlInput input(overuse_detector->State(),
|
static_cast<double>(overuse_detectors_.size());
|
||||||
|
const RateControlInput input(bw_state,
|
||||||
incoming_bitrate_.BitRate(time_now),
|
incoming_bitrate_.BitRate(time_now),
|
||||||
overuse_detector->NoiseVar());
|
mean_noise_var);
|
||||||
const RateControlRegion region = remote_rate_.Update(&input, time_now);
|
const RateControlRegion region = remote_rate_.Update(&input, time_now);
|
||||||
unsigned int target_bitrate = remote_rate_.UpdateBandwidthEstimate(time_now);
|
unsigned int target_bitrate = remote_rate_.UpdateBandwidthEstimate(time_now);
|
||||||
if (remote_rate_.ValidEstimate()) {
|
if (remote_rate_.ValidEstimate()) {
|
||||||
std::vector<unsigned int> ssrcs;
|
std::vector<unsigned int> ssrcs;
|
||||||
GetSsrcs(&ssrcs);
|
GetSsrcs(&ssrcs);
|
||||||
if (!ssrcs.empty()) {
|
observer_->OnReceiveBitrateChanged(&ssrcs, target_bitrate);
|
||||||
observer_->OnReceiveBitrateChanged(&ssrcs, target_bitrate);
|
}
|
||||||
}
|
for (it = overuse_detectors_.begin(); it != overuse_detectors_.end(); ++it) {
|
||||||
|
it->second.SetRateControlRegion(region);
|
||||||
}
|
}
|
||||||
overuse_detector->SetRateControlRegion(region);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteBitrateEstimatorSingleStream::SetRtt(unsigned int rtt) {
|
void RemoteBitrateEstimatorSingleStream::OnRttUpdate(uint32_t rtt) {
|
||||||
CriticalSectionScoped cs(crit_sect_.get());
|
CriticalSectionScoped cs(crit_sect_.get());
|
||||||
remote_rate_.SetRtt(rtt);
|
remote_rate_.SetRtt(rtt);
|
||||||
}
|
}
|
||||||
|
@ -15,20 +15,25 @@
|
|||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "modules/remote_bitrate_estimator/bitrate_estimator.h"
|
#include "webrtc/modules/remote_bitrate_estimator/bitrate_estimator.h"
|
||||||
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
||||||
#include "modules/remote_bitrate_estimator/overuse_detector.h"
|
#include "webrtc/modules/remote_bitrate_estimator/overuse_detector.h"
|
||||||
#include "modules/remote_bitrate_estimator/remote_rate_control.h"
|
#include "webrtc/modules/remote_bitrate_estimator/remote_rate_control.h"
|
||||||
#include "system_wrappers/interface/critical_section_wrapper.h"
|
#include "webrtc/system_wrappers/interface/critical_section_wrapper.h"
|
||||||
#include "system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
#include "typedefs.h"
|
#include "webrtc/typedefs.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
class Clock;
|
||||||
|
|
||||||
class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator {
|
class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator {
|
||||||
public:
|
public:
|
||||||
RemoteBitrateEstimatorSingleStream(RemoteBitrateObserver* observer,
|
RemoteBitrateEstimatorSingleStream(const OverUseDetectorOptions& options,
|
||||||
const OverUseDetectorOptions& options);
|
RemoteBitrateObserver* observer,
|
||||||
|
Clock* clock);
|
||||||
|
|
||||||
|
virtual ~RemoteBitrateEstimatorSingleStream() {}
|
||||||
|
|
||||||
void IncomingRtcp(unsigned int ssrc, uint32_t ntp_secs, uint32_t ntp_frac,
|
void IncomingRtcp(unsigned int ssrc, uint32_t ntp_secs, uint32_t ntp_frac,
|
||||||
uint32_t rtp_timestamp) {}
|
uint32_t rtp_timestamp) {}
|
||||||
@ -43,12 +48,13 @@ class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator {
|
|||||||
int64_t arrival_time,
|
int64_t arrival_time,
|
||||||
uint32_t rtp_timestamp);
|
uint32_t rtp_timestamp);
|
||||||
|
|
||||||
// Triggers a new estimate calculation for the stream identified by |ssrc|.
|
// Triggers a new estimate calculation.
|
||||||
void UpdateEstimate(unsigned int ssrc, int64_t time_now);
|
// Implements the Module interface.
|
||||||
|
virtual int32_t Process();
|
||||||
// Set the current round-trip time experienced by the stream identified by
|
virtual int32_t TimeUntilNextProcess();
|
||||||
// |ssrc|.
|
// Set the current round-trip time experienced by the stream.
|
||||||
void SetRtt(unsigned int ssrc);
|
// Implements the StatsObserver interface.
|
||||||
|
virtual void OnRttUpdate(uint32_t rtt);
|
||||||
|
|
||||||
// Removes all data for |ssrc|.
|
// Removes all data for |ssrc|.
|
||||||
void RemoveStream(unsigned int ssrc);
|
void RemoveStream(unsigned int ssrc);
|
||||||
@ -62,14 +68,19 @@ class RemoteBitrateEstimatorSingleStream : public RemoteBitrateEstimator {
|
|||||||
private:
|
private:
|
||||||
typedef std::map<unsigned int, OveruseDetector> SsrcOveruseDetectorMap;
|
typedef std::map<unsigned int, OveruseDetector> SsrcOveruseDetectorMap;
|
||||||
|
|
||||||
|
// Triggers a new estimate calculation.
|
||||||
|
void UpdateEstimate(int64_t time_now);
|
||||||
|
|
||||||
void GetSsrcs(std::vector<unsigned int>* ssrcs) const;
|
void GetSsrcs(std::vector<unsigned int>* ssrcs) const;
|
||||||
|
|
||||||
const OverUseDetectorOptions& options_;
|
const OverUseDetectorOptions& options_;
|
||||||
|
Clock* clock_;
|
||||||
SsrcOveruseDetectorMap overuse_detectors_;
|
SsrcOveruseDetectorMap overuse_detectors_;
|
||||||
BitRateStats incoming_bitrate_;
|
BitRateStats incoming_bitrate_;
|
||||||
RemoteRateControl remote_rate_;
|
RemoteRateControl remote_rate_;
|
||||||
RemoteBitrateObserver* observer_;
|
RemoteBitrateObserver* observer_;
|
||||||
scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
scoped_ptr<CriticalSectionWrapper> crit_sect_;
|
||||||
|
int64_t last_process_time_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -23,73 +23,84 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
TEST_F(RemoteBitrateEstimatorTest, TestInitialBehavior) {
|
TEST_F(RemoteBitrateEstimatorTest, TestInitialBehavior) {
|
||||||
|
const int kFramerate = 50; // 50 fps to avoid rounding errors.
|
||||||
|
const int kFrameIntervalMs = 1000 / kFramerate;
|
||||||
unsigned int bitrate_bps = 0;
|
unsigned int bitrate_bps = 0;
|
||||||
int64_t time_now = 0;
|
|
||||||
uint32_t timestamp = 0;
|
uint32_t timestamp = 0;
|
||||||
std::vector<unsigned int> ssrcs;
|
std::vector<unsigned int> ssrcs;
|
||||||
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
||||||
EXPECT_EQ(0u, ssrcs.size());
|
EXPECT_EQ(0u, ssrcs.size());
|
||||||
bitrate_estimator_->UpdateEstimate(kDefaultSsrc, time_now);
|
clock_.AdvanceTimeMilliseconds(1000);
|
||||||
|
bitrate_estimator_->Process();
|
||||||
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
||||||
EXPECT_FALSE(bitrate_observer_->updated());
|
EXPECT_FALSE(bitrate_observer_->updated());
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
|
clock_.AdvanceTimeMilliseconds(1000);
|
||||||
// Inserting a packet. Still no valid estimate. We need to wait 1 second.
|
// Inserting a packet. Still no valid estimate. We need to wait 1 second.
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc, kMtu, time_now,
|
bitrate_estimator_->IncomingPacket(kDefaultSsrc, kMtu,
|
||||||
timestamp);
|
clock_.TimeInMilliseconds(), timestamp);
|
||||||
bitrate_estimator_->UpdateEstimate(kDefaultSsrc, time_now);
|
bitrate_estimator_->Process();
|
||||||
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
EXPECT_FALSE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
||||||
EXPECT_EQ(0u, ssrcs.size());
|
EXPECT_EQ(0u, ssrcs.size());
|
||||||
EXPECT_FALSE(bitrate_observer_->updated());
|
EXPECT_FALSE(bitrate_observer_->updated());
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
// Waiting more than one second gives us a valid estimate.
|
// Inserting packets for one second to get a valid estimate.
|
||||||
// We need at least two packets for the incoming bitrate to be > 0 since the
|
for (int i = 0; i < kFramerate; ++i) {
|
||||||
// window is 500 ms.
|
bitrate_estimator_->IncomingPacket(kDefaultSsrc, kMtu,
|
||||||
time_now += 499;
|
clock_.TimeInMilliseconds(), timestamp);
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc, kMtu, time_now,
|
clock_.AdvanceTimeMilliseconds(1000 / kFramerate);
|
||||||
timestamp);
|
timestamp += 90 * kFrameIntervalMs;
|
||||||
time_now += 2;
|
}
|
||||||
bitrate_estimator_->UpdateEstimate(kDefaultSsrc, time_now);
|
bitrate_estimator_->Process();
|
||||||
EXPECT_TRUE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
EXPECT_TRUE(bitrate_estimator_->LatestEstimate(&ssrcs, &bitrate_bps));
|
||||||
EXPECT_EQ(1u, ssrcs.size());
|
ASSERT_EQ(1u, ssrcs.size());
|
||||||
EXPECT_EQ(kDefaultSsrc, ssrcs.front());
|
EXPECT_EQ(kDefaultSsrc, ssrcs.front());
|
||||||
EXPECT_EQ(20607u, bitrate_bps);
|
EXPECT_EQ(498075u, bitrate_bps);
|
||||||
EXPECT_TRUE(bitrate_observer_->updated());
|
EXPECT_TRUE(bitrate_observer_->updated());
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
EXPECT_EQ(bitrate_observer_->latest_bitrate(), bitrate_bps);
|
EXPECT_EQ(bitrate_observer_->latest_bitrate(), bitrate_bps);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(RemoteBitrateEstimatorTest, TestRateIncreaseReordering) {
|
TEST_F(RemoteBitrateEstimatorTest, TestRateIncreaseReordering) {
|
||||||
int64_t time_now = 0;
|
|
||||||
uint32_t timestamp = 0;
|
uint32_t timestamp = 0;
|
||||||
const int framerate = 50; // 50 fps to avoid rounding errors.
|
const int kFramerate = 50; // 50 fps to avoid rounding errors.
|
||||||
const int frame_interval_ms = 1000 / framerate;
|
const int kFrameIntervalMs = 1000 / kFramerate;
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc, 1000, time_now, timestamp);
|
bitrate_estimator_->IncomingPacket(kDefaultSsrc, 1000,
|
||||||
bitrate_estimator_->UpdateEstimate(kDefaultSsrc, time_now);
|
clock_.TimeInMilliseconds(), timestamp);
|
||||||
|
bitrate_estimator_->Process();
|
||||||
EXPECT_FALSE(bitrate_observer_->updated()); // No valid estimate.
|
EXPECT_FALSE(bitrate_observer_->updated()); // No valid estimate.
|
||||||
// Increase time with 1 second to get a valid estimate.
|
// Inserting packets for one second to get a valid estimate.
|
||||||
time_now += 1000;
|
for (int i = 0; i < kFramerate; ++i) {
|
||||||
timestamp += 90 * 1000;
|
bitrate_estimator_->IncomingPacket(kDefaultSsrc, kMtu,
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc, 1000, time_now, timestamp);
|
clock_.TimeInMilliseconds(), timestamp);
|
||||||
bitrate_estimator_->UpdateEstimate(kDefaultSsrc, time_now);
|
clock_.AdvanceTimeMilliseconds(kFrameIntervalMs);
|
||||||
|
timestamp += 90 * kFrameIntervalMs;
|
||||||
|
}
|
||||||
|
bitrate_estimator_->Process();
|
||||||
EXPECT_TRUE(bitrate_observer_->updated());
|
EXPECT_TRUE(bitrate_observer_->updated());
|
||||||
EXPECT_EQ(17645u, bitrate_observer_->latest_bitrate());
|
EXPECT_EQ(498136u, bitrate_observer_->latest_bitrate());
|
||||||
for (int i = 0; i < 10; ++i) {
|
for (int i = 0; i < 10; ++i) {
|
||||||
time_now += 2 * frame_interval_ms;
|
clock_.AdvanceTimeMilliseconds(2 * kFrameIntervalMs);
|
||||||
timestamp += 2 * 90 * frame_interval_ms;
|
timestamp += 2 * 90 * kFrameIntervalMs;
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc, 1000, time_now, timestamp);
|
bitrate_estimator_->IncomingPacket(kDefaultSsrc, 1000,
|
||||||
|
clock_.TimeInMilliseconds(), timestamp);
|
||||||
bitrate_estimator_->IncomingPacket(kDefaultSsrc,
|
bitrate_estimator_->IncomingPacket(kDefaultSsrc,
|
||||||
1000,
|
1000,
|
||||||
time_now - frame_interval_ms,
|
clock_.TimeInMilliseconds() -
|
||||||
timestamp - 90 * frame_interval_ms);
|
kFrameIntervalMs,
|
||||||
|
timestamp - 90 * kFrameIntervalMs);
|
||||||
}
|
}
|
||||||
bitrate_estimator_->UpdateEstimate(kDefaultSsrc, time_now);
|
bitrate_estimator_->Process();
|
||||||
EXPECT_TRUE(bitrate_observer_->updated());
|
EXPECT_TRUE(bitrate_observer_->updated());
|
||||||
EXPECT_EQ(18985u, bitrate_observer_->latest_bitrate());
|
EXPECT_EQ(498136u, bitrate_observer_->latest_bitrate());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we initially increase the bitrate as expected.
|
// Make sure we initially increase the bitrate as expected.
|
||||||
TEST_F(RemoteBitrateEstimatorTest, TestRateIncreaseRtpTimestamps) {
|
TEST_F(RemoteBitrateEstimatorTest, TestRateIncreaseRtpTimestamps) {
|
||||||
const int kExpectedIterations = 276;
|
// This threshold corresponds approximately to increasing linearly with
|
||||||
|
// bitrate(i) = 1.04 * bitrate(i-1) + 1000
|
||||||
|
// until bitrate(i) > 500000, with bitrate(1) ~= 30000.
|
||||||
|
const int kExpectedIterations = 1621;
|
||||||
unsigned int bitrate_bps = 30000;
|
unsigned int bitrate_bps = 30000;
|
||||||
int iterations = 0;
|
int iterations = 0;
|
||||||
AddDefaultStream();
|
AddDefaultStream();
|
||||||
@ -114,32 +125,35 @@ TEST_F(RemoteBitrateEstimatorTest, TestRateIncreaseRtpTimestamps) {
|
|||||||
// Verify that the time it takes for the estimator to reduce the bitrate when
|
// Verify that the time it takes for the estimator to reduce the bitrate when
|
||||||
// the capacity is tightened stays the same.
|
// the capacity is tightened stays the same.
|
||||||
TEST_F(RemoteBitrateEstimatorTest, TestCapacityDropRtpTimestamps) {
|
TEST_F(RemoteBitrateEstimatorTest, TestCapacityDropRtpTimestamps) {
|
||||||
const int kNumberOfFrames= 300;
|
const int kNumberOfFrames = 300;
|
||||||
const int kStartBitrate = 900e3;
|
const int kStartBitrate = 900e3;
|
||||||
const int kMinExpectedBitrate = 800e3;
|
const int kMinExpectedBitrate = 800e3;
|
||||||
const int kMaxExpectedBitrate = 1100e3;
|
const int kMaxExpectedBitrate = 1100e3;
|
||||||
AddDefaultStream();
|
AddDefaultStream();
|
||||||
// Run in steady state to make the estimator converge.
|
// Run in steady state to make the estimator converge.
|
||||||
|
unsigned int capacity_bps = 1000e3;
|
||||||
stream_generator_->set_capacity_bps(1000e3);
|
stream_generator_->set_capacity_bps(1000e3);
|
||||||
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc, kNumberOfFrames,
|
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc, kNumberOfFrames,
|
||||||
kStartBitrate, kMinExpectedBitrate,
|
kStartBitrate, kMinExpectedBitrate,
|
||||||
kMaxExpectedBitrate);
|
kMaxExpectedBitrate, capacity_bps);
|
||||||
// Reduce the capacity and verify the decrease time.
|
// Reduce the capacity and verify the decrease time.
|
||||||
stream_generator_->set_capacity_bps(500e3);
|
capacity_bps = 500e3;
|
||||||
|
stream_generator_->set_capacity_bps(capacity_bps);
|
||||||
|
int64_t overuse_start_time = clock_.TimeInMilliseconds();
|
||||||
int64_t bitrate_drop_time = -1;
|
int64_t bitrate_drop_time = -1;
|
||||||
for (int i = 0; i < 200; ++i) {
|
for (int i = 0; i < 200; ++i) {
|
||||||
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
||||||
// Check for either increase or decrease.
|
// Check for either increase or decrease.
|
||||||
if (bitrate_observer_->updated()) {
|
if (bitrate_observer_->updated()) {
|
||||||
if (bitrate_drop_time == -1 &&
|
if (bitrate_drop_time == -1 &&
|
||||||
bitrate_observer_->latest_bitrate() <= 500e3) {
|
bitrate_observer_->latest_bitrate() <= capacity_bps) {
|
||||||
bitrate_drop_time = time_now_;
|
bitrate_drop_time = clock_.TimeInMilliseconds();
|
||||||
}
|
}
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
bitrate_bps = bitrate_observer_->latest_bitrate();
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPECT_EQ(10333, bitrate_drop_time);
|
EXPECT_EQ(367, bitrate_drop_time - overuse_start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the time it takes for the estimator to reduce the bitrate when
|
// Verify that the time it takes for the estimator to reduce the bitrate when
|
||||||
@ -156,29 +170,33 @@ TEST_F(RemoteBitrateEstimatorTest, TestCapacityDropRtpTimestampsWrap) {
|
|||||||
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
||||||
std::numeric_limits<uint32_t>::max() - kSteadyStateTime * 90000);
|
std::numeric_limits<uint32_t>::max() - kSteadyStateTime * 90000);
|
||||||
// Run in steady state to make the estimator converge.
|
// Run in steady state to make the estimator converge.
|
||||||
|
unsigned int capacity_bps = 1000e3;
|
||||||
stream_generator_->set_capacity_bps(1000e3);
|
stream_generator_->set_capacity_bps(1000e3);
|
||||||
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
||||||
kSteadyStateTime * kFramerate,
|
kSteadyStateTime * kFramerate,
|
||||||
kStartBitrate,
|
kStartBitrate,
|
||||||
kMinExpectedBitrate,
|
kMinExpectedBitrate,
|
||||||
kMaxExpectedBitrate);
|
kMaxExpectedBitrate,
|
||||||
|
capacity_bps);
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
// Reduce the capacity and verify the decrease time.
|
// Reduce the capacity and verify the decrease time.
|
||||||
stream_generator_->set_capacity_bps(500e3);
|
capacity_bps = 500e3;
|
||||||
|
stream_generator_->set_capacity_bps(capacity_bps);
|
||||||
|
int64_t overuse_start_time = clock_.TimeInMilliseconds();
|
||||||
int64_t bitrate_drop_time = -1;
|
int64_t bitrate_drop_time = -1;
|
||||||
for (int i = 0; i < 200; ++i) {
|
for (int i = 0; i < 200; ++i) {
|
||||||
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
||||||
// Check for either increase or decrease.
|
// Check for either increase or decrease.
|
||||||
if (bitrate_observer_->updated()) {
|
if (bitrate_observer_->updated()) {
|
||||||
if (bitrate_drop_time == -1 &&
|
if (bitrate_drop_time == -1 &&
|
||||||
bitrate_observer_->latest_bitrate() <= 500e3) {
|
bitrate_observer_->latest_bitrate() <= capacity_bps) {
|
||||||
bitrate_drop_time = time_now_;
|
bitrate_drop_time = clock_.TimeInMilliseconds();
|
||||||
}
|
}
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
bitrate_bps = bitrate_observer_->latest_bitrate();
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPECT_EQ(8299, bitrate_drop_time);
|
EXPECT_EQ(367, bitrate_drop_time - overuse_start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the time it takes for the estimator to reduce the bitrate when
|
// Verify that the time it takes for the estimator to reduce the bitrate when
|
||||||
@ -196,29 +214,33 @@ TEST_F(RemoteBitrateEstimatorTestAlign, TestCapacityDropRtpTimestampsWrap) {
|
|||||||
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
||||||
std::numeric_limits<uint32_t>::max() - kSteadyStateTime * 90000);
|
std::numeric_limits<uint32_t>::max() - kSteadyStateTime * 90000);
|
||||||
// Run in steady state to make the estimator converge.
|
// Run in steady state to make the estimator converge.
|
||||||
stream_generator_->set_capacity_bps(1000e3);
|
unsigned int capacity_bps = 1000e3;
|
||||||
|
stream_generator_->set_capacity_bps(capacity_bps);
|
||||||
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
||||||
kSteadyStateTime * kFramerate,
|
kSteadyStateTime * kFramerate,
|
||||||
kStartBitrate,
|
kStartBitrate,
|
||||||
kMinExpectedBitrate,
|
kMinExpectedBitrate,
|
||||||
kMaxExpectedBitrate);
|
kMaxExpectedBitrate,
|
||||||
|
capacity_bps);
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
// Reduce the capacity and verify the decrease time.
|
// Reduce the capacity and verify the decrease time.
|
||||||
stream_generator_->set_capacity_bps(500e3);
|
capacity_bps = 500e3;
|
||||||
|
stream_generator_->set_capacity_bps(capacity_bps);
|
||||||
|
int64_t overuse_start_time = clock_.TimeInMilliseconds();
|
||||||
int64_t bitrate_drop_time = -1;
|
int64_t bitrate_drop_time = -1;
|
||||||
for (int i = 0; i < 200; ++i) {
|
for (int i = 0; i < 200; ++i) {
|
||||||
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
||||||
// Check for either increase or decrease.
|
// Check for either increase or decrease.
|
||||||
if (bitrate_observer_->updated()) {
|
if (bitrate_observer_->updated()) {
|
||||||
if (bitrate_drop_time == -1 &&
|
if (bitrate_drop_time == -1 &&
|
||||||
bitrate_observer_->latest_bitrate() <= 500e3) {
|
bitrate_observer_->latest_bitrate() <= capacity_bps) {
|
||||||
bitrate_drop_time = time_now_;
|
bitrate_drop_time = clock_.TimeInMilliseconds();
|
||||||
}
|
}
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
bitrate_bps = bitrate_observer_->latest_bitrate();
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPECT_EQ(8299, bitrate_drop_time);
|
EXPECT_EQ(367, bitrate_drop_time - overuse_start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the time it takes for the estimator to reduce the bitrate when
|
// Verify that the time it takes for the estimator to reduce the bitrate when
|
||||||
@ -229,7 +251,7 @@ TEST_F(RemoteBitrateEstimatorTestAlign, TwoStreamsCapacityDropWithWrap) {
|
|||||||
const int kStartBitrate = 900e3;
|
const int kStartBitrate = 900e3;
|
||||||
const int kMinExpectedBitrate = 800e3;
|
const int kMinExpectedBitrate = 800e3;
|
||||||
const int kMaxExpectedBitrate = 1100e3;
|
const int kMaxExpectedBitrate = 1100e3;
|
||||||
const int kSteadyStateTime = 7; // Seconds.
|
const int kSteadyStateFrames = 9 * kFramerate;
|
||||||
stream_generator_->AddStream(new testing::RtpStream(
|
stream_generator_->AddStream(new testing::RtpStream(
|
||||||
30, // Frames per second.
|
30, // Frames per second.
|
||||||
kStartBitrate/2, // Bitrate.
|
kStartBitrate/2, // Bitrate.
|
||||||
@ -247,31 +269,35 @@ TEST_F(RemoteBitrateEstimatorTestAlign, TwoStreamsCapacityDropWithWrap) {
|
|||||||
0)); // RTCP receive time.
|
0)); // RTCP receive time.
|
||||||
// Trigger wrap right after the steady state run.
|
// Trigger wrap right after the steady state run.
|
||||||
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
||||||
std::numeric_limits<uint32_t>::max() - kSteadyStateTime * 90000);
|
std::numeric_limits<uint32_t>::max() - kSteadyStateFrames * 90000);
|
||||||
// Run in steady state to make the estimator converge.
|
// Run in steady state to make the estimator converge.
|
||||||
stream_generator_->set_capacity_bps(1000e3);
|
unsigned int capacity_bps = 1000e3;
|
||||||
|
stream_generator_->set_capacity_bps(capacity_bps);
|
||||||
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
||||||
kSteadyStateTime * kFramerate,
|
kSteadyStateFrames,
|
||||||
kStartBitrate,
|
kStartBitrate,
|
||||||
kMinExpectedBitrate,
|
kMinExpectedBitrate,
|
||||||
kMaxExpectedBitrate);
|
kMaxExpectedBitrate,
|
||||||
|
capacity_bps);
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
// Reduce the capacity and verify the decrease time.
|
// Reduce the capacity and verify the decrease time.
|
||||||
stream_generator_->set_capacity_bps(500e3);
|
capacity_bps = 500e3;
|
||||||
|
stream_generator_->set_capacity_bps(capacity_bps);
|
||||||
|
int64_t overuse_start_time = clock_.TimeInMilliseconds();
|
||||||
int64_t bitrate_drop_time = -1;
|
int64_t bitrate_drop_time = -1;
|
||||||
for (int i = 0; i < 200; ++i) {
|
for (int i = 0; i < 200; ++i) {
|
||||||
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
||||||
// Check for either increase or decrease.
|
// Check for either increase or decrease.
|
||||||
if (bitrate_observer_->updated()) {
|
if (bitrate_observer_->updated()) {
|
||||||
if (bitrate_drop_time == -1 &&
|
if (bitrate_drop_time == -1 &&
|
||||||
bitrate_observer_->latest_bitrate() <= 500e3) {
|
bitrate_observer_->latest_bitrate() <= capacity_bps) {
|
||||||
bitrate_drop_time = time_now_;
|
bitrate_drop_time = clock_.TimeInMilliseconds();
|
||||||
}
|
}
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
bitrate_bps = bitrate_observer_->latest_bitrate();
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPECT_EQ(4933, bitrate_drop_time);
|
EXPECT_EQ(567, bitrate_drop_time - overuse_start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the time it takes for the estimator to reduce the bitrate when
|
// Verify that the time it takes for the estimator to reduce the bitrate when
|
||||||
@ -282,9 +308,9 @@ TEST_F(RemoteBitrateEstimatorTestAlign, ThreeStreams) {
|
|||||||
const int kStartBitrate = 900e3;
|
const int kStartBitrate = 900e3;
|
||||||
const int kMinExpectedBitrate = 800e3;
|
const int kMinExpectedBitrate = 800e3;
|
||||||
const int kMaxExpectedBitrate = 1100e3;
|
const int kMaxExpectedBitrate = 1100e3;
|
||||||
const int kSteadyStateTime = 11; // Seconds.
|
const int kSteadyStateFrames = 12 * kFramerate;
|
||||||
stream_generator_->AddStream(new testing::RtpStream(
|
stream_generator_->AddStream(new testing::RtpStream(
|
||||||
30, // Frames per second.
|
kFramerate, // Frames per second.
|
||||||
kStartBitrate/2, // Bitrate.
|
kStartBitrate/2, // Bitrate.
|
||||||
1, // SSRC.
|
1, // SSRC.
|
||||||
90000, // RTP frequency.
|
90000, // RTP frequency.
|
||||||
@ -292,7 +318,7 @@ TEST_F(RemoteBitrateEstimatorTestAlign, ThreeStreams) {
|
|||||||
0)); // RTCP receive time.
|
0)); // RTCP receive time.
|
||||||
|
|
||||||
stream_generator_->AddStream(new testing::RtpStream(
|
stream_generator_->AddStream(new testing::RtpStream(
|
||||||
30, // Frames per second.
|
kFramerate, // Frames per second.
|
||||||
kStartBitrate/3, // Bitrate.
|
kStartBitrate/3, // Bitrate.
|
||||||
2, // SSRC.
|
2, // SSRC.
|
||||||
90000, // RTP frequency.
|
90000, // RTP frequency.
|
||||||
@ -300,7 +326,7 @@ TEST_F(RemoteBitrateEstimatorTestAlign, ThreeStreams) {
|
|||||||
0)); // RTCP receive time.
|
0)); // RTCP receive time.
|
||||||
|
|
||||||
stream_generator_->AddStream(new testing::RtpStream(
|
stream_generator_->AddStream(new testing::RtpStream(
|
||||||
30, // Frames per second.
|
kFramerate, // Frames per second.
|
||||||
kStartBitrate/6, // Bitrate.
|
kStartBitrate/6, // Bitrate.
|
||||||
3, // SSRC.
|
3, // SSRC.
|
||||||
90000, // RTP frequency.
|
90000, // RTP frequency.
|
||||||
@ -308,31 +334,35 @@ TEST_F(RemoteBitrateEstimatorTestAlign, ThreeStreams) {
|
|||||||
0)); // RTCP receive time.
|
0)); // RTCP receive time.
|
||||||
// Trigger wrap right after the steady state run.
|
// Trigger wrap right after the steady state run.
|
||||||
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
stream_generator_->set_rtp_timestamp_offset(kDefaultSsrc,
|
||||||
std::numeric_limits<uint32_t>::max() - kSteadyStateTime * 90000);
|
std::numeric_limits<uint32_t>::max() - kSteadyStateFrames * 90000);
|
||||||
// Run in steady state to make the estimator converge.
|
// Run in steady state to make the estimator converge.
|
||||||
stream_generator_->set_capacity_bps(1000e3);
|
unsigned int capacity_bps = 1000e3;
|
||||||
|
stream_generator_->set_capacity_bps(capacity_bps);
|
||||||
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
unsigned int bitrate_bps = SteadyStateRun(kDefaultSsrc,
|
||||||
kSteadyStateTime * kFramerate,
|
kSteadyStateFrames,
|
||||||
kStartBitrate,
|
kStartBitrate,
|
||||||
kMinExpectedBitrate,
|
kMinExpectedBitrate,
|
||||||
kMaxExpectedBitrate);
|
kMaxExpectedBitrate,
|
||||||
|
capacity_bps);
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
// Reduce the capacity and verify the decrease time.
|
// Reduce the capacity and verify the decrease time.
|
||||||
stream_generator_->set_capacity_bps(500e3);
|
capacity_bps = 500e3;
|
||||||
|
stream_generator_->set_capacity_bps(capacity_bps);
|
||||||
|
int64_t overuse_start_time = clock_.TimeInMilliseconds();
|
||||||
int64_t bitrate_drop_time = -1;
|
int64_t bitrate_drop_time = -1;
|
||||||
for (int i = 0; i < 200; ++i) {
|
for (int i = 0; i < 200; ++i) {
|
||||||
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
GenerateAndProcessFrame(kDefaultSsrc, bitrate_bps);
|
||||||
// Check for either increase or decrease.
|
// Check for either increase or decrease.
|
||||||
if (bitrate_observer_->updated()) {
|
if (bitrate_observer_->updated()) {
|
||||||
if (bitrate_drop_time == -1 &&
|
if (bitrate_drop_time == -1 &&
|
||||||
bitrate_observer_->latest_bitrate() <= 500e3) {
|
bitrate_observer_->latest_bitrate() <= capacity_bps) {
|
||||||
bitrate_drop_time = time_now_;
|
bitrate_drop_time = clock_.TimeInMilliseconds();
|
||||||
}
|
}
|
||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
bitrate_bps = bitrate_observer_->latest_bitrate();
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXPECT_EQ(3966, bitrate_drop_time);
|
EXPECT_EQ(433, bitrate_drop_time - overuse_start_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -39,25 +39,25 @@ void RtpStream::set_rtp_timestamp_offset(uint32_t offset) {
|
|||||||
// Generates a new frame for this stream. If called too soon after the
|
// Generates a new frame for this stream. If called too soon after the
|
||||||
// previous frame, no frame will be generated. The frame is split into
|
// previous frame, no frame will be generated. The frame is split into
|
||||||
// packets.
|
// packets.
|
||||||
int64_t RtpStream::GenerateFrame(double time_now, PacketList* packets) {
|
int64_t RtpStream::GenerateFrame(int64_t time_now_us, PacketList* packets) {
|
||||||
if (time_now < next_rtp_time_) {
|
if (time_now_us < next_rtp_time_) {
|
||||||
return next_rtp_time_;
|
return next_rtp_time_;
|
||||||
}
|
}
|
||||||
assert(packets != NULL);
|
assert(packets != NULL);
|
||||||
int bits_per_frame = (bitrate_bps_ + fps_ / 2) / fps_;
|
int bits_per_frame = (bitrate_bps_ + fps_ / 2) / fps_;
|
||||||
int n_packets = std::max((bits_per_frame + 8 * kMtu) / (8 * kMtu), 1);
|
int n_packets = std::max((bits_per_frame + 4 * kMtu) / (8 * kMtu), 1);
|
||||||
int packet_size = (bits_per_frame + 4 * n_packets) / (8 * n_packets);
|
int packet_size = (bits_per_frame + 4 * n_packets) / (8 * n_packets);
|
||||||
assert(n_packets >= 0);
|
assert(n_packets >= 0);
|
||||||
for (int i = 0; i < n_packets; ++i) {
|
for (int i = 0; i < n_packets; ++i) {
|
||||||
RtpPacket* packet = new RtpPacket;
|
RtpPacket* packet = new RtpPacket;
|
||||||
packet->send_time = time_now + kSendSideOffsetMs + 0.5f;
|
packet->send_time = time_now_us + kSendSideOffsetUs;
|
||||||
packet->size = packet_size;
|
packet->size = packet_size;
|
||||||
packet->rtp_timestamp = rtp_timestamp_offset_ + static_cast<uint32_t>(
|
packet->rtp_timestamp = rtp_timestamp_offset_ + static_cast<uint32_t>(
|
||||||
(frequency_ / 1000.0) * packet->send_time + 0.5);
|
((frequency_ / 1000) * packet->send_time + 500) / 1000);
|
||||||
packet->ssrc = ssrc_;
|
packet->ssrc = ssrc_;
|
||||||
packets->push_back(packet);
|
packets->push_back(packet);
|
||||||
}
|
}
|
||||||
next_rtp_time_ = time_now + 1000.0 / static_cast<double>(fps_);
|
next_rtp_time_ = time_now_us + (1000000 + fps_ / 2) / fps_;
|
||||||
return next_rtp_time_;
|
return next_rtp_time_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,18 +67,18 @@ double RtpStream::next_rtp_time() const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generates an RTCP packet.
|
// Generates an RTCP packet.
|
||||||
RtpStream::RtcpPacket* RtpStream::Rtcp(double time_now) {
|
RtpStream::RtcpPacket* RtpStream::Rtcp(int64_t time_now_us) {
|
||||||
if (time_now < next_rtcp_time_) {
|
if (time_now_us < next_rtcp_time_) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
RtcpPacket* rtcp = new RtcpPacket;
|
RtcpPacket* rtcp = new RtcpPacket;
|
||||||
int64_t send_time = RtpStream::kSendSideOffsetMs + time_now + 0.5;
|
int64_t send_time_us = RtpStream::kSendSideOffsetUs + time_now_us;
|
||||||
rtcp->timestamp = rtp_timestamp_offset_ + static_cast<uint32_t>(
|
rtcp->timestamp = rtp_timestamp_offset_ + static_cast<uint32_t>(
|
||||||
(frequency_ / 1000.0) * send_time + 0.5);
|
((frequency_ / 1000) * send_time_us + 500) / 1000);
|
||||||
rtcp->ntp_secs = send_time / 1000;
|
rtcp->ntp_secs = send_time_us / 1000000;
|
||||||
rtcp->ntp_frac = (send_time % 1000) * kNtpFracPerMs;
|
rtcp->ntp_frac = (send_time_us % 1000000) * kNtpFracPerMs;
|
||||||
rtcp->ssrc = ssrc_;
|
rtcp->ssrc = ssrc_;
|
||||||
next_rtcp_time_ = time_now + kRtcpIntervalMs;
|
next_rtcp_time_ = time_now_us + kRtcpIntervalUs;
|
||||||
return rtcp;
|
return rtcp;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -102,7 +102,7 @@ bool RtpStream::Compare(const std::pair<unsigned int, RtpStream*>& left,
|
|||||||
|
|
||||||
StreamGenerator::StreamGenerator(int capacity, double time_now)
|
StreamGenerator::StreamGenerator(int capacity, double time_now)
|
||||||
: capacity_(capacity),
|
: capacity_(capacity),
|
||||||
prev_arrival_time_(time_now) {}
|
prev_arrival_time_us_(time_now) {}
|
||||||
|
|
||||||
StreamGenerator::~StreamGenerator() {
|
StreamGenerator::~StreamGenerator() {
|
||||||
for (StreamMap::iterator it = streams_.begin(); it != streams_.end();
|
for (StreamMap::iterator it = streams_.begin(); it != streams_.end();
|
||||||
@ -150,30 +150,33 @@ void StreamGenerator::set_rtp_timestamp_offset(unsigned int ssrc,
|
|||||||
|
|
||||||
// TODO(holmer): Break out the channel simulation part from this class to make
|
// TODO(holmer): Break out the channel simulation part from this class to make
|
||||||
// it possible to simulate different types of channels.
|
// it possible to simulate different types of channels.
|
||||||
double StreamGenerator::GenerateFrame(RtpStream::PacketList* packets,
|
int64_t StreamGenerator::GenerateFrame(RtpStream::PacketList* packets,
|
||||||
double time_now) {
|
int64_t time_now_us) {
|
||||||
assert(packets != NULL);
|
assert(packets != NULL);
|
||||||
assert(packets->empty());
|
assert(packets->empty());
|
||||||
assert(capacity_ > 0);
|
assert(capacity_ > 0);
|
||||||
StreamMap::iterator it = std::min_element(streams_.begin(), streams_.end(),
|
StreamMap::iterator it = std::min_element(streams_.begin(), streams_.end(),
|
||||||
RtpStream::Compare);
|
RtpStream::Compare);
|
||||||
(*it).second->GenerateFrame(time_now, packets);
|
(*it).second->GenerateFrame(time_now_us, packets);
|
||||||
|
int i = 0;
|
||||||
for (RtpStream::PacketList::iterator packet_it = packets->begin();
|
for (RtpStream::PacketList::iterator packet_it = packets->begin();
|
||||||
packet_it != packets->end(); ++packet_it) {
|
packet_it != packets->end(); ++packet_it) {
|
||||||
int required_network_time =
|
int capacity_bpus = capacity_ / 1000;
|
||||||
(8 * 1000 * (*packet_it)->size + capacity_ / 2) / capacity_;
|
int64_t required_network_time_us =
|
||||||
prev_arrival_time_ = std::max(time_now + required_network_time,
|
(8 * 1000 * (*packet_it)->size + capacity_bpus / 2) / capacity_bpus;
|
||||||
prev_arrival_time_ + required_network_time);
|
prev_arrival_time_us_ = std::max(time_now_us + required_network_time_us,
|
||||||
(*packet_it)->arrival_time = prev_arrival_time_ + 0.5;
|
prev_arrival_time_us_ + required_network_time_us);
|
||||||
|
(*packet_it)->arrival_time = prev_arrival_time_us_;
|
||||||
|
++i;
|
||||||
}
|
}
|
||||||
it = std::min_element(streams_.begin(), streams_.end(), RtpStream::Compare);
|
it = std::min_element(streams_.begin(), streams_.end(), RtpStream::Compare);
|
||||||
return (*it).second->next_rtp_time();
|
return (*it).second->next_rtp_time();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StreamGenerator::Rtcps(RtcpList* rtcps, double time_now) const {
|
void StreamGenerator::Rtcps(RtcpList* rtcps, int64_t time_now_us) const {
|
||||||
for (StreamMap::const_iterator it = streams_.begin(); it != streams_.end();
|
for (StreamMap::const_iterator it = streams_.begin(); it != streams_.end();
|
||||||
++it) {
|
++it) {
|
||||||
RtpStream::RtcpPacket* rtcp = it->second->Rtcp(time_now);
|
RtpStream::RtcpPacket* rtcp = it->second->Rtcp(time_now_us);
|
||||||
if (rtcp) {
|
if (rtcp) {
|
||||||
rtcps->push_front(rtcp);
|
rtcps->push_front(rtcp);
|
||||||
}
|
}
|
||||||
@ -182,22 +185,24 @@ void StreamGenerator::Rtcps(RtcpList* rtcps, double time_now) const {
|
|||||||
} // namespace testing
|
} // namespace testing
|
||||||
|
|
||||||
RemoteBitrateEstimatorTest::RemoteBitrateEstimatorTest()
|
RemoteBitrateEstimatorTest::RemoteBitrateEstimatorTest()
|
||||||
: time_now_(0.0),
|
: clock_(0),
|
||||||
align_streams_(false) {}
|
align_streams_(false) {}
|
||||||
|
|
||||||
RemoteBitrateEstimatorTest::RemoteBitrateEstimatorTest(bool align_streams)
|
RemoteBitrateEstimatorTest::RemoteBitrateEstimatorTest(bool align_streams)
|
||||||
: time_now_(0.0),
|
: clock_(0),
|
||||||
align_streams_(align_streams) {}
|
align_streams_(align_streams) {}
|
||||||
|
|
||||||
void RemoteBitrateEstimatorTest::SetUp() {
|
void RemoteBitrateEstimatorTest::SetUp() {
|
||||||
bitrate_observer_.reset(new testing::TestBitrateObserver);
|
bitrate_observer_.reset(new testing::TestBitrateObserver);
|
||||||
bitrate_estimator_.reset(
|
bitrate_estimator_.reset(
|
||||||
RemoteBitrateEstimator::Create(
|
RemoteBitrateEstimator::Create(
|
||||||
|
overuse_detector_options_,
|
||||||
|
RemoteBitrateEstimator::kSingleStreamEstimation,
|
||||||
bitrate_observer_.get(),
|
bitrate_observer_.get(),
|
||||||
over_use_detector_options_,
|
&clock_));
|
||||||
RemoteBitrateEstimator::kSingleStreamEstimation));
|
stream_generator_.reset(new testing::StreamGenerator(
|
||||||
stream_generator_.reset(new testing::StreamGenerator(1e6, // Capacity.
|
1e6, // Capacity.
|
||||||
time_now_));
|
clock_.TimeInMicroseconds()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void RemoteBitrateEstimatorTest::AddDefaultStream() {
|
void RemoteBitrateEstimatorTest::AddDefaultStream() {
|
||||||
@ -220,15 +225,14 @@ bool RemoteBitrateEstimatorTest::GenerateAndProcessFrame(unsigned int ssrc,
|
|||||||
unsigned int bitrate_bps) {
|
unsigned int bitrate_bps) {
|
||||||
stream_generator_->set_bitrate_bps(bitrate_bps);
|
stream_generator_->set_bitrate_bps(bitrate_bps);
|
||||||
testing::RtpStream::PacketList packets;
|
testing::RtpStream::PacketList packets;
|
||||||
time_now_ = stream_generator_->GenerateFrame(&packets, time_now_);
|
int64_t next_time_us = stream_generator_->GenerateFrame(
|
||||||
int64_t last_arrival_time = -1;
|
&packets, clock_.TimeInMicroseconds());
|
||||||
bool prev_was_decrease = false;
|
|
||||||
bool overuse = false;
|
bool overuse = false;
|
||||||
while (!packets.empty()) {
|
while (!packets.empty()) {
|
||||||
testing::RtpStream::RtpPacket* packet = packets.front();
|
testing::RtpStream::RtpPacket* packet = packets.front();
|
||||||
if (align_streams_) {
|
if (align_streams_) {
|
||||||
testing::StreamGenerator::RtcpList rtcps;
|
testing::StreamGenerator::RtcpList rtcps;
|
||||||
stream_generator_->Rtcps(&rtcps, time_now_);
|
stream_generator_->Rtcps(&rtcps, clock_.TimeInMicroseconds());
|
||||||
for (testing::StreamGenerator::RtcpList::iterator it = rtcps.begin();
|
for (testing::StreamGenerator::RtcpList::iterator it = rtcps.begin();
|
||||||
it != rtcps.end(); ++it) {
|
it != rtcps.end(); ++it) {
|
||||||
bitrate_estimator_->IncomingRtcp((*it)->ssrc,
|
bitrate_estimator_->IncomingRtcp((*it)->ssrc,
|
||||||
@ -241,40 +245,39 @@ bool RemoteBitrateEstimatorTest::GenerateAndProcessFrame(unsigned int ssrc,
|
|||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
bitrate_estimator_->IncomingPacket(packet->ssrc,
|
bitrate_estimator_->IncomingPacket(packet->ssrc,
|
||||||
packet->size,
|
packet->size,
|
||||||
packet->arrival_time,
|
(packet->arrival_time + 500) / 1000,
|
||||||
packet->rtp_timestamp);
|
packet->rtp_timestamp);
|
||||||
if (bitrate_observer_->updated()) {
|
if (bitrate_observer_->updated()) {
|
||||||
// Verify that new estimates only are triggered by an overuse and a
|
// Verify that new estimates only are triggered by an overuse and a
|
||||||
// rate decrease.
|
// rate decrease.
|
||||||
overuse = true;
|
overuse = true;
|
||||||
EXPECT_LE(bitrate_observer_->latest_bitrate(), bitrate_bps);
|
EXPECT_LE(bitrate_observer_->latest_bitrate(), bitrate_bps);
|
||||||
EXPECT_FALSE(prev_was_decrease);
|
|
||||||
prev_was_decrease = true;
|
|
||||||
} else {
|
|
||||||
prev_was_decrease = false;
|
|
||||||
}
|
}
|
||||||
last_arrival_time = packet->arrival_time;
|
clock_.AdvanceTimeMicroseconds(packet->arrival_time -
|
||||||
|
clock_.TimeInMicroseconds());
|
||||||
delete packet;
|
delete packet;
|
||||||
packets.pop_front();
|
packets.pop_front();
|
||||||
}
|
}
|
||||||
EXPECT_GT(last_arrival_time, -1);
|
bitrate_estimator_->Process();
|
||||||
bitrate_estimator_->UpdateEstimate(ssrc, last_arrival_time);
|
clock_.AdvanceTimeMicroseconds(next_time_us - clock_.TimeInMicroseconds());
|
||||||
return overuse;
|
return overuse;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the bandwidth estimator with a stream of |number_of_frames| frames.
|
// Run the bandwidth estimator with a stream of |number_of_frames| frames, or
|
||||||
|
// until it reaches |target_bitrate|.
|
||||||
// Can for instance be used to run the estimator for some time to get it
|
// Can for instance be used to run the estimator for some time to get it
|
||||||
// into a steady state.
|
// into a steady state.
|
||||||
unsigned int RemoteBitrateEstimatorTest::SteadyStateRun(
|
unsigned int RemoteBitrateEstimatorTest::SteadyStateRun(
|
||||||
unsigned int ssrc,
|
unsigned int ssrc,
|
||||||
int number_of_frames,
|
int max_number_of_frames,
|
||||||
unsigned int start_bitrate,
|
unsigned int start_bitrate,
|
||||||
unsigned int min_bitrate,
|
unsigned int min_bitrate,
|
||||||
unsigned int max_bitrate) {
|
unsigned int max_bitrate,
|
||||||
|
unsigned int target_bitrate) {
|
||||||
unsigned int bitrate_bps = start_bitrate;
|
unsigned int bitrate_bps = start_bitrate;
|
||||||
bool bitrate_update_seen = false;
|
bool bitrate_update_seen = false;
|
||||||
// Produce |number_of_frames| frames and give them to the estimator.
|
// Produce |number_of_frames| frames and give them to the estimator.
|
||||||
for (int i = 0; i < number_of_frames; ++i) {
|
for (int i = 0; i < max_number_of_frames; ++i) {
|
||||||
bool overuse = GenerateAndProcessFrame(ssrc, bitrate_bps);
|
bool overuse = GenerateAndProcessFrame(ssrc, bitrate_bps);
|
||||||
if (overuse) {
|
if (overuse) {
|
||||||
EXPECT_LT(bitrate_observer_->latest_bitrate(), max_bitrate);
|
EXPECT_LT(bitrate_observer_->latest_bitrate(), max_bitrate);
|
||||||
@ -285,6 +288,9 @@ unsigned int RemoteBitrateEstimatorTest::SteadyStateRun(
|
|||||||
bitrate_bps = bitrate_observer_->latest_bitrate();
|
bitrate_bps = bitrate_observer_->latest_bitrate();
|
||||||
bitrate_observer_->Reset();
|
bitrate_observer_->Reset();
|
||||||
}
|
}
|
||||||
|
if (bitrate_update_seen && bitrate_bps > target_bitrate) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
EXPECT_TRUE(bitrate_update_seen);
|
EXPECT_TRUE(bitrate_update_seen);
|
||||||
return bitrate_bps;
|
return bitrate_bps;
|
||||||
|
@ -17,9 +17,10 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
|
||||||
#include "system_wrappers/interface/constructor_magic.h"
|
#include "webrtc/system_wrappers/interface/clock.h"
|
||||||
#include "system_wrappers/interface/scoped_ptr.h"
|
#include "webrtc/system_wrappers/interface/constructor_magic.h"
|
||||||
|
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
@ -74,7 +75,7 @@ class RtpStream {
|
|||||||
|
|
||||||
typedef std::list<RtpPacket*> PacketList;
|
typedef std::list<RtpPacket*> PacketList;
|
||||||
|
|
||||||
enum { kSendSideOffsetMs = 1000 };
|
enum { kSendSideOffsetUs = 1000000 };
|
||||||
|
|
||||||
RtpStream(int fps, int bitrate_bps, unsigned int ssrc, unsigned int frequency,
|
RtpStream(int fps, int bitrate_bps, unsigned int ssrc, unsigned int frequency,
|
||||||
uint32_t timestamp_offset, int64_t rtcp_receive_time);
|
uint32_t timestamp_offset, int64_t rtcp_receive_time);
|
||||||
@ -83,13 +84,13 @@ class RtpStream {
|
|||||||
// Generates a new frame for this stream. If called too soon after the
|
// Generates a new frame for this stream. If called too soon after the
|
||||||
// previous frame, no frame will be generated. The frame is split into
|
// previous frame, no frame will be generated. The frame is split into
|
||||||
// packets.
|
// packets.
|
||||||
int64_t GenerateFrame(double time_now, PacketList* packets);
|
int64_t GenerateFrame(int64_t time_now_us, PacketList* packets);
|
||||||
|
|
||||||
// The send-side time when the next frame can be generated.
|
// The send-side time when the next frame can be generated.
|
||||||
double next_rtp_time() const;
|
double next_rtp_time() const;
|
||||||
|
|
||||||
// Generates an RTCP packet.
|
// Generates an RTCP packet.
|
||||||
RtcpPacket* Rtcp(double time_now);
|
RtcpPacket* Rtcp(int64_t time_now_us);
|
||||||
|
|
||||||
void set_bitrate_bps(int bitrate_bps);
|
void set_bitrate_bps(int bitrate_bps);
|
||||||
|
|
||||||
@ -101,14 +102,14 @@ class RtpStream {
|
|||||||
const std::pair<unsigned int, RtpStream*>& right);
|
const std::pair<unsigned int, RtpStream*>& right);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum { kRtcpIntervalMs = 1000 };
|
enum { kRtcpIntervalUs = 1000000 };
|
||||||
|
|
||||||
int fps_;
|
int fps_;
|
||||||
int bitrate_bps_;
|
int bitrate_bps_;
|
||||||
unsigned int ssrc_;
|
unsigned int ssrc_;
|
||||||
unsigned int frequency_;
|
unsigned int frequency_;
|
||||||
double next_rtp_time_;
|
int64_t next_rtp_time_;
|
||||||
double next_rtcp_time_;
|
int64_t next_rtcp_time_;
|
||||||
uint32_t rtp_timestamp_offset_;
|
uint32_t rtp_timestamp_offset_;
|
||||||
const double kNtpFracPerMs;
|
const double kNtpFracPerMs;
|
||||||
|
|
||||||
@ -138,9 +139,9 @@ class StreamGenerator {
|
|||||||
|
|
||||||
// TODO(holmer): Break out the channel simulation part from this class to make
|
// TODO(holmer): Break out the channel simulation part from this class to make
|
||||||
// it possible to simulate different types of channels.
|
// it possible to simulate different types of channels.
|
||||||
double GenerateFrame(RtpStream::PacketList* packets, double time_now);
|
int64_t GenerateFrame(RtpStream::PacketList* packets, int64_t time_now_us);
|
||||||
|
|
||||||
void Rtcps(RtcpList* rtcps, double time_now) const;
|
void Rtcps(RtcpList* rtcps, int64_t time_now_us) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::map<unsigned int, RtpStream*> StreamMap;
|
typedef std::map<unsigned int, RtpStream*> StreamMap;
|
||||||
@ -148,7 +149,7 @@ class StreamGenerator {
|
|||||||
// Capacity of the simulated channel in bits per second.
|
// Capacity of the simulated channel in bits per second.
|
||||||
int capacity_;
|
int capacity_;
|
||||||
// The time when the last packet arrived.
|
// The time when the last packet arrived.
|
||||||
double prev_arrival_time_;
|
int64_t prev_arrival_time_us_;
|
||||||
// All streams being transmitted on this simulated channel.
|
// All streams being transmitted on this simulated channel.
|
||||||
StreamMap streams_;
|
StreamMap streams_;
|
||||||
|
|
||||||
@ -174,19 +175,21 @@ class RemoteBitrateEstimatorTest : public ::testing::Test {
|
|||||||
// target bitrate after the call to this function.
|
// target bitrate after the call to this function.
|
||||||
bool GenerateAndProcessFrame(unsigned int ssrc, unsigned int bitrate_bps);
|
bool GenerateAndProcessFrame(unsigned int ssrc, unsigned int bitrate_bps);
|
||||||
|
|
||||||
// Run the bandwidth estimator with a stream of |number_of_frames| frames.
|
// Run the bandwidth estimator with a stream of |number_of_frames| frames, or
|
||||||
|
// until it reaches |target_bitrate|.
|
||||||
// Can for instance be used to run the estimator for some time to get it
|
// Can for instance be used to run the estimator for some time to get it
|
||||||
// into a steady state.
|
// into a steady state.
|
||||||
unsigned int SteadyStateRun(unsigned int ssrc,
|
unsigned int SteadyStateRun(unsigned int ssrc,
|
||||||
int number_of_frames,
|
int number_of_frames,
|
||||||
unsigned int start_bitrate,
|
unsigned int start_bitrate,
|
||||||
unsigned int min_bitrate,
|
unsigned int min_bitrate,
|
||||||
unsigned int max_bitrate);
|
unsigned int max_bitrate,
|
||||||
|
unsigned int target_bitrate);
|
||||||
|
|
||||||
enum { kDefaultSsrc = 1 };
|
enum { kDefaultSsrc = 1 };
|
||||||
|
|
||||||
double time_now_; // Current time at the receiver.
|
SimulatedClock clock_; // Time at the receiver.
|
||||||
OverUseDetectorOptions over_use_detector_options_;
|
OverUseDetectorOptions overuse_detector_options_;
|
||||||
scoped_ptr<RemoteBitrateEstimator> bitrate_estimator_;
|
scoped_ptr<RemoteBitrateEstimator> bitrate_estimator_;
|
||||||
scoped_ptr<testing::TestBitrateObserver> bitrate_observer_;
|
scoped_ptr<testing::TestBitrateObserver> bitrate_observer_;
|
||||||
scoped_ptr<testing::StreamGenerator> stream_generator_;
|
scoped_ptr<testing::StreamGenerator> stream_generator_;
|
||||||
|
@ -24,6 +24,9 @@ extern MatlabEngine eng; // global variable defined elsewhere
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
|
const unsigned int kDefaultRttMs = 200;
|
||||||
|
|
||||||
RemoteRateControl::RemoteRateControl()
|
RemoteRateControl::RemoteRateControl()
|
||||||
:
|
:
|
||||||
_minConfiguredBitRate(30000),
|
_minConfiguredBitRate(30000),
|
||||||
@ -43,7 +46,7 @@ _initializedBitRate(false),
|
|||||||
_avgChangePeriod(1000.0f),
|
_avgChangePeriod(1000.0f),
|
||||||
_lastChangeMs(-1),
|
_lastChangeMs(-1),
|
||||||
_beta(0.9f),
|
_beta(0.9f),
|
||||||
_rtt(0)
|
_rtt(kDefaultRttMs)
|
||||||
#ifdef MATLAB
|
#ifdef MATLAB
|
||||||
,_plot1(NULL),
|
,_plot1(NULL),
|
||||||
_plot2(NULL)
|
_plot2(NULL)
|
||||||
@ -86,6 +89,20 @@ bool RemoteRateControl::ValidEstimate() const {
|
|||||||
return _initializedBitRate;
|
return _initializedBitRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RemoteRateControl::TimeToReduceFurther(
|
||||||
|
int64_t time_now, unsigned int incoming_bitrate) const {
|
||||||
|
const int bitrate_reduction_interval = BWE_MAX(BWE_MIN(_rtt, 200), 10);
|
||||||
|
if (time_now - _lastBitRateChange >= bitrate_reduction_interval) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (ValidEstimate()) {
|
||||||
|
const int threshold = static_cast<int>(1.05 * incoming_bitrate);
|
||||||
|
const int bitrate_difference = LatestEstimate() - incoming_bitrate;
|
||||||
|
return bitrate_difference > threshold;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
WebRtc_Word32 RemoteRateControl::SetConfiguredBitRates(
|
WebRtc_Word32 RemoteRateControl::SetConfiguredBitRates(
|
||||||
WebRtc_UWord32 minBitRateBps, WebRtc_UWord32 maxBitRateBps)
|
WebRtc_UWord32 minBitRateBps, WebRtc_UWord32 maxBitRateBps)
|
||||||
{
|
{
|
||||||
|
@ -36,6 +36,12 @@ public:
|
|||||||
// Returns true if there is a valid estimate of the incoming bitrate, false
|
// Returns true if there is a valid estimate of the incoming bitrate, false
|
||||||
// otherwise.
|
// otherwise.
|
||||||
bool ValidEstimate() const;
|
bool ValidEstimate() const;
|
||||||
|
// Returns true if the bitrate estimate hasn't been changed for more than
|
||||||
|
// an RTT, or if the incoming_bitrate is more than 5% above the current
|
||||||
|
// estimate. Should be used to decide if we should reduce the rate further
|
||||||
|
// when over-using.
|
||||||
|
bool TimeToReduceFurther(int64_t time_now,
|
||||||
|
unsigned int incoming_bitrate) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
WebRtc_UWord32 ChangeBitRate(WebRtc_UWord32 currentBitRate,
|
WebRtc_UWord32 ChangeBitRate(WebRtc_UWord32 currentBitRate,
|
||||||
|
@ -462,12 +462,6 @@ class RtpRtcp : public Module {
|
|||||||
WebRtc_UWord32* fecRate,
|
WebRtc_UWord32* fecRate,
|
||||||
WebRtc_UWord32* nackRate) const = 0;
|
WebRtc_UWord32* nackRate) const = 0;
|
||||||
|
|
||||||
/*
|
|
||||||
* Get the receive-side estimate of the available bandwidth.
|
|
||||||
*/
|
|
||||||
virtual int EstimatedReceiveBandwidth(
|
|
||||||
WebRtc_UWord32* available_bandwidth) const = 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Used by the codec module to deliver a video or audio frame for
|
* Used by the codec module to deliver a video or audio frame for
|
||||||
* packetization.
|
* packetization.
|
||||||
|
@ -60,11 +60,13 @@ class RtcpFormatRembTest : public ::testing::Test {
|
|||||||
protected:
|
protected:
|
||||||
RtcpFormatRembTest()
|
RtcpFormatRembTest()
|
||||||
: over_use_detector_options_(),
|
: over_use_detector_options_(),
|
||||||
|
system_clock_(Clock::GetRealTimeClock()),
|
||||||
remote_bitrate_observer_(),
|
remote_bitrate_observer_(),
|
||||||
remote_bitrate_estimator_(RemoteBitrateEstimator::Create(
|
remote_bitrate_estimator_(RemoteBitrateEstimator::Create(
|
||||||
&remote_bitrate_observer_,
|
|
||||||
over_use_detector_options_,
|
over_use_detector_options_,
|
||||||
RemoteBitrateEstimator::kMultiStreamEstimation)) {}
|
RemoteBitrateEstimator::kMultiStreamEstimation,
|
||||||
|
&remote_bitrate_observer_,
|
||||||
|
system_clock_)) {}
|
||||||
virtual void SetUp();
|
virtual void SetUp();
|
||||||
virtual void TearDown();
|
virtual void TearDown();
|
||||||
|
|
||||||
@ -79,7 +81,6 @@ class RtcpFormatRembTest : public ::testing::Test {
|
|||||||
};
|
};
|
||||||
|
|
||||||
void RtcpFormatRembTest::SetUp() {
|
void RtcpFormatRembTest::SetUp() {
|
||||||
system_clock_ = Clock::GetRealTimeClock();
|
|
||||||
RtpRtcp::Configuration configuration;
|
RtpRtcp::Configuration configuration;
|
||||||
configuration.id = 0;
|
configuration.id = 0;
|
||||||
configuration.audio = false;
|
configuration.audio = false;
|
||||||
|
@ -113,6 +113,19 @@ RTCPReceiver::LastReceived()
|
|||||||
return _lastReceived;
|
return _lastReceived;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WebRtc_Word64
|
||||||
|
RTCPReceiver::LastReceivedReceiverReport() const {
|
||||||
|
CriticalSectionScoped lock(_criticalSectionRTCPReceiver);
|
||||||
|
WebRtc_Word64 last_received_rr = -1;
|
||||||
|
for (ReceivedInfoMap::const_iterator it = _receivedInfoMap.begin();
|
||||||
|
it != _receivedInfoMap.end(); ++it) {
|
||||||
|
if (it->second->lastTimeReceived > last_received_rr) {
|
||||||
|
last_received_rr = it->second->lastTimeReceived;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return last_received_rr;
|
||||||
|
}
|
||||||
|
|
||||||
WebRtc_Word32
|
WebRtc_Word32
|
||||||
RTCPReceiver::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
|
RTCPReceiver::SetRemoteSSRC( const WebRtc_UWord32 ssrc)
|
||||||
{
|
{
|
||||||
|
@ -37,6 +37,7 @@ public:
|
|||||||
WebRtc_Word32 SetRTCPStatus(const RTCPMethod method);
|
WebRtc_Word32 SetRTCPStatus(const RTCPMethod method);
|
||||||
|
|
||||||
WebRtc_Word64 LastReceived();
|
WebRtc_Word64 LastReceived();
|
||||||
|
WebRtc_Word64 LastReceivedReceiverReport() const;
|
||||||
|
|
||||||
void SetSSRC( const WebRtc_UWord32 ssrc);
|
void SetSSRC( const WebRtc_UWord32 ssrc);
|
||||||
void SetRelaySSRC( const WebRtc_UWord32 ssrc);
|
void SetRelaySSRC( const WebRtc_UWord32 ssrc);
|
||||||
@ -197,6 +198,8 @@ protected:
|
|||||||
RTCPHelp::RTCPPacketInformation& rtcpPacketInformation);
|
RTCPHelp::RTCPPacketInformation& rtcpPacketInformation);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
typedef std::map<WebRtc_UWord32, RTCPHelp::RTCPReceiveInformation*>
|
||||||
|
ReceivedInfoMap;
|
||||||
WebRtc_Word32 _id;
|
WebRtc_Word32 _id;
|
||||||
Clock* _clock;
|
Clock* _clock;
|
||||||
RTCPMethod _method;
|
RTCPMethod _method;
|
||||||
@ -221,8 +224,7 @@ protected:
|
|||||||
// Received report blocks.
|
// Received report blocks.
|
||||||
std::map<WebRtc_UWord32, RTCPHelp::RTCPReportBlockInformation*>
|
std::map<WebRtc_UWord32, RTCPHelp::RTCPReportBlockInformation*>
|
||||||
_receivedReportBlockMap;
|
_receivedReportBlockMap;
|
||||||
std::map<WebRtc_UWord32, RTCPHelp::RTCPReceiveInformation*>
|
ReceivedInfoMap _receivedInfoMap;
|
||||||
_receivedInfoMap;
|
|
||||||
std::map<WebRtc_UWord32, RTCPUtility::RTCPCnameInformation*>
|
std::map<WebRtc_UWord32, RTCPUtility::RTCPCnameInformation*>
|
||||||
_receivedCnameMap;
|
_receivedCnameMap;
|
||||||
|
|
||||||
|
@ -172,9 +172,10 @@ class RtcpReceiverTest : public ::testing::Test {
|
|||||||
remote_bitrate_observer_(),
|
remote_bitrate_observer_(),
|
||||||
remote_bitrate_estimator_(
|
remote_bitrate_estimator_(
|
||||||
RemoteBitrateEstimator::Create(
|
RemoteBitrateEstimator::Create(
|
||||||
&remote_bitrate_observer_,
|
|
||||||
over_use_detector_options_,
|
over_use_detector_options_,
|
||||||
RemoteBitrateEstimator::kMultiStreamEstimation)) {
|
RemoteBitrateEstimator::kMultiStreamEstimation,
|
||||||
|
&remote_bitrate_observer_,
|
||||||
|
&system_clock_)) {
|
||||||
test_transport_ = new TestTransport();
|
test_transport_ = new TestTransport();
|
||||||
|
|
||||||
RtpRtcp::Configuration configuration;
|
RtpRtcp::Configuration configuration;
|
||||||
|
@ -99,13 +99,14 @@ class RtcpSenderTest : public ::testing::Test {
|
|||||||
protected:
|
protected:
|
||||||
RtcpSenderTest()
|
RtcpSenderTest()
|
||||||
: over_use_detector_options_(),
|
: over_use_detector_options_(),
|
||||||
|
system_clock_(Clock::GetRealTimeClock()),
|
||||||
remote_bitrate_observer_(),
|
remote_bitrate_observer_(),
|
||||||
remote_bitrate_estimator_(
|
remote_bitrate_estimator_(
|
||||||
RemoteBitrateEstimator::Create(
|
RemoteBitrateEstimator::Create(
|
||||||
&remote_bitrate_observer_,
|
|
||||||
over_use_detector_options_,
|
over_use_detector_options_,
|
||||||
RemoteBitrateEstimator::kMultiStreamEstimation)) {
|
RemoteBitrateEstimator::kMultiStreamEstimation,
|
||||||
system_clock_ = Clock::GetRealTimeClock();
|
&remote_bitrate_observer_,
|
||||||
|
system_clock_)) {
|
||||||
test_transport_ = new TestTransport();
|
test_transport_ = new TestTransport();
|
||||||
|
|
||||||
RtpRtcp::Configuration configuration;
|
RtpRtcp::Configuration configuration;
|
||||||
|
@ -15,7 +15,8 @@
|
|||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
enum { kRtpRtcpMaxIdleTimeProcess = 5,
|
enum { kRtpRtcpMaxIdleTimeProcess = 5,
|
||||||
kRtpRtcpBitrateProcessTimeMs = 10,
|
kRtpRtcpBitrateProcessTimeMs = 10,
|
||||||
kRtpRtcpPacketTimeoutProcessTimeMs = 100 };
|
kRtpRtcpPacketTimeoutProcessTimeMs = 100,
|
||||||
|
kRtpRtcpRttProcessTimeMs = 1000 };
|
||||||
|
|
||||||
enum { NACK_PACKETS_MAX_SIZE = 256 }; // in packets
|
enum { NACK_PACKETS_MAX_SIZE = 256 }; // in packets
|
||||||
enum { NACK_BYTECOUNT_SIZE = 60}; // size of our NACK history
|
enum { NACK_BYTECOUNT_SIZE = 60}; // size of our NACK history
|
||||||
|
@ -11,7 +11,6 @@
|
|||||||
#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
|
#include "webrtc/modules/rtp_rtcp/source/rtp_rtcp_impl.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include "webrtc/common_types.h"
|
#include "webrtc/common_types.h"
|
||||||
@ -39,8 +38,6 @@ const float kFracMs = 4.294967296E6f;
|
|||||||
|
|
||||||
namespace webrtc {
|
namespace webrtc {
|
||||||
|
|
||||||
const WebRtc_UWord16 kDefaultRtt = 200;
|
|
||||||
|
|
||||||
static RtpData* NullObjectRtpData() {
|
static RtpData* NullObjectRtpData() {
|
||||||
static NullRtpData null_rtp_data;
|
static NullRtpData null_rtp_data;
|
||||||
return &null_rtp_data;
|
return &null_rtp_data;
|
||||||
@ -107,6 +104,7 @@ ModuleRtpRtcpImpl::ModuleRtpRtcpImpl(const Configuration& configuration)
|
|||||||
last_bitrate_process_time_(configuration.clock->TimeInMilliseconds()),
|
last_bitrate_process_time_(configuration.clock->TimeInMilliseconds()),
|
||||||
last_packet_timeout_process_time_(
|
last_packet_timeout_process_time_(
|
||||||
configuration.clock->TimeInMilliseconds()),
|
configuration.clock->TimeInMilliseconds()),
|
||||||
|
last_rtt_process_time_(configuration.clock->TimeInMilliseconds()),
|
||||||
packet_overhead_(28), // IPV4 UDP.
|
packet_overhead_(28), // IPV4 UDP.
|
||||||
critical_section_module_ptrs_(
|
critical_section_module_ptrs_(
|
||||||
CriticalSectionWrapper::CreateCriticalSection()),
|
CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
@ -258,33 +256,30 @@ WebRtc_Word32 ModuleRtpRtcpImpl::Process() {
|
|||||||
ProcessDeadOrAliveTimer();
|
ProcessDeadOrAliveTimer();
|
||||||
|
|
||||||
const bool default_instance(child_modules_.empty() ? false : true);
|
const bool default_instance(child_modules_.empty() ? false : true);
|
||||||
if (!default_instance && rtcp_sender_.TimeToSendRTCPReport()) {
|
if (!default_instance) {
|
||||||
WebRtc_UWord16 max_rtt = 0;
|
|
||||||
if (rtcp_sender_.Sending()) {
|
if (rtcp_sender_.Sending()) {
|
||||||
std::vector<RTCPReportBlock> receive_blocks;
|
// Process RTT if we have received a receiver report and we haven't
|
||||||
rtcp_receiver_.StatisticsReceived(&receive_blocks);
|
// processed RTT for at least |kRtpRtcpRttProcessTimeMs| milliseconds.
|
||||||
for (std::vector<RTCPReportBlock>::iterator it = receive_blocks.begin();
|
if (rtcp_receiver_.LastReceivedReceiverReport() >
|
||||||
it != receive_blocks.end(); ++it) {
|
last_rtt_process_time_ && now >= last_rtt_process_time_ +
|
||||||
WebRtc_UWord16 rtt = 0;
|
kRtpRtcpRttProcessTimeMs) {
|
||||||
rtcp_receiver_.RTT(it->remoteSSRC, &rtt, NULL, NULL, NULL);
|
last_rtt_process_time_ = now;
|
||||||
max_rtt = (rtt > max_rtt) ? rtt : max_rtt;
|
std::vector<RTCPReportBlock> receive_blocks;
|
||||||
|
rtcp_receiver_.StatisticsReceived(&receive_blocks);
|
||||||
|
uint16_t max_rtt = 0;
|
||||||
|
for (std::vector<RTCPReportBlock>::iterator it = receive_blocks.begin();
|
||||||
|
it != receive_blocks.end(); ++it) {
|
||||||
|
uint16_t rtt = 0;
|
||||||
|
rtcp_receiver_.RTT(it->remoteSSRC, &rtt, NULL, NULL, NULL);
|
||||||
|
max_rtt = (rtt > max_rtt) ? rtt : max_rtt;
|
||||||
|
}
|
||||||
|
// Report the rtt.
|
||||||
|
if (rtt_observer_ && max_rtt != 0)
|
||||||
|
rtt_observer_->OnRttUpdate(max_rtt);
|
||||||
}
|
}
|
||||||
// Report the rtt.
|
|
||||||
if (rtt_observer_ && max_rtt != 0)
|
|
||||||
rtt_observer_->OnRttUpdate(max_rtt);
|
|
||||||
} else {
|
|
||||||
// No valid RTT estimate, probably since this is a receive only channel.
|
|
||||||
// Use an estimate set by a send module.
|
|
||||||
max_rtt = rtcp_receiver_.RTT();
|
|
||||||
}
|
|
||||||
if (max_rtt == 0) {
|
|
||||||
// No own rtt calculation or set rtt, use default value.
|
|
||||||
max_rtt = kDefaultRtt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify receiver reports are delivered and the reported sequence number is
|
// Verify receiver reports are delivered and the reported sequence number
|
||||||
// increasing.
|
// is increasing.
|
||||||
if (rtcp_sender_.Sending()) {
|
|
||||||
int64_t rtcp_interval = RtcpReportInterval();
|
int64_t rtcp_interval = RtcpReportInterval();
|
||||||
if (rtcp_receiver_.RtcpRrTimeout(rtcp_interval)) {
|
if (rtcp_receiver_.RtcpRrTimeout(rtcp_interval)) {
|
||||||
LOG_F(LS_WARNING) << "Timeout: No RTCP RR received.";
|
LOG_F(LS_WARNING) << "Timeout: No RTCP RR received.";
|
||||||
@ -292,13 +287,8 @@ WebRtc_Word32 ModuleRtpRtcpImpl::Process() {
|
|||||||
LOG_F(LS_WARNING) <<
|
LOG_F(LS_WARNING) <<
|
||||||
"Timeout: No increase in RTCP RR extended highest sequence number.";
|
"Timeout: No increase in RTCP RR extended highest sequence number.";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (remote_bitrate_) {
|
if (remote_bitrate_ && TMMBR()) {
|
||||||
// TODO(mflodman) Remove this and let this be propagated by CallStats.
|
|
||||||
remote_bitrate_->SetRtt(max_rtt);
|
|
||||||
remote_bitrate_->UpdateEstimate(rtp_receiver_->SSRC(), now);
|
|
||||||
if (TMMBR()) {
|
|
||||||
unsigned int target_bitrate = 0;
|
unsigned int target_bitrate = 0;
|
||||||
std::vector<unsigned int> ssrcs;
|
std::vector<unsigned int> ssrcs;
|
||||||
if (remote_bitrate_->LatestEstimate(&ssrcs, &target_bitrate)) {
|
if (remote_bitrate_->LatestEstimate(&ssrcs, &target_bitrate)) {
|
||||||
@ -309,7 +299,8 @@ WebRtc_Word32 ModuleRtpRtcpImpl::Process() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rtcp_sender_.SendRTCP(kRtcpReport);
|
if (rtcp_sender_.TimeToSendRTCPReport())
|
||||||
|
rtcp_sender_.SendRTCP(kRtcpReport);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UpdateRTCPReceiveInformationTimers()) {
|
if (UpdateRTCPReceiveInformationTimers()) {
|
||||||
@ -1995,22 +1986,6 @@ void ModuleRtpRtcpImpl::BitrateSent(WebRtc_UWord32* total_rate,
|
|||||||
*nack_rate = rtp_sender_.NackOverheadRate();
|
*nack_rate = rtp_sender_.NackOverheadRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ModuleRtpRtcpImpl::EstimatedReceiveBandwidth(
|
|
||||||
WebRtc_UWord32* available_bandwidth) const {
|
|
||||||
if (remote_bitrate_) {
|
|
||||||
std::vector<unsigned int> ssrcs;
|
|
||||||
if (!remote_bitrate_->LatestEstimate(&ssrcs, available_bandwidth)) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (!ssrcs.empty()) {
|
|
||||||
*available_bandwidth /= ssrcs.size();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
// No bandwidth receive-side bandwidth estimation is connected to this module.
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bad state of RTP receiver request a keyframe.
|
// Bad state of RTP receiver request a keyframe.
|
||||||
void ModuleRtpRtcpImpl::OnRequestIntraFrame() {
|
void ModuleRtpRtcpImpl::OnRequestIntraFrame() {
|
||||||
RequestKeyFrame();
|
RequestKeyFrame();
|
||||||
|
@ -427,9 +427,6 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
|
|||||||
WebRtc_UWord32* fec_rate,
|
WebRtc_UWord32* fec_rate,
|
||||||
WebRtc_UWord32* nackRate) const;
|
WebRtc_UWord32* nackRate) const;
|
||||||
|
|
||||||
virtual int EstimatedReceiveBandwidth(
|
|
||||||
WebRtc_UWord32* available_bandwidth) const;
|
|
||||||
|
|
||||||
virtual void SetRemoteSSRC(const WebRtc_UWord32 ssrc);
|
virtual void SetRemoteSSRC(const WebRtc_UWord32 ssrc);
|
||||||
|
|
||||||
virtual WebRtc_UWord32 SendTimeOfSendReport(const WebRtc_UWord32 send_report);
|
virtual WebRtc_UWord32 SendTimeOfSendReport(const WebRtc_UWord32 send_report);
|
||||||
@ -493,6 +490,7 @@ class ModuleRtpRtcpImpl : public RtpRtcp {
|
|||||||
WebRtc_Word64 last_process_time_;
|
WebRtc_Word64 last_process_time_;
|
||||||
WebRtc_Word64 last_bitrate_process_time_;
|
WebRtc_Word64 last_bitrate_process_time_;
|
||||||
WebRtc_Word64 last_packet_timeout_process_time_;
|
WebRtc_Word64 last_packet_timeout_process_time_;
|
||||||
|
WebRtc_Word64 last_rtt_process_time_;
|
||||||
WebRtc_UWord16 packet_overhead_;
|
WebRtc_UWord16 packet_overhead_;
|
||||||
|
|
||||||
scoped_ptr<CriticalSectionWrapper> critical_section_module_ptrs_;
|
scoped_ptr<CriticalSectionWrapper> critical_section_module_ptrs_;
|
||||||
|
@ -271,7 +271,7 @@ TEST_F(RtpRtcpRtcpTest, RTCP) {
|
|||||||
std::vector<RTCPReportBlock> report_blocks;
|
std::vector<RTCPReportBlock> report_blocks;
|
||||||
EXPECT_EQ(-1, module1->RemoteRTCPStat(NULL));
|
EXPECT_EQ(-1, module1->RemoteRTCPStat(NULL));
|
||||||
EXPECT_EQ(0, module1->RemoteRTCPStat(&report_blocks));
|
EXPECT_EQ(0, module1->RemoteRTCPStat(&report_blocks));
|
||||||
EXPECT_EQ(1u, report_blocks.size());
|
ASSERT_EQ(1u, report_blocks.size());
|
||||||
const RTCPReportBlock& reportBlockReceived = report_blocks[0];
|
const RTCPReportBlock& reportBlockReceived = report_blocks[0];
|
||||||
|
|
||||||
float secSinceLastReport =
|
float secSinceLastReport =
|
||||||
|
@ -21,15 +21,7 @@ namespace webrtc {
|
|||||||
|
|
||||||
class CriticalSectionWrapper;
|
class CriticalSectionWrapper;
|
||||||
class RtcpRttObserver;
|
class RtcpRttObserver;
|
||||||
|
class StatsObserver;
|
||||||
// Interface used to distribute call statistics. Callbacks will be triggered as
|
|
||||||
// soon as the class has been registered using RegisterStatsObserver.
|
|
||||||
class StatsObserver {
|
|
||||||
public:
|
|
||||||
virtual void OnRttUpdate(uint32_t rtt) = 0;
|
|
||||||
|
|
||||||
virtual ~StatsObserver() {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// CallStats keeps track of statistics for a call.
|
// CallStats keeps track of statistics for a call.
|
||||||
class CallStats : public Module {
|
class CallStats : public Module {
|
||||||
|
@ -1158,7 +1158,9 @@ void ViEChannel::GetBandwidthUsage(uint32_t* total_bitrate_sent,
|
|||||||
|
|
||||||
int ViEChannel::GetEstimatedReceiveBandwidth(
|
int ViEChannel::GetEstimatedReceiveBandwidth(
|
||||||
uint32_t* estimated_bandwidth) const {
|
uint32_t* estimated_bandwidth) const {
|
||||||
return rtp_rtcp_->EstimatedReceiveBandwidth(estimated_bandwidth);
|
if (!vie_receiver_.EstimatedReceiveBandwidth(estimated_bandwidth))
|
||||||
|
return -1;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
WebRtc_Word32 ViEChannel::StartRTPDump(const char file_nameUTF8[1024],
|
WebRtc_Word32 ViEChannel::StartRTPDump(const char file_nameUTF8[1024],
|
||||||
|
@ -25,18 +25,22 @@ namespace webrtc {
|
|||||||
ChannelGroup::ChannelGroup(ProcessThread* process_thread,
|
ChannelGroup::ChannelGroup(ProcessThread* process_thread,
|
||||||
const OverUseDetectorOptions& options,
|
const OverUseDetectorOptions& options,
|
||||||
RemoteBitrateEstimator::EstimationMode mode)
|
RemoteBitrateEstimator::EstimationMode mode)
|
||||||
: remb_(new VieRemb(process_thread)),
|
: remb_(new VieRemb()),
|
||||||
bitrate_controller_(BitrateController::CreateBitrateController()),
|
bitrate_controller_(BitrateController::CreateBitrateController()),
|
||||||
call_stats_(new CallStats()),
|
call_stats_(new CallStats()),
|
||||||
remote_bitrate_estimator_(RemoteBitrateEstimator::Create(remb_.get(),
|
remote_bitrate_estimator_(RemoteBitrateEstimator::Create(
|
||||||
options, mode)),
|
options, mode, remb_.get(), Clock::GetRealTimeClock())),
|
||||||
encoder_state_feedback_(new EncoderStateFeedback()),
|
encoder_state_feedback_(new EncoderStateFeedback()),
|
||||||
process_thread_(process_thread) {
|
process_thread_(process_thread) {
|
||||||
|
call_stats_->RegisterStatsObserver(remote_bitrate_estimator_.get());
|
||||||
process_thread->RegisterModule(call_stats_.get());
|
process_thread->RegisterModule(call_stats_.get());
|
||||||
|
process_thread->RegisterModule(remote_bitrate_estimator_.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
ChannelGroup::~ChannelGroup() {
|
ChannelGroup::~ChannelGroup() {
|
||||||
|
call_stats_->DeregisterStatsObserver(remote_bitrate_estimator_.get());
|
||||||
process_thread_->DeRegisterModule(call_stats_.get());
|
process_thread_->DeRegisterModule(call_stats_.get());
|
||||||
|
process_thread_->DeRegisterModule(remote_bitrate_estimator_.get());
|
||||||
assert(channels_.empty());
|
assert(channels_.empty());
|
||||||
assert(!remb_->InUse());
|
assert(!remb_->InUse());
|
||||||
}
|
}
|
||||||
|
@ -284,4 +284,18 @@ int ViEReceiver::StopRTPDump() {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(holmer): To be moved to ViEChannelGroup.
|
||||||
|
bool ViEReceiver::EstimatedReceiveBandwidth(
|
||||||
|
unsigned int* available_bandwidth) const {
|
||||||
|
std::vector<unsigned int> ssrcs;
|
||||||
|
if (!remote_bitrate_estimator_->LatestEstimate(&ssrcs,
|
||||||
|
available_bandwidth)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!ssrcs.empty()) {
|
||||||
|
*available_bandwidth /= ssrcs.size();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -74,6 +74,8 @@ class ViEReceiver : public UdpTransportData, public RtpData {
|
|||||||
uint32_t ntp_frac,
|
uint32_t ntp_frac,
|
||||||
uint32_t timestamp);
|
uint32_t timestamp);
|
||||||
|
|
||||||
|
bool EstimatedReceiveBandwidth(unsigned int* available_bandwidth) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int InsertRTPPacket(const WebRtc_Word8* rtp_packet, int rtp_packet_length);
|
int InsertRTPPacket(const WebRtc_Word8* rtp_packet, int rtp_packet_length);
|
||||||
int InsertRTCPPacket(const WebRtc_Word8* rtcp_packet, int rtcp_packet_length);
|
int InsertRTCPPacket(const WebRtc_Word8* rtcp_packet, int rtcp_packet_length);
|
||||||
|
@ -28,19 +28,13 @@ const unsigned int kRembMinimumBitrateKbps = 50;
|
|||||||
// % threshold for if we should send a new REMB asap.
|
// % threshold for if we should send a new REMB asap.
|
||||||
const unsigned int kSendThresholdPercent = 97;
|
const unsigned int kSendThresholdPercent = 97;
|
||||||
|
|
||||||
VieRemb::VieRemb(ProcessThread* process_thread)
|
VieRemb::VieRemb()
|
||||||
: process_thread_(process_thread),
|
: list_crit_(CriticalSectionWrapper::CreateCriticalSection()),
|
||||||
list_crit_(CriticalSectionWrapper::CreateCriticalSection()),
|
|
||||||
last_remb_time_(TickTime::MillisecondTimestamp()),
|
last_remb_time_(TickTime::MillisecondTimestamp()),
|
||||||
last_send_bitrate_(0),
|
last_send_bitrate_(0),
|
||||||
bitrate_(0),
|
bitrate_(0) {}
|
||||||
bitrate_update_time_ms_(-1) {
|
|
||||||
process_thread->RegisterModule(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
VieRemb::~VieRemb() {
|
VieRemb::~VieRemb() {}
|
||||||
process_thread_->DeRegisterModule(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VieRemb::AddReceiveChannel(RtpRtcp* rtp_rtcp) {
|
void VieRemb::AddReceiveChannel(RtpRtcp* rtp_rtcp) {
|
||||||
assert(rtp_rtcp);
|
assert(rtp_rtcp);
|
||||||
@ -115,7 +109,7 @@ void VieRemb::OnReceiveBitrateChanged(std::vector<unsigned int>* ssrcs,
|
|||||||
WEBRTC_TRACE(kTraceStream, kTraceVideo, -1,
|
WEBRTC_TRACE(kTraceStream, kTraceVideo, -1,
|
||||||
"VieRemb::UpdateBitrateEstimate(bitrate: %u)", bitrate);
|
"VieRemb::UpdateBitrateEstimate(bitrate: %u)", bitrate);
|
||||||
assert(ssrcs);
|
assert(ssrcs);
|
||||||
CriticalSectionScoped cs(list_crit_.get());
|
list_crit_->Enter();
|
||||||
// If we already have an estimate, check if the new total estimate is below
|
// If we already have an estimate, check if the new total estimate is below
|
||||||
// kSendThresholdPercent of the previous estimate.
|
// kSendThresholdPercent of the previous estimate.
|
||||||
if (last_send_bitrate_ > 0) {
|
if (last_send_bitrate_ > 0) {
|
||||||
@ -128,40 +122,23 @@ void VieRemb::OnReceiveBitrateChanged(std::vector<unsigned int>* ssrcs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
bitrate_ = bitrate;
|
bitrate_ = bitrate;
|
||||||
|
// TODO(holmer): Remove |ssrcs_| from this class as the REMB is produced
|
||||||
|
// immediately upon a call to this function.
|
||||||
ssrcs_.resize(ssrcs->size());
|
ssrcs_.resize(ssrcs->size());
|
||||||
std::copy(ssrcs->begin(), ssrcs->end(), ssrcs_.begin());
|
std::copy(ssrcs->begin(), ssrcs->end(), ssrcs_.begin());
|
||||||
bitrate_update_time_ms_ = TickTime::MillisecondTimestamp();
|
|
||||||
}
|
|
||||||
|
|
||||||
WebRtc_Word32 VieRemb::ChangeUniqueId(const WebRtc_Word32 id) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
WebRtc_Word32 VieRemb::TimeUntilNextProcess() {
|
|
||||||
return kRembSendIntervallMs -
|
|
||||||
(TickTime::MillisecondTimestamp() - last_remb_time_);
|
|
||||||
}
|
|
||||||
|
|
||||||
WebRtc_Word32 VieRemb::Process() {
|
|
||||||
int64_t now = TickTime::MillisecondTimestamp();
|
|
||||||
if (now - last_remb_time_ < kRembSendIntervallMs)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
last_remb_time_ = now;
|
|
||||||
|
|
||||||
// Calculate total receive bitrate estimate.
|
// Calculate total receive bitrate estimate.
|
||||||
list_crit_->Enter();
|
int64_t now = TickTime::MillisecondTimestamp();
|
||||||
|
|
||||||
// Reset the estimate if it has timed out.
|
if (now - last_remb_time_ < kRembSendIntervallMs) {
|
||||||
if (TickTime::MillisecondTimestamp() - bitrate_update_time_ms_ >
|
|
||||||
kRembTimeOutThresholdMs) {
|
|
||||||
bitrate_ = 0;
|
|
||||||
bitrate_update_time_ms_ = -1;
|
|
||||||
}
|
|
||||||
if (bitrate_update_time_ms_ == -1 || ssrcs_.empty() ||
|
|
||||||
receive_modules_.empty()) {
|
|
||||||
list_crit_->Leave();
|
list_crit_->Leave();
|
||||||
return 0;
|
return;
|
||||||
|
}
|
||||||
|
last_remb_time_ = now;
|
||||||
|
|
||||||
|
if (ssrcs_.empty() || receive_modules_.empty()) {
|
||||||
|
list_crit_->Leave();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send a REMB packet.
|
// Send a REMB packet.
|
||||||
@ -179,18 +156,17 @@ WebRtc_Word32 VieRemb::Process() {
|
|||||||
}
|
}
|
||||||
// Copy SSRCs to avoid race conditions.
|
// Copy SSRCs to avoid race conditions.
|
||||||
int ssrcs_length = ssrcs_.size();
|
int ssrcs_length = ssrcs_.size();
|
||||||
unsigned int* ssrcs = new unsigned int[ssrcs_length];
|
unsigned int* ssrcs_copy = new unsigned int[ssrcs_length];
|
||||||
for (int i = 0; i < ssrcs_length; ++i) {
|
for (int i = 0; i < ssrcs_length; ++i) {
|
||||||
ssrcs[i] = ssrcs_[i];
|
ssrcs_copy[i] = ssrcs_[i];
|
||||||
}
|
}
|
||||||
list_crit_->Leave();
|
list_crit_->Leave();
|
||||||
|
|
||||||
if (sender) {
|
if (sender) {
|
||||||
// TODO(holmer): Change RTP module API to take a vector pointer.
|
// TODO(holmer): Change RTP module API to take a vector pointer.
|
||||||
sender->SetREMBData(bitrate_, ssrcs_length, ssrcs);
|
sender->SetREMBData(bitrate_, ssrcs_length, ssrcs_copy);
|
||||||
}
|
}
|
||||||
delete [] ssrcs;
|
delete [] ssrcs_copy;
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -26,9 +26,9 @@ class CriticalSectionWrapper;
|
|||||||
class ProcessThread;
|
class ProcessThread;
|
||||||
class RtpRtcp;
|
class RtpRtcp;
|
||||||
|
|
||||||
class VieRemb : public RemoteBitrateObserver, public Module {
|
class VieRemb : public RemoteBitrateObserver {
|
||||||
public:
|
public:
|
||||||
explicit VieRemb(ProcessThread* process_thread);
|
VieRemb();
|
||||||
~VieRemb();
|
~VieRemb();
|
||||||
|
|
||||||
// Called to add a receive channel to include in the REMB packet.
|
// Called to add a receive channel to include in the REMB packet.
|
||||||
@ -54,15 +54,9 @@ class VieRemb : public RemoteBitrateObserver, public Module {
|
|||||||
virtual void OnReceiveBitrateChanged(std::vector<unsigned int>* ssrcs,
|
virtual void OnReceiveBitrateChanged(std::vector<unsigned int>* ssrcs,
|
||||||
unsigned int bitrate);
|
unsigned int bitrate);
|
||||||
|
|
||||||
// Implements Module.
|
|
||||||
virtual WebRtc_Word32 ChangeUniqueId(const WebRtc_Word32 id);
|
|
||||||
virtual WebRtc_Word32 TimeUntilNextProcess();
|
|
||||||
virtual WebRtc_Word32 Process();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::list<RtpRtcp*> RtpModules;
|
typedef std::list<RtpRtcp*> RtpModules;
|
||||||
|
|
||||||
ProcessThread* process_thread_;
|
|
||||||
scoped_ptr<CriticalSectionWrapper> list_crit_;
|
scoped_ptr<CriticalSectionWrapper> list_crit_;
|
||||||
|
|
||||||
// The last time a REMB was sent.
|
// The last time a REMB was sent.
|
||||||
@ -78,7 +72,6 @@ class VieRemb : public RemoteBitrateObserver, public Module {
|
|||||||
// The last bitrate update.
|
// The last bitrate update.
|
||||||
unsigned int bitrate_;
|
unsigned int bitrate_;
|
||||||
std::vector<unsigned int> ssrcs_;
|
std::vector<unsigned int> ssrcs_;
|
||||||
int64_t bitrate_update_time_ms_;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
@ -44,7 +44,7 @@ class ViERembTest : public ::testing::Test {
|
|||||||
virtual void SetUp() {
|
virtual void SetUp() {
|
||||||
TickTime::UseFakeClock(12345);
|
TickTime::UseFakeClock(12345);
|
||||||
process_thread_.reset(new TestProcessThread);
|
process_thread_.reset(new TestProcessThread);
|
||||||
vie_remb_.reset(new VieRemb(process_thread_.get()));
|
vie_remb_.reset(new VieRemb());
|
||||||
}
|
}
|
||||||
scoped_ptr<TestProcessThread> process_thread_;
|
scoped_ptr<TestProcessThread> process_thread_;
|
||||||
scoped_ptr<VieRemb> vie_remb_;
|
scoped_ptr<VieRemb> vie_remb_;
|
||||||
@ -64,13 +64,12 @@ TEST_F(ViERembTest, OneModuleTestForSendingRemb) {
|
|||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->Process();
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Lower bitrate to send another REMB packet.
|
// Lower bitrate to send another REMB packet.
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate - 100);
|
|
||||||
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate - 100, 1, _))
|
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate - 100, 1, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->Process();
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate - 100);
|
||||||
|
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp);
|
vie_remb_->RemoveReceiveChannel(&rtp);
|
||||||
vie_remb_->RemoveRembSender(&rtp);
|
vie_remb_->RemoveRembSender(&rtp);
|
||||||
@ -86,11 +85,11 @@ TEST_F(ViERembTest, LowerEstimateToSendRemb) {
|
|||||||
std::vector<unsigned int> ssrcs(&ssrc, &ssrc + 1);
|
std::vector<unsigned int> ssrcs(&ssrc, &ssrc + 1);
|
||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
// Call process to get a first estimate.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->Process();
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Lower the estimate with more than 3% to trigger a call to SetREMBData right
|
// Lower the estimate with more than 3% to trigger a call to SetREMBData right
|
||||||
// away.
|
// away.
|
||||||
@ -98,7 +97,6 @@ TEST_F(ViERembTest, LowerEstimateToSendRemb) {
|
|||||||
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
vie_remb_->Process();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ViERembTest, VerifyIncreasingAndDecreasing) {
|
TEST_F(ViERembTest, VerifyIncreasingAndDecreasing) {
|
||||||
@ -114,11 +112,11 @@ TEST_F(ViERembTest, VerifyIncreasingAndDecreasing) {
|
|||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[0]);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[0]);
|
||||||
|
|
||||||
// Call process to get a first estimate.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[0], 2, _))
|
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[0], 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
vie_remb_->Process();
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[0]);
|
||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[1] + 100);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[1] + 100);
|
||||||
|
|
||||||
@ -126,7 +124,6 @@ TEST_F(ViERembTest, VerifyIncreasingAndDecreasing) {
|
|||||||
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[1], 2, _))
|
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate[1], 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[1]);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate[1]);
|
||||||
vie_remb_->Process();
|
|
||||||
|
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
||||||
vie_remb_->RemoveRembSender(&rtp_0);
|
vie_remb_->RemoveRembSender(&rtp_0);
|
||||||
@ -145,24 +142,23 @@ TEST_F(ViERembTest, NoRembForIncreasedBitrate) {
|
|||||||
std::vector<unsigned int> ssrcs(ssrc, ssrc + sizeof(ssrc) / sizeof(ssrc[0]));
|
std::vector<unsigned int> ssrcs(ssrc, ssrc + sizeof(ssrc) / sizeof(ssrc[0]));
|
||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
// Trigger a first call to have a running state.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->Process();
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Increased estimate shouldn't trigger a callback right away.
|
// Increased estimate shouldn't trigger a callback right away.
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate + 1);
|
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp_0, SetREMBData(_, _, _))
|
||||||
.Times(0);
|
.Times(0);
|
||||||
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate + 1);
|
||||||
|
|
||||||
// Decreasing the estimate less than 3% shouldn't trigger a new callback.
|
// Decreasing the estimate less than 3% shouldn't trigger a new callback.
|
||||||
int lower_estimate = bitrate_estimate * 98 / 100;
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, lower_estimate);
|
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp_0, SetREMBData(_, _, _))
|
||||||
.Times(0);
|
.Times(0);
|
||||||
|
int lower_estimate = bitrate_estimate * 98 / 100;
|
||||||
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, lower_estimate);
|
||||||
|
|
||||||
vie_remb_->Process();
|
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp_1);
|
vie_remb_->RemoveReceiveChannel(&rtp_1);
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
||||||
vie_remb_->RemoveRembSender(&rtp_0);
|
vie_remb_->RemoveRembSender(&rtp_0);
|
||||||
@ -180,18 +176,17 @@ TEST_F(ViERembTest, ChangeSendRtpModule) {
|
|||||||
std::vector<unsigned int> ssrcs(ssrc, ssrc + sizeof(ssrc) / sizeof(ssrc[0]));
|
std::vector<unsigned int> ssrcs(ssrc, ssrc + sizeof(ssrc) / sizeof(ssrc[0]));
|
||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
// Call process to get a first estimate.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->Process();
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Decrease estimate to trigger a REMB.
|
// Decrease estimate to trigger a REMB.
|
||||||
bitrate_estimate = bitrate_estimate - 100;
|
bitrate_estimate = bitrate_estimate - 100;
|
||||||
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
EXPECT_CALL(rtp_0, SetREMBData(bitrate_estimate, 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
vie_remb_->Process();
|
|
||||||
|
|
||||||
// Remove the sending module, add it again -> should get remb on the second
|
// Remove the sending module, add it again -> should get remb on the second
|
||||||
// module.
|
// module.
|
||||||
@ -203,7 +198,6 @@ TEST_F(ViERembTest, ChangeSendRtpModule) {
|
|||||||
EXPECT_CALL(rtp_1, SetREMBData(bitrate_estimate, 2, _))
|
EXPECT_CALL(rtp_1, SetREMBData(bitrate_estimate, 2, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
vie_remb_->Process();
|
|
||||||
|
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
vie_remb_->RemoveReceiveChannel(&rtp_0);
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp_1);
|
vie_remb_->RemoveReceiveChannel(&rtp_1);
|
||||||
@ -218,39 +212,22 @@ TEST_F(ViERembTest, OnlyOneRembForDoubleProcess) {
|
|||||||
vie_remb_->AddReceiveChannel(&rtp);
|
vie_remb_->AddReceiveChannel(&rtp);
|
||||||
vie_remb_->AddRembSender(&rtp);
|
vie_remb_->AddRembSender(&rtp);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
// Call process to get a first estimate.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->Process();
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Lower the estimate, should trigger a call to SetREMBData right away.
|
// Lower the estimate, should trigger a call to SetREMBData right away.
|
||||||
bitrate_estimate = bitrate_estimate - 100;
|
bitrate_estimate = bitrate_estimate - 100;
|
||||||
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
EXPECT_CALL(rtp, SetREMBData(bitrate_estimate, 1, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
vie_remb_->Process();
|
|
||||||
|
|
||||||
// Call Process again, this should not trigger a new callback.
|
// Call OnReceiveBitrateChanged again, this should not trigger a new callback.
|
||||||
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
||||||
.Times(0);
|
.Times(0);
|
||||||
vie_remb_->Process();
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp);
|
|
||||||
vie_remb_->RemoveRembSender(&rtp);
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_F(ViERembTest, NoOnReceivedBitrateChangedCall) {
|
|
||||||
MockRtpRtcp rtp;
|
|
||||||
|
|
||||||
vie_remb_->AddReceiveChannel(&rtp);
|
|
||||||
vie_remb_->AddRembSender(&rtp);
|
|
||||||
// TODO(mflodman) Add fake clock.
|
|
||||||
TickTime::AdvanceFakeClock(1000);
|
|
||||||
// No bitrate estimate given, no callback expected.
|
|
||||||
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
|
||||||
.Times(0);
|
|
||||||
vie_remb_->Process();
|
|
||||||
|
|
||||||
vie_remb_->RemoveReceiveChannel(&rtp);
|
vie_remb_->RemoveReceiveChannel(&rtp);
|
||||||
vie_remb_->RemoveRembSender(&rtp);
|
vie_remb_->RemoveRembSender(&rtp);
|
||||||
}
|
}
|
||||||
@ -267,18 +244,17 @@ TEST_F(ViERembTest, NoSendingRtpModule) {
|
|||||||
|
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Call process to get a first estimate.
|
// Call OnReceiveBitrateChanged twice to get a first estimate.
|
||||||
TickTime::AdvanceFakeClock(1000);
|
TickTime::AdvanceFakeClock(1000);
|
||||||
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->Process();
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
|
|
||||||
// Lower the estimate to trigger a new packet REMB packet.
|
// Lower the estimate to trigger a new packet REMB packet.
|
||||||
bitrate_estimate = bitrate_estimate - 100;
|
bitrate_estimate = bitrate_estimate - 100;
|
||||||
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
EXPECT_CALL(rtp, SetREMBData(_, _, _))
|
||||||
.Times(1);
|
.Times(1);
|
||||||
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
vie_remb_->OnReceiveBitrateChanged(&ssrcs, bitrate_estimate);
|
||||||
vie_remb_->Process();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace webrtc
|
} // namespace webrtc
|
||||||
|
Loading…
Reference in New Issue
Block a user