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
24bool 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
36TestLoadGenerator::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
48TestLoadGenerator::~TestLoadGenerator ()
49{
50    if (_running)
51    {
52        Stop();
53    }
54
55    delete _critSect;
56}
57
58int32_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
75int32_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
97int32_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
126int TestLoadGenerator::generatePayload ()
127{
128    return(generatePayload( static_cast<uint32_t>( TickTime::MillisecondTimestamp() * _rtpSampleRate / 1000 )));
129}
130
131
132int 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
142CBRGenerator::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]),
147TestLoadGenerator(sender, rtpSampleRate)
148{
149    SetBitrate (bitrateKbps);
150}
151
152CBRGenerator::~CBRGenerator ()
153{
154    if (_running)
155    {
156        Stop();
157    }
158
159    if (_payload)
160    {
161        delete [] _payload;
162    }
163
164}
165
166bool 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
195int 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
212CBRFixFRGenerator::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),
222TestLoadGenerator(sender, rtpSampleRate)
223{
224    SetBitrate (bitrateKbps);
225}
226
227CBRFixFRGenerator::~CBRFixFRGenerator ()
228{
229    if (_running)
230    {
231        Stop();
232    }
233
234    if (_payload)
235    {
236        delete [] _payload;
237        _payloadAllocLen = 0;
238    }
239
240}
241
242bool 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
303int32_t CBRFixFRGenerator::nextPayloadSize()
304{
305    const double periodMs = 1000.0 / _frameRateFps;
306    return static_cast<int32_t>(_bitrateKbps * periodMs / 8 + 0.5);
307}
308
309int 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
330PeriodicKeyFixFRGenerator::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),
337CBRFixFRGenerator(sender, bitrateKbps, rtpSampleRate, frameRateFps, spread)
338{
339}
340
341int32_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
358CBRVarFRGenerator::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),
367CBRFixFRGenerator(sender, bitrateKbps, rtpSampleRate, frameRates[0], spreadFactor)
368{
369    _frameRates = new uint8_t[_numFrameRates];
370    memcpy(_frameRates, frameRates, _numFrameRates);
371}
372
373CBRVarFRGenerator::~CBRVarFRGenerator()
374{
375    delete [] _frameRates;
376}
377
378void 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
399int32_t CBRVarFRGenerator::nextPayloadSize()
400{
401    ChangeFrameRate();
402    return CBRFixFRGenerator::nextPayloadSize();
403}
404
405////////////////////
406
407CBRFrameDropGenerator::CBRFrameDropGenerator(TestSenderReceiver *sender, int32_t bitrateKbps,
408                                         int32_t rtpSampleRate, double spreadFactor)
409:
410_accBits(0),
411CBRFixFRGenerator(sender, bitrateKbps, rtpSampleRate, 30, spreadFactor)
412{
413}
414
415CBRFrameDropGenerator::~CBRFrameDropGenerator()
416{
417}
418
419int32_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