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