diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe.cc b/webrtc/modules/remote_bitrate_estimator/test/bwe.cc index 6edfe3d08d..6e8dbc7c06 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe.cc @@ -22,6 +22,16 @@ namespace webrtc { namespace testing { namespace bwe { +// With the assumption that packet loss is lower than 97%, the max gap +// between elements in the set is lower than 0x8000, hence we have a +// total order in the set. For (x,y,z) subset of the LinkedSet, +// (x<=y and y<=z) ==> x<=z so the set can be sorted. +const int kSetCapacity = 1000; + +BweReceiver::BweReceiver(int flow_id) + : flow_id_(flow_id), received_packets_(kSetCapacity) { +} + class NullBweSender : public BweSender { public: NullBweSender() {} @@ -86,6 +96,98 @@ BweReceiver* CreateBweReceiver(BandwidthEstimatorType type, assert(false); return NULL; } + +float BweReceiver::GlobalPacketLossRatio() { + if (received_packets_.empty()) { + return 0.0f; + } + // Possibly there are packets missing. + const uint16_t kMaxGap = 1.5 * kSetCapacity; + uint16_t min = received_packets_.find_min(); + uint16_t max = received_packets_.find_max(); + + int gap; + if (max - min < kMaxGap) { + gap = max - min + 1; + } else { // There was an overflow. + max = received_packets_.upper_bound(kMaxGap); + min = received_packets_.lower_bound(0xFFFF - kMaxGap); + gap = max + (0xFFFF - min) + 2; + } + return static_cast(received_packets_.size()) / gap; +} + +// Go through a fixed time window of most recent packets received and +// counts packets missing to obtain the packet loss ratio. If an unordered +// packet falls out of the timewindow it will be counted as missing. +// E.g.: for a timewindow covering 5 packets of the following arrival sequence +// {10 7 9 5 6} 8 3 2 4 1, the output will be 1/6 (#8 is considered as missing). +float BweReceiver::RecentPacketLossRatio() { + if (received_packets_.empty()) { + return 0.0f; + } + int number_packets_received = 0; + + PacketNodeIt node_it = received_packets_.begin(); // Latest. + + // Lowest timestamp limit, oldest one that should be checked. + int64_t time_limit_ms = (*node_it)->arrival_time_ms - kPacketLossTimeWindowMs; + // Oldest and newest values found within the given time window. + uint16_t oldest_seq_nb = (*node_it)->sequence_number; + uint16_t newest_seq_nb = oldest_seq_nb; + + while (node_it != received_packets_.end()) { + if ((*node_it)->arrival_time_ms < time_limit_ms) { + break; + } + uint16_t seq_nb = (*node_it)->sequence_number; + if (IsNewerSequenceNumber(seq_nb, newest_seq_nb)) { + newest_seq_nb = seq_nb; + } + if (IsNewerSequenceNumber(oldest_seq_nb, seq_nb)) { + oldest_seq_nb = seq_nb; + } + ++node_it; + ++number_packets_received; + } + // Interval width between oldest and newest sequence number. + // There was an overflow if newest_seq_nb < oldest_seq_nb. + int gap = static_cast(newest_seq_nb - oldest_seq_nb + 1); + + return static_cast(gap - number_packets_received) / gap; +} + +void LinkedSet::Insert(uint16_t sequence_number, + int64_t send_time_ms, + int64_t arrival_time_ms, + size_t payload_size) { + std::map::iterator it = map_.find(sequence_number); + if (it != map_.end()) { + PacketNodeIt node_it = it->second; + PacketIdentifierNode* node = *node_it; + node->arrival_time_ms = arrival_time_ms; + if (node_it != list_.begin()) { + list_.erase(node_it); + list_.push_front(node); + map_[sequence_number] = list_.begin(); + } + } else { + if (size() == capacity_) { + RemoveTail(); + } + UpdateHead(new PacketIdentifierNode(sequence_number, send_time_ms, + arrival_time_ms, payload_size)); + } +} +void LinkedSet::RemoveTail() { + map_.erase(list_.back()->sequence_number); + list_.pop_back(); +} +void LinkedSet::UpdateHead(PacketIdentifierNode* new_head) { + list_.push_front(new_head); + map_[new_head->sequence_number] = list_.begin(); +} + } // namespace bwe } // namespace testing } // namespace webrtc diff --git a/webrtc/modules/remote_bitrate_estimator/test/bwe.h b/webrtc/modules/remote_bitrate_estimator/test/bwe.h index 0c79bf2ccc..d059871488 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/bwe.h +++ b/webrtc/modules/remote_bitrate_estimator/test/bwe.h @@ -20,6 +20,66 @@ namespace webrtc { namespace testing { namespace bwe { +// Holds only essential information about packets to be saved for +// further use, e.g. for calculating packet loss and receiving rate. +struct PacketIdentifierNode { + PacketIdentifierNode(uint16_t sequence_number, + int64_t send_time_ms, + int64_t arrival_time_ms, + size_t payload_size) + : sequence_number(sequence_number), + send_time_ms(send_time_ms), + arrival_time_ms(arrival_time_ms), + payload_size(payload_size) {} + + uint16_t sequence_number; + int64_t send_time_ms; + int64_t arrival_time_ms; + size_t payload_size; +}; + +typedef std::list::iterator PacketNodeIt; + +// FIFO implementation for a limited capacity set. +// Used for keeping the latest arrived packets while avoiding duplicates. +// Allows efficient insertion, deletion and search. +class LinkedSet { + public: + explicit LinkedSet(int capacity) : capacity_(capacity) {} + + // If the arriving packet (identified by its sequence number) is already + // in the LinkedSet, move its Node to the head of the list. Else, create + // a PacketIdentifierNode n_ and then UpdateHead(n_), calling RemoveTail() + // if the LinkedSet reached its maximum capacity. + void Insert(uint16_t sequence_number, + int64_t send_time_ms, + int64_t arrival_time_ms, + size_t payload_size); + + PacketNodeIt begin() { return list_.begin(); } + PacketNodeIt end() { return list_.end(); } + bool empty() { return list_.empty(); } + size_t size() { return list_.size(); } + // Gets the latest arrived sequence number. + uint16_t find_max() { return map_.rbegin()->first; } + // Gets the first arrived sequence number still saved in the LinkedSet. + uint16_t find_min() { return map_.begin()->first; } + // Gets the lowest saved sequence number that is >= than the input key. + uint16_t lower_bound(uint16_t key) { return map_.lower_bound(key)->first; } + // Gets the highest saved sequence number that is <= than the input key. + uint16_t upper_bound(uint16_t key) { return map_.upper_bound(key)->first; } + size_t capacity() { return capacity_; } + + private: + // Pop oldest element from the back of the list and remove it from the map. + void RemoveTail(); + // Add new element to the front of the list and insert it in the map. + void UpdateHead(PacketIdentifierNode* new_head); + size_t capacity_; + std::map map_; + std::list list_; +}; + const int kMinBitrateKbps = 150; const int kMaxBitrateKbps = 3000; @@ -38,15 +98,23 @@ class BweSender : public Module { class BweReceiver { public: - explicit BweReceiver(int flow_id) : flow_id_(flow_id) {} + explicit BweReceiver(int flow_id); virtual ~BweReceiver() {} virtual void ReceivePacket(int64_t arrival_time_ms, const MediaPacket& media_packet) {} virtual FeedbackPacket* GetFeedback(int64_t now_ms) { return NULL; } + float GlobalPacketLossRatio(); + float RecentPacketLossRatio(); + size_t GetSetCapacity() { return received_packets_.capacity(); } + + static const int64_t kPacketLossTimeWindowMs = 500; + protected: int flow_id_; + // Deals with packets sent more than once. + LinkedSet received_packets_; }; enum BandwidthEstimatorType { diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.cc index 4c4638b613..c28749d1d3 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.cc @@ -28,10 +28,9 @@ namespace testing { namespace bwe { const int NadaBweReceiver::kMedian; -const int64_t NadaBweReceiver::kPacketLossTimeWindowMs; -const int64_t NadaBweReceiver::kReceivingRateTimeWindowMs; const int NadaBweSender::kMinRefRateKbps; const int NadaBweSender::kMaxRefRateKbps; +const int64_t NadaBweReceiver::kReceivingRateTimeWindowMs; NadaBweReceiver::NadaBweReceiver(int flow_id) : BweReceiver(flow_id), @@ -84,9 +83,9 @@ void NadaBweReceiver::ReceivePacket(int64_t arrival_time_ms, est_queuing_delay_signal_ms_ = 0; } - received_packets_->Insert(media_packet.sequence_number(), - media_packet.send_time_ms(), arrival_time_ms, - media_packet.payload_size()); + received_packets_.Insert(media_packet.sequence_number(), + media_packet.send_time_ms(), arrival_time_ms, + media_packet.payload_size()); } FeedbackPacket* NadaBweReceiver::GetFeedback(int64_t now_ms) { @@ -110,7 +109,7 @@ FeedbackPacket* NadaBweReceiver::GetFeedback(int64_t now_ms) { last_feedback_ms_ = now_ms; last_congestion_signal_ms_ = congestion_signal_ms; - PacketIdentifierNode* latest = *(received_packets_->begin()); + PacketIdentifierNode* latest = *(received_packets_.begin()); int64_t corrected_send_time_ms = latest->send_time_ms + now_ms - latest->arrival_time_ms; @@ -122,83 +121,22 @@ FeedbackPacket* NadaBweReceiver::GetFeedback(int64_t now_ms) { corrected_send_time_ms); } -float NadaBweReceiver::GlobalPacketLossRatio() { - if (received_packets_->empty()) { - return 0.0f; - } - // Possibly there are packets missing. - const uint16_t kMaxGap = 1.5 * kSetCapacity; - uint16_t min = received_packets_->find_min(); - uint16_t max = received_packets_->find_max(); - - int gap; - if (max - min < kMaxGap) { - gap = max - min + 1; - } else { // There was an overflow. - max = received_packets_->upper_bound(kMaxGap); - min = received_packets_->lower_bound(0xFFFF - kMaxGap); - gap = max + (0xFFFF - min) + 2; - } - return static_cast(received_packets_->size()) / gap; -} - -// Go through a fixed time window of most recent packets received and -// counts packets missing to obtain the packet loss ratio. If an unordered -// packet falls out of the timewindow it will be counted as missing. -// E.g.: for a timewindow covering 5 packets of the following arrival sequence -// {10 7 9 5 6} 8 3 2 4 1, the output will be 1/6 (#8 is considered as missing). -float NadaBweReceiver::RecentPacketLossRatio() { - - if (received_packets_->empty()) { - return 0.0f; - } - int number_packets_received = 0; - - PacketNodeIt node_it = received_packets_->begin(); // Latest. - - // Lowest timestamp limit, oldest one that should be checked. - int64_t time_limit_ms = (*node_it)->arrival_time_ms - kPacketLossTimeWindowMs; - // Oldest and newest values found within the given time window. - uint16_t oldest_seq_nb = (*node_it)->sequence_number; - uint16_t newest_seq_nb = oldest_seq_nb; - - while (node_it != received_packets_->end()) { - if ((*node_it)->arrival_time_ms < time_limit_ms) { - break; - } - uint16_t seq_nb = (*node_it)->sequence_number; - if (IsNewerSequenceNumber(seq_nb, newest_seq_nb)) { - newest_seq_nb = seq_nb; - } - if (IsNewerSequenceNumber(oldest_seq_nb, seq_nb)) { - oldest_seq_nb = seq_nb; - } - ++node_it; - ++number_packets_received; - } - // Interval width between oldest and newest sequence number. - // There was an overflow if newest_seq_nb < oldest_seq_nb. - int gap = static_cast(newest_seq_nb - oldest_seq_nb + 1); - - return static_cast(gap - number_packets_received) / gap; -} - // For a given time window, compute the receiving speed rate in kbps. // As described below, three cases are considered depending on the number of // packets received. size_t NadaBweReceiver::RecentReceivingRate() { // If the receiver didn't receive any packet, return 0. - if (received_packets_->empty()) { + if (received_packets_.empty()) { return 0.0f; } size_t total_size = 0; int number_packets = 0; - PacketNodeIt node_it = received_packets_->begin(); + PacketNodeIt node_it = received_packets_.begin(); int64_t last_time_ms = (*node_it)->arrival_time_ms; int64_t start_time_ms = last_time_ms; - PacketNodeIt end = received_packets_->end(); + PacketNodeIt end = received_packets_.end(); // Stops after including the first packet out of the timeWindow. // Ameliorates results when there are wide gaps between packets. @@ -218,13 +156,14 @@ size_t NadaBweReceiver::RecentReceivingRate() { // If the receiver received a single packet, return its size*8/timeWindow. if (number_packets == 1) { corrected_time_ms = kReceivingRateTimeWindowMs; - } else { - // If the receiver received multiple packets, use as time interval the gap - // between first and last packet falling in the timeWindow corrected by the - // factor number_packets/(number_packets-1). - // E.g: Let timeWindow = 500ms, payload_size = 500bytes, number_packets=2, - // packets received at t1(0ms) and t2(499 or 501ms). This prevent the - // function from returning ~2*8, sending instead a more likely ~1*8 kbps. + } + // If the receiver received multiple packets, use as time interval the gap + // between first and last packet falling in the timeWindow corrected by the + // factor number_packets/(number_packets-1). + // E.g: Let timeWindow = 500ms, payload_size = 500 bytes, number_packets = 2, + // packets received at t1(0ms) and t2(499 or 501ms). This prevent the function + // from returning ~2*8, sending instead a more likely ~1*8 kbps. + else { corrected_time_ms = (number_packets * (start_time_ms - last_time_ms)) / (number_packets - 1); } @@ -383,37 +322,6 @@ void NadaBweSender::GradualRateUpdate(const NadaFeedback& fb, bitrate_kbps_ = bitrate_kbps_ + smoothing_factor * original_increase; } -void LinkedSet::Insert(uint16_t sequence_number, - int64_t send_time_ms, - int64_t arrival_time_ms, - size_t payload_size) { - std::map::iterator it = map_.find(sequence_number); - if (it != map_.end()) { - PacketNodeIt node_it = it->second; - PacketIdentifierNode* node = *node_it; - node->arrival_time_ms = arrival_time_ms; - if (node_it != list_.begin()) { - list_.erase(node_it); - list_.push_front(node); - map_[sequence_number] = list_.begin(); - } - } else { - if (size() == capacity_) { - RemoveTail(); - } - UpdateHead(new PacketIdentifierNode(sequence_number, send_time_ms, - arrival_time_ms, payload_size)); - } -} -void LinkedSet::RemoveTail() { - map_.erase(list_.back()->sequence_number); - list_.pop_back(); -} -void LinkedSet::UpdateHead(PacketIdentifierNode* new_head) { - list_.push_front(new_head); - map_[new_head->sequence_number] = list_.begin(); -} - } // namespace bwe } // namespace testing } // namespace webrtc diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h b/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h index 99e6c6a171..6fea624035 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h @@ -31,65 +31,6 @@ class ReceiveStatistics; namespace testing { namespace bwe { -// Holds only essential information about packets to be saved for -// further use, e.g. for calculating packet loss and receiving rate. -struct PacketIdentifierNode { - PacketIdentifierNode(uint16_t sequence_number, - int64_t send_time_ms, - int64_t arrival_time_ms, - size_t payload_size) - : sequence_number(sequence_number), - send_time_ms(send_time_ms), - arrival_time_ms(arrival_time_ms), - payload_size(payload_size) {} - - uint16_t sequence_number; - int64_t send_time_ms; - int64_t arrival_time_ms; - size_t payload_size; -}; - -typedef std::list::iterator PacketNodeIt; - -// FIFO implementation for a limited capacity set. -// Used for keeping the latest arrived packets while avoiding duplicates. -// Allows efficient insertion, deletion and search. -class LinkedSet { - public: - explicit LinkedSet(size_t capacity) : capacity_(capacity) {} - - // If the arriving packet (identified by its sequence number) is already - // in the LinkedSet, move its Node to the head of the list. Else, create - // a PacketIdentifierNode n_ and then UpdateHead(n_), calling RemoveTail() - // if the LinkedSet reached its maximum capacity. - void Insert(uint16_t sequence_number, - int64_t send_time_ms, - int64_t arrival_time_ms, - size_t payload_size); - - PacketNodeIt begin() { return list_.begin(); } - PacketNodeIt end() { return list_.end(); } - bool empty() { return list_.empty(); } - size_t size() { return list_.size(); } - // Gets the latest arrived sequence number. - uint16_t find_max() { return map_.rbegin()->first; } - // Gets the first arrived sequence number still saved in the LinkedSet. - uint16_t find_min() { return map_.begin()->first; } - // Gets the lowest saved sequence number that is >= than the input key. - uint16_t lower_bound(uint16_t key) { return map_.lower_bound(key)->first; } - // Gets the highest saved sequence number that is <= than the input key. - uint16_t upper_bound(uint16_t key) { return map_.upper_bound(key)->first; } - - private: - // Pop oldest element from the back of the list and remove it from the map. - void RemoveTail(); - // Add new element to the front of the list and insert it in the map. - void UpdateHead(PacketIdentifierNode* new_head); - size_t capacity_; - std::map map_; - std::list list_; -}; - class NadaBweReceiver : public BweReceiver { public: explicit NadaBweReceiver(int flow_id); @@ -98,20 +39,13 @@ class NadaBweReceiver : public BweReceiver { void ReceivePacket(int64_t arrival_time_ms, const MediaPacket& media_packet) override; FeedbackPacket* GetFeedback(int64_t now_ms) override; - float GlobalPacketLossRatio(); - float RecentPacketLossRatio(); + size_t RecentReceivingRate(); static int64_t MedianFilter(int64_t* v, int size); static int64_t ExponentialSmoothingFilter(int64_t new_value, int64_t last_smoothed_value, float alpha); - // With the assumption that packet loss is lower than 97%, the max gap - // between elements in the set is lower than 0x8000, hence we have a - // total order in the set. For (x,y,z) subset of the LinkedSet, - // (x<=y and y<=z) ==> x<=z so the set can be sorted. - static const int kSetCapacity = 1000; - static const int64_t kPacketLossTimeWindowMs = 500; static const int64_t kReceivingRateTimeWindowMs = 500; private: @@ -125,8 +59,6 @@ class NadaBweReceiver : public BweReceiver { int64_t exp_smoothed_delay_ms_; // Referred as d_hat_n. int64_t est_queuing_delay_signal_ms_; // Referred as d_tilde_n. - // Deals with packets sent more than once. - LinkedSet* received_packets_ = new LinkedSet(kSetCapacity); static const int kMedian = 5; // Used for k-points Median Filter. int64_t last_delays_ms_[kMedian]; // Used for Median Filter. }; diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/nada_unittest.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/nada_unittest.cc index 300c800f55..b637eed679 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/nada_unittest.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/nada_unittest.cc @@ -435,7 +435,7 @@ TEST_F(NadaReceiverSideTest, PacketLossSinglePacket) { TEST_F(NadaReceiverSideTest, PacketLossContiguousPackets) { const int64_t kTimeWindowMs = NadaBweReceiver::kPacketLossTimeWindowMs; - const int kSetCapacity = NadaBweReceiver::kSetCapacity; + size_t set_capacity = nada_receiver_.GetSetCapacity(); for (int i = 0; i < 10; ++i) { uint16_t sequence_number = static_cast(i); @@ -465,7 +465,7 @@ TEST_F(NadaReceiverSideTest, PacketLossContiguousPackets) { EXPECT_EQ(nada_receiver_.RecentPacketLossRatio(), 0.0f); // Should handle set overflow. - for (int i = 0; i < kSetCapacity * 1.5; ++i) { + for (int i = 0; i < set_capacity * 1.5; ++i) { uint16_t sequence_number = static_cast(i); const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); // Only the packets sent in this for loop will be considered. @@ -503,11 +503,11 @@ TEST_F(NadaReceiverSideTest, PacketLossDuplicatedPackets) { } TEST_F(NadaReceiverSideTest, PacketLossLakingPackets) { - const int kSetCapacity = NadaBweReceiver::kSetCapacity; - EXPECT_LT(kSetCapacity, 0xFFFF); + size_t set_capacity = nada_receiver_.GetSetCapacity(); + EXPECT_LT(set_capacity, static_cast(0xFFFF)); // Missing every other packet. - for (int i = 0; i < kSetCapacity; ++i) { + for (size_t i = 0; i < set_capacity; ++i) { if ((i & 1) == 0) { // Only even sequence numbers. uint16_t sequence_number = static_cast(i); const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); @@ -519,12 +519,12 @@ TEST_F(NadaReceiverSideTest, PacketLossLakingPackets) { } TEST_F(NadaReceiverSideTest, PacketLossLakingFewPackets) { - const int kSetCapacity = NadaBweReceiver::kSetCapacity; - EXPECT_LT(kSetCapacity, 0xFFFF); + size_t set_capacity = nada_receiver_.GetSetCapacity(); + EXPECT_LT(set_capacity, static_cast(0xFFFF)); const int kPeriod = 100; // Missing one for each kPeriod packets. - for (int i = 0; i < kSetCapacity; ++i) { + for (size_t i = 0; i < set_capacity; ++i) { if ((i % kPeriod) != 0) { uint16_t sequence_number = static_cast(i); const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); @@ -557,16 +557,16 @@ TEST_F(NadaReceiverSideTest, PacketLossWideGap) { // Packets arriving unordered should not be counted as losted. TEST_F(NadaReceiverSideTest, PacketLossUnorderedPackets) { - const int kNumPackets = NadaBweReceiver::kSetCapacity / 2; + int num_packets = nada_receiver_.GetSetCapacity() / 2; std::vector sequence_numbers; - for (int i = 0; i < kNumPackets; ++i) { + for (int i = 0; i < num_packets; ++i) { sequence_numbers.push_back(static_cast(i + 1)); } random_shuffle(sequence_numbers.begin(), sequence_numbers.end()); - for (int i = 0; i < kNumPackets; ++i) { + for (int i = 0; i < num_packets; ++i) { const MediaPacket media_packet(kFlowId, 0, 0, sequence_numbers[i]); // Arrival time = 0, all packets will be considered. nada_receiver_.ReceivePacket(0, media_packet); diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.cc index d1ba46a143..fe1a1cd5c2 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/remb.cc @@ -99,6 +99,10 @@ void RembReceiver::ReceivePacket(int64_t arrival_time_ms, media_packet.header()); clock_.AdvanceTimeMilliseconds(arrival_time_ms - clock_.TimeInMilliseconds()); ASSERT_TRUE(arrival_time_ms == clock_.TimeInMilliseconds()); + + received_packets_.Insert(media_packet.sequence_number(), + media_packet.send_time_ms(), arrival_time_ms, + media_packet.payload_size()); } FeedbackPacket* RembReceiver::GetFeedback(int64_t now_ms) { diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.cc index f7074d27e9..d7f03230e6 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/send_side.cc @@ -127,6 +127,10 @@ void SendSideBweReceiver::ReceivePacket(int64_t arrival_time_ms, packet_feedback_vector_.push_back(PacketInfo( arrival_time_ms, media_packet.sender_timestamp_us() / 1000, media_packet.header().sequenceNumber, media_packet.payload_size())); + + received_packets_.Insert(media_packet.sequence_number(), + media_packet.send_time_ms(), arrival_time_ms, + media_packet.payload_size()); } FeedbackPacket* SendSideBweReceiver::GetFeedback(int64_t now_ms) { diff --git a/webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.cc b/webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.cc index 4c16895564..154d68c520 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/estimators/tcp.cc @@ -35,6 +35,10 @@ void TcpBweReceiver::ReceivePacket(int64_t arrival_time_ms, const MediaPacket& media_packet) { latest_owd_ms_ = arrival_time_ms - media_packet.sender_timestamp_us() / 1000; acks_.push_back(media_packet.header().sequenceNumber); + + received_packets_.Insert(media_packet.sequence_number(), + media_packet.send_time_ms(), arrival_time_ms, + media_packet.payload_size()); } FeedbackPacket* TcpBweReceiver::GetFeedback(int64_t now_ms) { diff --git a/webrtc/modules/remote_bitrate_estimator/test/packet_receiver.cc b/webrtc/modules/remote_bitrate_estimator/test/packet_receiver.cc index aa429d03e9..c13f14437a 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/packet_receiver.cc +++ b/webrtc/modules/remote_bitrate_estimator/test/packet_receiver.cc @@ -10,6 +10,7 @@ #include "webrtc/modules/remote_bitrate_estimator/test/packet_receiver.h" +#include #include #include "testing/gtest/include/gtest/gtest.h" @@ -31,13 +32,32 @@ PacketReceiver::PacketReceiver(PacketProcessorListener* listener, bool plot_bwe) : PacketProcessor(listener, flow_id, kReceiver), delay_log_prefix_(), + metric_log_prefix_(), + packet_loss_log_prefix_(), last_delay_plot_ms_(0), + last_metric_plot_ms_(0), + last_packet_loss_plot_ms_(0), plot_delay_(plot_delay), - bwe_receiver_(CreateBweReceiver(bwe_type, flow_id, plot_bwe)) { + // TODO(magalhaesc) Add separated plot_objective_function and + // plot_packet_loss parameters to the constructor. + plot_objective_function_(plot_delay), + plot_packet_loss_(plot_delay), + bwe_receiver_(CreateBweReceiver(bwe_type, flow_id, plot_bwe)), + total_delay_ms_(0), + total_throughput_(0), + number_packets_(0) { // Setup the prefix ststd::rings used when logging. - std::stringstream ss; - ss << "Delay_" << flow_id << "#2"; - delay_log_prefix_ = ss.str(); + std::stringstream ss1; + ss1 << "Delay_" << flow_id << "#2"; + delay_log_prefix_ = ss1.str(); + + std::stringstream ss2; + ss2 << "Objective_function_" << flow_id << "#2"; + metric_log_prefix_ = ss2.str(); + + std::stringstream ss3; + ss3 << "Packet_Loss_" << flow_id << "#2"; + packet_loss_log_prefix_ = ss3.str(); } PacketReceiver::~PacketReceiver() { @@ -61,6 +81,12 @@ void PacketReceiver::RunFor(int64_t time_ms, Packets* in_out) { int64_t send_time_ms = (media_packet->creation_time_us() + 500) / 1000; delay_stats_.Push(arrival_time_ms - send_time_ms); PlotDelay(arrival_time_ms, send_time_ms); + PlotObjectiveFunction(arrival_time_ms); + PlotPacketLoss(arrival_time_ms); + + total_delay_ms_ += arrival_time_ms - send_time_ms; + total_throughput_ += media_packet->payload_size(); + ++number_packets_; bwe_receiver_->ReceivePacket(arrival_time_ms, *media_packet); FeedbackPacket* fb = bwe_receiver_->GetFeedback(arrival_time_ms); @@ -87,6 +113,37 @@ void PacketReceiver::PlotDelay(int64_t arrival_time_ms, int64_t send_time_ms) { } } +double PacketReceiver::ObjectiveFunction() { + const double kDelta = 1.0; // Delay penalty factor. + double throughput_metric = log(static_cast(total_throughput_)); + double delay_penalty = kDelta * log(static_cast(total_delay_ms_)); + return throughput_metric - delay_penalty; +} + +void PacketReceiver::PlotObjectiveFunction(int64_t arrival_time_ms) { + static const int kMetricPlotIntervalMs = 1000; + if (!plot_objective_function_) { + return; + } + if (arrival_time_ms - last_metric_plot_ms_ > kMetricPlotIntervalMs) { + BWE_TEST_LOGGING_PLOT(1, metric_log_prefix_, arrival_time_ms, + ObjectiveFunction()); + last_metric_plot_ms_ = arrival_time_ms; + } +} + +void PacketReceiver::PlotPacketLoss(int64_t arrival_time_ms) { + static const int kPacketLossPlotIntervalMs = 500; + if (!plot_packet_loss_) { + return; + } + if (arrival_time_ms - last_packet_loss_plot_ms_ > kPacketLossPlotIntervalMs) { + BWE_TEST_LOGGING_PLOT(2, packet_loss_log_prefix_, arrival_time_ms, + bwe_receiver_->RecentPacketLossRatio()); + last_packet_loss_plot_ms_ = arrival_time_ms; + } +} + Stats PacketReceiver::GetDelayStats() const { return delay_stats_; } diff --git a/webrtc/modules/remote_bitrate_estimator/test/packet_receiver.h b/webrtc/modules/remote_bitrate_estimator/test/packet_receiver.h index 0589d66b3b..a6838269c6 100644 --- a/webrtc/modules/remote_bitrate_estimator/test/packet_receiver.h +++ b/webrtc/modules/remote_bitrate_estimator/test/packet_receiver.h @@ -40,14 +40,27 @@ class PacketReceiver : public PacketProcessor { protected: void PlotDelay(int64_t arrival_time_ms, int64_t send_time_ms); + void PlotObjectiveFunction(int64_t arrival_time_ms); + void PlotPacketLoss(int64_t arrival_time_ms); + double ObjectiveFunction(); int64_t now_ms_; std::string delay_log_prefix_; + std::string metric_log_prefix_; + std::string packet_loss_log_prefix_; int64_t last_delay_plot_ms_; + int64_t last_metric_plot_ms_; + int64_t last_packet_loss_plot_ms_; bool plot_delay_; + bool plot_objective_function_; + bool plot_packet_loss_; Stats delay_stats_; rtc::scoped_ptr bwe_receiver_; + int64_t total_delay_ms_; + size_t total_throughput_; + int number_packets_; + private: DISALLOW_IMPLICIT_CONSTRUCTORS(PacketReceiver); };