| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved. | |
| 3 * | |
| 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 | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestLoadGenerator.h" | |
| 12 | |
| 13 #include <stdio.h> | |
| 14 | |
| 15 #include <algorithm> | |
| 16 | |
| 17 #include "webrtc/modules/rtp_rtcp/test/BWEStandAlone/TestSenderReceiver.h" | |
| 18 #include "webrtc/system_wrappers/include/critical_section_wrapper.h" | |
| 19 #include "webrtc/system_wrappers/include/event_wrapper.h" | |
| 20 #include "webrtc/system_wrappers/include/tick_util.h" | |
| 21 | |
| 22 | |
| 23 bool SenderThreadFunction(void *obj) | |
| 24 { | |
| 25 if (obj == NULL) | |
| 26 { | |
| 27 return false; | |
| 28 } | |
| 29 TestLoadGenerator *_genObj = static_cast<TestLoadGenerator *>(obj); | |
| 30 | |
| 31 return _genObj->GeneratorLoop(); | |
| 32 } | |
| 33 | |
| 34 | |
| 35 TestLoadGenerator::TestLoadGenerator(TestSenderReceiver *sender, int32_t rtpSamp
leRate) | |
| 36 : | |
| 37 _critSect(CriticalSectionWrapper::CreateCriticalSection()), | |
| 38 _eventPtr(NULL), | |
| 39 _bitrateKbps(0), | |
| 40 _sender(sender), | |
| 41 _running(false), | |
| 42 _rtpSampleRate(rtpSampleRate) | |
| 43 { | |
| 44 } | |
| 45 | |
| 46 TestLoadGenerator::~TestLoadGenerator () | |
| 47 { | |
| 48 if (_running) | |
| 49 { | |
| 50 Stop(); | |
| 51 } | |
| 52 | |
| 53 delete _critSect; | |
| 54 } | |
| 55 | |
| 56 int32_t TestLoadGenerator::SetBitrate (int32_t newBitrateKbps) | |
| 57 { | |
| 58 CriticalSectionScoped cs(_critSect); | |
| 59 | |
| 60 if (newBitrateKbps < 0) | |
| 61 { | |
| 62 return -1; | |
| 63 } | |
| 64 | |
| 65 _bitrateKbps = newBitrateKbps; | |
| 66 | |
| 67 printf("New bitrate = %i kbps\n", _bitrateKbps); | |
| 68 | |
| 69 return _bitrateKbps; | |
| 70 } | |
| 71 | |
| 72 | |
| 73 int32_t TestLoadGenerator::Start (const char *threadName) | |
| 74 { | |
| 75 CriticalSectionScoped cs(_critSect); | |
| 76 | |
| 77 _eventPtr = EventWrapper::Create(); | |
| 78 | |
| 79 _genThread.reset( | |
| 80 new rtc::PlatformThread(SenderThreadFunction, this, threadName)); | |
| 81 _running = true; | |
| 82 | |
| 83 _genThread->Start(); | |
| 84 _genThread->SetPriority(rtc::kRealtimePriority); | |
| 85 | |
| 86 return 0; | |
| 87 } | |
| 88 | |
| 89 | |
| 90 int32_t TestLoadGenerator::Stop () | |
| 91 { | |
| 92 _critSect.Enter(); | |
| 93 | |
| 94 if (_genThread) | |
| 95 { | |
| 96 _running = false; | |
| 97 _eventPtr->Set(); | |
| 98 | |
| 99 _genThread->Stop(); | |
| 100 _genThread.reset(); | |
| 101 | |
| 102 delete _eventPtr; | |
| 103 _eventPtr = NULL; | |
| 104 } | |
| 105 | |
| 106 _critSect.Leave(); | |
| 107 return (0); | |
| 108 } | |
| 109 | |
| 110 | |
| 111 int TestLoadGenerator::generatePayload () | |
| 112 { | |
| 113 return(generatePayload( static_cast<uint32_t>( TickTime::MillisecondTimestam
p() * _rtpSampleRate / 1000 ))); | |
| 114 } | |
| 115 | |
| 116 | |
| 117 int TestLoadGenerator::sendPayload (const uint32_t timeStamp, | |
| 118 const uint8_t* payloadData, | |
| 119 const size_t payloadSize, | |
| 120 const webrtc::FrameType frameType /*= webrtc
::kVideoFrameDelta*/) | |
| 121 { | |
| 122 | |
| 123 return (_sender->SendOutgoingData(timeStamp, payloadData, payloadSize, frame
Type)); | |
| 124 } | |
| 125 | |
| 126 | |
| 127 CBRGenerator::CBRGenerator (TestSenderReceiver *sender, | |
| 128 size_t payloadSizeBytes, | |
| 129 int32_t bitrateKbps, | |
| 130 int32_t rtpSampleRate) | |
| 131 : | |
| 132 //_eventPtr(NULL), | |
| 133 _payloadSizeBytes(payloadSizeBytes), | |
| 134 _payload(new uint8_t[payloadSizeBytes]), | |
| 135 TestLoadGenerator(sender, rtpSampleRate) | |
| 136 { | |
| 137 SetBitrate (bitrateKbps); | |
| 138 } | |
| 139 | |
| 140 CBRGenerator::~CBRGenerator () | |
| 141 { | |
| 142 if (_running) | |
| 143 { | |
| 144 Stop(); | |
| 145 } | |
| 146 | |
| 147 if (_payload) | |
| 148 { | |
| 149 delete [] _payload; | |
| 150 } | |
| 151 | |
| 152 } | |
| 153 | |
| 154 bool CBRGenerator::GeneratorLoop () | |
| 155 { | |
| 156 double periodMs; | |
| 157 int64_t nextSendTime = TickTime::MillisecondTimestamp(); | |
| 158 | |
| 159 | |
| 160 // no critSect | |
| 161 while (_running) | |
| 162 { | |
| 163 // send data (critSect inside) | |
| 164 generatePayload( static_cast<uint32_t>(nextSendTime * _rtpSampleRate / 1
000) ); | |
| 165 | |
| 166 // calculate wait time | |
| 167 periodMs = 8.0 * _payloadSizeBytes / ( _bitrateKbps ); | |
| 168 | |
| 169 nextSendTime = static_cast<int64_t>(nextSendTime + periodMs); | |
| 170 | |
| 171 int32_t waitTime = static_cast<int32_t>(nextSendTime - TickTime::Millise
condTimestamp()); | |
| 172 if (waitTime < 0) | |
| 173 { | |
| 174 waitTime = 0; | |
| 175 } | |
| 176 // wait | |
| 177 _eventPtr->Wait(static_cast<int32_t>(waitTime)); | |
| 178 } | |
| 179 | |
| 180 return true; | |
| 181 } | |
| 182 | |
| 183 int CBRGenerator::generatePayload ( uint32_t timestamp ) | |
| 184 { | |
| 185 CriticalSectionScoped cs(_critSect); | |
| 186 | |
| 187 //uint8_t *payload = new uint8_t[_payloadSizeBytes]; | |
| 188 | |
| 189 int ret = sendPayload(timestamp, _payload, _payloadSizeBytes); | |
| 190 | |
| 191 //delete [] payload; | |
| 192 return ret; | |
| 193 } | |
| 194 | |
| 195 | |
| 196 | |
| 197 | |
| 198 ///////////////////// | |
| 199 | |
| 200 CBRFixFRGenerator::CBRFixFRGenerator (TestSenderReceiver *sender, int32_t bitrat
eKbps, | |
| 201 int32_t rtpSampleRate, int32_t frameRateFp
s /*= 30*/, | |
| 202 double spread /*= 0.0*/) | |
| 203 : | |
| 204 //_eventPtr(NULL), | |
| 205 _payloadSizeBytes(0), | |
| 206 _payload(NULL), | |
| 207 _payloadAllocLen(0), | |
| 208 _frameRateFps(frameRateFps), | |
| 209 _spreadFactor(spread), | |
| 210 TestLoadGenerator(sender, rtpSampleRate) | |
| 211 { | |
| 212 SetBitrate (bitrateKbps); | |
| 213 } | |
| 214 | |
| 215 CBRFixFRGenerator::~CBRFixFRGenerator () | |
| 216 { | |
| 217 if (_running) | |
| 218 { | |
| 219 Stop(); | |
| 220 } | |
| 221 | |
| 222 if (_payload) | |
| 223 { | |
| 224 delete [] _payload; | |
| 225 _payloadAllocLen = 0; | |
| 226 } | |
| 227 | |
| 228 } | |
| 229 | |
| 230 bool CBRFixFRGenerator::GeneratorLoop () | |
| 231 { | |
| 232 double periodMs; | |
| 233 int64_t nextSendTime = TickTime::MillisecondTimestamp(); | |
| 234 | |
| 235 _critSect.Enter(); | |
| 236 | |
| 237 if (_frameRateFps <= 0) | |
| 238 { | |
| 239 return false; | |
| 240 } | |
| 241 | |
| 242 _critSect.Leave(); | |
| 243 | |
| 244 // no critSect | |
| 245 while (_running) | |
| 246 { | |
| 247 _critSect.Enter(); | |
| 248 | |
| 249 // calculate payload size | |
| 250 _payloadSizeBytes = nextPayloadSize(); | |
| 251 | |
| 252 if (_payloadSizeBytes > 0) | |
| 253 { | |
| 254 | |
| 255 if (_payloadAllocLen < _payloadSizeBytes * (1 + _spreadFactor)) | |
| 256 { | |
| 257 // re-allocate _payload | |
| 258 if (_payload) | |
| 259 { | |
| 260 delete [] _payload; | |
| 261 _payload = NULL; | |
| 262 } | |
| 263 | |
| 264 _payloadAllocLen = static_cast<int32_t>((_payloadSizeBytes * (1
+ _spreadFactor) * 3) / 2 + .5); // 50% extra to avoid frequent re-alloc | |
| 265 _payload = new uint8_t[_payloadAllocLen]; | |
| 266 } | |
| 267 | |
| 268 | |
| 269 // send data (critSect inside) | |
| 270 generatePayload( static_cast<uint32_t>(nextSendTime * _rtpSampleRate
/ 1000) ); | |
| 271 } | |
| 272 | |
| 273 _critSect.Leave(); | |
| 274 | |
| 275 // calculate wait time | |
| 276 periodMs = 1000.0 / _frameRateFps; | |
| 277 nextSendTime = static_cast<int64_t>(nextSendTime + periodMs + 0.5); | |
| 278 | |
| 279 int32_t waitTime = static_cast<int32_t>(nextSendTime - TickTime::Millise
condTimestamp()); | |
| 280 if (waitTime < 0) | |
| 281 { | |
| 282 waitTime = 0; | |
| 283 } | |
| 284 // wait | |
| 285 _eventPtr->Wait(waitTime); | |
| 286 } | |
| 287 | |
| 288 return true; | |
| 289 } | |
| 290 | |
| 291 size_t CBRFixFRGenerator::nextPayloadSize() | |
| 292 { | |
| 293 const double periodMs = 1000.0 / _frameRateFps; | |
| 294 return static_cast<size_t>(_bitrateKbps * periodMs / 8 + 0.5); | |
| 295 } | |
| 296 | |
| 297 int CBRFixFRGenerator::generatePayload ( uint32_t timestamp ) | |
| 298 { | |
| 299 CriticalSectionScoped cs(_critSect); | |
| 300 | |
| 301 double factor = ((double) rand() - RAND_MAX/2) / RAND_MAX; // [-0.5; 0.5] | |
| 302 factor = 1 + 2 * _spreadFactor * factor; // [1 - _spreadFactor ; 1 + _spread
Factor] | |
| 303 | |
| 304 size_t thisPayloadBytes = static_cast<size_t>(_payloadSizeBytes * factor); | |
| 305 // sanity | |
| 306 if (thisPayloadBytes > _payloadAllocLen) | |
| 307 { | |
| 308 thisPayloadBytes = _payloadAllocLen; | |
| 309 } | |
| 310 | |
| 311 int ret = sendPayload(timestamp, _payload, thisPayloadBytes); | |
| 312 return ret; | |
| 313 } | |
| 314 | |
| 315 | |
| 316 ///////////////////// | |
| 317 | |
| 318 PeriodicKeyFixFRGenerator::PeriodicKeyFixFRGenerator (TestSenderReceiver *sender
, int32_t bitrateKbps, | |
| 319 int32_t rtpSampleRate, int
32_t frameRateFps /*= 30*/, | |
| 320 double spread /*= 0.0*/, d
ouble keyFactor /*= 4.0*/, uint32_t keyPeriod /*= 300*/) | |
| 321 : | |
| 322 _keyFactor(keyFactor), | |
| 323 _keyPeriod(keyPeriod), | |
| 324 _frameCount(0), | |
| 325 CBRFixFRGenerator(sender, bitrateKbps, rtpSampleRate, frameRateFps, spread) | |
| 326 { | |
| 327 } | |
| 328 | |
| 329 size_t PeriodicKeyFixFRGenerator::nextPayloadSize() | |
| 330 { | |
| 331 // calculate payload size for a delta frame | |
| 332 size_t payloadSizeBytes = static_cast<size_t>(1000 * _bitrateKbps / | |
| 333 (8.0 * _frameRateFps * (1.0 + (_keyFactor - 1.0) / _keyPeriod)) + 0.5); | |
| 334 | |
| 335 if (_frameCount % _keyPeriod == 0) | |
| 336 { | |
| 337 // this is a key frame, scale the payload size | |
| 338 payloadSizeBytes = | |
| 339 static_cast<size_t>(_keyFactor * _payloadSizeBytes + 0.5); | |
| 340 } | |
| 341 _frameCount++; | |
| 342 | |
| 343 return payloadSizeBytes; | |
| 344 } | |
| 345 | |
| 346 //////////////////// | |
| 347 | |
| 348 CBRVarFRGenerator::CBRVarFRGenerator(TestSenderReceiver *sender, int32_t bitrate
Kbps, const uint8_t* frameRates, | |
| 349 uint16_t numFrameRates, int32_t rtpSampleRa
te, double avgFrPeriodMs, | |
| 350 double frSpreadFactor, double spreadFactor) | |
| 351 : | |
| 352 _avgFrPeriodMs(avgFrPeriodMs), | |
| 353 _frSpreadFactor(frSpreadFactor), | |
| 354 _frameRates(NULL), | |
| 355 _numFrameRates(numFrameRates), | |
| 356 _frChangeTimeMs(TickTime::MillisecondTimestamp() + _avgFrPeriodMs), | |
| 357 CBRFixFRGenerator(sender, bitrateKbps, rtpSampleRate, frameRates[0], spreadFacto
r) | |
| 358 { | |
| 359 _frameRates = new uint8_t[_numFrameRates]; | |
| 360 memcpy(_frameRates, frameRates, _numFrameRates); | |
| 361 } | |
| 362 | |
| 363 CBRVarFRGenerator::~CBRVarFRGenerator() | |
| 364 { | |
| 365 delete [] _frameRates; | |
| 366 } | |
| 367 | |
| 368 void CBRVarFRGenerator::ChangeFrameRate() | |
| 369 { | |
| 370 const int64_t nowMs = TickTime::MillisecondTimestamp(); | |
| 371 if (nowMs < _frChangeTimeMs) | |
| 372 { | |
| 373 return; | |
| 374 } | |
| 375 // Time to change frame rate | |
| 376 uint16_t frIndex = static_cast<uint16_t>(static_cast<double>(rand()) / RAND_
MAX | |
| 377 * (_numFrameRates - 1) + 0.5) ; | |
| 378 assert(frIndex < _numFrameRates); | |
| 379 _frameRateFps = _frameRates[frIndex]; | |
| 380 // Update the next frame rate change time | |
| 381 double factor = ((double) rand() - RAND_MAX/2) / RAND_MAX; // [-0.5; 0.5] | |
| 382 factor = 1 + 2 * _frSpreadFactor * factor; // [1 - _frSpreadFactor ; 1 + _fr
SpreadFactor] | |
| 383 _frChangeTimeMs = nowMs + static_cast<int64_t>(1000.0 * factor * | |
| 384 _avgFrPeriodMs + 0.5); | |
| 385 | |
| 386 printf("New frame rate: %d\n", _frameRateFps); | |
| 387 } | |
| 388 | |
| 389 size_t CBRVarFRGenerator::nextPayloadSize() | |
| 390 { | |
| 391 ChangeFrameRate(); | |
| 392 return CBRFixFRGenerator::nextPayloadSize(); | |
| 393 } | |
| 394 | |
| 395 //////////////////// | |
| 396 | |
| 397 CBRFrameDropGenerator::CBRFrameDropGenerator(TestSenderReceiver *sender, int32_t
bitrateKbps, | |
| 398 int32_t rtpSampleRate, double spreadFac
tor) | |
| 399 : | |
| 400 _accBits(0), | |
| 401 CBRFixFRGenerator(sender, bitrateKbps, rtpSampleRate, 30, spreadFactor) | |
| 402 { | |
| 403 } | |
| 404 | |
| 405 CBRFrameDropGenerator::~CBRFrameDropGenerator() | |
| 406 { | |
| 407 } | |
| 408 | |
| 409 size_t CBRFrameDropGenerator::nextPayloadSize() | |
| 410 { | |
| 411 _accBits -= 1000 * _bitrateKbps / _frameRateFps; | |
| 412 if (_accBits < 0) | |
| 413 { | |
| 414 _accBits = 0; | |
| 415 } | |
| 416 if (_accBits > 0.3 * _bitrateKbps * 1000) | |
| 417 { | |
| 418 //printf("drop\n"); | |
| 419 return 0; | |
| 420 } | |
| 421 else | |
| 422 { | |
| 423 //printf("keep\n"); | |
| 424 const double periodMs = 1000.0 / _frameRateFps; | |
| 425 size_t frameSize = | |
| 426 static_cast<size_t>(_bitrateKbps * periodMs / 8 + 0.5); | |
| 427 frameSize = | |
| 428 std::max(frameSize, static_cast<size_t>(300 * periodMs / 8 + 0.5)); | |
| 429 _accBits += frameSize * 8; | |
| 430 return frameSize; | |
| 431 } | |
| 432 } | |
| OLD | NEW |