#define MS_CLASS "RTC::RateCalculator"
#include "RTC/RateCalculator.hpp"
#include "Logger.hpp"
#include <cmath>
namespace RTC
{
void RateCalculator::Update(size_t size, uint64_t nowMs)
{
MS_TRACE();
if (nowMs < this->oldestItemStartTime)
return;
this->bytes += size;
RemoveOldData(nowMs);
if (this->newestItemIndex < 0 || nowMs - this->newestItemStartTime >= this->itemSizeMs)
{
this->newestItemIndex++;
this->newestItemStartTime = nowMs;
if (this->newestItemIndex >= this->windowItems)
this->newestItemIndex = 0;
MS_ASSERT(
this->newestItemIndex != this->oldestItemIndex || this->oldestItemIndex == -1,
"newest index overlaps with the oldest one");
BufferItem& item = this->buffer[this->newestItemIndex];
item.count = size;
item.time = nowMs;
}
else
{
BufferItem& item = this->buffer[this->newestItemIndex];
item.count += size;
}
if (this->oldestItemIndex < 0)
{
this->oldestItemIndex = this->newestItemIndex;
this->oldestItemStartTime = nowMs;
}
this->totalCount += size;
this->lastRate = 0;
this->lastTime = 0;
}
uint32_t RateCalculator::GetRate(uint64_t nowMs)
{
MS_TRACE();
if (nowMs == this->lastTime)
return this->lastRate;
RemoveOldData(nowMs);
float scale = this->scale / this->windowSizeMs;
this->lastTime = nowMs;
this->lastRate = static_cast<uint32_t>(std::trunc(this->totalCount * scale + 0.5f));
return this->lastRate;
}
inline void RateCalculator::RemoveOldData(uint64_t nowMs)
{
MS_TRACE();
if (this->newestItemIndex < 0 || this->oldestItemIndex < 0)
return;
uint64_t newOldestTime = nowMs - this->windowSizeMs;
if (newOldestTime < this->oldestItemStartTime)
return;
if (newOldestTime >= this->newestItemStartTime)
{
Reset();
return;
}
while (newOldestTime >= this->oldestItemStartTime)
{
BufferItem& oldestItem = this->buffer[this->oldestItemIndex];
this->totalCount -= oldestItem.count;
oldestItem.count = 0u;
oldestItem.time = 0u;
if (++this->oldestItemIndex >= this->windowItems)
this->oldestItemIndex = 0;
const BufferItem& newOldestItem = this->buffer[this->oldestItemIndex];
this->oldestItemStartTime = newOldestItem.time;
}
}
void RtpDataCounter::Update(RTC::RtpPacket* packet)
{
uint64_t nowMs = DepLibUV::GetTimeMs();
this->packets++;
this->rate.Update(packet->GetSize(), nowMs);
}
}