| /* |
| * 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" |
| |
| #define BITRATE_AVERAGE_WINDOW 2000 |
| |
| namespace webrtc { |
| Bitrate::Bitrate(RtpRtcpClock* clock) : |
| _clock(*clock), |
| _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 = _clock.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 = _clock.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(), _accumulatedBytes(0) |
| { |
| } |
| |
| BitRateStats::~BitRateStats() |
| { |
| while (_dataSamples.size() > 0) |
| { |
| delete _dataSamples.front(); |
| _dataSamples.pop_front(); |
| } |
| } |
| |
| void BitRateStats::Init() |
| { |
| _accumulatedBytes = 0; |
| while (_dataSamples.size() > 0) |
| { |
| delete _dataSamples.front(); |
| _dataSamples.pop_front(); |
| } |
| } |
| |
| void BitRateStats::Update(WebRtc_UWord32 packetSizeBytes, WebRtc_Word64 nowMs) |
| { |
| // Find an empty slot for storing the new sample and at the same time |
| // accumulate the history. |
| _dataSamples.push_back(new DataTimeSizeTuple(packetSizeBytes, nowMs)); |
| _accumulatedBytes += packetSizeBytes; |
| EraseOld(nowMs); |
| } |
| |
| void BitRateStats::EraseOld(WebRtc_Word64 nowMs) |
| { |
| while (_dataSamples.size() > 0) |
| { |
| if (nowMs - _dataSamples.front()->_timeCompleteMs > |
| BITRATE_AVERAGE_WINDOW) |
| { |
| // Delete old sample |
| _accumulatedBytes -= _dataSamples.front()->_sizeBytes; |
| delete _dataSamples.front(); |
| _dataSamples.pop_front(); |
| } |
| else |
| { |
| break; |
| } |
| } |
| } |
| |
| WebRtc_UWord32 BitRateStats::BitRate(WebRtc_Word64 nowMs) |
| { |
| // Calculate the average bit rate the past BITRATE_AVERAGE_WINDOW ms. |
| // Removes any old samples from the list. |
| EraseOld(nowMs); |
| WebRtc_Word64 timeOldest = nowMs; |
| if (_dataSamples.size() > 0) |
| { |
| timeOldest = _dataSamples.front()->_timeCompleteMs; |
| } |
| // Update average bit rate |
| float denom = static_cast<float>(nowMs - timeOldest); |
| if (nowMs == timeOldest) |
| { |
| // Calculate with a one second window when we haven't |
| // received more than one packet. |
| denom = 1000.0; |
| } |
| return static_cast<WebRtc_UWord32>(_accumulatedBytes * 8.0f * 1000.0f / |
| denom + 0.5f); |
| } |
| } // namespace webrtc |