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/audio_conference_mixer/source/time_scheduler.h" 12 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 13 14 namespace webrtc { TimeScheduler(const uint32_t periodicityInMs)15TimeScheduler::TimeScheduler(const uint32_t periodicityInMs) 16 : _crit(CriticalSectionWrapper::CreateCriticalSection()), 17 _isStarted(false), 18 _lastPeriodMark(), 19 _periodicityInMs(periodicityInMs), 20 _periodicityInTicks(TickTime::MillisecondsToTicks(periodicityInMs)), 21 _missedPeriods(0) 22 { 23 } 24 ~TimeScheduler()25TimeScheduler::~TimeScheduler() 26 { 27 delete _crit; 28 } 29 UpdateScheduler()30int32_t TimeScheduler::UpdateScheduler() 31 { 32 CriticalSectionScoped cs(_crit); 33 if(!_isStarted) 34 { 35 _isStarted = true; 36 _lastPeriodMark = TickTime::Now(); 37 return 0; 38 } 39 // Don't perform any calculations until the debt of pending periods have 40 // been worked off. 41 if(_missedPeriods > 0) 42 { 43 _missedPeriods--; 44 return 0; 45 } 46 47 // Calculate the time that has past since previous call to this function. 48 TickTime tickNow = TickTime::Now(); 49 TickInterval amassedTicks = tickNow - _lastPeriodMark; 50 int64_t amassedMs = amassedTicks.Milliseconds(); 51 52 // Calculate the number of periods the time that has passed correspond to. 53 int32_t periodsToClaim = static_cast<int32_t>(amassedMs / 54 static_cast<int32_t>(_periodicityInMs)); 55 56 // One period will be worked off by this call. Make sure that the number of 57 // pending periods don't end up being negative (e.g. if this function is 58 // called to often). 59 if(periodsToClaim < 1) 60 { 61 periodsToClaim = 1; 62 } 63 64 // Update the last period mark without introducing any drifting. 65 // Note that if this fuunction is called to often _lastPeriodMark can 66 // refer to a time in the future which in turn will yield TimeToNextUpdate 67 // that is greater than the periodicity 68 for(int32_t i = 0; i < periodsToClaim; i++) 69 { 70 _lastPeriodMark += _periodicityInTicks; 71 } 72 73 // Update the total amount of missed periods note that we have processed 74 // one period hence the - 1 75 _missedPeriods += periodsToClaim - 1; 76 return 0; 77 } 78 TimeToNextUpdate(int32_t & updateTimeInMS) const79int32_t TimeScheduler::TimeToNextUpdate( 80 int32_t& updateTimeInMS) const 81 { 82 CriticalSectionScoped cs(_crit); 83 // Missed periods means that the next UpdateScheduler() should happen 84 // immediately. 85 if(_missedPeriods > 0) 86 { 87 updateTimeInMS = 0; 88 return 0; 89 } 90 91 // Calculate the time (in ms) that has past since last call to 92 // UpdateScheduler() 93 TickTime tickNow = TickTime::Now(); 94 TickInterval ticksSinceLastUpdate = tickNow - _lastPeriodMark; 95 const int32_t millisecondsSinceLastUpdate = 96 static_cast<int32_t>(ticksSinceLastUpdate.Milliseconds()); 97 98 updateTimeInMS = _periodicityInMs - millisecondsSinceLastUpdate; 99 updateTimeInMS = (updateTimeInMS < 0) ? 0 : updateTimeInMS; 100 return 0; 101 } 102 } // namespace webrtc 103