/* * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_H_ #define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_H_ #include #include #include #include #include "webrtc/test/testsupport/gtest_prod_util.h" #include "webrtc/modules/remote_bitrate_estimator/test/packet.h" #include "webrtc/modules/bitrate_controller/include/bitrate_controller.h" #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h" namespace webrtc { namespace testing { namespace bwe { // Overload map comparator. class SequenceNumberOlderThan { public: bool operator()(uint16_t seq_num_1, uint16_t seq_num_2) const { return IsNewerSequenceNumber(seq_num_2, seq_num_1); } }; // Holds information for computing global packet loss. struct LossAccount { LossAccount() : num_total(0), num_lost(0) {} LossAccount(size_t num_total, size_t num_lost) : num_total(num_total), num_lost(num_lost) {} void Add(LossAccount rhs); void Subtract(LossAccount rhs); float LossRatio(); size_t num_total; size_t num_lost; }; // 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) {} ~LinkedSet(); // 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); void Insert(PacketIdentifierNode packet_identifier); PacketNodeIt begin() { return list_.begin(); } PacketNodeIt end() { return list_.end(); } bool empty() const { return list_.empty(); } size_t size() const { return list_.size(); } size_t capacity() const { return capacity_; } uint16_t OldestSeqNumber() const { return empty() ? 0 : map_.begin()->first; } uint16_t NewestSeqNumber() const { return empty() ? 0 : map_.rbegin()->first; } void Erase(PacketNodeIt node_it); 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 = 50; const int kMaxBitrateKbps = 2500; class BweSender : public Module { public: BweSender() {} explicit BweSender(int bitrate_kbps) : bitrate_kbps_(bitrate_kbps) {} virtual ~BweSender() {} virtual int GetFeedbackIntervalMs() const = 0; virtual void GiveFeedback(const FeedbackPacket& feedback) = 0; virtual void OnPacketsSent(const Packets& packets) = 0; protected: int bitrate_kbps_; private: RTC_DISALLOW_COPY_AND_ASSIGN(BweSender); }; class BweReceiver { public: explicit BweReceiver(int flow_id); BweReceiver(int flow_id, int64_t window_size_ms); virtual ~BweReceiver() {} virtual void ReceivePacket(int64_t arrival_time_ms, const MediaPacket& media_packet); virtual FeedbackPacket* GetFeedback(int64_t now_ms) { return NULL; } size_t GetSetCapacity() { return received_packets_.capacity(); } double BitrateWindowS() const { return rate_counter_.BitrateWindowS(); } uint32_t RecentKbps() const; // Receiving Rate. // Computes packet loss during an entire simulation, up to 4 billion packets. float GlobalReceiverPacketLossRatio(); // Plot histogram. float RecentPacketLossRatio(); // Plot dynamics. static const int64_t kPacketLossTimeWindowMs = 500; static const int64_t kReceivingRateTimeWindowMs = 1000; protected: int flow_id_; // Deals with packets sent more than once. LinkedSet received_packets_; // Used for calculating recent receiving rate. RateCounter rate_counter_; private: FRIEND_TEST_ALL_PREFIXES(BweReceiverTest, RecentKbps); FRIEND_TEST_ALL_PREFIXES(BweReceiverTest, Loss); void UpdateLoss(); void RelieveSetAndUpdateLoss(); // Packet loss for packets stored in the LinkedSet, up to 1000 packets. // Used to update global loss account whenever the set is filled and cleared. LossAccount LinkedSetPacketLossRatio(); // Used for calculating global packet loss ratio. LossAccount loss_account_; }; enum BandwidthEstimatorType { kNullEstimator, kNadaEstimator, kRembEstimator, kFullSendSideEstimator, kTcpEstimator }; const std::string bwe_names[] = {"Null", "NADA", "REMB", "GCC", "TCP"}; int64_t GetAbsSendTimeInMs(uint32_t abs_send_time); BweSender* CreateBweSender(BandwidthEstimatorType estimator, int kbps, BitrateObserver* observer, Clock* clock); BweReceiver* CreateBweReceiver(BandwidthEstimatorType type, int flow_id, bool plot); } // namespace bwe } // namespace testing } // namespace webrtc #endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_TEST_BWE_H_