Wire up new feedback format by introducing a FeedbackPacket type.
The new format instantiates the RemoteBitrateEstimator at the send-side and feeds back all packet arrival timestamps and sequence numbers to the sender, where inter-arrival deltas are calculated.
Next step will be to make feedback packets part of regular packets and send them over the network. This also requires bi-directional simulations.
BUG=4173
R=mflodman@webrtc.org, sprang@webrtc.org
Review URL: https://webrtc-codereview.appspot.com/37109004
Cr-Commit-Position: refs/heads/master@{#8264}
git-svn-id: http://webrtc.googlecode.com/svn/trunk@8264 4adac7df-926f-26a2-2b94-8c16560cd09d
diff --git a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc
index 58c8b5b..f607fd0 100644
--- a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc
+++ b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc
@@ -25,7 +25,8 @@
AbsoluteSendTimeRemoteBitrateEstimatorFactory();
return BweTestConfig::EstimatorConfig("AST", flow_id, &factory, kAimdControl,
- plot_delay, plot_estimate);
+ kRembEstimator, plot_delay,
+ plot_estimate);
}
BweTestConfig MakeAdaptiveBweTestConfig() {
@@ -65,7 +66,7 @@
TEST_P(BweSimulation, SprintUplinkTest) {
VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0);
- RegularVideoSender sender(this, &source, 300);
+ PacketSender sender(this, &source, kRembEstimator);
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
RateCounterFilter counter2(this, "receiver_input");
@@ -76,7 +77,7 @@
TEST_P(BweSimulation, Verizon4gDownlinkTest) {
VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0);
- RegularVideoSender sender(this, &source, 300);
+ PacketSender sender(this, &source, kRembEstimator);
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
RateCounterFilter counter2(this, "receiver_input");
@@ -87,7 +88,7 @@
TEST_P(BweSimulation, Choke1000kbps500kbps1000kbps) {
VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0);
- RegularVideoSender sender(this, &source, 300);
+ PacketSender sender(this, &source, kRembEstimator);
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
filter.SetCapacity(1000);
@@ -102,7 +103,7 @@
TEST_P(BweSimulation, PacerChoke1000kbps500kbps1000kbps) {
VerboseLogging(true);
PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
- PacedVideoSender sender(this, &source, 300);
+ PacedVideoSender sender(this, &source, kRembEstimator);
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
filter.SetCapacity(1000);
@@ -117,7 +118,7 @@
TEST_P(BweSimulation, PacerChoke10000kbps) {
VerboseLogging(true);
PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
- PacedVideoSender sender(this, &source, 300);
+ PacedVideoSender sender(this, &source, kRembEstimator);
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
filter.SetCapacity(10000);
@@ -128,7 +129,7 @@
TEST_P(BweSimulation, PacerChoke200kbps30kbps200kbps) {
VerboseLogging(true);
PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
- PacedVideoSender sender(this, &source, 300);
+ PacedVideoSender sender(this, &source, kRembEstimator);
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
filter.SetCapacity(200);
@@ -143,7 +144,7 @@
TEST_P(BweSimulation, Choke200kbps30kbps200kbps) {
VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0);
- RegularVideoSender sender(this, &source, 300);
+ PacketSender sender(this, &source, kRembEstimator);
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
filter.SetCapacity(200);
@@ -158,7 +159,7 @@
TEST_P(BweSimulation, GoogleWifiTrace3Mbps) {
VerboseLogging(true);
AdaptiveVideoSource source(0, 30, 300, 0, 0);
- RegularVideoSender sender(this, &source, 300);
+ PacketSender sender(this, &source, kRembEstimator);
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
filter.SetMaxDelay(500);
@@ -170,7 +171,7 @@
TEST_P(BweSimulation, PacerGoogleWifiTrace3Mbps) {
VerboseLogging(true);
PeriodicKeyFrameSource source(0, 30, 300, 0, 0, 1000);
- PacedVideoSender sender(this, &source, 300);
+ PacedVideoSender sender(this, &source, kRembEstimator);
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
filter.SetMaxDelay(500);
@@ -196,13 +197,13 @@
const int kAllFlowIds[] = {0, 1, 2};
const size_t kNumFlows = sizeof(kAllFlowIds) / sizeof(kAllFlowIds[0]);
scoped_ptr<AdaptiveVideoSource> sources[kNumFlows];
- scoped_ptr<RegularVideoSender> senders[kNumFlows];
+ scoped_ptr<PacketSender> senders[kNumFlows];
for (size_t i = 0; i < kNumFlows; ++i) {
// Streams started 20 seconds apart to give them different advantage when
// competing for the bandwidth.
sources[i].reset(
new AdaptiveVideoSource(kAllFlowIds[i], 30, 300, 0, i * 20000));
- senders[i].reset(new RegularVideoSender(this, sources[i].get(), 300));
+ senders[i].reset(new PacketSender(this, sources[i].get(), kRembEstimator));
}
ChokeFilter choke(this, CreateFlowIds(kAllFlowIds, kNumFlows));
@@ -232,7 +233,8 @@
// competing for the bandwidth.
sources[i].reset(new PeriodicKeyFrameSource(kAllFlowIds[i], 30, 300, 0,
i * 20000, 1000));
- senders[i].reset(new PacedVideoSender(this, sources[i].get(), 300));
+ senders[i].reset(
+ new PacedVideoSender(this, sources[i].get(), kRembEstimator));
}
ChokeFilter choke(this, CreateFlowIds(kAllFlowIds, kNumFlows));
diff --git a/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h b/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
index 92a0eb8..4986467 100644
--- a/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
+++ b/webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h
@@ -63,10 +63,37 @@
std::vector<int64_t> recent_arrival_time_ms;
};
+struct PacketInfo {
+ PacketInfo(int64_t arrival_time_ms,
+ int64_t send_time_ms,
+ uint16_t sequence_number,
+ size_t payload_size)
+ : arrival_time_ms(arrival_time_ms),
+ send_time_ms(send_time_ms),
+ sequence_number(sequence_number),
+ payload_size(payload_size) {}
+ // Time corresponding to when the packet was received. Timestamped with the
+ // receiver's clock.
+ int64_t arrival_time_ms;
+ // Time corresponding to when the packet was sent, timestamped with the
+ // sender's clock.
+ int64_t send_time_ms;
+ // Packet identifier, incremented with 1 for every packet generated by the
+ // sender.
+ uint16_t sequence_number;
+ // Size of the packet excluding RTP headers.
+ size_t payload_size;
+};
+
class RemoteBitrateEstimator : public CallStatsObserver, public Module {
public:
virtual ~RemoteBitrateEstimator() {}
+ virtual void IncomingPacketFeedbackVector(
+ const std::vector<PacketInfo>& packet_feedback_vector) {
+ assert(false);
+ }
+
// Called for each incoming packet. Updates the incoming payload bitrate
// estimate and the over-use detector. If an over-use is detected the
// remote bitrate estimate will be updated. Note that |payload_size| is the
diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
index c357577..e32ef72 100644
--- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
+++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimator_abs_send_time.cc
@@ -111,6 +111,9 @@
uint32_t min_bitrate_bps);
virtual ~RemoteBitrateEstimatorAbsSendTimeImpl() {}
+ virtual void IncomingPacketFeedbackVector(
+ const std::vector<PacketInfo>& packet_feedback_vector) OVERRIDE;
+
virtual void IncomingPacket(int64_t arrival_time_ms,
size_t payload_size,
const RTPHeader& header) OVERRIDE;
@@ -129,7 +132,6 @@
private:
typedef std::map<unsigned int, int64_t> Ssrcs;
-
static bool IsWithinClusterBounds(int send_delta_ms,
const Cluster& cluster_aggregate) {
if (cluster_aggregate.count == 0)
@@ -150,6 +152,11 @@
return static_cast<int>(reinterpret_cast<uint64_t>(this));
}
+ void IncomingPacketInfo(int64_t arrival_time_ms,
+ uint32_t send_time_24bits,
+ size_t payload_size,
+ uint32_t ssrc);
+
bool IsProbe(int64_t send_time_ms, int payload_size) const
EXCLUSIVE_LOCKS_REQUIRED(crit_sect_.get());
@@ -322,6 +329,19 @@
return initial_probe || bitrate_above_estimate;
}
+void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacketFeedbackVector(
+ const std::vector<PacketInfo>& packet_feedback_vector) {
+ for (const auto& packet_info : packet_feedback_vector) {
+ // TODO(holmer): We should get rid of this conversion if possible as we may
+ // lose precision.
+ uint32_t send_time_32bits = (packet_info.send_time_ms) / kTimestampToMs;
+ uint32_t send_time_24bits =
+ send_time_32bits >> kAbsSendTimeInterArrivalUpshift;
+ IncomingPacketInfo(packet_info.arrival_time_ms, send_time_24bits,
+ packet_info.payload_size, 0);
+ }
+}
+
void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacket(
int64_t arrival_time_ms,
size_t payload_size,
@@ -330,27 +350,38 @@
LOG(LS_WARNING) << "RemoteBitrateEstimatorAbsSendTimeImpl: Incoming packet "
"is missing absolute send time extension!";
}
- uint32_t absolute_send_time = header.extension.absoluteSendTime;
- assert(absolute_send_time < (1ul << 24));
- int64_t now_ms = clock_->TimeInMilliseconds();
+ IncomingPacketInfo(arrival_time_ms, header.extension.absoluteSendTime,
+ payload_size, header.ssrc);
+}
+
+void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacketInfo(
+ int64_t arrival_time_ms,
+ uint32_t send_time_24bits,
+ size_t payload_size,
+ uint32_t ssrc) {
+ assert(send_time_24bits < (1ul << 24));
+ // Shift up send time to use the full 32 bits that inter_arrival works with,
+ // so wrapping works properly.
+ uint32_t timestamp = send_time_24bits << kAbsSendTimeInterArrivalUpshift;
+ int64_t send_time_ms = static_cast<int64_t>(timestamp) * kTimestampToMs;
+
CriticalSectionScoped cs(crit_sect_.get());
- ssrcs_[header.ssrc] = now_ms;
+ int64_t now_ms = clock_->TimeInMilliseconds();
+ // TODO(holmer): SSRCs are only needed for REMB, should be broken out from
+ // here.
+ ssrcs_[ssrc] = now_ms;
incoming_bitrate_.Update(payload_size, now_ms);
const BandwidthUsage prior_state = detector_.State();
if (first_packet_time_ms_ == -1)
first_packet_time_ms_ = clock_->TimeInMilliseconds();
- // Shift up send time to use the full 32 bits that inter_arrival works with,
- // so wrapping works properly.
- uint32_t timestamp = absolute_send_time << kAbsSendTimeInterArrivalUpshift;
uint32_t ts_delta = 0;
int64_t t_delta = 0;
int size_delta = 0;
// For now only try to detect probes while we don't have a valid estimate.
if (!remote_rate_->ValidEstimate() ||
now_ms - first_packet_time_ms_ < kInitialProbingIntervalMs) {
- int64_t send_time_ms = static_cast<int64_t>(timestamp) * kTimestampToMs;
// TODO(holmer): Use a map instead to get correct order?
if (total_probes_received_ < kMaxProbePackets) {
int send_delta_ms = -1;
@@ -370,15 +401,11 @@
}
if (!inter_arrival_.get()) {
inter_arrival_.reset(new InterArrival(
- (kTimestampGroupLengthMs << kInterArrivalShift) / 1000,
- kTimestampToMs, remote_rate_->GetControlType() == kAimdControl));
+ (kTimestampGroupLengthMs << kInterArrivalShift) / 1000, kTimestampToMs,
+ remote_rate_->GetControlType() == kAimdControl));
}
- if (inter_arrival_->ComputeDeltas(timestamp,
- arrival_time_ms,
- payload_size,
- &ts_delta,
- &t_delta,
- &size_delta)) {
+ if (inter_arrival_->ComputeDeltas(timestamp, arrival_time_ms, payload_size,
+ &ts_delta, &t_delta, &size_delta)) {
double ts_delta_ms = (1000.0 * ts_delta) / (1 << kInterArrivalShift);
estimator_.Update(t_delta, ts_delta_ms, size_delta, detector_.State());
detector_.Detect(estimator_.offset(), ts_delta_ms,
diff --git a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc
index b33f033..1f5dac1 100644
--- a/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc
+++ b/webrtc/modules/remote_bitrate_estimator/remote_bitrate_estimators_test.cc
@@ -31,10 +31,12 @@
switch (estimator) {
case kTransmissionOffset:
return BweTestConfig::EstimatorConfig("TOF", flow_id, &factories[0],
- kMimdControl, false, false);
+ kAimdControl, kRembEstimator, false,
+ false);
case kAbsSendTime:
return BweTestConfig::EstimatorConfig("AST", flow_id, &factories[1],
- kMimdControl, false, false);
+ kAimdControl, kRembEstimator, false,
+ false);
}
assert(false);
return BweTestConfig::EstimatorConfig();
@@ -64,7 +66,8 @@
SetupTestFromConfig(config.bwe_test_config);
for (size_t i = 0; i < config.number_of_senders; ++i) {
sources_.push_back(new VideoSource(0, 30, 300, 0, 0));
- packet_senders_.push_back(new PacketSender(this, sources_.back()));
+ packet_senders_.push_back(
+ new PacketSender(this, sources_.back(), kNullEstimator));
}
}
@@ -283,7 +286,7 @@
TEST_F(BweFeedbackTest, Choke1000kbps500kbps1000kbps) {
AdaptiveVideoSource source(0, 30, 300, 0, 0);
- RegularVideoSender sender(this, &source, 300);
+ PacketSender sender(this, &source, kRembEstimator);
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
const int kHighCapacityKbps = 1000;
@@ -301,7 +304,7 @@
TEST_F(BweFeedbackTest, Choke200kbps30kbps200kbps) {
AdaptiveVideoSource source(0, 30, 300, 0, 0);
- RegularVideoSender sender(this, &source, 300);
+ PacketSender sender(this, &source, kRembEstimator);
ChokeFilter filter(this);
RateCounterFilter counter(this, "receiver_input");
const int kHighCapacityKbps = 200;
@@ -320,7 +323,7 @@
TEST_F(BweFeedbackTest, Verizon4gDownlinkTest) {
AdaptiveVideoSource source(0, 30, 300, 0, 0);
- RegularVideoSender sender(this, &source, 300);
+ PacketSender sender(this, &source, kRembEstimator);
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
RateCounterFilter counter2(this, "receiver_input");
@@ -333,7 +336,7 @@
// webrtc:3277
TEST_F(BweFeedbackTest, DISABLED_GoogleWifiTrace3Mbps) {
AdaptiveVideoSource source(0, 30, 300, 0, 0);
- RegularVideoSender sender(this, &source, 300);
+ PacketSender sender(this, &source, kRembEstimator);
RateCounterFilter counter1(this, "sender_output");
TraceBasedDeliveryFilter filter(this, "link_capacity");
filter.SetMaxDelay(500);
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc
index 911f662..1f9526d 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.cc
@@ -26,36 +26,110 @@
namespace testing {
namespace bwe {
-class PacketReceiver : public RemoteBitrateObserver {
+class PacketReceiver {
public:
- static const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
- static const int kDelayPlotIntervalMs = 100;
-
PacketReceiver(const string& test_name,
const BweTestConfig::EstimatorConfig& config)
- : debug_name_(config.debug_name),
+ : flow_id_(config.flow_id),
+ debug_name_(config.debug_name),
delay_log_prefix_(),
- estimate_log_prefix_(),
last_delay_plot_ms_(0),
plot_delay_(config.plot_delay),
+ baseline_(BaseLineFileInterface::Create(test_name + "_" + debug_name_,
+ config.update_baseline)) {
+ // Setup the prefix strings used when logging.
+ std::stringstream ss;
+ ss << "Delay_" << config.flow_id << "#2";
+ delay_log_prefix_ = ss.str();
+ }
+ virtual ~PacketReceiver() {}
+
+ virtual void ReceivePacket(const Packet& packet) {}
+
+ virtual FeedbackPacket* GetFeedback() { return NULL; }
+
+ void LogStats() {
+ BWE_TEST_LOGGING_CONTEXT(debug_name_);
+ BWE_TEST_LOGGING_CONTEXT("Mean");
+ stats_.Log("kbps");
+ }
+
+ void VerifyOrWriteBaseline() { EXPECT_TRUE(baseline_->VerifyOrWrite()); }
+
+ protected:
+ static const int kDelayPlotIntervalMs = 100;
+
+ void LogDelay(int64_t arrival_time_ms, int64_t send_time_ms) {
+ if (plot_delay_) {
+ if (arrival_time_ms - last_delay_plot_ms_ > kDelayPlotIntervalMs) {
+ BWE_TEST_LOGGING_PLOT(delay_log_prefix_, arrival_time_ms,
+ arrival_time_ms - send_time_ms);
+ last_delay_plot_ms_ = arrival_time_ms;
+ }
+ }
+ }
+
+ const int flow_id_;
+ const string debug_name_;
+ string delay_log_prefix_;
+ int64_t last_delay_plot_ms_;
+ bool plot_delay_;
+ scoped_ptr<BaseLineFileInterface> baseline_;
+ Stats<double> stats_;
+
+ private:
+ DISALLOW_IMPLICIT_CONSTRUCTORS(PacketReceiver);
+};
+
+class SendSideBweReceiver : public PacketReceiver {
+ public:
+ SendSideBweReceiver(const string& test_name,
+ const BweTestConfig::EstimatorConfig& config)
+ : PacketReceiver(test_name, config) {}
+
+ virtual void EatPacket(const Packet& packet) {
+ const MediaPacket& media_packet = static_cast<const MediaPacket&>(packet);
+ // We're treating the send time (from previous filter) as the arrival
+ // time once packet reaches the estimator.
+ int64_t arrival_time_ms = (media_packet.send_time_us() + 500) / 1000;
+ BWE_TEST_LOGGING_TIME(arrival_time_ms);
+ LogDelay(arrival_time_ms, (media_packet.creation_time_us() + 500) / 1000);
+ packet_feedback_vector_.push_back(PacketInfo(
+ arrival_time_ms, media_packet.GetAbsSendTimeInMs(),
+ media_packet.header().sequenceNumber, media_packet.payload_size()));
+ }
+
+ virtual FeedbackPacket* GetFeedback() {
+ FeedbackPacket* fb =
+ new SendSideBweFeedback(flow_id_, 0, packet_feedback_vector_);
+ packet_feedback_vector_.clear();
+ return fb;
+ }
+
+ private:
+ std::vector<PacketInfo> packet_feedback_vector_;
+};
+
+class RembReceiver : public PacketReceiver, public RemoteBitrateObserver {
+ public:
+ static const uint32_t kRemoteBitrateEstimatorMinBitrateBps = 30000;
+
+ RembReceiver(const string& test_name,
+ const BweTestConfig::EstimatorConfig& config)
+ : PacketReceiver(test_name, config),
+ estimate_log_prefix_(),
plot_estimate_(config.plot_estimate),
clock_(0),
- stats_(),
recv_stats_(ReceiveStatistics::Create(&clock_)),
latest_estimate_bps_(-1),
estimator_(config.estimator_factory->Create(
this,
&clock_,
config.control_type,
- kRemoteBitrateEstimatorMinBitrateBps)),
- baseline_(BaseLineFileInterface::Create(test_name + "_" + debug_name_,
- config.update_baseline)) {
+ kRemoteBitrateEstimatorMinBitrateBps)) {
assert(estimator_.get());
assert(baseline_.get());
- // Setup the prefix strings used when logging.
std::stringstream ss;
- ss << "Delay_" << config.flow_id << "#2";
- delay_log_prefix_ = ss.str();
ss.str("");
ss << "Estimate_" << config.flow_id << "#1";
estimate_log_prefix_ = ss.str();
@@ -63,53 +137,45 @@
estimator_->OnRttUpdate(50);
}
- void EatPacket(const Packet& packet) {
+ virtual void ReceivePacket(const Packet& packet) {
BWE_TEST_LOGGING_CONTEXT(debug_name_);
-
- recv_stats_->IncomingPacket(packet.header(), packet.payload_size(), false);
+ assert(packet.GetPacketType() == Packet::kMediaPacket);
+ const MediaPacket& media_packet = static_cast<const MediaPacket&>(packet);
+ // We're treating the send time (from previous filter) as the arrival
+ // time once packet reaches the estimator.
+ int64_t arrival_time_ms = (media_packet.send_time_us() + 500) / 1000;
+ BWE_TEST_LOGGING_TIME(arrival_time_ms);
+ LogDelay(arrival_time_ms, (media_packet.creation_time_us() + 500) / 1000);
+ recv_stats_->IncomingPacket(media_packet.header(),
+ media_packet.payload_size(), false);
latest_estimate_bps_ = -1;
- // We're treating the send time (from previous filter) as the arrival
- // time once packet reaches the estimator.
- int64_t packet_time_ms = (packet.send_time_us() + 500) / 1000;
- BWE_TEST_LOGGING_TIME(packet_time_ms);
- if (plot_delay_) {
- if (clock_.TimeInMilliseconds() - last_delay_plot_ms_ >
- kDelayPlotIntervalMs) {
- BWE_TEST_LOGGING_PLOT(delay_log_prefix_, clock_.TimeInMilliseconds(),
- packet_time_ms -
- (packet.creation_time_us() + 500) / 1000);
- last_delay_plot_ms_ = clock_.TimeInMilliseconds();
- }
- }
-
int64_t step_ms = std::max<int64_t>(estimator_->TimeUntilNextProcess(), 0);
- while ((clock_.TimeInMilliseconds() + step_ms) < packet_time_ms) {
+ while ((clock_.TimeInMilliseconds() + step_ms) < arrival_time_ms) {
clock_.AdvanceTimeMilliseconds(step_ms);
estimator_->Process();
step_ms = std::max<int64_t>(estimator_->TimeUntilNextProcess(), 0);
}
- estimator_->IncomingPacket(packet_time_ms, packet.payload_size(),
- packet.header());
- clock_.AdvanceTimeMilliseconds(packet_time_ms -
+ estimator_->IncomingPacket(arrival_time_ms, media_packet.payload_size(),
+ media_packet.header());
+ clock_.AdvanceTimeMilliseconds(arrival_time_ms -
clock_.TimeInMilliseconds());
- ASSERT_TRUE(packet_time_ms == clock_.TimeInMilliseconds());
+ ASSERT_TRUE(arrival_time_ms == clock_.TimeInMilliseconds());
}
- bool GetFeedback(PacketSender::Feedback* feedback) {
- assert(feedback);
+ virtual FeedbackPacket* GetFeedback() {
BWE_TEST_LOGGING_CONTEXT(debug_name_);
uint32_t estimated_bps = 0;
+ RembFeedback* feedback = NULL;
if (LatestEstimate(&estimated_bps)) {
- feedback->estimated_bps = estimated_bps;
StatisticianMap statisticians = recv_stats_->GetActiveStatisticians();
- if (statisticians.empty()) {
- feedback->report_block = RTCPReportBlock();
- } else {
- feedback->report_block =
- BuildReportBlock(statisticians.begin()->second);
+ RTCPReportBlock report_block;
+ if (!statisticians.empty()) {
+ report_block = BuildReportBlock(statisticians.begin()->second);
}
+ feedback = new RembFeedback(flow_id_, clock_.TimeInMilliseconds(),
+ estimated_bps, report_block);
baseline_->Estimate(clock_.TimeInMilliseconds(), estimated_bps);
double estimated_kbps = static_cast<double>(estimated_bps) / 1000.0;
@@ -118,19 +184,8 @@
BWE_TEST_LOGGING_PLOT(estimate_log_prefix_, clock_.TimeInMilliseconds(),
estimated_kbps);
}
- return true;
}
- return false;
- }
-
- void LogStats() {
- BWE_TEST_LOGGING_CONTEXT(debug_name_);
- BWE_TEST_LOGGING_CONTEXT("Mean");
- stats_.Log("kbps");
- }
-
- void VerifyOrWriteBaseline() {
- EXPECT_TRUE(baseline_->VerifyOrWrite());
+ return feedback;
}
virtual void OnReceiveBitrateChanged(const vector<unsigned int>& ssrcs,
@@ -163,29 +218,39 @@
return true;
}
- string debug_name_;
- string delay_log_prefix_;
string estimate_log_prefix_;
- int64_t last_delay_plot_ms_;
- bool plot_delay_;
bool plot_estimate_;
SimulatedClock clock_;
- Stats<double> stats_;
scoped_ptr<ReceiveStatistics> recv_stats_;
int64_t latest_estimate_bps_;
scoped_ptr<RemoteBitrateEstimator> estimator_;
- scoped_ptr<BaseLineFileInterface> baseline_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(PacketReceiver);
+ DISALLOW_IMPLICIT_CONSTRUCTORS(RembReceiver);
};
+PacketReceiver* CreatePacketReceiver(
+ BandwidthEstimatorType type,
+ const string& test_name,
+ const BweTestConfig::EstimatorConfig& config) {
+ switch (type) {
+ case kRembEstimator:
+ return new RembReceiver(test_name, config);
+ case kFullSendSideEstimator:
+ return new SendSideBweReceiver(test_name, config);
+ case kNullEstimator:
+ return new PacketReceiver(test_name, config);
+ }
+ assert(false);
+ return NULL;
+}
+
class PacketProcessorRunner {
public:
explicit PacketProcessorRunner(PacketProcessor* processor)
: processor_(processor) {}
~PacketProcessorRunner() {
- for (auto* packet : queue_)
+ for (Packet* packet : queue_)
delete packet;
}
@@ -253,16 +318,14 @@
BweTest::~BweTest() {
BWE_TEST_LOGGING_GLOBAL_ENABLE(true);
- for (EstimatorMap::iterator it = estimators_.begin(); it != estimators_.end();
- ++it) {
- it->second->VerifyOrWriteBaseline();
- it->second->LogStats();
+ for (const auto& estimator : estimators_) {
+ estimator.second->VerifyOrWriteBaseline();
+ estimator.second->LogStats();
}
BWE_TEST_LOGGING_GLOBAL_CONTEXT("");
- for (EstimatorMap::iterator it = estimators_.begin();
- it != estimators_.end(); ++it) {
- delete it->second;
+ for (const auto& estimator : estimators_) {
+ delete estimator.second;
}
}
@@ -272,11 +335,11 @@
string test_name =
string(test_info->test_case_name()) + "_" + string(test_info->name());
BWE_TEST_LOGGING_GLOBAL_CONTEXT(test_name);
- for (vector<BweTestConfig::EstimatorConfig>::const_iterator it =
- config.estimator_configs.begin(); it != config.estimator_configs.end();
- ++it) {
+ for (const auto& estimator_config : config.estimator_configs) {
estimators_.insert(
- std::make_pair(it->flow_id, new PacketReceiver(test_name, *it)));
+ std::make_pair(estimator_config.flow_id,
+ CreatePacketReceiver(estimator_config.bwe_type,
+ test_name, estimator_config)));
}
BWE_TEST_LOGGING_GLOBAL_ENABLE(false);
}
@@ -287,7 +350,7 @@
senders_.push_back(static_cast<PacketSender*>(processor));
}
processors_.push_back(PacketProcessorRunner(processor));
- for (const auto& flow_id : processor->flow_ids()) {
+ for (const int& flow_id : processor->flow_ids()) {
RTC_UNUSED(flow_id);
assert(estimators_.count(flow_id) == 1);
}
@@ -308,22 +371,18 @@
BWE_TEST_LOGGING_GLOBAL_ENABLE(enable);
}
-void BweTest::GiveFeedbackToAffectedSenders(int flow_id,
- PacketReceiver* estimator) {
- std::list<PacketSender*> affected_senders;
- for (auto* sender : senders_) {
- if (sender->flow_ids().find(flow_id) != sender->flow_ids().end()) {
- affected_senders.push_back(sender);
+void BweTest::GiveFeedbackToAffectedSenders(PacketReceiver* estimator) {
+ FeedbackPacket* feedback = estimator->GetFeedback();
+ if (feedback) {
+ for (PacketSender* sender : senders_) {
+ if (sender->flow_ids().find(feedback->flow_id()) !=
+ sender->flow_ids().end()) {
+ sender->GiveFeedback(*feedback);
+ break;
+ }
}
}
- PacketSender::Feedback feedback = {0};
- if (estimator->GetFeedback(&feedback) && !affected_senders.empty()) {
- // Allocate the bitrate evenly between the senders.
- feedback.estimated_bps /= affected_senders.size();
- for (auto* sender : affected_senders) {
- sender->GiveFeedback(feedback);
- }
- }
+ delete feedback;
}
void BweTest::RunFor(int64_t time_ms) {
@@ -340,7 +399,7 @@
time_now_ms_ <= run_time_ms_ - simulation_interval_ms_;
time_now_ms_ += simulation_interval_ms_) {
Packets packets;
- for (auto& processor : processors_) {
+ for (PacketProcessorRunner& processor : processors_) {
processor.RunFor(simulation_interval_ms_, time_now_ms_, &packets);
}
@@ -359,15 +418,15 @@
ASSERT_TRUE(IsTimeSorted(packets));
}
- for (const auto* packet : packets) {
+ for (const Packet* packet : packets) {
EstimatorMap::iterator est_it = estimators_.find(packet->flow_id());
ASSERT_TRUE(est_it != estimators_.end());
- est_it->second->EatPacket(*packet);
+ est_it->second->ReceivePacket(*packet);
delete packet;
}
for (const auto& estimator : estimators_) {
- GiveFeedbackToAffectedSenders(estimator.first, estimator.second);
+ GiveFeedbackToAffectedSenders(estimator.second);
}
}
}
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h
index e3e0097..2648733 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test.h
@@ -29,55 +29,59 @@
: debug_name(),
flow_id(0),
estimator_factory(NULL),
- control_type(kMimdControl),
+ control_type(kAimdControl),
+ bwe_type(kRembEstimator),
update_baseline(false),
plot_delay(true),
- plot_estimate(true) {
- }
+ plot_estimate(true) {}
EstimatorConfig(std::string debug_name,
int flow_id,
const RemoteBitrateEstimatorFactory* estimator_factory,
+ BandwidthEstimatorType estimator_type,
bool plot_delay,
bool plot_estimate)
: debug_name(debug_name),
flow_id(flow_id),
estimator_factory(estimator_factory),
- control_type(kMimdControl),
+ control_type(kAimdControl),
+ bwe_type(kRembEstimator),
update_baseline(false),
plot_delay(plot_delay),
- plot_estimate(plot_estimate) {
- }
+ plot_estimate(plot_estimate) {}
EstimatorConfig(std::string debug_name,
int flow_id,
const RemoteBitrateEstimatorFactory* estimator_factory,
RateControlType control_type,
+ BandwidthEstimatorType estimator_type,
bool plot_delay,
bool plot_estimate)
: debug_name(debug_name),
flow_id(flow_id),
estimator_factory(estimator_factory),
control_type(control_type),
+ bwe_type(estimator_type),
update_baseline(false),
plot_delay(plot_delay),
- plot_estimate(plot_estimate) {
- }
+ plot_estimate(plot_estimate) {}
EstimatorConfig(std::string debug_name,
int flow_id,
const RemoteBitrateEstimatorFactory* estimator_factory,
RateControlType control_type,
+ BandwidthEstimatorType estimator_type,
bool update_baseline)
: debug_name(debug_name),
flow_id(flow_id),
estimator_factory(estimator_factory),
control_type(control_type),
+ bwe_type(kRembEstimator),
update_baseline(update_baseline),
plot_delay(false),
- plot_estimate(false) {
- }
+ plot_estimate(false) {}
std::string debug_name;
int flow_id;
const RemoteBitrateEstimatorFactory* estimator_factory;
RateControlType control_type;
+ BandwidthEstimatorType bwe_type;
bool update_baseline;
bool plot_delay;
bool plot_estimate;
@@ -108,7 +112,7 @@
void FindPacketsToProcess(const FlowIds& flow_ids, Packets* in,
Packets* out);
- void GiveFeedbackToAffectedSenders(int flow_id, PacketReceiver* estimator);
+ void GiveFeedbackToAffectedSenders(PacketReceiver* estimator);
int64_t run_time_ms_;
int64_t time_now_ms_;
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
index 1520db7..b2627a1 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc
@@ -17,6 +17,10 @@
namespace webrtc {
namespace testing {
namespace bwe {
+
+const int kMinBitrateKbps = 10;
+const int kMaxBitrateKbps = 20000;
+
class DelayCapHelper {
public:
DelayCapHelper() : max_delay_us_(0), delay_stats_() {}
@@ -120,29 +124,14 @@
}
Packet::Packet()
- : flow_id_(0),
- creation_time_us_(-1),
- send_time_us_(-1),
- payload_size_(0) {
- memset(&header_, 0, sizeof(header_));
+ : flow_id_(0), creation_time_us_(-1), send_time_us_(-1), payload_size_(0) {
}
-Packet::Packet(int flow_id, int64_t send_time_us, size_t payload_size,
- const RTPHeader& header)
+Packet::Packet(int flow_id, int64_t send_time_us, size_t payload_size)
: flow_id_(flow_id),
creation_time_us_(send_time_us),
send_time_us_(send_time_us),
- payload_size_(payload_size),
- header_(header) {
-}
-
-Packet::Packet(int64_t send_time_us, uint32_t sequence_number)
- : flow_id_(0),
- creation_time_us_(send_time_us),
- send_time_us_(send_time_us),
- payload_size_(0) {
- memset(&header_, 0, sizeof(header_));
- header_.sequenceNumber = sequence_number;
+ payload_size_(payload_size) {
}
Packet::~Packet() {
@@ -157,12 +146,56 @@
send_time_us_ = send_time_us;
}
-void Packet::SetAbsSendTimeMs(int64_t abs_send_time_ms) {
+MediaPacket::MediaPacket() {
+ memset(&header_, 0, sizeof(header_));
+}
+
+MediaPacket::MediaPacket(int flow_id,
+ int64_t send_time_us,
+ size_t payload_size,
+ const RTPHeader& header)
+ : Packet(flow_id, send_time_us, payload_size), header_(header) {
+}
+
+MediaPacket::MediaPacket(int64_t send_time_us, uint32_t sequence_number)
+ : Packet(0, send_time_us, 0) {
+ memset(&header_, 0, sizeof(header_));
+ header_.sequenceNumber = sequence_number;
+}
+
+int64_t MediaPacket::GetAbsSendTimeInMs() const {
+ const int kInterArrivalShift = 26;
+ const int kAbsSendTimeInterArrivalUpshift = 8;
+ const double kTimestampToMs =
+ 1000.0 / static_cast<double>(1 << kInterArrivalShift);
+ uint32_t timestamp = header_.extension.absoluteSendTime
+ << kAbsSendTimeInterArrivalUpshift;
+ return static_cast<int64_t>(timestamp) * kTimestampToMs;
+}
+
+void MediaPacket::SetAbsSendTimeMs(int64_t abs_send_time_ms) {
header_.extension.hasAbsoluteSendTime = true;
header_.extension.absoluteSendTime = ((static_cast<int64_t>(abs_send_time_ms *
(1 << 18)) + 500) / 1000) & 0x00fffffful;
}
+RembFeedback::RembFeedback(int flow_id,
+ int64_t send_time_us,
+ uint32_t estimated_bps,
+ RTCPReportBlock report_block)
+ : FeedbackPacket(flow_id, send_time_us),
+ estimated_bps_(estimated_bps),
+ report_block_(report_block) {
+}
+
+SendSideBweFeedback::SendSideBweFeedback(
+ int flow_id,
+ int64_t send_time_us,
+ const std::vector<PacketInfo>& packet_feedback_vector)
+ : FeedbackPacket(flow_id, send_time_us),
+ packet_feedback_vector_(packet_feedback_vector) {
+}
+
bool IsTimeSorted(const Packets& packets) {
PacketsConstIt last_it = packets.begin();
for (PacketsConstIt it = last_it; it != packets.end(); ++it) {
@@ -233,7 +266,7 @@
name_(name) {
std::stringstream ss;
ss << name_ << "_";
- for (auto flow_id : flow_ids) {
+ for (int flow_id : flow_ids) {
ss << flow_id << ",";
}
name_ = ss.str();
@@ -269,7 +302,7 @@
void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
assert(in_out);
- for (const auto* packet : *in_out) {
+ for (const Packet* packet : *in_out) {
rate_counter_->UpdateRates(packet->send_time_us(), packet->payload_size());
}
packets_per_second_stats_.Push(rate_counter_->packets_per_second());
@@ -317,7 +350,7 @@
void DelayFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
assert(in_out);
- for (auto* packet : *in_out) {
+ for (Packet* packet : *in_out) {
int64_t new_send_time_us = packet->send_time_us() + delay_us_;
last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
packet->set_send_time_us(last_send_time_us_);
@@ -341,7 +374,7 @@
void JitterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) {
assert(in_out);
- for (auto* packet : *in_out) {
+ for (Packet* packet : *in_out) {
int64_t new_send_time_us = packet->send_time_us();
new_send_time_us += random_.Gaussian(0, stddev_jitter_us_);
last_send_time_us_ = std::max(last_send_time_us_, new_send_time_us);
@@ -372,7 +405,7 @@
if (random_.Rand() < reorder_fraction_) {
int64_t t1 = (*last_it)->send_time_us();
int64_t t2 = (*it)->send_time_us();
- std::swap(**last_it, **it);
+ std::swap(*last_it, *it);
(*last_it)->set_send_time_us(t1);
(*it)->set_send_time_us(t2);
}
@@ -540,7 +573,7 @@
++next_delivery_it_;
if (next_delivery_it_ == delivery_times_us_.end()) {
// When the trace wraps we allow two packets to be sent back-to-back.
- for (auto& delivery_time_us : delivery_times_us_) {
+ for (int64_t& delivery_time_us : delivery_times_us_) {
delivery_time_us += local_time_us_ - current_offset_us_;
}
current_offset_us_ += local_time_us_ - current_offset_us_;
@@ -600,9 +633,10 @@
while (payload_size > 0) {
++prototype_header_.sequenceNumber;
uint32_t size = NextPacketSize(frame_size, payload_size);
- new_packets.push_back(
- new Packet(flow_id_, send_time_us, size, prototype_header_));
- new_packets.back()->SetAbsSendTimeMs(next_frame_ms_);
+ MediaPacket* new_packet =
+ new MediaPacket(flow_id_, send_time_us, size, prototype_header_);
+ new_packets.push_back(new_packet);
+ new_packet->SetAbsSendTimeMs(next_frame_ms_);
payload_size -= size;
}
@@ -672,60 +706,155 @@
return std::min(avg_size, remaining_payload);
}
-PacketSender::PacketSender(PacketProcessorListener* listener,
- VideoSource* source)
- : PacketProcessor(listener, source->flow_id(), true), source_(source) {
-}
-
-void PacketSender::RunFor(int64_t time_ms, Packets* in_out) {
- source_->RunFor(time_ms, in_out);
-}
-
-RegularVideoSender::RegularVideoSender(PacketProcessorListener* listener,
- VideoSource* source,
- uint32_t kbps)
- // It is important that the first_frame_offset and the initial time of
- // clock_ are both zero, otherwise we can't have absolute time in this
- // class.
- : PacketSender(listener, source),
- clock_(kInitialTimeMs),
- bitrate_controller_(BitrateController::CreateBitrateController(&clock_,
- false)),
+RembSendSideBwe::RembSendSideBwe(int kbps,
+ BitrateObserver* observer,
+ Clock* clock)
+ : bitrate_controller_(
+ BitrateController::CreateBitrateController(clock, false)),
feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
- modules_() {
- const int kMinBitrateBps = 10000;
- const int kMaxBitrateBps = 20000000;
- bitrate_controller_->SetBitrateObserver(this, 1000 * kbps, kMinBitrateBps,
- kMaxBitrateBps);
- modules_.push_back(bitrate_controller_.get());
+ clock_(clock) {
+ assert(kbps >= kMinBitrateKbps);
+ assert(kbps <= kMaxBitrateKbps);
+ bitrate_controller_->SetBitrateObserver(
+ observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
}
-RegularVideoSender::~RegularVideoSender() {
+RembSendSideBwe::~RembSendSideBwe() {
}
-void RegularVideoSender::GiveFeedback(const Feedback& feedback) {
- feedback_observer_->OnReceivedEstimatedBitrate(feedback.estimated_bps);
+void RembSendSideBwe::GiveFeedback(const FeedbackPacket& feedback) {
+ const RembFeedback& remb_feedback =
+ static_cast<const RembFeedback&>(feedback);
+ feedback_observer_->OnReceivedEstimatedBitrate(remb_feedback.estimated_bps());
ReportBlockList report_blocks;
- report_blocks.push_back(feedback.report_block);
- feedback_observer_->OnReceivedRtcpReceiverReport(report_blocks, 0,
- clock_.TimeInMilliseconds());
+ report_blocks.push_back(remb_feedback.report_block());
+ feedback_observer_->OnReceivedRtcpReceiverReport(
+ report_blocks, 0, clock_->TimeInMilliseconds());
bitrate_controller_->Process();
}
-void RegularVideoSender::RunFor(int64_t time_ms, Packets* in_out) {
+int64_t RembSendSideBwe::TimeUntilNextProcess() {
+ return bitrate_controller_->TimeUntilNextProcess();
+}
+
+int RembSendSideBwe::Process() {
+ return bitrate_controller_->Process();
+}
+
+FullSendSideBwe::FullSendSideBwe(int kbps,
+ BitrateObserver* observer,
+ Clock* clock)
+ : bitrate_controller_(
+ BitrateController::CreateBitrateController(clock, false)),
+ rbe_(AbsoluteSendTimeRemoteBitrateEstimatorFactory()
+ .Create(this, clock, kAimdControl, 1000 * kMinBitrateKbps)),
+ feedback_observer_(bitrate_controller_->CreateRtcpBandwidthObserver()),
+ clock_(clock) {
+ assert(kbps >= kMinBitrateKbps);
+ assert(kbps <= kMaxBitrateKbps);
+ bitrate_controller_->SetBitrateObserver(
+ observer, 1000 * kbps, 1000 * kMinBitrateKbps, 1000 * kMaxBitrateKbps);
+}
+
+FullSendSideBwe::~FullSendSideBwe() {
+}
+
+void FullSendSideBwe::GiveFeedback(const FeedbackPacket& feedback) {
+ const SendSideBweFeedback& fb =
+ static_cast<const SendSideBweFeedback&>(feedback);
+ if (fb.packet_feedback_vector().empty())
+ return;
+ rbe_->IncomingPacketFeedbackVector(fb.packet_feedback_vector());
+ if (rbe_->TimeUntilNextProcess() <= 0)
+ rbe_->Process();
+ // TODO(holmer): Handle losses in between feedback packets.
+ int expected_packets = fb.packet_feedback_vector().back().sequence_number -
+ fb.packet_feedback_vector().front().sequence_number +
+ 1;
+ int lost_packets = expected_packets - fb.packet_feedback_vector().size();
+ report_block_.fractionLost = (lost_packets << 8) / expected_packets;
+ report_block_.cumulativeLost += lost_packets;
+ ReportBlockList report_blocks;
+ report_blocks.push_back(report_block_);
+ feedback_observer_->OnReceivedRtcpReceiverReport(
+ report_blocks, 0, clock_->TimeInMilliseconds());
+ bitrate_controller_->Process();
+}
+
+void FullSendSideBwe::OnReceiveBitrateChanged(
+ const std::vector<unsigned int>& ssrcs,
+ unsigned int bitrate) {
+ feedback_observer_->OnReceivedEstimatedBitrate(bitrate);
+}
+
+int64_t FullSendSideBwe::TimeUntilNextProcess() {
+ return bitrate_controller_->TimeUntilNextProcess();
+}
+
+int FullSendSideBwe::Process() {
+ rbe_->Process();
+ return bitrate_controller_->Process();
+}
+
+SendSideBwe* CreateEstimator(BandwidthEstimatorType estimator,
+ int kbps,
+ BitrateObserver* observer,
+ Clock* clock) {
+ switch (estimator) {
+ case kRembEstimator:
+ return new RembSendSideBwe(kbps, observer, clock);
+ case kFullSendSideEstimator:
+ return new FullSendSideBwe(kbps, observer, clock);
+ case kNullEstimator: {
+ static NullSendSideBwe null_bwe;
+ return &null_bwe;
+ }
+ }
+ assert(false);
+ return NULL;
+}
+
+PacketSender::PacketSender(PacketProcessorListener* listener,
+ VideoSource* source,
+ BandwidthEstimatorType estimator)
+ : PacketProcessor(listener, source->flow_id(), true),
+ // For Packet::send_time_us() to be comparable with timestamps from
+ // clock_, the clock of the PacketSender and the Source must be aligned.
+ // We assume that both start at time 0.
+ clock_(0),
+ source_(source),
+ bwe_(CreateEstimator(estimator,
+ 8 * source_->bytes_per_second() / 1000,
+ this,
+ &clock_)) {
+ modules_.push_back(bwe_.get());
+}
+
+PacketSender::~PacketSender() {
+}
+
+void PacketSender::RunFor(int64_t time_ms, Packets* in_out) {
start_of_run_ms_ = clock_.TimeInMilliseconds();
while (time_ms > 0) {
int64_t time_to_run_ms = std::min(time_ms, static_cast<int64_t>(100));
- PacketSender::RunFor(time_to_run_ms, in_out);
+ source_->RunFor(time_to_run_ms, in_out);
clock_.AdvanceTimeMilliseconds(time_to_run_ms);
- bitrate_controller_->Process();
+ bwe_->Process();
time_ms -= time_to_run_ms;
}
}
-void RegularVideoSender::OnNetworkChanged(uint32_t target_bitrate_bps,
- uint8_t fraction_lost,
- int64_t rtt) {
+int PacketSender::GetFeedbackIntervalMs() const {
+ return bwe_->GetFeedbackIntervalMs();
+}
+
+void PacketSender::GiveFeedback(const FeedbackPacket& feedback) {
+ bwe_->GiveFeedback(feedback);
+}
+
+void PacketSender::OnNetworkChanged(uint32_t target_bitrate_bps,
+ uint8_t fraction_lost,
+ int64_t rtt) {
source_->SetBitrateBps(target_bitrate_bps);
std::stringstream ss;
ss << "SendEstimate_" << source_->flow_id() << "#1";
@@ -735,23 +864,22 @@
PacedVideoSender::PacedVideoSender(PacketProcessorListener* listener,
VideoSource* source,
- uint32_t kbps)
- // It is important that the first_frame_offset and the initial time of
- // clock_ are both zero, otherwise we can't have absolute time in this
- // class.
- : RegularVideoSender(listener, source, kbps),
+ BandwidthEstimatorType estimator)
+ : PacketSender(listener, source, estimator),
pacer_(&clock_,
this,
- kbps,
- PacedSender::kDefaultPaceMultiplier* kbps,
+ 8 * source->bytes_per_second() / 1000,
+ PacedSender::kDefaultPaceMultiplier * 8 *
+ source->bytes_per_second() /
+ 1000,
0) {
modules_.push_back(&pacer_);
}
PacedVideoSender::~PacedVideoSender() {
- for (auto* packet : pacer_queue_)
+ for (Packet* packet : pacer_queue_)
delete packet;
- for (auto* packet : queue_)
+ for (Packet* packet : queue_)
delete packet;
}
@@ -786,11 +914,13 @@
CallProcess(modules_);
} else {
// Time to send next packet to pacer.
- pacer_.SendPacket(PacedSender::kNormalPriority, (*it)->header().ssrc,
- (*it)->header().sequenceNumber,
- ((*it)->send_time_us() + 500) / 1000,
- (*it)->payload_size(), false);
- pacer_queue_.push_back(*it);
+ MediaPacket* media_packet = static_cast<MediaPacket*>(*it);
+ pacer_.SendPacket(PacedSender::kNormalPriority,
+ media_packet->header().ssrc,
+ media_packet->header().sequenceNumber,
+ (media_packet->send_time_us() + 500) / 1000,
+ media_packet->payload_size(), false);
+ pacer_queue_.push_back(media_packet);
assert(pacer_queue_.size() < 10000);
++it;
}
@@ -801,7 +931,7 @@
int64_t PacedVideoSender::TimeUntilNextProcess(
const std::list<Module*>& modules) {
int64_t time_until_next_process_ms = 10;
- for (auto* module : modules) {
+ for (Module* module : modules) {
int64_t next_process_ms = module->TimeUntilNextProcess();
if (next_process_ms < time_until_next_process_ms)
time_until_next_process_ms = next_process_ms;
@@ -812,7 +942,7 @@
}
void PacedVideoSender::CallProcess(const std::list<Module*>& modules) {
- for (auto* module : modules) {
+ for (Module* module : modules) {
if (module->TimeUntilNextProcess() <= 0) {
module->Process();
}
@@ -842,14 +972,15 @@
bool retransmission) {
for (Packets::iterator it = pacer_queue_.begin(); it != pacer_queue_.end();
++it) {
- if ((*it)->header().sequenceNumber == sequence_number) {
+ MediaPacket* media_packet = static_cast<MediaPacket*>(*it);
+ if (media_packet->header().sequenceNumber == sequence_number) {
int64_t pace_out_time_ms = clock_.TimeInMilliseconds();
// Make sure a packet is never paced out earlier than when it was put into
// the pacer.
- assert(pace_out_time_ms >= ((*it)->send_time_us() + 500) / 1000);
- (*it)->SetAbsSendTimeMs(pace_out_time_ms);
- (*it)->set_send_time_us(1000 * pace_out_time_ms);
- queue_.push_back(*it);
+ assert(pace_out_time_ms >= (media_packet->send_time_us() + 500) / 1000);
+ media_packet->SetAbsSendTimeMs(pace_out_time_ms);
+ media_packet->set_send_time_us(1000 * pace_out_time_ms);
+ queue_.push_back(media_packet);
pacer_queue_.erase(it);
return true;
}
@@ -864,7 +995,7 @@
void PacedVideoSender::OnNetworkChanged(uint32_t target_bitrate_bps,
uint8_t fraction_lost,
int64_t rtt) {
- RegularVideoSender::OnNetworkChanged(target_bitrate_bps, fraction_lost, rtt);
+ PacketSender::OnNetworkChanged(target_bitrate_bps, fraction_lost, rtt);
pacer_.UpdateBitrate(
target_bitrate_bps / 1000,
PacedSender::kDefaultPaceMultiplier * target_bitrate_bps / 1000, 0);
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h
index 3d79c96..bed7e7d 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h
@@ -15,6 +15,7 @@
#include <math.h>
#include <algorithm>
+#include <limits>
#include <list>
#include <numeric>
#include <sstream>
@@ -24,6 +25,7 @@
#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
#include "webrtc/modules/interface/module_common_types.h"
#include "webrtc/modules/pacing/include/paced_sender.h"
+#include "webrtc/modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h"
#include "webrtc/modules/rtp_rtcp/interface/rtp_rtcp_defines.h"
#include "webrtc/system_wrappers/interface/clock.h"
@@ -160,29 +162,86 @@
class Packet {
public:
- Packet();
- Packet(int flow_id, int64_t send_time_us, size_t payload_size,
- const RTPHeader& header);
- Packet(int64_t send_time_us, uint32_t sequence_number);
+ enum Type { kMediaPacket, kFeedbackPacket };
+ Packet();
+ Packet(int flow_id, int64_t send_time_us, size_t payload_size);
virtual ~Packet();
- bool operator<(const Packet& rhs) const;
+ virtual bool operator<(const Packet& rhs) const;
- int flow_id() const { return flow_id_; }
- int64_t creation_time_us() const { return creation_time_us_; }
- void set_send_time_us(int64_t send_time_us);
- int64_t send_time_us() const { return send_time_us_; }
- void SetAbsSendTimeMs(int64_t abs_send_time_ms);
- size_t payload_size() const { return payload_size_; }
- const RTPHeader& header() const { return header_; }
+ virtual int flow_id() const { return flow_id_; }
+ virtual int64_t creation_time_us() const { return creation_time_us_; }
+ virtual void set_send_time_us(int64_t send_time_us);
+ virtual int64_t send_time_us() const { return send_time_us_; }
+ virtual size_t payload_size() const { return payload_size_; }
+ virtual Packet::Type GetPacketType() const = 0;
private:
int flow_id_;
int64_t creation_time_us_; // Time when the packet was created.
int64_t send_time_us_; // Time the packet left last processor touching it.
size_t payload_size_; // Size of the (non-existent, simulated) payload.
- RTPHeader header_; // Actual contents.
+};
+
+class MediaPacket : public Packet {
+ public:
+ MediaPacket();
+ MediaPacket(int flow_id,
+ int64_t send_time_us,
+ size_t payload_size,
+ const RTPHeader& header);
+ MediaPacket(int64_t send_time_us, uint32_t sequence_number);
+ virtual ~MediaPacket() {}
+
+ int64_t GetAbsSendTimeInMs() const;
+ void SetAbsSendTimeMs(int64_t abs_send_time_ms);
+ const RTPHeader& header() const { return header_; }
+ virtual Packet::Type GetPacketType() const { return kMediaPacket; }
+
+ private:
+ RTPHeader header_;
+};
+
+class FeedbackPacket : public Packet {
+ public:
+ FeedbackPacket(int flow_id, int64_t send_time_us)
+ : Packet(flow_id, send_time_us, 0) {}
+ virtual ~FeedbackPacket() {}
+
+ virtual Packet::Type GetPacketType() const { return kFeedbackPacket; }
+};
+
+class RembFeedback : public FeedbackPacket {
+ public:
+ RembFeedback(int flow_id,
+ int64_t send_time_us,
+ uint32_t estimated_bps,
+ RTCPReportBlock report_block);
+ virtual ~RembFeedback() {}
+
+ uint32_t estimated_bps() const { return estimated_bps_; }
+ RTCPReportBlock report_block() const { return report_block_; }
+
+ private:
+ const uint32_t estimated_bps_;
+ const RTCPReportBlock report_block_;
+};
+
+class SendSideBweFeedback : public FeedbackPacket {
+ public:
+ typedef std::map<uint16_t, int64_t> ArrivalTimesMap;
+ SendSideBweFeedback(int flow_id,
+ int64_t send_time_us,
+ const std::vector<PacketInfo>& packet_feedback_vector);
+ virtual ~SendSideBweFeedback() {}
+
+ const std::vector<PacketInfo>& packet_feedback_vector() const {
+ return packet_feedback_vector_;
+ }
+
+ private:
+ const std::vector<PacketInfo> packet_feedback_vector_;
};
typedef std::list<Packet*> Packets;
@@ -303,6 +362,7 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(JitterFilter);
};
+// Reorders two consecutive packets with a probability of reorder_percent.
class ReorderFilter : public PacketProcessor {
public:
explicit ReorderFilter(PacketProcessorListener* listener);
@@ -448,70 +508,123 @@
DISALLOW_IMPLICIT_CONSTRUCTORS(PeriodicKeyFrameSource);
};
-class PacketSender : public PacketProcessor {
+class SendSideBwe : public Module {
public:
- struct Feedback {
- uint32_t estimated_bps;
- RTCPReportBlock report_block;
- };
+ SendSideBwe() {}
+ virtual ~SendSideBwe() {}
- PacketSender(PacketProcessorListener* listener, VideoSource* source);
- virtual ~PacketSender() {}
+ virtual int GetFeedbackIntervalMs() const = 0;
+ virtual void GiveFeedback(const FeedbackPacket& feedback) = 0;
- virtual uint32_t GetCapacityKbps() const { return 0; }
+ private:
+ DISALLOW_COPY_AND_ASSIGN(SendSideBwe);
+};
+
+class NullSendSideBwe : public SendSideBwe {
+ public:
+ NullSendSideBwe() {}
+ virtual ~NullSendSideBwe() {}
+
+ virtual int GetFeedbackIntervalMs() const OVERRIDE { return 1000; }
+ virtual void GiveFeedback(const FeedbackPacket& feedback) OVERRIDE {}
+ virtual int64_t TimeUntilNextProcess() OVERRIDE {
+ return std::numeric_limits<int64_t>::max();
+ }
+ virtual int Process() OVERRIDE { return 0; }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NullSendSideBwe);
+};
+
+class RembSendSideBwe : public SendSideBwe {
+ public:
+ RembSendSideBwe(int kbps, BitrateObserver* observer, Clock* clock);
+ virtual ~RembSendSideBwe();
+
+ virtual int GetFeedbackIntervalMs() const OVERRIDE { return 100; }
+ virtual void GiveFeedback(const FeedbackPacket& feedback) OVERRIDE;
+ virtual int64_t TimeUntilNextProcess() OVERRIDE;
+ virtual int Process() OVERRIDE;
+
+ protected:
+ scoped_ptr<BitrateController> bitrate_controller_;
+ scoped_ptr<RtcpBandwidthObserver> feedback_observer_;
+
+ private:
+ Clock* clock_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(RembSendSideBwe);
+};
+
+class FullSendSideBwe : public SendSideBwe, public RemoteBitrateObserver {
+ public:
+ FullSendSideBwe(int kbps, BitrateObserver* observer, Clock* clock);
+ virtual ~FullSendSideBwe();
+
+ virtual int GetFeedbackIntervalMs() const OVERRIDE { return 100; }
+ virtual void GiveFeedback(const FeedbackPacket& feedback) OVERRIDE;
+ virtual void OnReceiveBitrateChanged(const std::vector<unsigned int>& ssrcs,
+ unsigned int bitrate) OVERRIDE;
+ virtual int64_t TimeUntilNextProcess() OVERRIDE;
+ virtual int Process() OVERRIDE;
+
+ protected:
+ scoped_ptr<BitrateController> bitrate_controller_;
+ scoped_ptr<RemoteBitrateEstimator> rbe_;
+ scoped_ptr<RtcpBandwidthObserver> feedback_observer_;
+
+ private:
+ Clock* const clock_;
+ RTCPReportBlock report_block_;
+
+ DISALLOW_IMPLICIT_CONSTRUCTORS(FullSendSideBwe);
+};
+
+enum BandwidthEstimatorType {
+ kNullEstimator,
+ kRembEstimator,
+ kFullSendSideEstimator
+};
+
+class PacketSender : public PacketProcessor, public BitrateObserver {
+ public:
+ PacketSender(PacketProcessorListener* listener,
+ VideoSource* source,
+ BandwidthEstimatorType estimator);
+ virtual ~PacketSender();
// Call GiveFeedback() with the returned interval in milliseconds, provided
// there is a new estimate available.
// Note that changing the feedback interval affects the timing of when the
// output of the estimators is sampled and therefore the baseline files may
// have to be regenerated.
- virtual int GetFeedbackIntervalMs() const { return 1000; }
- virtual void GiveFeedback(const Feedback& feedback) {}
+ virtual int GetFeedbackIntervalMs() const;
+ virtual void GiveFeedback(const FeedbackPacket& feedback);
virtual void RunFor(int64_t time_ms, Packets* in_out) OVERRIDE;
virtual VideoSource* source() const { return source_; }
- protected:
- VideoSource* source_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PacketSender);
-};
-
-class RegularVideoSender : public PacketSender, public BitrateObserver {
- public:
- RegularVideoSender(PacketProcessorListener* listener,
- VideoSource* source,
- uint32_t kbps);
- virtual ~RegularVideoSender();
-
- virtual int GetFeedbackIntervalMs() const OVERRIDE { return 100; }
- virtual void GiveFeedback(const Feedback& feedback) OVERRIDE;
- virtual void RunFor(int64_t time_ms, Packets* in_out) OVERRIDE;
-
// Implements BitrateObserver.
virtual void OnNetworkChanged(uint32_t target_bitrate_bps,
uint8_t fraction_lost,
int64_t rtt) OVERRIDE;
protected:
- static const int64_t kInitialTimeMs = 0;
SimulatedClock clock_;
+ VideoSource* source_;
+ scoped_ptr<SendSideBwe> bwe_;
int64_t start_of_run_ms_;
- scoped_ptr<BitrateController> bitrate_controller_;
- scoped_ptr<RtcpBandwidthObserver> feedback_observer_;
std::list<Module*> modules_;
private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(RegularVideoSender);
+ DISALLOW_COPY_AND_ASSIGN(PacketSender);
};
-class PacedVideoSender : public RegularVideoSender,
- public PacedSender::Callback {
+class PacedVideoSender : public PacketSender, public PacedSender::Callback {
public:
PacedVideoSender(PacketProcessorListener* listener,
VideoSource* source,
- uint32_t kbps);
+ BandwidthEstimatorType estimator);
virtual ~PacedVideoSender();
virtual void RunFor(int64_t time_ms, Packets* in_out) OVERRIDE;
diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc
index 6865da5..ac57054 100644
--- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc
+++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework_unittest.cc
@@ -58,8 +58,10 @@
static bool IsSequenceNumberSorted(const Packets& packets) {
PacketsConstIt last_it = packets.begin();
for (PacketsConstIt it = last_it; it != packets.end(); ++it) {
- if (IsNewerSequenceNumber((*last_it)->header().sequenceNumber,
- (*it)->header().sequenceNumber)) {
+ const MediaPacket* packet = static_cast<const MediaPacket*>(*it);
+ const MediaPacket* last_packet = static_cast<const MediaPacket*>(*last_it);
+ if (IsNewerSequenceNumber(last_packet->header().sequenceNumber,
+ packet->header().sequenceNumber)) {
return false;
}
last_it = it;
@@ -72,20 +74,20 @@
// Insert some packets in order...
EXPECT_TRUE(IsTimeSorted(packets));
- packets.push_back(new Packet(100, 0));
+ packets.push_back(new MediaPacket(100, 0));
EXPECT_TRUE(IsTimeSorted(packets));
- packets.push_back(new Packet(110, 0));
+ packets.push_back(new MediaPacket(110, 0));
EXPECT_TRUE(IsTimeSorted(packets));
// ...and one out-of-order...
- packets.push_back(new Packet(100, 0));
+ packets.push_back(new MediaPacket(100, 0));
EXPECT_FALSE(IsTimeSorted(packets));
// ...remove the out-of-order packet, insert another in-order packet.
delete packets.back();
packets.pop_back();
- packets.push_back(new Packet(120, 0));
+ packets.push_back(new MediaPacket(120, 0));
EXPECT_TRUE(IsTimeSorted(packets));
for (auto* packet : packets)
@@ -97,20 +99,20 @@
// Insert some packets in order...
EXPECT_TRUE(IsSequenceNumberSorted(packets));
- packets.push_back(new Packet(0, 100));
+ packets.push_back(new MediaPacket(0, 100));
EXPECT_TRUE(IsSequenceNumberSorted(packets));
- packets.push_back(new Packet(0, 110));
+ packets.push_back(new MediaPacket(0, 110));
EXPECT_TRUE(IsSequenceNumberSorted(packets));
// ...and one out-of-order...
- packets.push_back(new Packet(0, 100));
+ packets.push_back(new MediaPacket(0, 100));
EXPECT_FALSE(IsSequenceNumberSorted(packets));
// ...remove the out-of-order packet, insert another in-order packet.
delete packets.back();
packets.pop_back();
- packets.push_back(new Packet(0, 120));
+ packets.push_back(new MediaPacket(0, 120));
EXPECT_TRUE(IsSequenceNumberSorted(packets));
for (auto* packet : packets)
@@ -193,7 +195,7 @@
// "Send" a packet every 10 ms.
for (int64_t i = 0; i < run_for_ms; i += 10, now_ms_ += 10) {
packets.push_back(
- new Packet(0, now_ms_ * 1000, payload_bits / 8, header));
+ new MediaPacket(0, now_ms_ * 1000, payload_bits / 8, header));
}
filter_.RunFor(run_for_ms, &packets);
ASSERT_TRUE(IsTimeSorted(packets));
@@ -265,7 +267,7 @@
for (int i = 0; i < 2225; ++i) {
Packets packets;
for (int j = 0; j < i % 10; ++j)
- packets.push_back(new Packet(i, i));
+ packets.push_back(new MediaPacket(i, i));
sent_packets += packets.size();
filter.RunFor(0, &packets);
ASSERT_TRUE(IsTimeSorted(packets));
@@ -320,8 +322,8 @@
uint32_t out_packets) {
Packets packets;
for (uint32_t i = 0; i < in_packets; ++i) {
- packets.push_back(new Packet(now_ms_ * 1000 + (sequence_number_ >> 4),
- sequence_number_));
+ packets.push_back(new MediaPacket(
+ now_ms_ * 1000 + (sequence_number_ >> 4), sequence_number_));
sequence_number_++;
}
filter_.RunFor(run_for_ms, &packets);
@@ -421,7 +423,7 @@
// Delay a bunch of packets, accumulate them to the 'acc' list.
delay.SetDelay(100.0f);
for (uint32_t i = 0; i < 10; ++i) {
- packets.push_back(new Packet(i * 100, i));
+ packets.push_back(new MediaPacket(i * 100, i));
}
delay.RunFor(1000, &packets);
acc.splice(acc.end(), packets);
@@ -432,7 +434,7 @@
// to the 'acc' list and verify that it is all sorted.
delay.SetDelay(0.0f);
for (uint32_t i = 10; i < 50; ++i) {
- packets.push_back(new Packet(i * 100, i));
+ packets.push_back(new MediaPacket(i * 100, i));
}
delay.RunFor(1000, &packets);
acc.splice(acc.end(), packets);
@@ -474,8 +476,8 @@
for (uint32_t i = 0; i < 1000; ++i) {
Packets packets;
for (uint32_t j = 0; j < i % 100; ++j) {
- packets.push_back(new Packet(now_ms * 1000, sequence_number));
- original.push_back(new Packet(now_ms * 1000, sequence_number));
+ packets.push_back(new MediaPacket(now_ms * 1000, sequence_number));
+ original.push_back(new MediaPacket(now_ms * 1000, sequence_number));
++sequence_number;
now_ms += 5 * stddev_jitter_ms;
}
@@ -496,8 +498,11 @@
Stats<double> jitter_us;
for (PacketsIt it1 = original.begin(), it2 = jittered.begin();
it1 != original.end() && it2 != jittered.end(); ++it1, ++it2) {
- EXPECT_EQ((*it1)->header().sequenceNumber, (*it2)->header().sequenceNumber);
- jitter_us.Push((*it2)->send_time_us() - (*it1)->send_time_us());
+ const MediaPacket* packet1 = static_cast<const MediaPacket*>(*it1);
+ const MediaPacket* packet2 = static_cast<const MediaPacket*>(*it2);
+ EXPECT_EQ(packet1->header().sequenceNumber,
+ packet2->header().sequenceNumber);
+ jitter_us.Push(packet1->send_time_us() - packet2->send_time_us());
}
EXPECT_NEAR(0.0, jitter_us.GetMean(), stddev_jitter_ms * 1000.0 * 0.008);
EXPECT_NEAR(stddev_jitter_ms * 1000.0, jitter_us.GetStdDev(),
@@ -536,7 +541,7 @@
int64_t now_ms = 0;
uint32_t sequence_number = 1;
for (uint32_t i = 0; i < kPacketCount; ++i, now_ms += 10) {
- packets.push_back(new Packet(now_ms * 1000, sequence_number++));
+ packets.push_back(new MediaPacket(now_ms * 1000, sequence_number++));
}
ASSERT_TRUE(IsTimeSorted(packets));
ASSERT_TRUE(IsSequenceNumberSorted(packets));
@@ -552,7 +557,8 @@
uint32_t distance = 0;
uint32_t last_sequence_number = 0;
for (auto* packet : packets) {
- uint32_t sequence_number = packet->header().sequenceNumber;
+ const MediaPacket* media_packet = static_cast<const MediaPacket*>(packet);
+ uint32_t sequence_number = media_packet->header().sequenceNumber;
if (sequence_number < last_sequence_number) {
distance += last_sequence_number - sequence_number;
}
@@ -622,7 +628,7 @@
int64_t send_time_ms = now_ms_ + (i * run_for_ms) / packets_to_generate;
header.sequenceNumber = sequence_number_++;
// Payload is 1000 bits.
- packets.push_back(new Packet(0, send_time_ms * 1000, 125, header));
+ packets.push_back(new MediaPacket(0, send_time_ms * 1000, 125, header));
send_times_us_.push_back(send_time_ms * 1000);
}
ASSERT_TRUE(IsTimeSorted(packets));
@@ -648,8 +654,9 @@
void CheckMaxDelay(int64_t max_delay_ms) {
for (const auto* packet : output_packets_) {
- int64_t delay_us = packet->send_time_us() -
- send_times_us_[packet->header().sequenceNumber];
+ const MediaPacket* media_packet = static_cast<const MediaPacket*>(packet);
+ int64_t delay_us = media_packet->send_time_us() -
+ send_times_us_[media_packet->header().sequenceNumber];
EXPECT_GE(max_delay_ms * 1000, delay_us);
}
}
@@ -781,20 +788,23 @@
uint32_t rtp_timestamp = 0;
uint32_t rtp_timestamp_wraps = 0;
for (const auto* packet : packets) {
- EXPECT_LE(send_time_us, packet->send_time_us());
- send_time_us = packet->send_time_us();
- if (sender->source()->max_payload_size_bytes() != packet->payload_size()) {
- EXPECT_EQ(expected_payload_size, packet->payload_size());
+ const MediaPacket* media_packet = static_cast<const MediaPacket*>(packet);
+ EXPECT_LE(send_time_us, media_packet->send_time_us());
+ send_time_us = media_packet->send_time_us();
+ if (sender->source()->max_payload_size_bytes() !=
+ media_packet->payload_size()) {
+ EXPECT_EQ(expected_payload_size, media_packet->payload_size());
}
- total_payload_size += packet->payload_size();
- if (absolute_send_time > packet->header().extension.absoluteSendTime) {
+ total_payload_size += media_packet->payload_size();
+ if (absolute_send_time >
+ media_packet->header().extension.absoluteSendTime) {
absolute_send_time_wraps++;
}
- absolute_send_time = packet->header().extension.absoluteSendTime;
- if (rtp_timestamp > packet->header().timestamp) {
+ absolute_send_time = media_packet->header().extension.absoluteSendTime;
+ if (rtp_timestamp > media_packet->header().timestamp) {
rtp_timestamp_wraps++;
}
- rtp_timestamp = packet->header().timestamp;
+ rtp_timestamp = media_packet->header().timestamp;
}
EXPECT_EQ(expected_total_payload_size, total_payload_size);
EXPECT_GE(1u, absolute_send_time_wraps);
@@ -807,7 +817,7 @@
TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s) {
// 1 fps, 80 kbps
VideoSource source(0, 1.0f, 80, 0x1234, 0);
- PacketSender sender(NULL, &source);
+ PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(10000u, source.bytes_per_second());
// We're at 1 fps, so all packets should be generated on first call, giving 10
// packets of each 1000 bytes, total 10000 bytes.
@@ -825,7 +835,7 @@
TEST(BweTestFramework_VideoSenderTest, Fps1Kbps80_1s_Offset) {
// 1 fps, 80 kbps, offset 0.5 of a frame period, ==0.5s in this case.
VideoSource source(0, 1.0f, 80, 0x1234, 500);
- PacketSender sender(NULL, &source);
+ PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(10000u, source.bytes_per_second());
// 499ms, no output.
TestVideoSender(&sender, 499, 0, 0, 0);
@@ -846,7 +856,7 @@
TEST(BweTestFramework_VideoSenderTest, Fps50Kpbs80_11s) {
// 50 fps, 80 kbps.
VideoSource source(0, 50.0f, 80, 0x1234, 0);
- PacketSender sender(NULL, &source);
+ PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(10000u, source.bytes_per_second());
// 9998ms, should see 500 frames, 200 byte payloads, total 100000 bytes.
TestVideoSender(&sender, 9998, 500, 200, 100000);
@@ -863,7 +873,7 @@
TEST(BweTestFramework_VideoSenderTest, Fps10Kpbs120_1s) {
// 20 fps, 120 kbps.
VideoSource source(0, 20.0f, 120, 0x1234, 0);
- PacketSender sender(NULL, &source);
+ PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(15000u, source.bytes_per_second());
// 498ms, 10 frames with 750 byte payloads, total 7500 bytes.
TestVideoSender(&sender, 498, 10, 750, 7500);
@@ -880,7 +890,7 @@
TEST(BweTestFramework_VideoSenderTest, Fps30Kbps800_20s) {
// 20 fps, 820 kbps.
VideoSource source(0, 25.0f, 820, 0x1234, 0);
- PacketSender sender(NULL, &source);
+ PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(102500u, source.bytes_per_second());
// 9998ms, 250 frames. 820 kbps = 102500 bytes/s, so total should be 1025000.
// Each frame is 102500/25=4100 bytes, or 5 packets (4 @1000 bytes, 1 @100),
@@ -902,7 +912,7 @@
TEST(BweTestFramework_VideoSenderTest, TestAppendInOrder) {
// 1 fps, 80 kbps, 250ms offset.
VideoSource source1(0, 1.0f, 80, 0x1234, 250);
- PacketSender sender1(NULL, &source1);
+ PacketSender sender1(NULL, &source1, kNullEstimator);
EXPECT_EQ(10000u, source1.bytes_per_second());
Packets packets;
// Generate some packets, verify they are sorted.
@@ -918,7 +928,7 @@
// Another sender, 2 fps, 160 kbps, 150ms offset
VideoSource source2(0, 2.0f, 160, 0x2234, 150);
- PacketSender sender2(NULL, &source2);
+ PacketSender sender2(NULL, &source2, kNullEstimator);
EXPECT_EQ(20000u, source2.bytes_per_second());
// Generate some packets, verify that they are merged with the packets already
// on the list.
@@ -936,13 +946,13 @@
TEST(BweTestFramework_VideoSenderTest, FeedbackIneffective) {
VideoSource source(0, 25.0f, 820, 0x1234, 0);
- PacketSender sender(NULL, &source);
+ PacketSender sender(NULL, &source, kNullEstimator);
EXPECT_EQ(102500u, source.bytes_per_second());
TestVideoSender(&sender, 9998, 1000, 500, 1025000);
// Make sure feedback has no effect on a regular video sender.
- PacketSender::Feedback feedback = { 512000 };
+ RembFeedback feedback(0, 0, 512000, RTCPReportBlock());
sender.GiveFeedback(feedback);
EXPECT_EQ(102500u, source.bytes_per_second());
TestVideoSender(&sender, 9998, 1000, 500, 1025000);
@@ -950,20 +960,20 @@
TEST(BweTestFramework_AdaptiveVideoSenderTest, FeedbackChangesBitrate) {
AdaptiveVideoSource source(0, 25.0f, 820, 0x1234, 0);
- RegularVideoSender sender(NULL, &source, 820);
+ PacketSender sender(NULL, &source, kRembEstimator);
EXPECT_EQ(102500u, source.bytes_per_second());
TestVideoSender(&sender, 9998, 1000, 500, 1025000);
// Make sure we can reduce the bitrate.
- PacketSender::Feedback feedback = { 512000 };
+ RembFeedback feedback(0, 0, 512000, RTCPReportBlock());
sender.GiveFeedback(feedback);
EXPECT_EQ(64000u, source.bytes_per_second());
TestVideoSender(&sender, 9998, 750, 160, 640000);
// Increase the bitrate to the initial bitrate and verify that the output is
// the same.
- feedback.estimated_bps = 820000;
- sender.GiveFeedback(feedback);
+ RembFeedback feedback2(0, 0, 820000, RTCPReportBlock());
+ sender.GiveFeedback(feedback2);
Packets packets;
sender.RunFor(10000, &packets);
EXPECT_EQ(102500u, source.bytes_per_second());