diff --git a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc index 58c8b5b495..f607fd07e3 100644 --- a/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc +++ b/webrtc/modules/remote_bitrate_estimator/bwe_simulations.cc @@ -25,7 +25,8 @@ BweTestConfig::EstimatorConfig CreateEstimatorConfig( AbsoluteSendTimeRemoteBitrateEstimatorFactory(); return BweTestConfig::EstimatorConfig("AST", flow_id, &factory, kAimdControl, - plot_delay, plot_estimate); + kRembEstimator, plot_delay, + plot_estimate); } BweTestConfig MakeAdaptiveBweTestConfig() { @@ -65,7 +66,7 @@ INSTANTIATE_TEST_CASE_P(VideoSendersTest, BweSimulation, 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, SprintUplinkTest) { 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, Verizon4gDownlinkTest) { 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, Choke1000kbps500kbps1000kbps) { 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, PacerChoke1000kbps500kbps1000kbps) { 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, PacerChoke10000kbps) { 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, PacerChoke200kbps30kbps200kbps) { 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, Choke200kbps30kbps200kbps) { 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, GoogleWifiTrace3Mbps) { 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 @@ TEST_P(MultiFlowBweSimulation, SelfFairnessTest) { const int kAllFlowIds[] = {0, 1, 2}; const size_t kNumFlows = sizeof(kAllFlowIds) / sizeof(kAllFlowIds[0]); scoped_ptr sources[kNumFlows]; - scoped_ptr senders[kNumFlows]; + scoped_ptr 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 @@ TEST_P(MultiFlowBweSimulation, PacedSelfFairnessTest) { // 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 92a0eb86f6..4986467e8d 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 @@ struct ReceiveBandwidthEstimatorStats { std::vector 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& 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 c35757785b..e32ef72641 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 @@ class RemoteBitrateEstimatorAbsSendTimeImpl : public RemoteBitrateEstimator { uint32_t min_bitrate_bps); virtual ~RemoteBitrateEstimatorAbsSendTimeImpl() {} + virtual void IncomingPacketFeedbackVector( + const std::vector& packet_feedback_vector) OVERRIDE; + virtual void IncomingPacket(int64_t arrival_time_ms, size_t payload_size, const RTPHeader& header) OVERRIDE; @@ -129,7 +132,6 @@ class RemoteBitrateEstimatorAbsSendTimeImpl : public RemoteBitrateEstimator { private: typedef std::map Ssrcs; - static bool IsWithinClusterBounds(int send_delta_ms, const Cluster& cluster_aggregate) { if (cluster_aggregate.count == 0) @@ -150,6 +152,11 @@ class RemoteBitrateEstimatorAbsSendTimeImpl : public RemoteBitrateEstimator { return static_cast(reinterpret_cast(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 @@ bool RemoteBitrateEstimatorAbsSendTimeImpl::IsBitrateImproving( return initial_probe || bitrate_above_estimate; } +void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacketFeedbackVector( + const std::vector& 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 @@ void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacket( 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(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(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 @@ void RemoteBitrateEstimatorAbsSendTimeImpl::IncomingPacket( } 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 b33f033ec5..1f5dac10b7 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 @@ BweTestConfig::EstimatorConfig EstimatorConfigs(Estimator estimator, 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 @@ class DefaultBweTest : public BweTest, 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 @@ class BweFeedbackTest : public BweTest, 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, Choke1000kbps500kbps1000kbps) { 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, Choke200kbps30kbps200kbps) { 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 @@ TEST_F(BweFeedbackTest, Verizon4gDownlinkTest) { // 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 911f662707..1f9526d870 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 webrtc { 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 baseline_; + Stats 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(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 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 @@ class PacketReceiver : public RemoteBitrateObserver { 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(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(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(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(estimated_bps) / 1000.0; @@ -118,19 +184,8 @@ class PacketReceiver : public RemoteBitrateObserver { 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& ssrcs, @@ -163,29 +218,39 @@ class PacketReceiver : public RemoteBitrateObserver { 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 stats_; scoped_ptr recv_stats_; int64_t latest_estimate_bps_; scoped_ptr estimator_; - scoped_ptr 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() 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 @@ void BweTest::SetupTestFromConfig(const BweTestConfig& config) { string test_name = string(test_info->test_case_name()) + "_" + string(test_info->name()); BWE_TEST_LOGGING_GLOBAL_CONTEXT(test_name); - for (vector::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 @@ void BweTest::AddPacketProcessor(PacketProcessor* processor, bool is_sender) { senders_.push_back(static_cast(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 @@ void BweTest::VerboseLogging(bool enable) { BWE_TEST_LOGGING_GLOBAL_ENABLE(enable); } -void BweTest::GiveFeedbackToAffectedSenders(int flow_id, - PacketReceiver* estimator) { - std::list affected_senders; - for (auto* sender : senders_) { - if (sender->flow_ids().find(flow_id) != sender->flow_ids().end()) { - affected_senders.push_back(sender); - } - } - 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); +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; + } } } + delete feedback; } void BweTest::RunFor(int64_t time_ms) { @@ -340,7 +399,7 @@ void BweTest::RunFor(int64_t time_ms) { 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 @@ void BweTest::RunFor(int64_t time_ms) { 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 e3e0097dc4..2648733526 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 @@ struct BweTestConfig { : 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 @@ class BweTest : public PacketProcessorListener { 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 1520db7613..b2627a1cc7 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 @@ int Random::Gaussian(int mean, int standard_deviation) { } 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 @@ void Packet::set_send_time_us(int64_t send_time_us) { 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(1 << kInterArrivalShift); + uint32_t timestamp = header_.extension.absoluteSendTime + << kAbsSendTimeInterArrivalUpshift; + return static_cast(timestamp) * kTimestampToMs; +} + +void MediaPacket::SetAbsSendTimeMs(int64_t abs_send_time_ms) { header_.extension.hasAbsoluteSendTime = true; header_.extension.absoluteSendTime = ((static_cast(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& 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 @@ RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, 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::Plot(int64_t timestamp_ms) { 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::SetDelay(int64_t delay_ms) { 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::SetJitter(int64_t stddev_jitter_ms) { 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 @@ void ReorderFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { 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 @@ void TraceBasedDeliveryFilter::ProceedToNextSlot() { ++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 @@ void VideoSource::RunFor(int64_t time_ms, Packets* in_out) { 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 @@ uint32_t PeriodicKeyFrameSource::NextPacketSize(uint32_t frame_size, 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(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(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& 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(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 @@ void RegularVideoSender::OnNetworkChanged(uint32_t target_bitrate_bps, 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 @@ void PacedVideoSender::RunFor(int64_t time_ms, Packets* in_out) { 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(*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 @@ void PacedVideoSender::RunFor(int64_t time_ms, Packets* in_out) { int64_t PacedVideoSender::TimeUntilNextProcess( const std::list& 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 @@ int64_t PacedVideoSender::TimeUntilNextProcess( } void PacedVideoSender::CallProcess(const std::list& modules) { - for (auto* module : modules) { + for (Module* module : modules) { if (module->TimeUntilNextProcess() <= 0) { module->Process(); } @@ -842,14 +972,15 @@ bool PacedVideoSender::TimeToSendPacket(uint32_t ssrc, 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(*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 @@ size_t PacedVideoSender::TimeToSendPadding(size_t bytes) { 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 3d79c96525..bed7e7d831 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 #include +#include #include #include #include @@ -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 Random { 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 ArrivalTimesMap; + SendSideBweFeedback(int flow_id, + int64_t send_time_us, + const std::vector& packet_feedback_vector); + virtual ~SendSideBweFeedback() {} + + const std::vector& packet_feedback_vector() const { + return packet_feedback_vector_; + } + + private: + const std::vector packet_feedback_vector_; }; typedef std::list Packets; @@ -303,6 +362,7 @@ class JitterFilter : public PacketProcessor { 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 @@ class PeriodicKeyFrameSource : public AdaptiveVideoSource { 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::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 bitrate_controller_; + scoped_ptr 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& ssrcs, + unsigned int bitrate) OVERRIDE; + virtual int64_t TimeUntilNextProcess() OVERRIDE; + virtual int Process() OVERRIDE; + + protected: + scoped_ptr bitrate_controller_; + scoped_ptr rbe_; + scoped_ptr 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 bwe_; int64_t start_of_run_ms_; - scoped_ptr bitrate_controller_; - scoped_ptr feedback_observer_; std::list 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 6865da5a99..ac57054ff2 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 @@ TEST(BweTestFramework_RandomTest, Gaussian) { 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(*it); + const MediaPacket* last_packet = static_cast(*last_it); + if (IsNewerSequenceNumber(last_packet->header().sequenceNumber, + packet->header().sequenceNumber)) { return false; } last_it = it; @@ -72,20 +74,20 @@ TEST(BweTestFramework_PacketTest, IsTimeSorted) { // 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 @@ TEST(BweTestFramework_PacketTest, IsSequenceNumberSorted) { // 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 @@ class BweTestFramework_RateCounterFilterTest : public ::testing::Test { // "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 @@ static void TestLossFilter(float loss_percent, bool zero_tolerance) { 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 @@ class BweTestFramework_DelayFilterTest : public ::testing::Test { 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 @@ TEST_F(BweTestFramework_DelayFilterTest, JumpToZeroDelay) { // 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 @@ TEST_F(BweTestFramework_DelayFilterTest, JumpToZeroDelay) { // 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 @@ static void TestJitterFilter(int64_t stddev_jitter_ms) { 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 @@ static void TestJitterFilter(int64_t stddev_jitter_ms) { Stats 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(*it1); + const MediaPacket* packet2 = static_cast(*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 @@ static void TestReorderFilter(uint32_t reorder_percent, uint32_t near_value) { 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 @@ static void TestReorderFilter(uint32_t reorder_percent, uint32_t near_value) { 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(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 @@ class BweTestFramework_ChokeFilterTest : public ::testing::Test { 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 @@ class BweTestFramework_ChokeFilterTest : public ::testing::Test { 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(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 @@ void TestVideoSender(PacketSender* sender, 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(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 @@ void TestVideoSender(PacketSender* sender, 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) { 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, Fps1Kbps80_1s_Offset) { 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, Fps50Kpbs80_11s) { 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, Fps10Kpbs120_1s) { 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, Fps30Kbps800_20s) { 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 @@ TEST(BweTestFramework_VideoSenderTest, TestAppendInOrder) { // 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, TestAppendInOrder) { 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_VideoSenderTest, FeedbackIneffective) { 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());