├── .gitignore ├── LICENSE ├── README.md └── WebRTC_QoS ├── WebRTC_QoS.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcuserdata │ │ └── volvetzhang.xcuserdatad │ │ └── UserInterfaceState.xcuserstate └── xcuserdata │ └── volvetzhang.xcuserdatad │ ├── xcdebugger │ └── Breakpoints_v2.xcbkptlist │ └── xcschemes │ ├── WebRTC_QoS.xcscheme │ └── xcschememanagement.plist └── WebRTC_QoS ├── Random.cpp ├── Random.hpp ├── aimd_rate_control.cpp ├── aimd_rate_control.hpp ├── inter_arrival.cpp ├── inter_arrival.hpp ├── main.mm ├── overuse_detector.cpp ├── overuse_detector.hpp ├── overuse_detector_test.cpp ├── overuse_detector_test.hpp ├── overuse_estimator.cpp └── overuse_estimator.hpp /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 volvet 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WebRTC_QoS 2 | To test WebRTC_QoS 3 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | D3A63EF41DB3A0B0005A6929 /* aimd_rate_control.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3A63EF21DB3A0B0005A6929 /* aimd_rate_control.cpp */; }; 11 | D3EAB2E61DAA915600D03621 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = D3EAB2E51DAA915600D03621 /* main.mm */; }; 12 | D3EAB2EE1DAA918E00D03621 /* overuse_estimator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3EAB2EC1DAA918E00D03621 /* overuse_estimator.cpp */; }; 13 | D3EAB2F11DAA97B500D03621 /* overuse_detector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3EAB2EF1DAA97B500D03621 /* overuse_detector.cpp */; }; 14 | D3F252991DAC8108001AA7E6 /* Random.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3F252971DAC8108001AA7E6 /* Random.cpp */; }; 15 | D3F2529C1DAC8459001AA7E6 /* overuse_detector_test.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3F2529A1DAC8459001AA7E6 /* overuse_detector_test.cpp */; }; 16 | D3F2529F1DAC9326001AA7E6 /* inter_arrival.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3F2529D1DAC9326001AA7E6 /* inter_arrival.cpp */; }; 17 | /* End PBXBuildFile section */ 18 | 19 | /* Begin PBXCopyFilesBuildPhase section */ 20 | D3EAB2E01DAA915600D03621 /* CopyFiles */ = { 21 | isa = PBXCopyFilesBuildPhase; 22 | buildActionMask = 2147483647; 23 | dstPath = /usr/share/man/man1/; 24 | dstSubfolderSpec = 0; 25 | files = ( 26 | ); 27 | runOnlyForDeploymentPostprocessing = 1; 28 | }; 29 | /* End PBXCopyFilesBuildPhase section */ 30 | 31 | /* Begin PBXFileReference section */ 32 | D3A63EF21DB3A0B0005A6929 /* aimd_rate_control.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = aimd_rate_control.cpp; sourceTree = ""; }; 33 | D3A63EF31DB3A0B0005A6929 /* aimd_rate_control.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = aimd_rate_control.hpp; sourceTree = ""; }; 34 | D3EAB2E21DAA915600D03621 /* WebRTC_QoS */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = WebRTC_QoS; sourceTree = BUILT_PRODUCTS_DIR; }; 35 | D3EAB2E51DAA915600D03621 /* main.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = ""; }; 36 | D3EAB2EC1DAA918E00D03621 /* overuse_estimator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = overuse_estimator.cpp; sourceTree = ""; }; 37 | D3EAB2ED1DAA918E00D03621 /* overuse_estimator.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = overuse_estimator.hpp; sourceTree = ""; }; 38 | D3EAB2EF1DAA97B500D03621 /* overuse_detector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = overuse_detector.cpp; sourceTree = ""; }; 39 | D3EAB2F01DAA97B500D03621 /* overuse_detector.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = overuse_detector.hpp; sourceTree = ""; }; 40 | D3F252971DAC8108001AA7E6 /* Random.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Random.cpp; sourceTree = ""; }; 41 | D3F252981DAC8108001AA7E6 /* Random.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = Random.hpp; sourceTree = ""; }; 42 | D3F2529A1DAC8459001AA7E6 /* overuse_detector_test.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = overuse_detector_test.cpp; sourceTree = ""; }; 43 | D3F2529B1DAC8459001AA7E6 /* overuse_detector_test.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = overuse_detector_test.hpp; sourceTree = ""; }; 44 | D3F2529D1DAC9326001AA7E6 /* inter_arrival.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inter_arrival.cpp; sourceTree = ""; }; 45 | D3F2529E1DAC9326001AA7E6 /* inter_arrival.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = inter_arrival.hpp; sourceTree = ""; }; 46 | /* End PBXFileReference section */ 47 | 48 | /* Begin PBXFrameworksBuildPhase section */ 49 | D3EAB2DF1DAA915600D03621 /* Frameworks */ = { 50 | isa = PBXFrameworksBuildPhase; 51 | buildActionMask = 2147483647; 52 | files = ( 53 | ); 54 | runOnlyForDeploymentPostprocessing = 0; 55 | }; 56 | /* End PBXFrameworksBuildPhase section */ 57 | 58 | /* Begin PBXGroup section */ 59 | D3EAB2D91DAA915600D03621 = { 60 | isa = PBXGroup; 61 | children = ( 62 | D3EAB2E41DAA915600D03621 /* WebRTC_QoS */, 63 | D3EAB2E31DAA915600D03621 /* Products */, 64 | ); 65 | sourceTree = ""; 66 | }; 67 | D3EAB2E31DAA915600D03621 /* Products */ = { 68 | isa = PBXGroup; 69 | children = ( 70 | D3EAB2E21DAA915600D03621 /* WebRTC_QoS */, 71 | ); 72 | name = Products; 73 | sourceTree = ""; 74 | }; 75 | D3EAB2E41DAA915600D03621 /* WebRTC_QoS */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | D3EAB2E51DAA915600D03621 /* main.mm */, 79 | D3EAB2EC1DAA918E00D03621 /* overuse_estimator.cpp */, 80 | D3EAB2ED1DAA918E00D03621 /* overuse_estimator.hpp */, 81 | D3EAB2EF1DAA97B500D03621 /* overuse_detector.cpp */, 82 | D3EAB2F01DAA97B500D03621 /* overuse_detector.hpp */, 83 | D3F252971DAC8108001AA7E6 /* Random.cpp */, 84 | D3F252981DAC8108001AA7E6 /* Random.hpp */, 85 | D3F2529A1DAC8459001AA7E6 /* overuse_detector_test.cpp */, 86 | D3F2529B1DAC8459001AA7E6 /* overuse_detector_test.hpp */, 87 | D3F2529D1DAC9326001AA7E6 /* inter_arrival.cpp */, 88 | D3F2529E1DAC9326001AA7E6 /* inter_arrival.hpp */, 89 | D3A63EF21DB3A0B0005A6929 /* aimd_rate_control.cpp */, 90 | D3A63EF31DB3A0B0005A6929 /* aimd_rate_control.hpp */, 91 | ); 92 | path = WebRTC_QoS; 93 | sourceTree = ""; 94 | }; 95 | /* End PBXGroup section */ 96 | 97 | /* Begin PBXNativeTarget section */ 98 | D3EAB2E11DAA915600D03621 /* WebRTC_QoS */ = { 99 | isa = PBXNativeTarget; 100 | buildConfigurationList = D3EAB2E91DAA915600D03621 /* Build configuration list for PBXNativeTarget "WebRTC_QoS" */; 101 | buildPhases = ( 102 | D3EAB2DE1DAA915600D03621 /* Sources */, 103 | D3EAB2DF1DAA915600D03621 /* Frameworks */, 104 | D3EAB2E01DAA915600D03621 /* CopyFiles */, 105 | ); 106 | buildRules = ( 107 | ); 108 | dependencies = ( 109 | ); 110 | name = WebRTC_QoS; 111 | productName = WebRTC_QoS; 112 | productReference = D3EAB2E21DAA915600D03621 /* WebRTC_QoS */; 113 | productType = "com.apple.product-type.tool"; 114 | }; 115 | /* End PBXNativeTarget section */ 116 | 117 | /* Begin PBXProject section */ 118 | D3EAB2DA1DAA915600D03621 /* Project object */ = { 119 | isa = PBXProject; 120 | attributes = { 121 | LastUpgradeCheck = 0730; 122 | ORGANIZATIONNAME = volvet; 123 | TargetAttributes = { 124 | D3EAB2E11DAA915600D03621 = { 125 | CreatedOnToolsVersion = 7.3; 126 | }; 127 | }; 128 | }; 129 | buildConfigurationList = D3EAB2DD1DAA915600D03621 /* Build configuration list for PBXProject "WebRTC_QoS" */; 130 | compatibilityVersion = "Xcode 3.2"; 131 | developmentRegion = English; 132 | hasScannedForEncodings = 0; 133 | knownRegions = ( 134 | en, 135 | ); 136 | mainGroup = D3EAB2D91DAA915600D03621; 137 | productRefGroup = D3EAB2E31DAA915600D03621 /* Products */; 138 | projectDirPath = ""; 139 | projectRoot = ""; 140 | targets = ( 141 | D3EAB2E11DAA915600D03621 /* WebRTC_QoS */, 142 | ); 143 | }; 144 | /* End PBXProject section */ 145 | 146 | /* Begin PBXSourcesBuildPhase section */ 147 | D3EAB2DE1DAA915600D03621 /* Sources */ = { 148 | isa = PBXSourcesBuildPhase; 149 | buildActionMask = 2147483647; 150 | files = ( 151 | D3A63EF41DB3A0B0005A6929 /* aimd_rate_control.cpp in Sources */, 152 | D3F2529C1DAC8459001AA7E6 /* overuse_detector_test.cpp in Sources */, 153 | D3F252991DAC8108001AA7E6 /* Random.cpp in Sources */, 154 | D3EAB2EE1DAA918E00D03621 /* overuse_estimator.cpp in Sources */, 155 | D3EAB2F11DAA97B500D03621 /* overuse_detector.cpp in Sources */, 156 | D3F2529F1DAC9326001AA7E6 /* inter_arrival.cpp in Sources */, 157 | D3EAB2E61DAA915600D03621 /* main.mm in Sources */, 158 | ); 159 | runOnlyForDeploymentPostprocessing = 0; 160 | }; 161 | /* End PBXSourcesBuildPhase section */ 162 | 163 | /* Begin XCBuildConfiguration section */ 164 | D3EAB2E71DAA915600D03621 /* Debug */ = { 165 | isa = XCBuildConfiguration; 166 | buildSettings = { 167 | ALWAYS_SEARCH_USER_PATHS = NO; 168 | CLANG_ANALYZER_NONNULL = YES; 169 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 170 | CLANG_CXX_LIBRARY = "libc++"; 171 | CLANG_ENABLE_MODULES = YES; 172 | CLANG_ENABLE_OBJC_ARC = YES; 173 | CLANG_WARN_BOOL_CONVERSION = YES; 174 | CLANG_WARN_CONSTANT_CONVERSION = YES; 175 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 176 | CLANG_WARN_EMPTY_BODY = YES; 177 | CLANG_WARN_ENUM_CONVERSION = YES; 178 | CLANG_WARN_INT_CONVERSION = YES; 179 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 180 | CLANG_WARN_UNREACHABLE_CODE = YES; 181 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 182 | CODE_SIGN_IDENTITY = "-"; 183 | COPY_PHASE_STRIP = NO; 184 | DEBUG_INFORMATION_FORMAT = dwarf; 185 | ENABLE_STRICT_OBJC_MSGSEND = YES; 186 | ENABLE_TESTABILITY = YES; 187 | GCC_C_LANGUAGE_STANDARD = gnu99; 188 | GCC_DYNAMIC_NO_PIC = NO; 189 | GCC_NO_COMMON_BLOCKS = YES; 190 | GCC_OPTIMIZATION_LEVEL = 0; 191 | GCC_PREPROCESSOR_DEFINITIONS = ( 192 | "DEBUG=1", 193 | "$(inherited)", 194 | ); 195 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 196 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 197 | GCC_WARN_UNDECLARED_SELECTOR = YES; 198 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 199 | GCC_WARN_UNUSED_FUNCTION = YES; 200 | GCC_WARN_UNUSED_VARIABLE = YES; 201 | MACOSX_DEPLOYMENT_TARGET = 10.11; 202 | MTL_ENABLE_DEBUG_INFO = YES; 203 | ONLY_ACTIVE_ARCH = YES; 204 | SDKROOT = macosx; 205 | }; 206 | name = Debug; 207 | }; 208 | D3EAB2E81DAA915600D03621 /* Release */ = { 209 | isa = XCBuildConfiguration; 210 | buildSettings = { 211 | ALWAYS_SEARCH_USER_PATHS = NO; 212 | CLANG_ANALYZER_NONNULL = YES; 213 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 214 | CLANG_CXX_LIBRARY = "libc++"; 215 | CLANG_ENABLE_MODULES = YES; 216 | CLANG_ENABLE_OBJC_ARC = YES; 217 | CLANG_WARN_BOOL_CONVERSION = YES; 218 | CLANG_WARN_CONSTANT_CONVERSION = YES; 219 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 220 | CLANG_WARN_EMPTY_BODY = YES; 221 | CLANG_WARN_ENUM_CONVERSION = YES; 222 | CLANG_WARN_INT_CONVERSION = YES; 223 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 224 | CLANG_WARN_UNREACHABLE_CODE = YES; 225 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 226 | CODE_SIGN_IDENTITY = "-"; 227 | COPY_PHASE_STRIP = NO; 228 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 229 | ENABLE_NS_ASSERTIONS = NO; 230 | ENABLE_STRICT_OBJC_MSGSEND = YES; 231 | GCC_C_LANGUAGE_STANDARD = gnu99; 232 | GCC_NO_COMMON_BLOCKS = YES; 233 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 234 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 235 | GCC_WARN_UNDECLARED_SELECTOR = YES; 236 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 237 | GCC_WARN_UNUSED_FUNCTION = YES; 238 | GCC_WARN_UNUSED_VARIABLE = YES; 239 | MACOSX_DEPLOYMENT_TARGET = 10.11; 240 | MTL_ENABLE_DEBUG_INFO = NO; 241 | SDKROOT = macosx; 242 | }; 243 | name = Release; 244 | }; 245 | D3EAB2EA1DAA915600D03621 /* Debug */ = { 246 | isa = XCBuildConfiguration; 247 | buildSettings = { 248 | PRODUCT_NAME = "$(TARGET_NAME)"; 249 | }; 250 | name = Debug; 251 | }; 252 | D3EAB2EB1DAA915600D03621 /* Release */ = { 253 | isa = XCBuildConfiguration; 254 | buildSettings = { 255 | PRODUCT_NAME = "$(TARGET_NAME)"; 256 | }; 257 | name = Release; 258 | }; 259 | /* End XCBuildConfiguration section */ 260 | 261 | /* Begin XCConfigurationList section */ 262 | D3EAB2DD1DAA915600D03621 /* Build configuration list for PBXProject "WebRTC_QoS" */ = { 263 | isa = XCConfigurationList; 264 | buildConfigurations = ( 265 | D3EAB2E71DAA915600D03621 /* Debug */, 266 | D3EAB2E81DAA915600D03621 /* Release */, 267 | ); 268 | defaultConfigurationIsVisible = 0; 269 | defaultConfigurationName = Release; 270 | }; 271 | D3EAB2E91DAA915600D03621 /* Build configuration list for PBXNativeTarget "WebRTC_QoS" */ = { 272 | isa = XCConfigurationList; 273 | buildConfigurations = ( 274 | D3EAB2EA1DAA915600D03621 /* Debug */, 275 | D3EAB2EB1DAA915600D03621 /* Release */, 276 | ); 277 | defaultConfigurationIsVisible = 0; 278 | defaultConfigurationName = Release; 279 | }; 280 | /* End XCConfigurationList section */ 281 | }; 282 | rootObject = D3EAB2DA1DAA915600D03621 /* Project object */; 283 | } 284 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/volvet/WebRTC_QoS/bc1ac3d16907b346f03c8feb1c32e2a7da9d522c/WebRTC_QoS/WebRTC_QoS.xcodeproj/project.xcworkspace/xcuserdata/volvetzhang.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 8 | 18 | 19 | 20 | 22 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/WebRTC_QoS.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 32 | 33 | 39 | 40 | 41 | 42 | 43 | 44 | 54 | 56 | 62 | 63 | 64 | 65 | 66 | 67 | 73 | 75 | 81 | 82 | 83 | 84 | 86 | 87 | 90 | 91 | 92 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS.xcodeproj/xcuserdata/volvetzhang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | WebRTC_QoS.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | D3EAB2E11DAA915600D03621 16 | 17 | primary 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/Random.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // Random.cpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/11. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #include "Random.hpp" 10 | 11 | 12 | /* 13 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 14 | * 15 | * Use of this source code is governed by a BSD-style license 16 | * that can be found in the LICENSE file in the root of the source 17 | * tree. An additional intellectual property rights grant can be found 18 | * in the file PATENTS. All contributing project authors may 19 | * be found in the AUTHORS file in the root of the source tree. 20 | */ 21 | #include 22 | 23 | //#include "webrtc/base/checks.h" 24 | 25 | namespace webrtc { 26 | 27 | Random::Random(uint64_t seed) { 28 | //RTC_DCHECK(seed != 0x0ull); 29 | state_ = seed; 30 | } 31 | 32 | uint32_t Random::Rand(uint32_t t) { 33 | // Casting the output to 32 bits will give an almost uniform number. 34 | // Pr[x=0] = (2^32-1) / (2^64-1) 35 | // Pr[x=k] = 2^32 / (2^64-1) for k!=0 36 | // Uniform would be Pr[x=k] = 2^32 / 2^64 for all 32-bit integers k. 37 | uint32_t x = NextOutput(); 38 | // If x / 2^32 is uniform on [0,1), then x / 2^32 * (t+1) is uniform on 39 | // the interval [0,t+1), so the integer part is uniform on [0,t]. 40 | uint64_t result = x * (static_cast(t) + 1); 41 | result >>= 32; 42 | return result; 43 | } 44 | 45 | uint32_t Random::Rand(uint32_t low, uint32_t high) { 46 | //RTC_DCHECK(low <= high); 47 | return Rand(high - low) + low; 48 | } 49 | 50 | int32_t Random::Rand(int32_t low, int32_t high) { 51 | //RTC_DCHECK(low <= high); 52 | // We rely on subtraction (and addition) to be the same for signed and 53 | // unsigned numbers in two-complement representation. Thus, although 54 | // high - low might be negative as an int, it is the correct difference 55 | // when interpreted as an unsigned. 56 | return Rand(high - low) + low; 57 | } 58 | 59 | template <> 60 | float Random::Rand() { 61 | double result = NextOutput() - 1; 62 | result = result / 0xFFFFFFFFFFFFFFFEull; 63 | return static_cast(result); 64 | } 65 | 66 | template <> 67 | double Random::Rand() { 68 | double result = NextOutput() - 1; 69 | result = result / 0xFFFFFFFFFFFFFFFEull; 70 | return result; 71 | } 72 | 73 | template <> 74 | bool Random::Rand() { 75 | return Rand(0, 1) == 1; 76 | } 77 | 78 | double Random::Gaussian(double mean, double standard_deviation) { 79 | // Creating a Normal distribution variable from two independent uniform 80 | // variables based on the Box-Muller transform, which is defined on the 81 | // interval (0, 1]. Note that we rely on NextOutput to generate integers 82 | // in the range [1, 2^64-1]. Normally this behavior is a bit frustrating, 83 | // but here it is exactly what we need. 84 | const double kPi = 3.14159265358979323846; 85 | double u1 = static_cast(NextOutput()) / 0xFFFFFFFFFFFFFFFFull; 86 | double u2 = static_cast(NextOutput()) / 0xFFFFFFFFFFFFFFFFull; 87 | return mean + standard_deviation * sqrt(-2 * log(u1)) * cos(2 * kPi * u2); 88 | } 89 | 90 | double Random::Exponential(double lambda) { 91 | double uniform = Rand(); 92 | return -log(uniform) / lambda; 93 | } 94 | 95 | } // namespace webrtc 96 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/Random.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // Random.hpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/11. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | 10 | /* 11 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 12 | * 13 | * Use of this source code is governed by a BSD-style license 14 | * that can be found in the LICENSE file in the root of the source 15 | * tree. An additional intellectual property rights grant can be found 16 | * in the file PATENTS. All contributing project authors may 17 | * be found in the AUTHORS file in the root of the source tree. 18 | */ 19 | 20 | #ifndef WEBRTC_BASE_RANDOM_H_ 21 | #define WEBRTC_BASE_RANDOM_H_ 22 | 23 | #include 24 | #include 25 | 26 | //#include "webrtc/typedefs.h" 27 | //#include "webrtc/base/constructormagic.h" 28 | //#include "webrtc/base/checks.h" 29 | 30 | #define RTC_DISALLOW_ASSIGN(TypeName) \ 31 | void operator=(const TypeName &) = delete 32 | #define RTC_DISALLOW_COPY_AND_ASSIGN(TypeName) \ 33 | TypeName(const TypeName &) = delete; \ 34 | RTC_DISALLOW_ASSIGN(TypeName) 35 | #define RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \ 36 | TypeName() = delete; \ 37 | RTC_DISALLOW_COPY_AND_ASSIGN(TypeName) 38 | 39 | namespace webrtc { 40 | 41 | class Random { 42 | public: 43 | // TODO(tommi): Change this so that the seed can be initialized internally, 44 | // e.g. by offering two ways of constructing or offer a static method that 45 | // returns a seed that's suitable for initialization. 46 | // The problem now is that callers are calling clock_->TimeInMicroseconds() 47 | // which calls TickTime::Now().Ticks(), which can return a very low value on 48 | // Mac and can result in a seed of 0 after conversion to microseconds. 49 | // Besides the quality of the random seed being poor, this also requires 50 | // the client to take on extra dependencies to generate a seed. 51 | // If we go for a static seed generator in Random, we can use something from 52 | // webrtc/base and make sure that it works the same way across platforms. 53 | // See also discussion here: https://codereview.webrtc.org/1623543002/ 54 | explicit Random(uint64_t seed); 55 | 56 | // Return pseudo-random integer of the specified type. 57 | // We need to limit the size to 32 bits to keep the output close to uniform. 58 | template 59 | T Rand() { 60 | static_assert(std::numeric_limits::is_integer && 61 | std::numeric_limits::radix == 2 && 62 | std::numeric_limits::digits <= 32, 63 | "Rand is only supported for built-in integer types that are " 64 | "32 bits or smaller."); 65 | return static_cast(NextOutput()); 66 | } 67 | 68 | // Uniformly distributed pseudo-random number in the interval [0, t]. 69 | uint32_t Rand(uint32_t t); 70 | 71 | // Uniformly distributed pseudo-random number in the interval [low, high]. 72 | uint32_t Rand(uint32_t low, uint32_t high); 73 | 74 | // Uniformly distributed pseudo-random number in the interval [low, high]. 75 | int32_t Rand(int32_t low, int32_t high); 76 | 77 | // Normal Distribution. 78 | double Gaussian(double mean, double standard_deviation); 79 | 80 | // Exponential Distribution. 81 | double Exponential(double lambda); 82 | 83 | private: 84 | // Outputs a nonzero 64-bit random number. 85 | uint64_t NextOutput() { 86 | state_ ^= state_ >> 12; 87 | state_ ^= state_ << 25; 88 | state_ ^= state_ >> 27; 89 | //RTC_DCHECK(state_ != 0x0ULL); 90 | return state_ * 2685821657736338717ull; 91 | } 92 | 93 | uint64_t state_; 94 | 95 | RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(Random); 96 | }; 97 | 98 | // Return pseudo-random number in the interval [0.0, 1.0). 99 | template <> 100 | float Random::Rand(); 101 | 102 | // Return pseudo-random number in the interval [0.0, 1.0). 103 | template <> 104 | double Random::Rand(); 105 | 106 | // Return pseudo-random boolean value. 107 | template <> 108 | bool Random::Rand(); 109 | 110 | } // namespace webrtc 111 | 112 | #endif // WEBRTC_BASE_RANDOM_H_ 113 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/aimd_rate_control.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // aimd_rate_control.cpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/16. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #include "aimd_rate_control.hpp" 10 | 11 | /* 12 | * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 13 | * 14 | * Use of this source code is governed by a BSD-style license 15 | * that can be found in the LICENSE file in the root of the source 16 | * tree. An additional intellectual property rights grant can be found 17 | * in the file PATENTS. All contributing project authors may 18 | * be found in the AUTHORS file in the root of the source tree. 19 | */ 20 | 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | namespace webrtc { 27 | 28 | static const int64_t kDefaultRttMs = 200; 29 | static const int64_t kLogIntervalMs = 1000; 30 | static const double kWithinIncomingBitrateHysteresis = 1.05; 31 | static const int64_t kMaxFeedbackIntervalMs = 1000; 32 | static const int kDefaultMinBitrateBps = 30000; 33 | 34 | AimdRateControl::AimdRateControl() 35 | : min_configured_bitrate_bps_(kDefaultMinBitrateBps), 36 | max_configured_bitrate_bps_(30000000), 37 | current_bitrate_bps_(max_configured_bitrate_bps_), 38 | avg_max_bitrate_kbps_(-1.0f), 39 | var_max_bitrate_kbps_(0.4f), 40 | rate_control_state_(kRcHold), 41 | rate_control_region_(kRcMaxUnknown), 42 | time_last_bitrate_change_(-1), 43 | current_input_(kBwNormal, 0, 1.0), 44 | updated_(false), 45 | time_first_incoming_estimate_(-1), 46 | bitrate_is_initialized_(false), 47 | beta_(0.85f), 48 | rtt_(kDefaultRttMs), 49 | time_of_last_log_(-1), 50 | in_experiment_(!AdaptiveThresholdExperimentIsDisabled()) {} 51 | 52 | void AimdRateControl::SetMinBitrate(int min_bitrate_bps) { 53 | min_configured_bitrate_bps_ = min_bitrate_bps; 54 | current_bitrate_bps_ = std::max(min_bitrate_bps, current_bitrate_bps_); 55 | } 56 | 57 | bool AimdRateControl::ValidEstimate() const { 58 | return bitrate_is_initialized_; 59 | } 60 | 61 | int64_t AimdRateControl::GetFeedbackInterval() const { 62 | // Estimate how often we can send RTCP if we allocate up to 5% of bandwidth 63 | // to feedback. 64 | static const int kRtcpSize = 80; 65 | int64_t interval = static_cast( 66 | kRtcpSize * 8.0 * 1000.0 / (0.05 * current_bitrate_bps_) + 0.5); 67 | const int64_t kMinFeedbackIntervalMs = 200; 68 | return std::min(std::max(interval, kMinFeedbackIntervalMs), 69 | kMaxFeedbackIntervalMs); 70 | } 71 | 72 | bool AimdRateControl::TimeToReduceFurther(int64_t time_now, 73 | uint32_t incoming_bitrate_bps) const { 74 | const int64_t bitrate_reduction_interval = 75 | std::max(std::min(rtt_, 200), 10); 76 | if (time_now - time_last_bitrate_change_ >= bitrate_reduction_interval) { 77 | return true; 78 | } 79 | if (ValidEstimate()) { 80 | const int threshold = static_cast(kWithinIncomingBitrateHysteresis * 81 | incoming_bitrate_bps); 82 | const int bitrate_difference = LatestEstimate() - incoming_bitrate_bps; 83 | return bitrate_difference > threshold; 84 | } 85 | return false; 86 | } 87 | 88 | uint32_t AimdRateControl::LatestEstimate() const { 89 | return current_bitrate_bps_; 90 | } 91 | 92 | uint32_t AimdRateControl::UpdateBandwidthEstimate(int64_t now_ms) { 93 | current_bitrate_bps_ = ChangeBitrate(current_bitrate_bps_, 94 | current_input_.incoming_bitrate, now_ms); 95 | if (now_ms - time_of_last_log_ > kLogIntervalMs) { 96 | time_of_last_log_ = now_ms; 97 | } 98 | return current_bitrate_bps_; 99 | } 100 | 101 | void AimdRateControl::SetRtt(int64_t rtt) { 102 | rtt_ = rtt; 103 | } 104 | 105 | void AimdRateControl::Update(const RateControlInput* input, int64_t now_ms) { 106 | assert(input); 107 | 108 | // Set the initial bit rate value to what we're receiving the first half 109 | // second. 110 | if (!bitrate_is_initialized_) { 111 | const int64_t kInitializationTimeMs = 5000; 112 | //RTC_DCHECK_LE(kBitrateWindowMs, kInitializationTimeMs); 113 | if (time_first_incoming_estimate_ < 0) { 114 | if (input->incoming_bitrate > 0) { 115 | time_first_incoming_estimate_ = now_ms; 116 | } 117 | } else if (now_ms - time_first_incoming_estimate_ > kInitializationTimeMs && 118 | input->incoming_bitrate > 0) { 119 | current_bitrate_bps_ = input->incoming_bitrate; 120 | bitrate_is_initialized_ = true; 121 | } 122 | } 123 | 124 | if (updated_ && current_input_.bw_state == kBwOverusing) { 125 | // Only update delay factor and incoming bit rate. We always want to react 126 | // on an over-use. 127 | current_input_.noise_var = input->noise_var; 128 | current_input_.incoming_bitrate = input->incoming_bitrate; 129 | } else { 130 | updated_ = true; 131 | current_input_ = *input; 132 | } 133 | } 134 | 135 | void AimdRateControl::SetEstimate(int bitrate_bps, int64_t now_ms) { 136 | updated_ = true; 137 | bitrate_is_initialized_ = true; 138 | current_bitrate_bps_ = ChangeBitrate(bitrate_bps, bitrate_bps, now_ms); 139 | } 140 | 141 | uint32_t AimdRateControl::ChangeBitrate(uint32_t current_bitrate_bps, 142 | uint32_t incoming_bitrate_bps, 143 | int64_t now_ms) { 144 | if (!updated_) { 145 | return current_bitrate_bps_; 146 | } 147 | // An over-use should always trigger us to reduce the bitrate, even though 148 | // we have not yet established our first estimate. By acting on the over-use, 149 | // we will end up with a valid estimate. 150 | if (!bitrate_is_initialized_ && current_input_.bw_state != kBwOverusing) 151 | return current_bitrate_bps_; 152 | updated_ = false; 153 | ChangeState(current_input_, now_ms); 154 | // Calculated here because it's used in multiple places. 155 | const float incoming_bitrate_kbps = incoming_bitrate_bps / 1000.0f; 156 | // Calculate the max bit rate std dev given the normalized 157 | // variance and the current incoming bit rate. 158 | const float std_max_bit_rate = sqrt(var_max_bitrate_kbps_ * 159 | avg_max_bitrate_kbps_); 160 | switch (rate_control_state_) { 161 | case kRcHold: 162 | break; 163 | 164 | case kRcIncrease: 165 | if (avg_max_bitrate_kbps_ >= 0 && 166 | incoming_bitrate_kbps > 167 | avg_max_bitrate_kbps_ + 3 * std_max_bit_rate) { 168 | ChangeRegion(kRcMaxUnknown); 169 | avg_max_bitrate_kbps_ = -1.0; 170 | } 171 | if (rate_control_region_ == kRcNearMax) { 172 | // Approximate the over-use estimator delay to 100 ms. 173 | const int64_t response_time = rtt_ + 100; 174 | uint32_t additive_increase_bps = AdditiveRateIncrease( 175 | now_ms, time_last_bitrate_change_, response_time); 176 | current_bitrate_bps += additive_increase_bps; 177 | 178 | } else { 179 | uint32_t multiplicative_increase_bps = MultiplicativeRateIncrease( 180 | now_ms, time_last_bitrate_change_, current_bitrate_bps); 181 | current_bitrate_bps += multiplicative_increase_bps; 182 | } 183 | 184 | time_last_bitrate_change_ = now_ms; 185 | break; 186 | 187 | case kRcDecrease: 188 | bitrate_is_initialized_ = true; 189 | if (incoming_bitrate_bps < min_configured_bitrate_bps_) { 190 | current_bitrate_bps = min_configured_bitrate_bps_; 191 | } else { 192 | // Set bit rate to something slightly lower than max 193 | // to get rid of any self-induced delay. 194 | current_bitrate_bps = static_cast(beta_ * 195 | incoming_bitrate_bps + 0.5); 196 | if (current_bitrate_bps > current_bitrate_bps_) { 197 | // Avoid increasing the rate when over-using. 198 | if (rate_control_region_ != kRcMaxUnknown) { 199 | current_bitrate_bps = static_cast( 200 | beta_ * avg_max_bitrate_kbps_ * 1000 + 0.5f); 201 | } 202 | current_bitrate_bps = std::min(current_bitrate_bps, 203 | current_bitrate_bps_); 204 | } 205 | ChangeRegion(kRcNearMax); 206 | 207 | if (incoming_bitrate_kbps < avg_max_bitrate_kbps_ - 208 | 3 * std_max_bit_rate) { 209 | avg_max_bitrate_kbps_ = -1.0f; 210 | } 211 | 212 | UpdateMaxBitRateEstimate(incoming_bitrate_kbps); 213 | } 214 | // Stay on hold until the pipes are cleared. 215 | ChangeState(kRcHold); 216 | time_last_bitrate_change_ = now_ms; 217 | break; 218 | 219 | default: 220 | assert(false); 221 | } 222 | if ((incoming_bitrate_bps > 100000 || current_bitrate_bps > 150000) && 223 | current_bitrate_bps > 1.5 * incoming_bitrate_bps) { 224 | // Allow changing the bit rate if we are operating at very low rates 225 | // Don't change the bit rate if the send side is too far off 226 | current_bitrate_bps = current_bitrate_bps_; 227 | time_last_bitrate_change_ = now_ms; 228 | } 229 | return current_bitrate_bps; 230 | } 231 | 232 | uint32_t AimdRateControl::MultiplicativeRateIncrease( 233 | int64_t now_ms, int64_t last_ms, uint32_t current_bitrate_bps) const { 234 | double alpha = 1.08; 235 | if (last_ms > -1) { 236 | int time_since_last_update_ms = std::min(static_cast(now_ms - last_ms), 237 | 1000); 238 | alpha = pow(alpha, time_since_last_update_ms / 1000.0); 239 | } 240 | uint32_t multiplicative_increase_bps = std::max( 241 | current_bitrate_bps * (alpha - 1.0), 1000.0); 242 | return multiplicative_increase_bps; 243 | } 244 | 245 | uint32_t AimdRateControl::AdditiveRateIncrease( 246 | int64_t now_ms, int64_t last_ms, int64_t response_time_ms) const { 247 | assert(response_time_ms > 0); 248 | double beta = 0.0; 249 | if (last_ms > 0) { 250 | beta = std::min((now_ms - last_ms) / static_cast(response_time_ms), 251 | 1.0); 252 | if (in_experiment_) 253 | beta /= 2.0; 254 | } 255 | double bits_per_frame = static_cast(current_bitrate_bps_) / 30.0; 256 | double packets_per_frame = std::ceil(bits_per_frame / (8.0 * 1200.0)); 257 | double avg_packet_size_bits = bits_per_frame / packets_per_frame; 258 | uint32_t additive_increase_bps = std::max( 259 | 1000.0, beta * avg_packet_size_bits); 260 | return additive_increase_bps; 261 | } 262 | 263 | void AimdRateControl::UpdateMaxBitRateEstimate(float incoming_bitrate_kbps) { 264 | const float alpha = 0.05f; 265 | if (avg_max_bitrate_kbps_ == -1.0f) { 266 | avg_max_bitrate_kbps_ = incoming_bitrate_kbps; 267 | } else { 268 | avg_max_bitrate_kbps_ = (1 - alpha) * avg_max_bitrate_kbps_ + 269 | alpha * incoming_bitrate_kbps; 270 | } 271 | // Estimate the max bit rate variance and normalize the variance 272 | // with the average max bit rate. 273 | const float norm = std::max(avg_max_bitrate_kbps_, 1.0f); 274 | var_max_bitrate_kbps_ = (1 - alpha) * var_max_bitrate_kbps_ + 275 | alpha * (avg_max_bitrate_kbps_ - incoming_bitrate_kbps) * 276 | (avg_max_bitrate_kbps_ - incoming_bitrate_kbps) / norm; 277 | // 0.4 ~= 14 kbit/s at 500 kbit/s 278 | if (var_max_bitrate_kbps_ < 0.4f) { 279 | var_max_bitrate_kbps_ = 0.4f; 280 | } 281 | // 2.5f ~= 35 kbit/s at 500 kbit/s 282 | if (var_max_bitrate_kbps_ > 2.5f) { 283 | var_max_bitrate_kbps_ = 2.5f; 284 | } 285 | } 286 | 287 | void AimdRateControl::ChangeState(const RateControlInput& input, 288 | int64_t now_ms) { 289 | switch (current_input_.bw_state) { 290 | case kBwNormal: 291 | if (rate_control_state_ == kRcHold) { 292 | time_last_bitrate_change_ = now_ms; 293 | ChangeState(kRcIncrease); 294 | } 295 | break; 296 | case kBwOverusing: 297 | if (rate_control_state_ != kRcDecrease) { 298 | ChangeState(kRcDecrease); 299 | } 300 | break; 301 | case kBwUnderusing: 302 | ChangeState(kRcHold); 303 | break; 304 | default: 305 | assert(false); 306 | } 307 | } 308 | 309 | void AimdRateControl::ChangeRegion(RateControlRegion region) { 310 | rate_control_region_ = region; 311 | } 312 | 313 | void AimdRateControl::ChangeState(RateControlState new_state) { 314 | rate_control_state_ = new_state; 315 | } 316 | } // namespace webrtc 317 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/aimd_rate_control.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // aimd_rate_control.hpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/16. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | /* 10 | * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. 11 | * 12 | * Use of this source code is governed by a BSD-style license 13 | * that can be found in the LICENSE file in the root of the source 14 | * tree. An additional intellectual property rights grant can be found 15 | * in the file PATENTS. All contributing project authors may 16 | * be found in the AUTHORS file in the root of the source tree. 17 | */ 18 | 19 | #ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_AIMD_RATE_CONTROL_H_ 20 | #define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_AIMD_RATE_CONTROL_H_ 21 | 22 | #include 23 | #include "overuse_detector.hpp" 24 | 25 | namespace webrtc { 26 | 27 | struct RateControlInput { 28 | RateControlInput(BandwidthUsage bw_state, 29 | uint32_t incoming_bitrate, 30 | double noise_var) 31 | : bw_state(bw_state), 32 | incoming_bitrate(incoming_bitrate), 33 | noise_var(noise_var) {} 34 | 35 | BandwidthUsage bw_state; 36 | uint32_t incoming_bitrate; 37 | double noise_var; 38 | }; 39 | 40 | // A rate control implementation based on additive increases of 41 | // bitrate when no over-use is detected and multiplicative decreases when 42 | // over-uses are detected. When we think the available bandwidth has changes or 43 | // is unknown, we will switch to a "slow-start mode" where we increase 44 | // multiplicatively. 45 | class AimdRateControl { 46 | public: 47 | AimdRateControl(); 48 | virtual ~AimdRateControl() {} 49 | 50 | // Returns true if there is a valid estimate of the incoming bitrate, false 51 | // otherwise. 52 | bool ValidEstimate() const; 53 | void SetMinBitrate(int min_bitrate_bps); 54 | int64_t GetFeedbackInterval() const; 55 | // Returns true if the bitrate estimate hasn't been changed for more than 56 | // an RTT, or if the incoming_bitrate is more than 5% above the current 57 | // estimate. Should be used to decide if we should reduce the rate further 58 | // when over-using. 59 | bool TimeToReduceFurther(int64_t time_now, 60 | uint32_t incoming_bitrate_bps) const; 61 | uint32_t LatestEstimate() const; 62 | uint32_t UpdateBandwidthEstimate(int64_t now_ms); 63 | void SetRtt(int64_t rtt); 64 | void Update(const RateControlInput* input, int64_t now_ms); 65 | void SetEstimate(int bitrate_bps, int64_t now_ms); 66 | 67 | private: 68 | // Update the target bitrate according based on, among other things, 69 | // the current rate control state, the current target bitrate and the incoming 70 | // bitrate. When in the "increase" state the bitrate will be increased either 71 | // additively or multiplicatively depending on the rate control region. When 72 | // in the "decrease" state the bitrate will be decreased to slightly below the 73 | // incoming bitrate. When in the "hold" state the bitrate will be kept 74 | // constant to allow built up queues to drain. 75 | uint32_t ChangeBitrate(uint32_t current_bit_rate, 76 | uint32_t incoming_bit_rate, 77 | int64_t now_ms); 78 | uint32_t MultiplicativeRateIncrease(int64_t now_ms, int64_t last_ms, 79 | uint32_t current_bitrate_bps) const; 80 | uint32_t AdditiveRateIncrease(int64_t now_ms, int64_t last_ms, 81 | int64_t response_time_ms) const; 82 | void UpdateChangePeriod(int64_t now_ms); 83 | void UpdateMaxBitRateEstimate(float incoming_bit_rate_kbps); 84 | void ChangeState(const RateControlInput& input, int64_t now_ms); 85 | void ChangeState(RateControlState new_state); 86 | void ChangeRegion(RateControlRegion region); 87 | 88 | uint32_t min_configured_bitrate_bps_; 89 | uint32_t max_configured_bitrate_bps_; 90 | uint32_t current_bitrate_bps_; 91 | uint32_t max_hold_rate_bps_; 92 | float avg_max_bitrate_kbps_; 93 | float var_max_bitrate_kbps_; 94 | RateControlState rate_control_state_; 95 | RateControlRegion rate_control_region_; 96 | int64_t time_last_bitrate_change_; 97 | RateControlInput current_input_; 98 | bool updated_; 99 | int64_t time_first_incoming_estimate_; 100 | bool bitrate_is_initialized_; 101 | float beta_; 102 | int64_t rtt_; 103 | int64_t time_of_last_log_; 104 | bool in_experiment_; 105 | }; 106 | } // namespace webrtc 107 | 108 | #endif 109 | 110 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/inter_arrival.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // inter_arrival.cpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/11. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #include "inter_arrival.hpp" 10 | 11 | /* 12 | * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 13 | * 14 | * Use of this source code is governed by a BSD-style license 15 | * that can be found in the LICENSE file in the root of the source 16 | * tree. An additional intellectual property rights grant can be found 17 | * in the file PATENTS. All contributing project authors may 18 | * be found in the AUTHORS file in the root of the source tree. 19 | */ 20 | 21 | 22 | 23 | #include 24 | #include 25 | 26 | //#include "webrtc/base/logging.h" 27 | //#include "webrtc/modules/include/module_common_types.h" 28 | 29 | namespace webrtc { 30 | 31 | static const int kBurstDeltaThresholdMs = 5; 32 | 33 | 34 | inline bool IsNewerTimestamp(uint32_t timestamp, uint32_t prev_timestamp) { 35 | // Distinguish between elements that are exactly 0x80000000 apart. 36 | // If t1>t2 and |t1-t2| = 0x80000000: IsNewer(t1,t2)=true, 37 | // IsNewer(t2,t1)=false 38 | // rather than having IsNewer(t1,t2) = IsNewer(t2,t1) = false. 39 | if (static_cast(timestamp - prev_timestamp) == 0x80000000) { 40 | return timestamp > prev_timestamp; 41 | } 42 | return timestamp != prev_timestamp && 43 | static_cast(timestamp - prev_timestamp) < 0x80000000; 44 | } 45 | 46 | inline uint32_t LatestTimestamp(uint32_t timestamp1, uint32_t timestamp2) { 47 | return IsNewerTimestamp(timestamp1, timestamp2) ? timestamp1 : timestamp2; 48 | } 49 | 50 | 51 | InterArrival::InterArrival(uint32_t timestamp_group_length_ticks, 52 | double timestamp_to_ms_coeff, 53 | bool enable_burst_grouping) 54 | : kTimestampGroupLengthTicks(timestamp_group_length_ticks), 55 | current_timestamp_group_(), 56 | prev_timestamp_group_(), 57 | timestamp_to_ms_coeff_(timestamp_to_ms_coeff), 58 | burst_grouping_(enable_burst_grouping) {} 59 | 60 | bool InterArrival::ComputeDeltas(uint32_t timestamp, 61 | int64_t arrival_time_ms, 62 | size_t packet_size, 63 | uint32_t* timestamp_delta, 64 | int64_t* arrival_time_delta_ms, 65 | int* packet_size_delta) { 66 | assert(timestamp_delta != NULL); 67 | assert(arrival_time_delta_ms != NULL); 68 | assert(packet_size_delta != NULL); 69 | bool calculated_deltas = false; 70 | if (current_timestamp_group_.IsFirstPacket()) { 71 | // We don't have enough data to update the filter, so we store it until we 72 | // have two frames of data to process. 73 | current_timestamp_group_.timestamp = timestamp; 74 | current_timestamp_group_.first_timestamp = timestamp; 75 | } else if (!PacketInOrder(timestamp)) { 76 | return false; 77 | } else if (NewTimestampGroup(arrival_time_ms, timestamp)) { 78 | // First packet of a later frame, the previous frame sample is ready. 79 | if (prev_timestamp_group_.complete_time_ms >= 0) { 80 | *timestamp_delta = current_timestamp_group_.timestamp - 81 | prev_timestamp_group_.timestamp; 82 | *arrival_time_delta_ms = current_timestamp_group_.complete_time_ms - 83 | prev_timestamp_group_.complete_time_ms; 84 | if (*arrival_time_delta_ms < 0) { 85 | // The group of packets has been reordered since receiving its local 86 | // arrival timestamp. 87 | //LOG(LS_WARNING) << "Packets are being reordered on the path from the " 88 | //"socket to the bandwidth estimator. Ignoring this " 89 | //"packet for bandwidth estimation."; 90 | return false; 91 | } 92 | assert(*arrival_time_delta_ms >= 0); 93 | *packet_size_delta = static_cast(current_timestamp_group_.size) - 94 | static_cast(prev_timestamp_group_.size); 95 | calculated_deltas = true; 96 | } 97 | prev_timestamp_group_ = current_timestamp_group_; 98 | // The new timestamp is now the current frame. 99 | current_timestamp_group_.first_timestamp = timestamp; 100 | current_timestamp_group_.timestamp = timestamp; 101 | current_timestamp_group_.size = 0; 102 | } else { 103 | current_timestamp_group_.timestamp = LatestTimestamp( 104 | current_timestamp_group_.timestamp, timestamp); 105 | } 106 | // Accumulate the frame size. 107 | current_timestamp_group_.size += packet_size; 108 | current_timestamp_group_.complete_time_ms = arrival_time_ms; 109 | 110 | return calculated_deltas; 111 | } 112 | 113 | bool InterArrival::PacketInOrder(uint32_t timestamp) { 114 | if (current_timestamp_group_.IsFirstPacket()) { 115 | return true; 116 | } else { 117 | // Assume that a diff which is bigger than half the timestamp interval 118 | // (32 bits) must be due to reordering. This code is almost identical to 119 | // that in IsNewerTimestamp() in module_common_types.h. 120 | uint32_t timestamp_diff = timestamp - 121 | current_timestamp_group_.first_timestamp; 122 | return timestamp_diff < 0x80000000; 123 | } 124 | } 125 | 126 | // Assumes that |timestamp| is not reordered compared to 127 | // |current_timestamp_group_|. 128 | bool InterArrival::NewTimestampGroup(int64_t arrival_time_ms, 129 | uint32_t timestamp) const { 130 | if (current_timestamp_group_.IsFirstPacket()) { 131 | return false; 132 | } else if (BelongsToBurst(arrival_time_ms, timestamp)) { 133 | return false; 134 | } else { 135 | uint32_t timestamp_diff = timestamp - 136 | current_timestamp_group_.first_timestamp; 137 | return timestamp_diff > kTimestampGroupLengthTicks; 138 | } 139 | } 140 | 141 | bool InterArrival::BelongsToBurst(int64_t arrival_time_ms, 142 | uint32_t timestamp) const { 143 | if (!burst_grouping_) { 144 | return false; 145 | } 146 | assert(current_timestamp_group_.complete_time_ms >= 0); 147 | int64_t arrival_time_delta_ms = arrival_time_ms - 148 | current_timestamp_group_.complete_time_ms; 149 | uint32_t timestamp_diff = timestamp - current_timestamp_group_.timestamp; 150 | int64_t ts_delta_ms = timestamp_to_ms_coeff_ * timestamp_diff + 0.5; 151 | if (ts_delta_ms == 0) 152 | return true; 153 | int propagation_delta_ms = arrival_time_delta_ms - ts_delta_ms; 154 | return propagation_delta_ms < 0 && 155 | arrival_time_delta_ms <= kBurstDeltaThresholdMs; 156 | } 157 | } // namespace webrtc 158 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/inter_arrival.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // inter_arrival.hpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/11. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #ifndef inter_arrival_hpp 10 | #define inter_arrival_hpp 11 | 12 | #include 13 | 14 | 15 | /* 16 | * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 17 | * 18 | * Use of this source code is governed by a BSD-style license 19 | * that can be found in the LICENSE file in the root of the source 20 | * tree. An additional intellectual property rights grant can be found 21 | * in the file PATENTS. All contributing project authors may 22 | * be found in the AUTHORS file in the root of the source tree. 23 | */ 24 | 25 | #include 26 | #include 27 | #include "Random.hpp" 28 | //#include "webrtc/base/constructormagic.h" 29 | //#include "webrtc/typedefs.h" 30 | 31 | namespace webrtc { 32 | 33 | // Helper class to compute the inter-arrival time delta and the size delta 34 | // between two timestamp groups. A timestamp is a 32 bit unsigned number with 35 | // a client defined rate. 36 | class InterArrival { 37 | public: 38 | // A timestamp group is defined as all packets with a timestamp which are at 39 | // most timestamp_group_length_ticks older than the first timestamp in that 40 | // group. 41 | InterArrival(uint32_t timestamp_group_length_ticks, 42 | double timestamp_to_ms_coeff, 43 | bool enable_burst_grouping); 44 | 45 | // This function returns true if a delta was computed, or false if the current 46 | // group is still incomplete or if only one group has been completed. 47 | // |timestamp| is the timestamp. 48 | // |arrival_time_ms| is the local time at which the packet arrived. 49 | // |packet_size| is the size of the packet. 50 | // |timestamp_delta| (output) is the computed timestamp delta. 51 | // |arrival_time_delta_ms| (output) is the computed arrival-time delta. 52 | // |packet_size_delta| (output) is the computed size delta. 53 | bool ComputeDeltas(uint32_t timestamp, 54 | int64_t arrival_time_ms, 55 | size_t packet_size, 56 | uint32_t* timestamp_delta, 57 | int64_t* arrival_time_delta_ms, 58 | int* packet_size_delta); 59 | 60 | private: 61 | struct TimestampGroup { 62 | TimestampGroup() 63 | : size(0), 64 | first_timestamp(0), 65 | timestamp(0), 66 | complete_time_ms(-1) {} 67 | 68 | bool IsFirstPacket() const { 69 | return complete_time_ms == -1; 70 | } 71 | 72 | size_t size; 73 | uint32_t first_timestamp; 74 | uint32_t timestamp; 75 | int64_t complete_time_ms; 76 | }; 77 | 78 | // Returns true if the packet with timestamp |timestamp| arrived in order. 79 | bool PacketInOrder(uint32_t timestamp); 80 | 81 | // Returns true if the last packet was the end of the current batch and the 82 | // packet with |timestamp| is the first of a new batch. 83 | bool NewTimestampGroup(int64_t arrival_time_ms, uint32_t timestamp) const; 84 | 85 | bool BelongsToBurst(int64_t arrival_time_ms, uint32_t timestamp) const; 86 | 87 | const uint32_t kTimestampGroupLengthTicks; 88 | TimestampGroup current_timestamp_group_; 89 | TimestampGroup prev_timestamp_group_; 90 | double timestamp_to_ms_coeff_; 91 | bool burst_grouping_; 92 | 93 | RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(InterArrival); 94 | }; 95 | } // namespace webrtc 96 | 97 | #endif /* inter_arrival_hpp */ 98 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/main.mm: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/9. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "overuse_detector_test.hpp" 11 | 12 | using namespace webrtc; 13 | 14 | int QoSTest() 15 | { 16 | NSLog(@"WebRTC QoS Test"); 17 | OveruseDetectorTest overuseDetectorTest; 18 | 19 | NSLog(@"GaussionRandom"); 20 | overuseDetectorTest.GaussionRandom(); 21 | 22 | NSLog(@"SimpleNonOveruse"); 23 | overuseDetectorTest.SimpleNonOveruse30fps(); 24 | 25 | NSLog(@"SimpleNonOveruseWithReceiveVariance"); 26 | overuseDetectorTest.SimpleNonOveruseWithReceiveVariance(); 27 | 28 | NSLog(@"SimpleNonOveruseWithRtpTimevariance"); 29 | overuseDetectorTest.SimpleNonOveruseWithRtpTimevariance(); 30 | 31 | NSLog(@"SimpleOveruse2000kbit30fps"); 32 | overuseDetectorTest.SimpleOveruse2000kbit30fps(); 33 | 34 | NSLog(@"Test Done"); 35 | return 0; 36 | } 37 | 38 | 39 | 40 | int main(int argc, const char * argv[]) { 41 | @autoreleasepool { 42 | // insert code here... 43 | QoSTest(); 44 | } 45 | return 0; 46 | } 47 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/overuse_detector.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // overuse_detector.cpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/9. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #include "overuse_detector.hpp" 10 | 11 | /* 12 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 13 | * 14 | * Use of this source code is governed by a BSD-style license 15 | * that can be found in the LICENSE file in the root of the source 16 | * tree. An additional intellectual property rights grant can be found 17 | * in the file PATENTS. All contributing project authors may 18 | * be found in the AUTHORS file in the root of the source tree. 19 | */ 20 | 21 | 22 | #include 23 | #include 24 | 25 | #include 26 | #include 27 | #include 28 | 29 | //#include "webrtc/base/checks.h" 30 | //#include "webrtc/base/common.h" 31 | //#include "webrtc/modules/remote_bitrate_estimator/include/bwe_defines.h" 32 | //#include "webrtc/modules/remote_bitrate_estimator/test/bwe_test_logging.h" 33 | //#include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" 34 | //#include "webrtc/system_wrappers/include/field_trial.h" 35 | //#include "webrtc/system_wrappers/include/trace.h" 36 | 37 | namespace webrtc { 38 | /* 39 | const char kAdaptiveThresholdExperiment[] = "WebRTC-AdaptiveBweThreshold"; 40 | const char kEnabledPrefix[] = "Enabled"; 41 | const size_t kEnabledPrefixLength = sizeof(kEnabledPrefix) - 1; 42 | const char kDisabledPrefix[] = "Disabled"; 43 | const size_t kDisabledPrefixLength = sizeof(kDisabledPrefix) - 1; 44 | */ 45 | const double kMaxAdaptOffsetMs = 15.0; 46 | const double kOverUsingTimeThreshold = 10; 47 | 48 | bool AdaptiveThresholdExperimentIsDisabled() { 49 | //std::string experiment_string = 50 | //webrtc::field_trial::FindFullName(kAdaptiveThresholdExperiment); 51 | //const size_t kMinExperimentLength = kDisabledPrefixLength; 52 | //if (experiment_string.length() < kMinExperimentLength) 53 | // return false; 54 | //return experiment_string.substr(0, kDisabledPrefixLength) == kDisabledPrefix; 55 | return true; 56 | } 57 | 58 | // Gets thresholds from the experiment name following the format 59 | // "WebRTC-AdaptiveBweThreshold/Enabled-0.5,0.002/". 60 | bool ReadExperimentConstants(double* k_up, double* k_down) { 61 | //std::string experiment_string = 62 | //webrtc::field_trial::FindFullName(kAdaptiveThresholdExperiment); 63 | //const size_t kMinExperimentLength = kEnabledPrefixLength + 3; 64 | //if (experiment_string.length() < kMinExperimentLength || 65 | // experiment_string.substr(0, kEnabledPrefixLength) != kEnabledPrefix) 66 | // return false; 67 | //return sscanf(experiment_string.substr(kEnabledPrefixLength + 1).c_str(), 68 | // "%lf,%lf", k_up, k_down) == 2; 69 | return false; 70 | } 71 | 72 | OveruseDetector::OveruseDetector(const OverUseDetectorOptions& options) 73 | // Experiment is on by default, but can be disabled with finch by setting 74 | // the field trial string to "WebRTC-AdaptiveBweThreshold/Disabled/". 75 | : in_experiment_(!AdaptiveThresholdExperimentIsDisabled()), 76 | k_up_(0.004), 77 | k_down_(0.00006), 78 | overusing_time_threshold_(100), 79 | options_(options), 80 | threshold_(12.5), 81 | last_update_ms_(-1), 82 | prev_offset_(0.0), 83 | time_over_using_(-1), 84 | overuse_counter_(0), 85 | hypothesis_(kBwNormal) { 86 | if (!AdaptiveThresholdExperimentIsDisabled()) 87 | InitializeExperiment(); 88 | } 89 | 90 | OveruseDetector::~OveruseDetector() {} 91 | 92 | BandwidthUsage OveruseDetector::State() const { 93 | return hypothesis_; 94 | } 95 | 96 | BandwidthUsage OveruseDetector::Detect(double offset, 97 | double ts_delta, 98 | int num_of_deltas, 99 | int64_t now_ms) { 100 | if (num_of_deltas < 2) { 101 | return kBwNormal; 102 | } 103 | const double prev_offset = prev_offset_; 104 | prev_offset_ = offset; 105 | const double T = std::min(num_of_deltas, 60) * offset; 106 | //BWE_TEST_LOGGING_PLOT(1, "offset", now_ms, T); 107 | //BWE_TEST_LOGGING_PLOT(1, "threshold", now_ms, threshold_); 108 | if (T > threshold_) { 109 | if (time_over_using_ == -1) { 110 | // Initialize the timer. Assume that we've been 111 | // over-using half of the time since the previous 112 | // sample. 113 | time_over_using_ = ts_delta / 2; 114 | } else { 115 | // Increment timer 116 | time_over_using_ += ts_delta; 117 | } 118 | overuse_counter_++; 119 | if (time_over_using_ > overusing_time_threshold_ && overuse_counter_ > 1) { 120 | if (offset >= prev_offset) { 121 | time_over_using_ = 0; 122 | overuse_counter_ = 0; 123 | hypothesis_ = kBwOverusing; 124 | } 125 | } 126 | } else if (T < -threshold_) { 127 | time_over_using_ = -1; 128 | overuse_counter_ = 0; 129 | hypothesis_ = kBwUnderusing; 130 | } else { 131 | time_over_using_ = -1; 132 | overuse_counter_ = 0; 133 | hypothesis_ = kBwNormal; 134 | } 135 | 136 | UpdateThreshold(T, now_ms); 137 | 138 | return hypothesis_; 139 | } 140 | 141 | void OveruseDetector::UpdateThreshold(double modified_offset, int64_t now_ms) { 142 | if (!in_experiment_) 143 | return; 144 | 145 | if (last_update_ms_ == -1) 146 | last_update_ms_ = now_ms; 147 | 148 | if (fabs(modified_offset) > threshold_ + kMaxAdaptOffsetMs) { 149 | // Avoid adapting the threshold to big latency spikes, caused e.g., 150 | // by a sudden capacity drop. 151 | last_update_ms_ = now_ms; 152 | return; 153 | } 154 | 155 | const double k = fabs(modified_offset) < threshold_ ? k_down_ : k_up_; 156 | const int64_t kMaxTimeDeltaMs = 100; 157 | int64_t time_delta_ms = std::min(now_ms - last_update_ms_, kMaxTimeDeltaMs); 158 | threshold_ += 159 | k * (fabs(modified_offset) - threshold_) * time_delta_ms; 160 | 161 | const double kMinThreshold = 6; 162 | const double kMaxThreshold = 600; 163 | threshold_ = std::min(std::max(threshold_, kMinThreshold), kMaxThreshold); 164 | 165 | last_update_ms_ = now_ms; 166 | } 167 | 168 | void OveruseDetector::InitializeExperiment() { 169 | //RTC_DCHECK(in_experiment_); 170 | double k_up = 0.0; 171 | double k_down = 0.0; 172 | overusing_time_threshold_ = kOverUsingTimeThreshold; 173 | if (ReadExperimentConstants(&k_up, &k_down)) { 174 | k_up_ = k_up; 175 | k_down_ = k_down; 176 | } 177 | } 178 | } // namespace webrtc -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/overuse_detector.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // overuse_detector.hpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/9. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | /* 10 | * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 11 | * 12 | * Use of this source code is governed by a BSD-style license 13 | * that can be found in the LICENSE file in the root of the source 14 | * tree. An additional intellectual property rights grant can be found 15 | * in the file PATENTS. All contributing project authors may 16 | * be found in the AUTHORS file in the root of the source tree. 17 | */ 18 | #ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_OVERUSE_DETECTOR_H_ 19 | #define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_OVERUSE_DETECTOR_H_ 20 | 21 | #include 22 | #include "overuse_estimator.hpp" 23 | 24 | 25 | namespace webrtc { 26 | enum RateControlState { kRcHold, kRcIncrease, kRcDecrease }; 27 | 28 | enum RateControlRegion { kRcNearMax, kRcAboveMax, kRcMaxUnknown }; 29 | 30 | bool AdaptiveThresholdExperimentIsDisabled(); 31 | 32 | class OveruseDetector { 33 | public: 34 | explicit OveruseDetector(const OverUseDetectorOptions& options); 35 | virtual ~OveruseDetector(); 36 | 37 | // Update the detection state based on the estimated inter-arrival time delta 38 | // offset. |timestamp_delta| is the delta between the last timestamp which the 39 | // estimated offset is based on and the last timestamp on which the last 40 | // offset was based on, representing the time between detector updates. 41 | // |num_of_deltas| is the number of deltas the offset estimate is based on. 42 | // Returns the state after the detection update. 43 | BandwidthUsage Detect(double offset, 44 | double timestamp_delta, 45 | int num_of_deltas, 46 | int64_t now_ms); 47 | 48 | // Returns the current detector state. 49 | BandwidthUsage State() const; 50 | 51 | private: 52 | void UpdateThreshold(double modified_offset, int64_t now_ms); 53 | void InitializeExperiment(); 54 | 55 | bool in_experiment_; 56 | double k_up_; 57 | double k_down_; 58 | double overusing_time_threshold_; 59 | // Must be first member variable. Cannot be const because we need to be 60 | // copyable. 61 | webrtc::OverUseDetectorOptions options_; 62 | double threshold_; 63 | int64_t last_update_ms_; 64 | double prev_offset_; 65 | double time_over_using_; 66 | int overuse_counter_; 67 | BandwidthUsage hypothesis_; 68 | 69 | RTC_DISALLOW_COPY_AND_ASSIGN(OveruseDetector); 70 | }; 71 | } // namespace webrtc 72 | 73 | #endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_OVERUSE_DETECTOR_H_ 74 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/overuse_detector_test.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // overuse_detector_test.cpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/11. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #include 10 | #include 11 | #include "overuse_detector_test.hpp" 12 | 13 | using namespace std; 14 | 15 | namespace webrtc { 16 | 17 | const double KRTPTimestampToMS = 1.0/90.0; 18 | 19 | std::string BandwdithState2String(BandwidthUsage state) 20 | { 21 | if( state == kBwNormal ){ 22 | return "BW Normal"; 23 | } else if ( state == kBwOverusing ) { 24 | return "BW Overusing"; 25 | } 26 | return "BW Underusning"; 27 | } 28 | 29 | OveruseDetectorTest::OveruseDetectorTest() : mRandom(123456789) 30 | { 31 | OverUseDetectorOptions options; 32 | m_pInterArrival = new InterArrival(5*90, KRTPTimestampToMS, true); 33 | m_pOveruseEstimator = new OveruseEstimator(options); 34 | m_pOveruseDetector = new OveruseDetector(options); 35 | mNow = 0; 36 | mReceiveTimestamp = 0; 37 | mRTPTimestamp = 0; 38 | } 39 | 40 | OveruseDetectorTest::~OveruseDetectorTest() 41 | { 42 | if( m_pInterArrival ){ 43 | delete m_pInterArrival; 44 | m_pInterArrival = nullptr; 45 | } 46 | 47 | if( m_pOveruseDetector ) { 48 | delete m_pOveruseDetector; 49 | m_pOveruseDetector = nullptr; 50 | } 51 | 52 | if( m_pOveruseEstimator ){ 53 | delete m_pOveruseEstimator; 54 | m_pOveruseEstimator = nullptr; 55 | } 56 | } 57 | 58 | void OveruseDetectorTest::UpdateDetector(uint32_t rtp_timestamp, int64_t receive_timestamp, size_t packet_size) 59 | { 60 | uint32_t timestamp_delta; 61 | int64_t arrive_time_delta; 62 | int size_delta; 63 | 64 | if( m_pInterArrival->ComputeDeltas(rtp_timestamp, receive_timestamp, packet_size, ×tamp_delta, &arrive_time_delta, &size_delta)) { 65 | double timestamp_delta_ms = timestamp_delta / 90.0; 66 | m_pOveruseEstimator->Update(arrive_time_delta, timestamp_delta_ms, size_delta, m_pOveruseDetector->State()); 67 | m_pOveruseDetector->Detect(m_pOveruseEstimator->offset(), timestamp_delta_ms, m_pOveruseEstimator->num_of_deltas(), receive_timestamp); 68 | } 69 | } 70 | 71 | int OveruseDetectorTest::Run100000Samples(int packets_per_frame, size_t packet_size, int mean_ms, int standard_deviation_ms) { 72 | int unique_overuse = 0; 73 | int last_overuse = -1; 74 | 75 | for( int i=0;i<1000000;i++ ){ 76 | for( int j=0;j( 83 | mReceiveTimestamp, mNow + static_cast(mRandom.Gaussian(0, standard_deviation_ms) + 0.5) 84 | ); 85 | if( kBwOverusing == m_pOveruseDetector->State() ){ 86 | if( last_overuse + 1 != i ){ 87 | unique_overuse ++; 88 | } 89 | } 90 | } 91 | 92 | return unique_overuse; 93 | } 94 | 95 | int OveruseDetectorTest::RunUntilOveruse(int packets_per_frame, size_t packet_size, int mean_ms, int standard_deviation_ms, int drift_per_frame_ms) { 96 | for(int i=0;i<1000;i++ ){ 97 | for( int j=0;j( 104 | mReceiveTimestamp, mNow + static_cast(mRandom.Gaussian(0, standard_deviation_ms) + 0.5) 105 | ); 106 | if( kBwOverusing == m_pOveruseDetector->State() ){ 107 | return i+1; 108 | } 109 | //printf("%s\n", BandwdithState2String(m_pOveruseDetector->State()).c_str()); 110 | } 111 | 112 | return -1; 113 | } 114 | 115 | 116 | void OveruseDetectorTest::GaussionRandom() 117 | { 118 | const static int MAX_BUCKET_SIZE = 100; 119 | int buckets[MAX_BUCKET_SIZE]; 120 | 121 | memset(buckets, 0, sizeof(buckets)); 122 | for( int i=0;i<10000;i++ ){ 123 | int index = mRandom.Gaussian(49, 10); 124 | if( index >= 0 && index < MAX_BUCKET_SIZE ){ 125 | buckets[index] ++; 126 | } 127 | } 128 | for( int i=0;iState()); 146 | //printf("%s\n", BandwdithState2String(m_pOveruseDetector->State()).c_str()); 147 | } 148 | } 149 | 150 | void OveruseDetectorTest::SimpleNonOveruseWithReceiveVariance() 151 | { 152 | size_t packet_size = 1200; 153 | uint32_t rtp_timestamp = 10*90; 154 | uint32_t frame_duration_ms = 10; 155 | 156 | for( int i=0;i<1000;i++ ) { 157 | UpdateDetector(rtp_timestamp, mNow, packet_size); 158 | rtp_timestamp += frame_duration_ms * 90; 159 | if( i%2 ){ 160 | mNow += frame_duration_ms - 5; 161 | } else { 162 | mNow += frame_duration_ms + 5; 163 | } 164 | 165 | assert(kBwNormal == m_pOveruseDetector->State()); 166 | } 167 | } 168 | 169 | void OveruseDetectorTest::SimpleNonOveruseWithRtpTimevariance() { 170 | uint32_t frame_duration_ms = 10; 171 | uint32_t rtp_timestamp = 10*90; 172 | size_t packet_size = 1200; 173 | 174 | for( int i=0;i<1000;i++ ) { 175 | UpdateDetector(rtp_timestamp, mNow, packet_size); 176 | mNow += frame_duration_ms; 177 | if( i % 2 ){ 178 | rtp_timestamp += (frame_duration_ms - 5)*90; 179 | } else { 180 | rtp_timestamp += (frame_duration_ms + 5)*90; 181 | } 182 | 183 | assert(kBwNormal == m_pOveruseDetector->State()); 184 | } 185 | } 186 | 187 | void OveruseDetectorTest::SimpleOveruse2000kbit30fps() { 188 | size_t packet_size = 1200; 189 | int packets_per_frame = 6; 190 | int frame_duration_ms = 33; 191 | int drift_per_frame_ms = 1; 192 | int sigma_ms = 0; 193 | int unique_overuse = Run100000Samples(packets_per_frame, packet_size, frame_duration_ms, sigma_ms); 194 | 195 | assert( 0 == unique_overuse ); 196 | int frames_until_overuse = RunUntilOveruse(packets_per_frame, packet_size, frame_duration_ms, sigma_ms, drift_per_frame_ms); 197 | 198 | printf("frames_until_overuse = %d\n", frames_until_overuse); 199 | 200 | assert( -1 != frames_until_overuse); 201 | } 202 | 203 | 204 | 205 | } 206 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/overuse_detector_test.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // overuse_detector_test.hpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/11. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #ifndef overuse_detector_test_hpp 10 | #define overuse_detector_test_hpp 11 | 12 | #include 13 | #include "Random.hpp" 14 | #include "overuse_detector.hpp" 15 | #include "inter_arrival.hpp" 16 | 17 | namespace webrtc { 18 | 19 | class OveruseDetectorTest 20 | { 21 | public: 22 | OveruseDetectorTest(); 23 | virtual ~OveruseDetectorTest(); 24 | 25 | 26 | void GaussionRandom(); 27 | void SimpleNonOveruse30fps(); 28 | void SimpleNonOveruseWithReceiveVariance(); 29 | void SimpleNonOveruseWithRtpTimevariance(); 30 | void SimpleOveruse2000kbit30fps(); 31 | 32 | protected: 33 | void UpdateDetector(uint32_t rtp_timestamp, int64_t receive_timestamp, size_t packet_size); 34 | int Run100000Samples(int packets_per_frame, size_t packet_size, int mean_ms, int standard_deviation_ms); 35 | int RunUntilOveruse(int packets_per_frame, size_t packet_size, int mean_ms, int standard_deviation_ms, int drift_per_frame_ms); 36 | 37 | private: 38 | int64_t mNow; 39 | int64_t mReceiveTimestamp; 40 | uint32_t mRTPTimestamp; 41 | Random mRandom; 42 | OveruseDetector * m_pOveruseDetector; 43 | OveruseEstimator * m_pOveruseEstimator; 44 | InterArrival * m_pInterArrival; 45 | }; 46 | 47 | } 48 | 49 | #endif /* overuse_detector_test_hpp */ 50 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/overuse_estimator.cpp: -------------------------------------------------------------------------------- 1 | // 2 | // overuse_estimator.cpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/9. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | #include "overuse_estimator.hpp" 10 | /* 11 | * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 12 | * 13 | * Use of this source code is governed by a BSD-style license 14 | * that can be found in the LICENSE file in the root of the source 15 | * tree. An additional intellectual property rights grant can be found 16 | * in the file PATENTS. All contributing project authors may 17 | * be found in the AUTHORS file in the root of the source tree. 18 | */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | namespace webrtc { 27 | 28 | enum { kMinFramePeriodHistoryLength = 60 }; 29 | enum { kDeltaCounterMax = 1000 }; 30 | 31 | OveruseEstimator::OveruseEstimator(const OverUseDetectorOptions& options) 32 | : options_(options), 33 | num_of_deltas_(0), 34 | slope_(options_.initial_slope), 35 | offset_(options_.initial_offset), 36 | prev_offset_(options_.initial_offset), 37 | E_(), 38 | process_noise_(), 39 | avg_noise_(options_.initial_avg_noise), 40 | var_noise_(options_.initial_var_noise), 41 | ts_delta_hist_() { 42 | memcpy(E_, options_.initial_e, sizeof(E_)); 43 | memcpy(process_noise_, options_.initial_process_noise, 44 | sizeof(process_noise_)); 45 | } 46 | 47 | OveruseEstimator::~OveruseEstimator() { 48 | ts_delta_hist_.clear(); 49 | } 50 | 51 | void OveruseEstimator::Update(int64_t t_delta, 52 | double ts_delta, 53 | int size_delta, 54 | BandwidthUsage current_hypothesis) { 55 | const double min_frame_period = UpdateMinFramePeriod(ts_delta); 56 | const double t_ts_delta = t_delta - ts_delta; 57 | double fs_delta = size_delta; 58 | 59 | ++num_of_deltas_; 60 | if (num_of_deltas_ > kDeltaCounterMax) { 61 | num_of_deltas_ = kDeltaCounterMax; 62 | } 63 | 64 | // Update the Kalman filter. 65 | E_[0][0] += process_noise_[0]; 66 | E_[1][1] += process_noise_[1]; 67 | 68 | if ((current_hypothesis == kBwOverusing && offset_ < prev_offset_) || 69 | (current_hypothesis == kBwUnderusing && offset_ > prev_offset_)) { 70 | E_[1][1] += 10 * process_noise_[1]; 71 | } 72 | 73 | const double h[2] = {fs_delta, 1.0}; 74 | const double Eh[2] = {E_[0][0]*h[0] + E_[0][1]*h[1], 75 | E_[1][0]*h[0] + E_[1][1]*h[1]}; 76 | 77 | const double residual = t_ts_delta - slope_*h[0] - offset_; 78 | 79 | const bool in_stable_state = (current_hypothesis == kBwNormal); 80 | const double max_residual = 3.0 * sqrt(var_noise_); 81 | // We try to filter out very late frames. For instance periodic key 82 | // frames doesn't fit the Gaussian model well. 83 | if (fabs(residual) < max_residual) { 84 | UpdateNoiseEstimate(residual, min_frame_period, in_stable_state); 85 | } else { 86 | UpdateNoiseEstimate(residual < 0 ? -max_residual : max_residual, 87 | min_frame_period, in_stable_state); 88 | } 89 | 90 | const double denom = var_noise_ + h[0]*Eh[0] + h[1]*Eh[1]; 91 | 92 | const double K[2] = {Eh[0] / denom, 93 | Eh[1] / denom}; 94 | 95 | const double IKh[2][2] = {{1.0 - K[0]*h[0], -K[0]*h[1]}, 96 | {-K[1]*h[0], 1.0 - K[1]*h[1]}}; 97 | const double e00 = E_[0][0]; 98 | const double e01 = E_[0][1]; 99 | 100 | // Update state. 101 | E_[0][0] = e00 * IKh[0][0] + E_[1][0] * IKh[0][1]; 102 | E_[0][1] = e01 * IKh[0][0] + E_[1][1] * IKh[0][1]; 103 | E_[1][0] = e00 * IKh[1][0] + E_[1][0] * IKh[1][1]; 104 | E_[1][1] = e01 * IKh[1][0] + E_[1][1] * IKh[1][1]; 105 | 106 | // The covariance matrix must be positive semi-definite. 107 | bool positive_semi_definite = E_[0][0] + E_[1][1] >= 0 && 108 | E_[0][0] * E_[1][1] - E_[0][1] * E_[1][0] >= 0 && E_[0][0] >= 0; 109 | assert(positive_semi_definite); 110 | if (!positive_semi_definite) { 111 | printf("The over-use estimator's covariance matrix is no longer " 112 | "semi-definite."); 113 | } 114 | 115 | slope_ = slope_ + K[0] * residual; 116 | prev_offset_ = offset_; 117 | offset_ = offset_ + K[1] * residual; 118 | } 119 | 120 | double OveruseEstimator::UpdateMinFramePeriod(double ts_delta) { 121 | double min_frame_period = ts_delta; 122 | if (ts_delta_hist_.size() >= kMinFramePeriodHistoryLength) { 123 | ts_delta_hist_.pop_front(); 124 | } 125 | std::list::iterator it = ts_delta_hist_.begin(); 126 | for (; it != ts_delta_hist_.end(); it++) { 127 | min_frame_period = std::min(*it, min_frame_period); 128 | } 129 | ts_delta_hist_.push_back(ts_delta); 130 | return min_frame_period; 131 | } 132 | 133 | void OveruseEstimator::UpdateNoiseEstimate(double residual, 134 | double ts_delta, 135 | bool stable_state) { 136 | if (!stable_state) { 137 | return; 138 | } 139 | // Faster filter during startup to faster adapt to the jitter level 140 | // of the network. |alpha| is tuned for 30 frames per second, but is scaled 141 | // according to |ts_delta|. 142 | double alpha = 0.01; 143 | if (num_of_deltas_ > 10*30) { 144 | alpha = 0.002; 145 | } 146 | // Only update the noise estimate if we're not over-using. |beta| is a 147 | // function of alpha and the time delta since the previous update. 148 | const double beta = pow(1 - alpha, ts_delta * 30.0 / 1000.0); 149 | avg_noise_ = beta * avg_noise_ 150 | + (1 - beta) * residual; 151 | var_noise_ = beta * var_noise_ 152 | + (1 - beta) * (avg_noise_ - residual) * (avg_noise_ - residual); 153 | if (var_noise_ < 1) { 154 | var_noise_ = 1; 155 | } 156 | } 157 | } // namespace webrtc 158 | -------------------------------------------------------------------------------- /WebRTC_QoS/WebRTC_QoS/overuse_estimator.hpp: -------------------------------------------------------------------------------- 1 | // 2 | // overuse_estimator.hpp 3 | // WebRTC_QoS 4 | // 5 | // Created by Volvet Zhang on 16/10/9. 6 | // Copyright © 2016年 volvet. All rights reserved. 7 | // 8 | 9 | /* 10 | * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. 11 | * 12 | * Use of this source code is governed by a BSD-style license 13 | * that can be found in the LICENSE file in the root of the source 14 | * tree. An additional intellectual property rights grant can be found 15 | * in the file PATENTS. All contributing project authors may 16 | * be found in the AUTHORS file in the root of the source tree. 17 | */ 18 | #ifndef WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_OVERUSE_ESTIMATOR_H_ 19 | #define WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_OVERUSE_ESTIMATOR_H_ 20 | 21 | #include 22 | #include "Random.hpp" 23 | 24 | namespace webrtc { 25 | 26 | enum BandwidthUsage { 27 | kBwNormal = 0, 28 | kBwUnderusing = 1, 29 | kBwOverusing = 2, 30 | }; 31 | 32 | 33 | // Bandwidth over-use detector options. These are used to drive 34 | // experimentation with bandwidth estimation parameters. 35 | // See modules/remote_bitrate_estimator/overuse_detector.h 36 | struct OverUseDetectorOptions { 37 | OverUseDetectorOptions() 38 | : initial_slope(8.0/512.0), 39 | initial_offset(0), 40 | initial_e(), 41 | initial_process_noise(), 42 | initial_avg_noise(0.0), 43 | initial_var_noise(50) { 44 | initial_e[0][0] = 100; 45 | initial_e[1][1] = 1e-1; 46 | initial_e[0][1] = initial_e[1][0] = 0; 47 | initial_process_noise[0] = 1e-13; 48 | initial_process_noise[1] = 1e-3; 49 | } 50 | double initial_slope; 51 | double initial_offset; 52 | double initial_e[2][2]; 53 | double initial_process_noise[2]; 54 | double initial_avg_noise; 55 | double initial_var_noise; 56 | }; 57 | 58 | 59 | class OveruseEstimator { 60 | public: 61 | explicit OveruseEstimator(const OverUseDetectorOptions& options); 62 | ~OveruseEstimator(); 63 | 64 | // Update the estimator with a new sample. The deltas should represent deltas 65 | // between timestamp groups as defined by the InterArrival class. 66 | // |current_hypothesis| should be the hypothesis of the over-use detector at 67 | // this time. 68 | void Update(int64_t t_delta, double ts_delta, int size_delta, 69 | BandwidthUsage current_hypothesis); 70 | 71 | // Returns the estimated noise/jitter variance in ms^2. 72 | double var_noise() const { 73 | return var_noise_; 74 | } 75 | 76 | // Returns the estimated inter-arrival time delta offset in ms. 77 | double offset() const { 78 | return offset_; 79 | } 80 | 81 | // Returns the number of deltas which the current over-use estimator state is 82 | // based on. 83 | unsigned int num_of_deltas() const { 84 | return num_of_deltas_; 85 | } 86 | 87 | private: 88 | double UpdateMinFramePeriod(double ts_delta); 89 | void UpdateNoiseEstimate(double residual, double ts_delta, bool stable_state); 90 | 91 | // Must be first member variable. Cannot be const because we need to be 92 | // copyable. 93 | OverUseDetectorOptions options_; 94 | uint16_t num_of_deltas_; 95 | double slope_; 96 | double offset_; 97 | double prev_offset_; 98 | double E_[2][2]; 99 | double process_noise_[2]; 100 | double avg_noise_; 101 | double var_noise_; 102 | std::list ts_delta_hist_; 103 | 104 | RTC_DISALLOW_COPY_AND_ASSIGN(OveruseEstimator); 105 | }; 106 | } // namespace webrtc 107 | 108 | #endif // WEBRTC_MODULES_REMOTE_BITRATE_ESTIMATOR_OVERUSE_ESTIMATOR_H_ 109 | --------------------------------------------------------------------------------