208 lines
5.5 KiB
C++
208 lines
5.5 KiB
C++
/*
|
|
* Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#include "Bitrate.h"
|
|
#include "rtp_utility.h"
|
|
#include "tick_util.h"
|
|
|
|
#define BITRATE_AVERAGE_WINDOW 2000
|
|
|
|
namespace webrtc {
|
|
Bitrate::Bitrate() :
|
|
_packetRate(0),
|
|
_bitrate(0),
|
|
_bitrateNextIdx(0),
|
|
_timeLastRateUpdate(0),
|
|
_bytesCount(0),
|
|
_packetCount(0)
|
|
{
|
|
memset(_packetRateArray, 0, sizeof(_packetRateArray));
|
|
memset(_bitrateDiffMS, 0, sizeof(_bitrateDiffMS));
|
|
memset(_bitrateArray, 0, sizeof(_bitrateArray));
|
|
}
|
|
|
|
void
|
|
Bitrate::Init()
|
|
{
|
|
_packetRate = 0;
|
|
_bitrate = 0;
|
|
_timeLastRateUpdate = 0;
|
|
_bytesCount = 0;
|
|
_packetCount = 0;
|
|
_bitrateNextIdx = 0;
|
|
|
|
memset(_packetRateArray, 0, sizeof(_packetRateArray));
|
|
memset(_bitrateDiffMS, 0, sizeof(_bitrateDiffMS));
|
|
memset(_bitrateArray, 0, sizeof(_bitrateArray));
|
|
}
|
|
|
|
void
|
|
Bitrate::Update(const WebRtc_Word32 bytes)
|
|
{
|
|
_bytesCount += bytes;
|
|
_packetCount++;
|
|
}
|
|
|
|
WebRtc_UWord32
|
|
Bitrate::PacketRate() const
|
|
{
|
|
return _packetRate;
|
|
}
|
|
|
|
WebRtc_UWord32
|
|
Bitrate::BitrateLast() const
|
|
{
|
|
return _bitrate;
|
|
}
|
|
|
|
WebRtc_UWord32
|
|
Bitrate::BitrateNow() const
|
|
{
|
|
WebRtc_UWord32 now = ModuleRTPUtility::GetTimeInMS();
|
|
WebRtc_UWord32 diffMS = now -_timeLastRateUpdate;
|
|
|
|
if(diffMS > 10000) // 10 sec
|
|
{
|
|
// too high diff ignore
|
|
return _bitrate; // bits/s
|
|
}
|
|
WebRtc_UWord64 bitsSinceLastRateUpdate = 8*_bytesCount*1000;
|
|
|
|
// have to consider the time when the measurement was done
|
|
// ((bits/sec * sec) + (bits)) / sec
|
|
WebRtc_UWord64 bitrate = (((WebRtc_UWord64)_bitrate * 1000) + bitsSinceLastRateUpdate)/(1000+diffMS);
|
|
return (WebRtc_UWord32)bitrate;
|
|
}
|
|
|
|
void
|
|
Bitrate::Process()
|
|
{
|
|
// triggered by timer
|
|
WebRtc_UWord32 now = ModuleRTPUtility::GetTimeInMS();
|
|
WebRtc_UWord32 diffMS = now -_timeLastRateUpdate;
|
|
|
|
if(diffMS > 100)
|
|
{
|
|
if(diffMS > 10000) // 10 sec
|
|
{
|
|
// too high diff ignore
|
|
_timeLastRateUpdate = now;
|
|
_bytesCount = 0;
|
|
_packetCount = 0;
|
|
return;
|
|
}
|
|
_packetRateArray[_bitrateNextIdx] = (_packetCount*1000)/diffMS;
|
|
_bitrateArray[_bitrateNextIdx] = 8*((_bytesCount*1000)/diffMS);
|
|
// will overflow at ~34 Mbit/s
|
|
_bitrateDiffMS[_bitrateNextIdx] = diffMS;
|
|
_bitrateNextIdx++;
|
|
if(_bitrateNextIdx >= 10)
|
|
{
|
|
_bitrateNextIdx = 0;
|
|
}
|
|
|
|
WebRtc_UWord32 sumDiffMS = 0;
|
|
WebRtc_UWord64 sumBitrateMS = 0;
|
|
WebRtc_UWord32 sumPacketrateMS = 0;
|
|
for(int i= 0; i <10; i++)
|
|
{
|
|
// sum of time
|
|
sumDiffMS += _bitrateDiffMS[i];
|
|
sumBitrateMS += _bitrateArray[i] * _bitrateDiffMS[i];
|
|
sumPacketrateMS += _packetRateArray[i] * _bitrateDiffMS[i];
|
|
}
|
|
_timeLastRateUpdate = now;
|
|
_bytesCount = 0;
|
|
_packetCount = 0;
|
|
|
|
_packetRate = sumPacketrateMS/sumDiffMS;
|
|
_bitrate = WebRtc_UWord32(sumBitrateMS / sumDiffMS);
|
|
}
|
|
}
|
|
|
|
|
|
BitRateStats::BitRateStats()
|
|
:_dataSamples(), _avgSentBitRateBps(0)
|
|
{
|
|
}
|
|
|
|
BitRateStats::~BitRateStats()
|
|
{
|
|
ListItem* item = _dataSamples.First();
|
|
while (item != NULL)
|
|
{
|
|
delete static_cast<DataTimeSizeTuple*>(item->GetItem());
|
|
_dataSamples.Erase(item);
|
|
item = _dataSamples.First();
|
|
}
|
|
}
|
|
|
|
void BitRateStats::Init()
|
|
{
|
|
_avgSentBitRateBps = 0;
|
|
|
|
ListItem* item = _dataSamples.First();
|
|
while (item != NULL)
|
|
{
|
|
delete static_cast<DataTimeSizeTuple*>(item->GetItem());
|
|
_dataSamples.Erase(item);
|
|
item = _dataSamples.First();
|
|
}
|
|
}
|
|
|
|
void BitRateStats::Update(WebRtc_Word64 packetSizeBytes, WebRtc_Word64 nowMs)
|
|
{
|
|
WebRtc_UWord32 sumBytes = 0;
|
|
WebRtc_Word64 timeOldest = nowMs;
|
|
// Find an empty slot for storing the new sample and at the same time
|
|
// accumulate the history.
|
|
_dataSamples.PushFront(new DataTimeSizeTuple(packetSizeBytes, nowMs));
|
|
ListItem* item = _dataSamples.First();
|
|
while (item != NULL)
|
|
{
|
|
const DataTimeSizeTuple* sample = static_cast<DataTimeSizeTuple*>(item->GetItem());
|
|
if (nowMs - sample->_timeCompleteMs < BITRATE_AVERAGE_WINDOW)
|
|
{
|
|
sumBytes += static_cast<WebRtc_UWord32>(sample->_sizeBytes);
|
|
item = _dataSamples.Next(item);
|
|
}
|
|
else
|
|
{
|
|
// Delete old sample
|
|
delete sample;
|
|
ListItem* itemToErase = item;
|
|
item = _dataSamples.Next(item);
|
|
_dataSamples.Erase(itemToErase);
|
|
}
|
|
}
|
|
const ListItem* oldest = _dataSamples.Last();
|
|
if (oldest != NULL)
|
|
{
|
|
timeOldest =
|
|
static_cast<DataTimeSizeTuple*>(oldest->GetItem())->_timeCompleteMs;
|
|
}
|
|
// Update average bit rate
|
|
float denom = static_cast<float>(nowMs - timeOldest);
|
|
if (denom < 1.0)
|
|
{
|
|
// Calculate with a one second window when we haven't
|
|
// received more than one packet.
|
|
denom = 1000.0;
|
|
}
|
|
_avgSentBitRateBps = static_cast<WebRtc_UWord32>(sumBytes * 8.0f * 1000.0f / denom + 0.5f);
|
|
}
|
|
|
|
WebRtc_UWord32 BitRateStats::BitRateNow()
|
|
{
|
|
Update(-1, TickTime::MillisecondTimestamp());
|
|
return static_cast<WebRtc_UWord32>(_avgSentBitRateBps + 0.5f);
|
|
}
|
|
} // namespace webrtc
|