Chromium Code Reviews| Index: webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc | 
| 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 ad1f5fd5bf0f3f4bb7f7f2d0367430d430923a66..c559f1a9c96464e811c1eed79507e83340346bad 100644 | 
| --- a/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc | 
| +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.cc | 
| @@ -20,9 +20,10 @@ namespace bwe { | 
| class DelayCapHelper { | 
| public: | 
| + // Max delay = 0 stands for +infinite. | 
| DelayCapHelper() : max_delay_us_(0), delay_stats_() {} | 
| - void SetMaxDelay(int max_delay_ms) { | 
| + void set_max_delay_ms(int64_t max_delay_ms) { | 
| BWE_TEST_LOGGING_ENABLE(false); | 
| BWE_TEST_LOGGING_LOG1("Max Delay", "%d ms", static_cast<int>(max_delay_ms)); | 
| assert(max_delay_ms >= 0); | 
| @@ -51,48 +52,49 @@ const FlowIds CreateFlowIds(const int *flow_ids_array, size_t num_flow_ids) { | 
| return flow_ids; | 
| } | 
| -class RateCounter { | 
| - public: | 
| - RateCounter() | 
| - : kWindowSizeUs(1000000), | 
| - packets_per_second_(0), | 
| - bytes_per_second_(0), | 
| - last_accumulated_us_(0), | 
| - window_() {} | 
| - | 
| - void UpdateRates(int64_t send_time_us, uint32_t payload_size) { | 
| - packets_per_second_++; | 
| - bytes_per_second_ += payload_size; | 
| - last_accumulated_us_ = send_time_us; | 
| - window_.push_back(std::make_pair(send_time_us, payload_size)); | 
| - while (!window_.empty()) { | 
| - const TimeSizePair& packet = window_.front(); | 
| - if (packet.first > (last_accumulated_us_ - kWindowSizeUs)) { | 
| - break; | 
| - } | 
| - assert(packets_per_second_ >= 1); | 
| - assert(bytes_per_second_ >= packet.second); | 
| - packets_per_second_--; | 
| - bytes_per_second_ -= packet.second; | 
| - window_.pop_front(); | 
| +const FlowIds CreateFlowIdRange(int initial_value, int last_value) { | 
| + int size = last_value - initial_value + 1; | 
| + assert(size > 0); | 
| + int* flow_ids_array = new int[size]; | 
| + for (int i = initial_value; i <= last_value; ++i) { | 
| + flow_ids_array[i - initial_value] = i; | 
| + } | 
| + return CreateFlowIds(flow_ids_array, size); | 
| +} | 
| + | 
| +void RateCounter::UpdateRates(int64_t send_time_us, uint32_t payload_size) { | 
| + recently_received_packets_++; | 
| + recently_received_bytes_ += payload_size; | 
| + last_accumulated_us_ = send_time_us; | 
| + window_.push_back(std::make_pair(send_time_us, payload_size)); | 
| + while (!window_.empty()) { | 
| + const TimeSizePair& packet = window_.front(); | 
| + if (packet.first > (last_accumulated_us_ - windows_size_us_)) { | 
| + break; | 
| } | 
| + assert(recently_received_packets_ >= 1); | 
| + assert(recently_received_bytes_ >= packet.second); | 
| + recently_received_packets_--; | 
| + recently_received_bytes_ -= packet.second; | 
| + window_.pop_front(); | 
| } | 
| +} | 
| - uint32_t bits_per_second() const { | 
| - return bytes_per_second_ * 8; | 
| - } | 
| +uint32_t RateCounter::bits_per_second() const { | 
| + return (8 * recently_received_bytes_) / windows_size_s(); | 
| +} | 
| - uint32_t packets_per_second() const { return packets_per_second_; } | 
| +uint32_t RateCounter::packets_per_second() const { | 
| + return recently_received_packets_ / windows_size_s(); | 
| +} | 
| - private: | 
| - typedef std::pair<int64_t, uint32_t> TimeSizePair; | 
| +void RateCounter::set_windows_size_ms(int64_t windows_size_ms) { | 
| + windows_size_us_ = 1000 * windows_size_ms; | 
| +} | 
| - const int64_t kWindowSizeUs; | 
| - uint32_t packets_per_second_; | 
| - uint32_t bytes_per_second_; | 
| - int64_t last_accumulated_us_; | 
| - std::list<TimeSizePair> window_; | 
| -}; | 
| +double RateCounter::windows_size_s() const { | 
| + return static_cast<double>(windows_size_us_) / (1000 * 1000); | 
| +} | 
| Random::Random(uint32_t seed) | 
| : a_(0x531FDB97 ^ seed), | 
| @@ -107,6 +109,11 @@ float Random::Rand() { | 
| return result; | 
| } | 
| +int Random::Rand(int low, int high) { | 
| + float uniform = Rand() * (high - low + 1) + low; | 
| + return static_cast<int>(uniform); | 
| +} | 
| + | 
| int Random::Gaussian(int mean, int standard_deviation) { | 
| // Creating a Normal distribution variable from two independent uniform | 
| // variables based on the Box-Muller transform, which is defined on the | 
| @@ -121,6 +128,11 @@ int Random::Gaussian(int mean, int standard_deviation) { | 
| sqrt(-2 * log(u1)) * cos(2 * kPi * u2)); | 
| } | 
| +int Random::Exponential(float lambda) { | 
| + float uniform = Rand(); | 
| + return static_cast<int>(-log(uniform) / lambda); | 
| +} | 
| + | 
| Packet::Packet() | 
| : flow_id_(0), creation_time_us_(-1), send_time_us_(-1), payload_size_(0) { | 
| } | 
| @@ -230,14 +242,22 @@ PacketProcessor::~PacketProcessor() { | 
| } | 
| } | 
| +uint32_t PacketProcessor::packets_per_second() const { | 
| + return rate_counter_.packets_per_second(); | 
| +} | 
| + | 
| +uint32_t PacketProcessor::bits_per_second() const { | 
| + return rate_counter_.bits_per_second(); | 
| +} | 
| + | 
| RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, | 
| int flow_id, | 
| const char* name) | 
| : PacketProcessor(listener, flow_id, kRegular), | 
| - rate_counter_(new RateCounter()), | 
| packets_per_second_stats_(), | 
| kbps_stats_(), | 
| - name_() { | 
| + name_(), | 
| + start_plotting_time_ms_(0) { | 
| std::stringstream ss; | 
| ss << name << "_" << flow_id; | 
| name_ = ss.str(); | 
| @@ -247,10 +267,10 @@ RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, | 
| const FlowIds& flow_ids, | 
| const char* name) | 
| : PacketProcessor(listener, flow_ids, kRegular), | 
| - rate_counter_(new RateCounter()), | 
| packets_per_second_stats_(), | 
| kbps_stats_(), | 
| - name_() { | 
| + name_(), | 
| + start_plotting_time_ms_(0) { | 
| std::stringstream ss; | 
| ss << name << "_"; | 
| for (int flow_id : flow_ids) { | 
| @@ -259,17 +279,18 @@ RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, | 
| name_ = ss.str(); | 
| } | 
| -RateCounterFilter::~RateCounterFilter() { | 
| - LogStats(); | 
| +RateCounterFilter::RateCounterFilter(PacketProcessorListener* listener, | 
| + const FlowIds& flow_ids, | 
| + const char* name, | 
| + int64_t start_plotting_time_ms) | 
| + : RateCounterFilter(listener, flow_ids, name) { | 
| + start_plotting_time_ms_ = start_plotting_time_ms; | 
| } | 
| -uint32_t RateCounterFilter::packets_per_second() const { | 
| - return rate_counter_->packets_per_second(); | 
| +RateCounterFilter::~RateCounterFilter() { | 
| + LogStats(); | 
| } | 
| -uint32_t RateCounterFilter::bits_per_second() const { | 
| - return rate_counter_->bits_per_second(); | 
| -} | 
| void RateCounterFilter::LogStats() { | 
| BWE_TEST_LOGGING_CONTEXT("RateCounterFilter"); | 
| @@ -282,19 +303,23 @@ Stats<double> RateCounterFilter::GetBitrateStats() const { | 
| } | 
| void RateCounterFilter::Plot(int64_t timestamp_ms) { | 
| + uint32_t plot_kbps = 0; | 
| + if (timestamp_ms >= start_plotting_time_ms_) { | 
| + plot_kbps = rate_counter_.bits_per_second() / 1000.0; | 
| + } | 
| BWE_TEST_LOGGING_CONTEXT(name_.c_str()); | 
| - BWE_TEST_LOGGING_PLOT(0, "Throughput_#1", timestamp_ms, | 
| - rate_counter_->bits_per_second() / 1000.0); | 
| + BWE_TEST_LOGGING_PLOT(0, "Throughput_#1", timestamp_ms, plot_kbps); | 
| + RTC_UNUSED(plot_kbps); | 
| } | 
| void RateCounterFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { | 
| assert(in_out); | 
| for (const Packet* packet : *in_out) { | 
| - rate_counter_->UpdateRates(packet->send_time_us(), | 
| - static_cast<int>(packet->payload_size())); | 
| + rate_counter_.UpdateRates(packet->send_time_us(), | 
| + static_cast<int>(packet->payload_size())); | 
| } | 
| - packets_per_second_stats_.Push(rate_counter_->packets_per_second()); | 
| - kbps_stats_.Push(rate_counter_->bits_per_second() / 1000.0); | 
| + packets_per_second_stats_.Push(rate_counter_.packets_per_second()); | 
| + kbps_stats_.Push(rate_counter_.bits_per_second() / 1000.0); | 
| } | 
| LossFilter::LossFilter(PacketProcessorListener* listener, int flow_id) | 
| @@ -330,30 +355,32 @@ void LossFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { | 
| } | 
| } | 
| +const int64_t kDefaultOneWayDelayUs = 0; | 
| + | 
| DelayFilter::DelayFilter(PacketProcessorListener* listener, int flow_id) | 
| : PacketProcessor(listener, flow_id, kRegular), | 
| - delay_us_(0), | 
| + one_way_delay_us_(kDefaultOneWayDelayUs), | 
| last_send_time_us_(0) { | 
| } | 
| DelayFilter::DelayFilter(PacketProcessorListener* listener, | 
| const FlowIds& flow_ids) | 
| : PacketProcessor(listener, flow_ids, kRegular), | 
| - delay_us_(0), | 
| + one_way_delay_us_(kDefaultOneWayDelayUs), | 
| last_send_time_us_(0) { | 
| } | 
| -void DelayFilter::SetDelayMs(int64_t delay_ms) { | 
| +void DelayFilter::SetOneWayDelayMs(int64_t one_way_delay_ms) { | 
| BWE_TEST_LOGGING_ENABLE(false); | 
| - BWE_TEST_LOGGING_LOG1("Delay", "%d ms", static_cast<int>(delay_ms)); | 
| - assert(delay_ms >= 0); | 
| - delay_us_ = delay_ms * 1000; | 
| + BWE_TEST_LOGGING_LOG1("Delay", "%d ms", static_cast<int>(one_way_delay_ms)); | 
| + assert(one_way_delay_ms >= 0); | 
| + one_way_delay_us_ = one_way_delay_ms * 1000; | 
| } | 
| void DelayFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { | 
| assert(in_out); | 
| for (Packet* packet : *in_out) { | 
| - int64_t new_send_time_us = packet->send_time_us() + delay_us_; | 
| + int64_t new_send_time_us = packet->send_time_us() + one_way_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_); | 
| } | 
| @@ -431,9 +458,11 @@ void ReorderFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { | 
| } | 
| } | 
| +const uint32_t kDefaultKbps = 1200; | 
| + | 
| ChokeFilter::ChokeFilter(PacketProcessorListener* listener, int flow_id) | 
| : PacketProcessor(listener, flow_id, kRegular), | 
| - kbps_(1200), | 
| + capacity_kbps_(kDefaultKbps), | 
| last_send_time_us_(0), | 
| delay_cap_helper_(new DelayCapHelper()) { | 
| } | 
| @@ -441,17 +470,21 @@ ChokeFilter::ChokeFilter(PacketProcessorListener* listener, int flow_id) | 
| ChokeFilter::ChokeFilter(PacketProcessorListener* listener, | 
| const FlowIds& flow_ids) | 
| : PacketProcessor(listener, flow_ids, kRegular), | 
| - kbps_(1200), | 
| + capacity_kbps_(kDefaultKbps), | 
| last_send_time_us_(0), | 
| delay_cap_helper_(new DelayCapHelper()) { | 
| } | 
| ChokeFilter::~ChokeFilter() {} | 
| -void ChokeFilter::SetCapacity(uint32_t kbps) { | 
| +void ChokeFilter::set_capacity_kbps(uint32_t kbps) { | 
| BWE_TEST_LOGGING_ENABLE(false); | 
| BWE_TEST_LOGGING_LOG1("BitrateChoke", "%d kbps", kbps); | 
| - kbps_ = kbps; | 
| + capacity_kbps_ = kbps; | 
| +} | 
| + | 
| +uint32_t ChokeFilter::capacity_kbps() { | 
| + return capacity_kbps_; | 
| } | 
| void ChokeFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { | 
| @@ -459,9 +492,12 @@ void ChokeFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { | 
| for (PacketsIt it = in_out->begin(); it != in_out->end(); ) { | 
| int64_t earliest_send_time_us = | 
| last_send_time_us_ + | 
| - ((*it)->payload_size() * 8 * 1000 + kbps_ / 2) / kbps_; | 
| + ((*it)->payload_size() * 8 * 1000 + capacity_kbps_ / 2) / | 
| + capacity_kbps_; | 
| + | 
| int64_t new_send_time_us = | 
| std::max((*it)->send_time_us(), earliest_send_time_us); | 
| + | 
| if (delay_cap_helper_->ShouldSendPacket(new_send_time_us, | 
| (*it)->send_time_us())) { | 
| (*it)->set_send_time_us(new_send_time_us); | 
| @@ -474,8 +510,8 @@ void ChokeFilter::RunFor(int64_t /*time_ms*/, Packets* in_out) { | 
| } | 
| } | 
| -void ChokeFilter::SetMaxDelay(int max_delay_ms) { | 
| - delay_cap_helper_->SetMaxDelay(max_delay_ms); | 
| +void ChokeFilter::set_max_delay_ms(int64_t max_delay_ms) { | 
| + delay_cap_helper_->set_max_delay_ms(max_delay_ms); | 
| } | 
| Stats<double> ChokeFilter::GetDelayStats() const { | 
| @@ -592,8 +628,8 @@ void TraceBasedDeliveryFilter::RunFor(int64_t time_ms, Packets* in_out) { | 
| kbps_stats_.Push(rate_counter_->bits_per_second() / 1000.0); | 
| } | 
| -void TraceBasedDeliveryFilter::SetMaxDelay(int max_delay_ms) { | 
| - delay_cap_helper_->SetMaxDelay(max_delay_ms); | 
| +void TraceBasedDeliveryFilter::set_max_delay_ms(int64_t max_delay_ms) { | 
| + delay_cap_helper_->set_max_delay_ms(max_delay_ms); | 
| } | 
| Stats<double> TraceBasedDeliveryFilter::GetDelayStats() const { | 
| @@ -631,10 +667,12 @@ VideoSource::VideoSource(int flow_id, | 
| frame_period_ms_(1000.0 / fps), | 
| bits_per_second_(1000 * kbps), | 
| frame_size_bytes_(bits_per_second_ / 8 / fps), | 
| + running_(true), | 
| flow_id_(flow_id), | 
| next_frame_ms_(first_frame_offset_ms), | 
| now_ms_(0), | 
| - prototype_header_() { | 
| + prototype_header_(), | 
| + start_plotting_ms_(first_frame_offset_ms) { | 
| memset(&prototype_header_, 0, sizeof(prototype_header_)); | 
| prototype_header_.ssrc = ssrc; | 
| prototype_header_.sequenceNumber = 0xf000u; | 
| @@ -651,11 +689,10 @@ uint32_t VideoSource::NextPacketSize(uint32_t frame_size, | 
| void VideoSource::RunFor(int64_t time_ms, Packets* in_out) { | 
| assert(in_out); | 
| - std::stringstream ss; | 
| - ss << "SendEstimate_" << flow_id_ << "#1"; | 
| - BWE_TEST_LOGGING_PLOT(0, ss.str(), now_ms_, bits_per_second_ / 1000); | 
| + | 
| now_ms_ += time_ms; | 
| Packets new_packets; | 
| + | 
| while (now_ms_ >= next_frame_ms_) { | 
| prototype_header_.timestamp = kTimestampBase + | 
| static_cast<uint32_t>(next_frame_ms_ * 90.0); | 
| @@ -665,26 +702,50 @@ void VideoSource::RunFor(int64_t time_ms, Packets* in_out) { | 
| // but the payload size is capped, so if the whole frame doesn't fit in | 
| // one packet, we will see a number of equally sized packets followed by | 
| // one smaller at the tail. | 
| + | 
| int64_t send_time_us = next_frame_ms_ * 1000.0; | 
| - uint32_t frame_size = NextFrameSize(); | 
| - uint32_t payload_size = frame_size; | 
| - | 
| - while (payload_size > 0) { | 
| - ++prototype_header_.sequenceNumber; | 
| - uint32_t size = NextPacketSize(frame_size, payload_size); | 
| - 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_); | 
| - new_packet->set_sender_timestamp_us(send_time_us); | 
| - payload_size -= size; | 
| + | 
| + if (running_) { | 
| + uint32_t frame_size = NextFrameSize(); | 
| + uint32_t payload_size = frame_size; | 
| + | 
| + while (payload_size > 0) { | 
| + ++prototype_header_.sequenceNumber; | 
| + uint32_t size = NextPacketSize(frame_size, payload_size); | 
| + 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_); | 
| + new_packet->set_sender_timestamp_us(send_time_us); | 
| + payload_size -= size; | 
| + } | 
| } | 
| - next_frame_ms_ += frame_period_ms_; | 
| + // A variance picked uniformly from {-1, 0, 1} ms is added to the frame | 
| + // timestamp. | 
| + next_frame_ms_ += | 
| + frame_period_ms_ - 1 + 2 * static_cast<float>(rand()) / RAND_MAX; | 
| } | 
| + | 
| in_out->merge(new_packets, DereferencingComparator<Packet>); | 
| } | 
| +void VideoSource::Pause() { | 
| + running_ = false; | 
| +} | 
| + | 
| +void VideoSource::Resume() { | 
| + running_ = true; | 
| +} | 
| + | 
| +void AdaptiveVideoSource::SetBitrateBps(int bitrate_bps) { | 
| 
 
stefan-webrtc
2015/07/06 08:24:51
I'd prefer to not move this up here, it should be
 
magalhaesc
2015/07/06 09:28:06
Done.
 
 | 
| + if (!running_) { | 
| + bitrate_bps = 0; | 
| + } | 
| + bits_per_second_ = std::min(bitrate_bps, 2500000); | 
| + frame_size_bytes_ = (bits_per_second_ / 8 * frame_period_ms_ + 500) / 1000; | 
| +} | 
| + | 
| AdaptiveVideoSource::AdaptiveVideoSource(int flow_id, | 
| float fps, | 
| uint32_t kbps, | 
| @@ -693,11 +754,6 @@ AdaptiveVideoSource::AdaptiveVideoSource(int flow_id, | 
| : VideoSource(flow_id, fps, kbps, ssrc, first_frame_offset_ms) { | 
| } | 
| -void AdaptiveVideoSource::SetBitrateBps(int bitrate_bps) { | 
| - bits_per_second_ = std::min(bitrate_bps, 2500000); | 
| - frame_size_bytes_ = (bits_per_second_ / 8 * frame_period_ms_ + 500) / 1000; | 
| -} | 
| - | 
| PeriodicKeyFrameSource::PeriodicKeyFrameSource(int flow_id, | 
| float fps, | 
| uint32_t kbps, |