| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| 11 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h" | 11 #include "webrtc/modules/remote_bitrate_estimator/test/estimators/nada.h" |
| 12 | 12 |
| 13 #include <algorithm> | 13 #include <algorithm> |
| 14 #include <numeric> | 14 #include <numeric> |
| 15 | 15 |
| 16 #include "webrtc/base/common.h" | 16 #include "webrtc/base/common.h" |
| 17 #include "webrtc/base/scoped_ptr.h" |
| 17 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h" | 18 #include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_framework.h" |
| 18 #include "webrtc/modules/remote_bitrate_estimator/test/packet.h" | 19 #include "webrtc/modules/remote_bitrate_estimator/test/packet.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 20 #include "webrtc/base/constructormagic.h" | 21 #include "webrtc/base/constructormagic.h" |
| 21 #include "webrtc/modules/remote_bitrate_estimator/test/packet_sender.h" | 22 #include "webrtc/modules/remote_bitrate_estimator/test/packet_sender.h" |
| 22 #include "webrtc/test/testsupport/fileutils.h" | 23 #include "webrtc/test/testsupport/fileutils.h" |
| 23 | 24 |
| 24 namespace webrtc { | 25 namespace webrtc { |
| 25 namespace testing { | 26 namespace testing { |
| 26 namespace bwe { | 27 namespace bwe { |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 | 106 |
| 106 private: | 107 private: |
| 107 TestBitrateObserver observer_; | 108 TestBitrateObserver observer_; |
| 108 SimulatedClock simulated_clock_; | 109 SimulatedClock simulated_clock_; |
| 109 | 110 |
| 110 protected: | 111 protected: |
| 111 NadaBweSender nada_sender_; | 112 NadaBweSender nada_sender_; |
| 112 }; | 113 }; |
| 113 | 114 |
| 114 class NadaReceiverSideTest : public ::testing::Test { | 115 class NadaReceiverSideTest : public ::testing::Test { |
| 115 protected: | 116 public: |
| 116 NadaReceiverSideTest() : nada_receiver_(kFlowId) {} | 117 NadaReceiverSideTest() : nada_receiver_(kFlowId) {} |
| 117 ~NadaReceiverSideTest() {} | 118 ~NadaReceiverSideTest() {} |
| 118 | 119 |
| 119 const int kFlowId = 0; | 120 protected: |
| 121 const int kFlowId = 1; // Arbitrary. |
| 120 NadaBweReceiver nada_receiver_; | 122 NadaBweReceiver nada_receiver_; |
| 121 }; | 123 }; |
| 122 | 124 |
| 123 class NadaFbGenerator { | 125 class NadaFbGenerator { |
| 124 public: | 126 public: |
| 125 NadaFbGenerator(); | 127 NadaFbGenerator(); |
| 126 | 128 |
| 127 static NadaFeedback NotCongestedFb(size_t receiving_rate, | 129 static NadaFeedback NotCongestedFb(size_t receiving_rate, |
| 128 int64_t ref_signal_ms, | 130 int64_t ref_signal_ms, |
| 129 int64_t send_time_ms) { | 131 int64_t send_time_ms) { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 158 } | 160 } |
| 159 | 161 |
| 160 private: | 162 private: |
| 161 // Arbitrary values, won't change these test results. | 163 // Arbitrary values, won't change these test results. |
| 162 static const int kFlowId = 2; | 164 static const int kFlowId = 2; |
| 163 static const int64_t kNowMs = 1000; | 165 static const int64_t kNowMs = 1000; |
| 164 }; | 166 }; |
| 165 | 167 |
| 166 // Verify if AcceleratedRampUp is called and that bitrate increases. | 168 // Verify if AcceleratedRampUp is called and that bitrate increases. |
| 167 TEST_F(NadaSenderSideTest, AcceleratedRampUp) { | 169 TEST_F(NadaSenderSideTest, AcceleratedRampUp) { |
| 168 const int64_t kRefSignalMs = 3; | 170 const int64_t kRefSignalMs = 1; |
| 169 const int64_t kOneWayDelayMs = 50; | 171 const int64_t kOneWayDelayMs = 50; |
| 170 int original_bitrate = 2 * NadaBweSender::kMinRefRateKbps; | 172 int original_bitrate = 2 * kMinBitrateKbps; |
| 171 size_t receiving_rate = static_cast<size_t>(original_bitrate); | 173 size_t receiving_rate = static_cast<size_t>(original_bitrate); |
| 172 int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; | 174 int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; |
| 173 | 175 |
| 174 NadaFeedback not_congested_fb = NadaFbGenerator::NotCongestedFb( | 176 NadaFeedback not_congested_fb = NadaFbGenerator::NotCongestedFb( |
| 175 receiving_rate, kRefSignalMs, send_time_ms); | 177 receiving_rate, kRefSignalMs, send_time_ms); |
| 176 | 178 |
| 177 nada_sender_.set_original_operating_mode(true); | 179 nada_sender_.set_original_operating_mode(true); |
| 178 nada_sender_.set_bitrate_kbps(original_bitrate); | 180 nada_sender_.set_bitrate_kbps(original_bitrate); |
| 179 | 181 |
| 180 // Trigger AcceleratedRampUp mode. | 182 // Trigger AcceleratedRampUp mode. |
| (...skipping 11 matching lines...) Expand all Loading... |
| 192 nada_sender_.GiveFeedback(not_congested_fb); | 194 nada_sender_.GiveFeedback(not_congested_fb); |
| 193 bitrate_1_kbps = nada_sender_.bitrate_kbps(); | 195 bitrate_1_kbps = nada_sender_.bitrate_kbps(); |
| 194 EXPECT_GT(bitrate_1_kbps, original_bitrate); | 196 EXPECT_GT(bitrate_1_kbps, original_bitrate); |
| 195 nada_sender_.AcceleratedRampUp(not_congested_fb); | 197 nada_sender_.AcceleratedRampUp(not_congested_fb); |
| 196 EXPECT_EQ(nada_sender_.bitrate_kbps(), bitrate_1_kbps); | 198 EXPECT_EQ(nada_sender_.bitrate_kbps(), bitrate_1_kbps); |
| 197 } | 199 } |
| 198 | 200 |
| 199 // Verify if AcceleratedRampDown is called and if bitrate decreases. | 201 // Verify if AcceleratedRampDown is called and if bitrate decreases. |
| 200 TEST_F(NadaSenderSideTest, AcceleratedRampDown) { | 202 TEST_F(NadaSenderSideTest, AcceleratedRampDown) { |
| 201 const int64_t kOneWayDelayMs = 50; | 203 const int64_t kOneWayDelayMs = 50; |
| 202 int original_bitrate = 3 * NadaBweSender::kMinRefRateKbps; | 204 int original_bitrate = 3 * kMinBitrateKbps; |
| 203 size_t receiving_rate = static_cast<size_t>(original_bitrate); | 205 size_t receiving_rate = static_cast<size_t>(original_bitrate); |
| 204 int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; | 206 int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; |
| 205 | 207 |
| 206 NadaFeedback congested_fb = | 208 NadaFeedback congested_fb = |
| 207 NadaFbGenerator::CongestedFb(receiving_rate, send_time_ms); | 209 NadaFbGenerator::CongestedFb(receiving_rate, send_time_ms); |
| 208 | 210 |
| 209 nada_sender_.set_original_operating_mode(false); | 211 nada_sender_.set_original_operating_mode(false); |
| 210 nada_sender_.set_bitrate_kbps(original_bitrate); | 212 nada_sender_.set_bitrate_kbps(original_bitrate); |
| 211 nada_sender_.GiveFeedback(congested_fb); // Trigger AcceleratedRampDown mode. | 213 nada_sender_.GiveFeedback(congested_fb); // Trigger AcceleratedRampDown mode. |
| 212 int bitrate_1_kbps = nada_sender_.bitrate_kbps(); | 214 int bitrate_1_kbps = nada_sender_.bitrate_kbps(); |
| 213 EXPECT_LE(bitrate_1_kbps, original_bitrate * 0.9f + 0.5f); | 215 EXPECT_LE(bitrate_1_kbps, original_bitrate * 0.9f + 0.5f); |
| 214 EXPECT_LT(bitrate_1_kbps, original_bitrate); | 216 EXPECT_LT(bitrate_1_kbps, original_bitrate); |
| 215 | 217 |
| 216 // Updates the bitrate according to the receiving rate and other constant | 218 // Updates the bitrate according to the receiving rate and other constant |
| 217 // parameters. | 219 // parameters. |
| 218 nada_sender_.AcceleratedRampDown(congested_fb); | 220 nada_sender_.AcceleratedRampDown(congested_fb); |
| 219 int bitrate_2_kbps = | 221 int bitrate_2_kbps = std::max(nada_sender_.bitrate_kbps(), kMinBitrateKbps); |
| 220 std::max(nada_sender_.bitrate_kbps(), NadaBweSender::kMinRefRateKbps); | |
| 221 EXPECT_EQ(bitrate_2_kbps, bitrate_1_kbps); | 222 EXPECT_EQ(bitrate_2_kbps, bitrate_1_kbps); |
| 222 } | 223 } |
| 223 | 224 |
| 224 TEST_F(NadaSenderSideTest, GradualRateUpdate) { | 225 TEST_F(NadaSenderSideTest, GradualRateUpdate) { |
| 225 const int64_t kDeltaSMs = 20; | 226 const int64_t kDeltaSMs = 20; |
| 226 const int64_t kRefSignalMs = 20; | 227 const int64_t kRefSignalMs = 20; |
| 227 const int64_t kOneWayDelayMs = 50; | 228 const int64_t kOneWayDelayMs = 50; |
| 228 int original_bitrate = 2 * NadaBweSender::kMinRefRateKbps; | 229 int original_bitrate = 2 * kMinBitrateKbps; |
| 229 size_t receiving_rate = static_cast<size_t>(original_bitrate); | 230 size_t receiving_rate = static_cast<size_t>(original_bitrate); |
| 230 int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; | 231 int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; |
| 231 | 232 |
| 232 NadaFeedback congested_fb = | 233 NadaFeedback congested_fb = |
| 233 NadaFbGenerator::CongestedFb(receiving_rate, send_time_ms); | 234 NadaFbGenerator::CongestedFb(receiving_rate, send_time_ms); |
| 234 NadaFeedback not_congested_fb = NadaFbGenerator::NotCongestedFb( | 235 NadaFeedback not_congested_fb = NadaFbGenerator::NotCongestedFb( |
| 235 original_bitrate, kRefSignalMs, send_time_ms); | 236 original_bitrate, kRefSignalMs, send_time_ms); |
| 236 | 237 |
| 237 nada_sender_.set_bitrate_kbps(original_bitrate); | 238 nada_sender_.set_bitrate_kbps(original_bitrate); |
| 238 double smoothing_factor = 0.0; | 239 double smoothing_factor = 0.0; |
| 239 nada_sender_.GradualRateUpdate(congested_fb, kDeltaSMs, smoothing_factor); | 240 nada_sender_.GradualRateUpdate(congested_fb, kDeltaSMs, smoothing_factor); |
| 240 EXPECT_EQ(nada_sender_.bitrate_kbps(), original_bitrate); | 241 EXPECT_EQ(nada_sender_.bitrate_kbps(), original_bitrate); |
| 241 | 242 |
| 242 smoothing_factor = 1.0; | 243 smoothing_factor = 1.0; |
| 243 nada_sender_.GradualRateUpdate(congested_fb, kDeltaSMs, smoothing_factor); | 244 nada_sender_.GradualRateUpdate(congested_fb, kDeltaSMs, smoothing_factor); |
| 244 EXPECT_LT(nada_sender_.bitrate_kbps(), original_bitrate); | 245 EXPECT_LT(nada_sender_.bitrate_kbps(), original_bitrate); |
| 245 | 246 |
| 246 nada_sender_.set_bitrate_kbps(original_bitrate); | 247 nada_sender_.set_bitrate_kbps(original_bitrate); |
| 247 nada_sender_.GradualRateUpdate(not_congested_fb, kDeltaSMs, smoothing_factor); | 248 nada_sender_.GradualRateUpdate(not_congested_fb, kDeltaSMs, smoothing_factor); |
| 248 EXPECT_GT(nada_sender_.bitrate_kbps(), original_bitrate); | 249 EXPECT_GT(nada_sender_.bitrate_kbps(), original_bitrate); |
| 249 } | 250 } |
| 250 | 251 |
| 251 // Sending bitrate should decrease and reach its Min bound. | 252 // Sending bitrate should decrease and reach its Min bound. |
| 252 TEST_F(NadaSenderSideTest, VeryLowBandwith) { | 253 TEST_F(NadaSenderSideTest, VeryLowBandwith) { |
| 253 const int64_t kOneWayDelayMs = 50; | 254 const int64_t kOneWayDelayMs = 50; |
| 254 const int kMin = NadaBweSender::kMinRefRateKbps; | 255 |
| 255 size_t receiving_rate = static_cast<size_t>(kMin); | 256 size_t receiving_rate = static_cast<size_t>(kMinBitrateKbps); |
| 256 int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; | 257 int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; |
| 257 | 258 |
| 258 NadaFeedback extremely_congested_fb = | 259 NadaFeedback extremely_congested_fb = |
| 259 NadaFbGenerator::ExtremelyCongestedFb(receiving_rate, send_time_ms); | 260 NadaFbGenerator::ExtremelyCongestedFb(receiving_rate, send_time_ms); |
| 260 NadaFeedback congested_fb = | 261 NadaFeedback congested_fb = |
| 261 NadaFbGenerator::CongestedFb(receiving_rate, send_time_ms); | 262 NadaFbGenerator::CongestedFb(receiving_rate, send_time_ms); |
| 262 | 263 |
| 263 nada_sender_.set_bitrate_kbps(5 * kMin); | 264 nada_sender_.set_bitrate_kbps(5 * kMinBitrateKbps); |
| 264 nada_sender_.set_original_operating_mode(true); | 265 nada_sender_.set_original_operating_mode(true); |
| 265 for (int i = 0; i < 100; ++i) { | 266 for (int i = 0; i < 100; ++i) { |
| 266 // Trigger GradualRateUpdate mode. | 267 // Trigger GradualRateUpdate mode. |
| 267 nada_sender_.GiveFeedback(extremely_congested_fb); | 268 nada_sender_.GiveFeedback(extremely_congested_fb); |
| 268 } | 269 } |
| 269 // The original implementation doesn't allow the bitrate to stay at kMin, | 270 // The original implementation doesn't allow the bitrate to stay at kMin, |
| 270 // even if the congestion signal is very high. | 271 // even if the congestion signal is very high. |
| 271 EXPECT_GE(nada_sender_.bitrate_kbps(), kMin); | 272 EXPECT_GE(nada_sender_.bitrate_kbps(), kMinBitrateKbps); |
| 272 | 273 |
| 273 nada_sender_.set_original_operating_mode(false); | 274 nada_sender_.set_original_operating_mode(false); |
| 274 nada_sender_.set_bitrate_kbps(5 * kMin); | 275 nada_sender_.set_bitrate_kbps(5 * kMinBitrateKbps); |
| 275 | 276 |
| 276 for (int i = 0; i < 100; ++i) { | 277 for (int i = 0; i < 1000; ++i) { |
| 277 int previous_bitrate = nada_sender_.bitrate_kbps(); | 278 int previous_bitrate = nada_sender_.bitrate_kbps(); |
| 278 // Trigger AcceleratedRampDown mode. | 279 // Trigger AcceleratedRampDown mode. |
| 279 nada_sender_.GiveFeedback(congested_fb); | 280 nada_sender_.GiveFeedback(congested_fb); |
| 280 EXPECT_LE(nada_sender_.bitrate_kbps(), previous_bitrate); | 281 EXPECT_LE(nada_sender_.bitrate_kbps(), previous_bitrate); |
| 281 } | 282 } |
| 282 EXPECT_EQ(nada_sender_.bitrate_kbps(), kMin); | 283 EXPECT_EQ(nada_sender_.bitrate_kbps(), kMinBitrateKbps); |
| 283 } | 284 } |
| 284 | 285 |
| 285 // Sending bitrate should increase and reach its Max bound. | 286 // Sending bitrate should increase and reach its Max bound. |
| 286 TEST_F(NadaSenderSideTest, VeryHighBandwith) { | 287 TEST_F(NadaSenderSideTest, VeryHighBandwith) { |
| 287 const int64_t kOneWayDelayMs = 50; | 288 const int64_t kOneWayDelayMs = 50; |
| 288 const int kMax = NadaBweSender::kMaxRefRateKbps; | 289 const size_t kRecentReceivingRate = static_cast<size_t>(kMaxBitrateKbps); |
| 289 const size_t kRecentReceivingRate = static_cast<size_t>(kMax); | 290 const int64_t kRefSignalMs = 1; |
| 290 const int64_t kRefSignalMs = 5; | |
| 291 int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; | 291 int64_t send_time_ms = nada_sender_.NowMs() - kOneWayDelayMs; |
| 292 | 292 |
| 293 NadaFeedback not_congested_fb = NadaFbGenerator::NotCongestedFb( | 293 NadaFeedback not_congested_fb = NadaFbGenerator::NotCongestedFb( |
| 294 kRecentReceivingRate, kRefSignalMs, send_time_ms); | 294 kRecentReceivingRate, kRefSignalMs, send_time_ms); |
| 295 | 295 |
| 296 nada_sender_.set_original_operating_mode(true); | 296 nada_sender_.set_original_operating_mode(true); |
| 297 for (int i = 0; i < 100; ++i) { | 297 for (int i = 0; i < 100; ++i) { |
| 298 int previous_bitrate = nada_sender_.bitrate_kbps(); | 298 int previous_bitrate = nada_sender_.bitrate_kbps(); |
| 299 nada_sender_.GiveFeedback(not_congested_fb); | 299 nada_sender_.GiveFeedback(not_congested_fb); |
| 300 EXPECT_GE(nada_sender_.bitrate_kbps(), previous_bitrate); | 300 EXPECT_GE(nada_sender_.bitrate_kbps(), previous_bitrate); |
| 301 } | 301 } |
| 302 EXPECT_EQ(nada_sender_.bitrate_kbps(), kMax); | 302 EXPECT_EQ(nada_sender_.bitrate_kbps(), kMaxBitrateKbps); |
| 303 | 303 |
| 304 nada_sender_.set_original_operating_mode(false); | 304 nada_sender_.set_original_operating_mode(false); |
| 305 nada_sender_.set_bitrate_kbps(NadaBweSender::kMinRefRateKbps); | 305 nada_sender_.set_bitrate_kbps(kMinBitrateKbps); |
| 306 | 306 |
| 307 for (int i = 0; i < 100; ++i) { | 307 for (int i = 0; i < 100; ++i) { |
| 308 int previous_bitrate = nada_sender_.bitrate_kbps(); | 308 int previous_bitrate = nada_sender_.bitrate_kbps(); |
| 309 nada_sender_.GiveFeedback(not_congested_fb); | 309 nada_sender_.GiveFeedback(not_congested_fb); |
| 310 EXPECT_GE(nada_sender_.bitrate_kbps(), previous_bitrate); | 310 EXPECT_GE(nada_sender_.bitrate_kbps(), previous_bitrate); |
| 311 } | 311 } |
| 312 EXPECT_EQ(nada_sender_.bitrate_kbps(), kMax); | 312 EXPECT_EQ(nada_sender_.bitrate_kbps(), kMaxBitrateKbps); |
| 313 } | 313 } |
| 314 | 314 |
| 315 TEST_F(NadaReceiverSideTest, ReceivingRateNoPackets) { | 315 TEST_F(NadaReceiverSideTest, FeedbackInitialCases) { |
| 316 EXPECT_EQ(nada_receiver_.RecentReceivingRate(), static_cast<size_t>(0)); | 316 rtc::scoped_ptr<NadaFeedback> nada_feedback( |
| 317 static_cast<NadaFeedback*>(nada_receiver_.GetFeedback(0))); |
| 318 EXPECT_EQ(nada_feedback, nullptr); |
| 319 |
| 320 nada_feedback.reset( |
| 321 static_cast<NadaFeedback*>(nada_receiver_.GetFeedback(100))); |
| 322 EXPECT_EQ(nada_feedback->exp_smoothed_delay_ms(), -1); |
| 323 EXPECT_EQ(nada_feedback->est_queuing_delay_signal_ms(), 0L); |
| 324 EXPECT_EQ(nada_feedback->congestion_signal(), 0L); |
| 325 EXPECT_EQ(nada_feedback->derivative(), 0.0f); |
| 326 EXPECT_EQ(nada_feedback->receiving_rate(), 0.0f); |
| 317 } | 327 } |
| 318 | 328 |
| 319 TEST_F(NadaReceiverSideTest, ReceivingRateSinglePacket) { | 329 TEST_F(NadaReceiverSideTest, FeedbackEmptyQueues) { |
| 320 const size_t kPayloadSizeBytes = 500 * 1000; | 330 const int64_t kTimeGapMs = 50; // Between each packet. |
| 321 const int64_t kSendTimeUs = 300 * 1000; | 331 const int64_t kOneWayDelayMs = 50; |
| 322 const int64_t kArrivalTimeMs = kSendTimeUs / 1000 + 100; | |
| 323 const uint16_t kSequenceNumber = 1; | |
| 324 const int64_t kTimeWindowMs = NadaBweReceiver::kReceivingRateTimeWindowMs; | |
| 325 | 332 |
| 326 const MediaPacket media_packet(kFlowId, kSendTimeUs, kPayloadSizeBytes, | 333 // No added latency, delay = kOneWayDelayMs. |
| 327 kSequenceNumber); | 334 for (int i = 1; i < 10; ++i) { |
| 328 nada_receiver_.ReceivePacket(kArrivalTimeMs, media_packet); | |
| 329 | |
| 330 const size_t kReceivingRateKbps = 8 * kPayloadSizeBytes / kTimeWindowMs; | |
| 331 | |
| 332 EXPECT_EQ(nada_receiver_.RecentReceivingRate(), kReceivingRateKbps); | |
| 333 } | |
| 334 | |
| 335 TEST_F(NadaReceiverSideTest, ReceivingRateLargePackets) { | |
| 336 const size_t kPayloadSizeBytes = 3000 * 1000; | |
| 337 const int64_t kTimeGapMs = 3000; // Between each packet. | |
| 338 const int64_t kOneWayDelayMs = 1000; | |
| 339 | |
| 340 for (int i = 1; i < 5; ++i) { | |
| 341 int64_t send_time_us = i * kTimeGapMs * 1000; | 335 int64_t send_time_us = i * kTimeGapMs * 1000; |
| 342 int64_t arrival_time_ms = send_time_us / 1000 + kOneWayDelayMs; | 336 int64_t arrival_time_ms = send_time_us / 1000 + kOneWayDelayMs; |
| 343 uint16_t sequence_number = i; | 337 uint16_t sequence_number = static_cast<uint16_t>(i); |
| 344 const MediaPacket media_packet(kFlowId, send_time_us, kPayloadSizeBytes, | 338 // Payload sizes are not important here. |
| 345 sequence_number); | 339 const MediaPacket media_packet(kFlowId, send_time_us, 0, sequence_number); |
| 346 nada_receiver_.ReceivePacket(arrival_time_ms, media_packet); | 340 nada_receiver_.ReceivePacket(arrival_time_ms, media_packet); |
| 347 } | 341 } |
| 348 | 342 |
| 349 const size_t kReceivingRateKbps = 8 * kPayloadSizeBytes / kTimeGapMs; | 343 // Baseline delay will be equal kOneWayDelayMs. |
| 350 EXPECT_EQ(nada_receiver_.RecentReceivingRate(), kReceivingRateKbps); | 344 rtc::scoped_ptr<NadaFeedback> nada_feedback( |
| 345 static_cast<NadaFeedback*>(nada_receiver_.GetFeedback(500))); |
| 346 EXPECT_EQ(nada_feedback->exp_smoothed_delay_ms(), 0L); |
| 347 EXPECT_EQ(nada_feedback->est_queuing_delay_signal_ms(), 0L); |
| 348 EXPECT_EQ(nada_feedback->congestion_signal(), 0L); |
| 349 EXPECT_EQ(nada_feedback->derivative(), 0.0f); |
| 351 } | 350 } |
| 352 | 351 |
| 353 TEST_F(NadaReceiverSideTest, ReceivingRateSmallPackets) { | 352 TEST_F(NadaReceiverSideTest, FeedbackIncreasingDelay) { |
| 354 const size_t kPayloadSizeBytes = 100 * 1000; | 353 // Since packets are 100ms apart, each one corresponds to a feedback. |
| 355 const int64_t kTimeGapMs = 50; // Between each packet. | 354 const int64_t kTimeGapMs = 100; // Between each packet. |
| 356 const int64_t kOneWayDelayMs = 50; | |
| 357 | 355 |
| 358 for (int i = 1; i < 50; ++i) { | 356 // Raw delays are = [10 20 30 40 50 60 70 80] ms. |
| 359 int64_t send_time_us = i * kTimeGapMs * 1000; | 357 // Baseline delay will be 50 ms. |
| 360 int64_t arrival_time_ms = send_time_us / 1000 + kOneWayDelayMs; | 358 // Delay signals should be: [0 10 20 30 40 50 60 70] ms. |
| 361 uint16_t sequence_number = i; | 359 const int64_t kMedianFilteredDelaysMs[] = {0, 10, 10, 20, 20, 30, 40, 50}; |
| 362 const MediaPacket media_packet(kFlowId, send_time_us, kPayloadSizeBytes, | 360 const int kNumPackets = ARRAY_SIZE(kMedianFilteredDelaysMs); |
| 363 sequence_number); | 361 const float kAlpha = 0.1f; // Used for exponential smoothing. |
| 364 nada_receiver_.ReceivePacket(arrival_time_ms, media_packet); | 362 |
| 363 int64_t exp_smoothed_delays_ms[kNumPackets]; |
| 364 exp_smoothed_delays_ms[0] = kMedianFilteredDelaysMs[0]; |
| 365 |
| 366 for (int i = 1; i < kNumPackets; ++i) { |
| 367 exp_smoothed_delays_ms[i] = static_cast<int64_t>( |
| 368 kAlpha * kMedianFilteredDelaysMs[i] + |
| 369 (1.0f - kAlpha) * exp_smoothed_delays_ms[i - 1] + 0.5f); |
| 365 } | 370 } |
| 366 | 371 |
| 367 const size_t kReceivingRateKbps = 8 * kPayloadSizeBytes / kTimeGapMs; | 372 for (int i = 0; i < kNumPackets; ++i) { |
| 368 EXPECT_EQ(nada_receiver_.RecentReceivingRate(), kReceivingRateKbps); | 373 int64_t send_time_us = (i + 1) * kTimeGapMs * 1000; |
| 374 int64_t arrival_time_ms = send_time_us / 1000 + 10 * (i + 1); |
| 375 uint16_t sequence_number = static_cast<uint16_t>(i + 1); |
| 376 // Payload sizes are not important here. |
| 377 const MediaPacket media_packet(kFlowId, send_time_us, 0, sequence_number); |
| 378 nada_receiver_.ReceivePacket(arrival_time_ms, media_packet); |
| 379 |
| 380 rtc::scoped_ptr<NadaFeedback> nada_feedback(static_cast<NadaFeedback*>( |
| 381 nada_receiver_.GetFeedback(arrival_time_ms))); |
| 382 EXPECT_EQ(nada_feedback->exp_smoothed_delay_ms(), |
| 383 exp_smoothed_delays_ms[i]); |
| 384 // Since delay signals are lower than 50ms, they will not be non-linearly |
| 385 // warped. |
| 386 EXPECT_EQ(nada_feedback->est_queuing_delay_signal_ms(), |
| 387 exp_smoothed_delays_ms[i]); |
| 388 // Zero loss, congestion signal = queuing_delay |
| 389 EXPECT_EQ(nada_feedback->congestion_signal(), exp_smoothed_delays_ms[i]); |
| 390 if (i == 0) { |
| 391 EXPECT_NEAR(nada_feedback->derivative(), |
| 392 static_cast<float>(exp_smoothed_delays_ms[i]) / kTimeGapMs, |
| 393 0.005f); |
| 394 } else { |
| 395 EXPECT_NEAR(nada_feedback->derivative(), |
| 396 static_cast<float>(exp_smoothed_delays_ms[i] - |
| 397 exp_smoothed_delays_ms[i - 1]) / |
| 398 kTimeGapMs, |
| 399 0.005f); |
| 400 } |
| 401 } |
| 369 } | 402 } |
| 370 | 403 |
| 371 TEST_F(NadaReceiverSideTest, ReceivingRateIntermittentPackets) { | 404 int64_t Warp(int64_t input) { |
| 372 const size_t kPayloadSizeBytes = 100 * 1000; | 405 const int64_t kMinThreshold = 50; // Referred as d_th. |
| 373 const int64_t kTimeGapMs = 50; // Between each packet. | 406 const int64_t kMaxThreshold = 400; // Referred as d_max. |
| 374 const int64_t kFirstSendTimeMs = 0; | 407 if (input < kMinThreshold) { |
| 375 const int64_t kOneWayDelayMs = 50; | 408 return input; |
| 409 } else if (input < kMaxThreshold) { |
| 410 return static_cast<int64_t>( |
| 411 pow((static_cast<double>(kMaxThreshold - input)) / |
| 412 (kMaxThreshold - kMinThreshold), |
| 413 4.0) * |
| 414 kMinThreshold); |
| 415 } else { |
| 416 return 0L; |
| 417 } |
| 418 } |
| 376 | 419 |
| 377 // Gap between first and other packets | 420 TEST_F(NadaReceiverSideTest, FeedbackWarpedDelay) { |
| 378 const MediaPacket media_packet(kFlowId, kFirstSendTimeMs, kPayloadSizeBytes, | 421 // Since packets are 100ms apart, each one corresponds to a feedback. |
| 379 1); | 422 const int64_t kTimeGapMs = 100; // Between each packet. |
| 380 nada_receiver_.ReceivePacket(kFirstSendTimeMs + kOneWayDelayMs, media_packet); | |
| 381 | 423 |
| 382 const int64_t kDelayAfterFirstPacketMs = 1000; | 424 // Raw delays are = [50 250 450 650 850 1050 1250 1450] ms. |
| 383 const int kNumPackets = 5; // Small enough so that all packets are covered. | 425 // Baseline delay will be 50 ms. |
| 384 EXPECT_LT((kNumPackets - 2) * kTimeGapMs, | 426 // Delay signals should be: [0 200 400 600 800 1000 1200 1400] ms. |
| 385 NadaBweReceiver::kReceivingRateTimeWindowMs); | 427 const int64_t kMedianFilteredDelaysMs[] = { |
| 386 const int64_t kTimeWindowMs = | 428 0, 200, 200, 400, 400, 600, 800, 1000}; |
| 387 kDelayAfterFirstPacketMs + (kNumPackets - 2) * kTimeGapMs; | 429 const int kNumPackets = ARRAY_SIZE(kMedianFilteredDelaysMs); |
| 430 const float kAlpha = 0.1f; // Used for exponential smoothing. |
| 388 | 431 |
| 389 for (int i = 2; i <= kNumPackets; ++i) { | 432 int64_t exp_smoothed_delays_ms[kNumPackets]; |
| 390 int64_t send_time_us = | 433 exp_smoothed_delays_ms[0] = kMedianFilteredDelaysMs[0]; |
| 391 ((i - 2) * kTimeGapMs + kFirstSendTimeMs + kDelayAfterFirstPacketMs) * | 434 |
| 392 1000; | 435 for (int i = 1; i < kNumPackets; ++i) { |
| 393 int64_t arrival_time_ms = send_time_us / 1000 + kOneWayDelayMs; | 436 exp_smoothed_delays_ms[i] = static_cast<int64_t>( |
| 394 uint16_t sequence_number = i; | 437 kAlpha * kMedianFilteredDelaysMs[i] + |
| 395 const MediaPacket media_packet(kFlowId, send_time_us, kPayloadSizeBytes, | 438 (1.0f - kAlpha) * exp_smoothed_delays_ms[i - 1] + 0.5f); |
| 396 sequence_number); | |
| 397 nada_receiver_.ReceivePacket(arrival_time_ms, media_packet); | |
| 398 } | 439 } |
| 399 | 440 |
| 400 const size_t kTotalReceivedKb = 8 * kNumPackets * kPayloadSizeBytes; | 441 for (int i = 0; i < kNumPackets; ++i) { |
| 401 const int64_t kCorrectedTimeWindowMs = | 442 int64_t send_time_us = (i + 1) * kTimeGapMs * 1000; |
| 402 (kTimeWindowMs * kNumPackets) / (kNumPackets - 1); | 443 int64_t arrival_time_ms = send_time_us / 1000 + 50 + 200 * i; |
| 403 EXPECT_EQ(nada_receiver_.RecentReceivingRate(), | 444 uint16_t sequence_number = static_cast<uint16_t>(i + 1); |
| 404 kTotalReceivedKb / kCorrectedTimeWindowMs); | 445 // Payload sizes are not important here. |
| 405 } | 446 const MediaPacket media_packet(kFlowId, send_time_us, 0, sequence_number); |
| 447 nada_receiver_.ReceivePacket(arrival_time_ms, media_packet); |
| 406 | 448 |
| 407 TEST_F(NadaReceiverSideTest, ReceivingRateDuplicatedPackets) { | 449 rtc::scoped_ptr<NadaFeedback> nada_feedback(static_cast<NadaFeedback*>( |
| 408 const size_t kPayloadSizeBytes = 500 * 1000; | 450 nada_receiver_.GetFeedback(arrival_time_ms))); |
| 409 const int64_t kSendTimeUs = 300 * 1000; | 451 EXPECT_EQ(nada_feedback->exp_smoothed_delay_ms(), |
| 410 const int64_t kArrivalTimeMs = kSendTimeUs / 1000 + 100; | 452 exp_smoothed_delays_ms[i]); |
| 411 const uint16_t kSequenceNumber = 1; | 453 // Delays can be non-linearly warped. |
| 412 const int64_t kTimeWindowMs = NadaBweReceiver::kReceivingRateTimeWindowMs; | 454 EXPECT_EQ(nada_feedback->est_queuing_delay_signal_ms(), |
| 413 | 455 Warp(exp_smoothed_delays_ms[i])); |
| 414 // Insert the same packet twice. | 456 // Zero loss, congestion signal = queuing_delay |
| 415 for (int i = 0; i < 2; ++i) { | 457 EXPECT_EQ(nada_feedback->congestion_signal(), |
| 416 const MediaPacket media_packet(kFlowId, kSendTimeUs + 50 * i, | 458 Warp(exp_smoothed_delays_ms[i])); |
| 417 kPayloadSizeBytes, kSequenceNumber); | |
| 418 nada_receiver_.ReceivePacket(kArrivalTimeMs + 50 * i, media_packet); | |
| 419 } | 459 } |
| 420 // Should be counted only once. | |
| 421 const size_t kReceivingRateKbps = 8 * kPayloadSizeBytes / kTimeWindowMs; | |
| 422 | |
| 423 EXPECT_EQ(nada_receiver_.RecentReceivingRate(), kReceivingRateKbps); | |
| 424 } | |
| 425 | |
| 426 TEST_F(NadaReceiverSideTest, PacketLossNoPackets) { | |
| 427 EXPECT_EQ(nada_receiver_.RecentPacketLossRatio(), 0.0f); | |
| 428 } | |
| 429 | |
| 430 TEST_F(NadaReceiverSideTest, PacketLossSinglePacket) { | |
| 431 const MediaPacket media_packet(kFlowId, 0, 0, 0); | |
| 432 nada_receiver_.ReceivePacket(0, media_packet); | |
| 433 EXPECT_EQ(nada_receiver_.RecentPacketLossRatio(), 0.0f); | |
| 434 } | |
| 435 | |
| 436 TEST_F(NadaReceiverSideTest, PacketLossContiguousPackets) { | |
| 437 const int64_t kTimeWindowMs = NadaBweReceiver::kPacketLossTimeWindowMs; | |
| 438 size_t set_capacity = nada_receiver_.GetSetCapacity(); | |
| 439 | |
| 440 for (int i = 0; i < 10; ++i) { | |
| 441 uint16_t sequence_number = static_cast<uint16_t>(i); | |
| 442 // Sequence_number and flow_id are the only members that matter here. | |
| 443 const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); | |
| 444 // Arrival time = 0, all packets will be considered. | |
| 445 nada_receiver_.ReceivePacket(0, media_packet); | |
| 446 } | |
| 447 EXPECT_EQ(nada_receiver_.RecentPacketLossRatio(), 0.0f); | |
| 448 | |
| 449 for (int i = 30; i > 20; i--) { | |
| 450 uint16_t sequence_number = static_cast<uint16_t>(i); | |
| 451 // Sequence_number and flow_id are the only members that matter here. | |
| 452 const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); | |
| 453 // Only the packets sent in this for loop will be considered. | |
| 454 nada_receiver_.ReceivePacket(2 * kTimeWindowMs, media_packet); | |
| 455 } | |
| 456 EXPECT_EQ(nada_receiver_.RecentPacketLossRatio(), 0.0f); | |
| 457 | |
| 458 // Should handle uint16_t overflow. | |
| 459 for (int i = 0xFFFF - 10; i < 0xFFFF + 10; ++i) { | |
| 460 uint16_t sequence_number = static_cast<uint16_t>(i); | |
| 461 const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); | |
| 462 // Only the packets sent in this for loop will be considered. | |
| 463 nada_receiver_.ReceivePacket(4 * kTimeWindowMs, media_packet); | |
| 464 } | |
| 465 EXPECT_EQ(nada_receiver_.RecentPacketLossRatio(), 0.0f); | |
| 466 | |
| 467 // Should handle set overflow. | |
| 468 for (int i = 0; i < set_capacity * 1.5; ++i) { | |
| 469 uint16_t sequence_number = static_cast<uint16_t>(i); | |
| 470 const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); | |
| 471 // Only the packets sent in this for loop will be considered. | |
| 472 nada_receiver_.ReceivePacket(6 * kTimeWindowMs, media_packet); | |
| 473 } | |
| 474 EXPECT_EQ(nada_receiver_.RecentPacketLossRatio(), 0.0f); | |
| 475 } | |
| 476 | |
| 477 // Should handle duplicates. | |
| 478 TEST_F(NadaReceiverSideTest, PacketLossDuplicatedPackets) { | |
| 479 const int64_t kTimeWindowMs = NadaBweReceiver::kPacketLossTimeWindowMs; | |
| 480 | |
| 481 for (int i = 0; i < 10; ++i) { | |
| 482 const MediaPacket media_packet(kFlowId, 0, 0, 0); | |
| 483 // Arrival time = 0, all packets will be considered. | |
| 484 nada_receiver_.ReceivePacket(0, media_packet); | |
| 485 } | |
| 486 EXPECT_EQ(nada_receiver_.RecentPacketLossRatio(), 0.0f); | |
| 487 | |
| 488 // Missing the element 5. | |
| 489 const uint16_t kSequenceNumbers[] = {1, 2, 3, 4, 6, 7, 8}; | |
| 490 const int kNumPackets = ARRAY_SIZE(kSequenceNumbers); | |
| 491 | |
| 492 // Insert each sequence number twice. | |
| 493 for (int i = 0; i < 2; ++i) { | |
| 494 for (int j = 0; j < kNumPackets; j++) { | |
| 495 const MediaPacket media_packet(kFlowId, 0, 0, kSequenceNumbers[j]); | |
| 496 // Only the packets sent in this for loop will be considered. | |
| 497 nada_receiver_.ReceivePacket(2 * kTimeWindowMs, media_packet); | |
| 498 } | |
| 499 } | |
| 500 | |
| 501 EXPECT_NEAR(nada_receiver_.RecentPacketLossRatio(), 1.0f / (kNumPackets + 1), | |
| 502 0.1f / (kNumPackets + 1)); | |
| 503 } | |
| 504 | |
| 505 TEST_F(NadaReceiverSideTest, PacketLossLakingPackets) { | |
| 506 size_t set_capacity = nada_receiver_.GetSetCapacity(); | |
| 507 EXPECT_LT(set_capacity, static_cast<size_t>(0xFFFF)); | |
| 508 | |
| 509 // Missing every other packet. | |
| 510 for (size_t i = 0; i < set_capacity; ++i) { | |
| 511 if ((i & 1) == 0) { // Only even sequence numbers. | |
| 512 uint16_t sequence_number = static_cast<uint16_t>(i); | |
| 513 const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); | |
| 514 // Arrival time = 0, all packets will be considered. | |
| 515 nada_receiver_.ReceivePacket(0, media_packet); | |
| 516 } | |
| 517 } | |
| 518 EXPECT_NEAR(nada_receiver_.RecentPacketLossRatio(), 0.5f, 0.01f); | |
| 519 } | |
| 520 | |
| 521 TEST_F(NadaReceiverSideTest, PacketLossLakingFewPackets) { | |
| 522 size_t set_capacity = nada_receiver_.GetSetCapacity(); | |
| 523 EXPECT_LT(set_capacity, static_cast<size_t>(0xFFFF)); | |
| 524 | |
| 525 const int kPeriod = 100; | |
| 526 // Missing one for each kPeriod packets. | |
| 527 for (size_t i = 0; i < set_capacity; ++i) { | |
| 528 if ((i % kPeriod) != 0) { | |
| 529 uint16_t sequence_number = static_cast<uint16_t>(i); | |
| 530 const MediaPacket media_packet(kFlowId, 0, 0, sequence_number); | |
| 531 // Arrival time = 0, all packets will be considered. | |
| 532 nada_receiver_.ReceivePacket(0, media_packet); | |
| 533 } | |
| 534 } | |
| 535 EXPECT_NEAR(nada_receiver_.RecentPacketLossRatio(), 1.0f / kPeriod, | |
| 536 0.1f / kPeriod); | |
| 537 } | |
| 538 | |
| 539 // Packet's sequence numbers greatly apart, expect high loss. | |
| 540 TEST_F(NadaReceiverSideTest, PacketLossWideGap) { | |
| 541 const int64_t kTimeWindowMs = NadaBweReceiver::kPacketLossTimeWindowMs; | |
| 542 | |
| 543 const MediaPacket media_packet1(0, 0, 0, 1); | |
| 544 const MediaPacket media_packet2(0, 0, 0, 1000); | |
| 545 // Only these two packets will be considered. | |
| 546 nada_receiver_.ReceivePacket(0, media_packet1); | |
| 547 nada_receiver_.ReceivePacket(0, media_packet2); | |
| 548 EXPECT_NEAR(nada_receiver_.RecentPacketLossRatio(), 0.998f, 0.0001f); | |
| 549 | |
| 550 const MediaPacket media_packet3(0, 0, 0, 0); | |
| 551 const MediaPacket media_packet4(0, 0, 0, 0x8000); | |
| 552 // Only these two packets will be considered. | |
| 553 nada_receiver_.ReceivePacket(2 * kTimeWindowMs, media_packet3); | |
| 554 nada_receiver_.ReceivePacket(2 * kTimeWindowMs, media_packet4); | |
| 555 EXPECT_NEAR(nada_receiver_.RecentPacketLossRatio(), 0.99994f, 0.00001f); | |
| 556 } | |
| 557 | |
| 558 // Packets arriving unordered should not be counted as losted. | |
| 559 TEST_F(NadaReceiverSideTest, PacketLossUnorderedPackets) { | |
| 560 size_t num_packets = nada_receiver_.GetSetCapacity() / 2; | |
| 561 std::vector<uint16_t> sequence_numbers; | |
| 562 | |
| 563 for (size_t i = 0; i < num_packets; ++i) { | |
| 564 sequence_numbers.push_back(static_cast<uint16_t>(i + 1)); | |
| 565 } | |
| 566 | |
| 567 random_shuffle(sequence_numbers.begin(), sequence_numbers.end()); | |
| 568 | |
| 569 for (size_t i = 0; i < num_packets; ++i) { | |
| 570 const MediaPacket media_packet(kFlowId, 0, 0, sequence_numbers[i]); | |
| 571 // Arrival time = 0, all packets will be considered. | |
| 572 nada_receiver_.ReceivePacket(0, media_packet); | |
| 573 } | |
| 574 | |
| 575 EXPECT_EQ(nada_receiver_.RecentPacketLossRatio(), 0.0f); | |
| 576 } | 460 } |
| 577 | 461 |
| 578 TEST_F(FilterTest, MedianConstantArray) { | 462 TEST_F(FilterTest, MedianConstantArray) { |
| 579 MedianFilterConstantArray(); | 463 MedianFilterConstantArray(); |
| 580 for (int i = 0; i < kNumElements; ++i) { | 464 for (int i = 0; i < kNumElements; ++i) { |
| 581 EXPECT_EQ(median_filtered_[i], raw_signal_[i]); | 465 EXPECT_EQ(median_filtered_[i], raw_signal_[i]); |
| 582 } | 466 } |
| 583 } | 467 } |
| 584 | 468 |
| 585 TEST_F(FilterTest, MedianIntermittentNoise) { | 469 TEST_F(FilterTest, MedianIntermittentNoise) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 602 for (int i = 1; i < kNumElements; ++i) { | 486 for (int i = 1; i < kNumElements; ++i) { |
| 603 EXPECT_EQ( | 487 EXPECT_EQ( |
| 604 exp_smoothed[i], | 488 exp_smoothed[i], |
| 605 static_cast<int64_t>(exp_smoothed[i - 1] * (1.0f - kAlpha) + 0.5f)); | 489 static_cast<int64_t>(exp_smoothed[i - 1] * (1.0f - kAlpha) + 0.5f)); |
| 606 } | 490 } |
| 607 } | 491 } |
| 608 | 492 |
| 609 } // namespace bwe | 493 } // namespace bwe |
| 610 } // namespace testing | 494 } // namespace testing |
| 611 } // namespace webrtc | 495 } // namespace webrtc |
| OLD | NEW |