1 /**
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <ImsMediaDefine.h>
18 #include <JitterNetworkAnalyser.h>
19 #include <ImsMediaTimer.h>
20 #include <ImsMediaTrace.h>
21 #include <numeric>
22 #include <cmath>
23 #include <algorithm>
24 
25 #define MAX_JITTER_LIST_SIZE    (150)
26 #define PACKET_INTERVAL         (20)    // milliseconds
27 #define BUFFER_INCREASE_TH      (200)   // milliseconds
28 #define BUFFER_DECREASE_TH      (3000)  // milliseconds
29 #define MARGIN_WEIGHT           (1.8f)
30 #define BUFFER_IN_DECREASE_SIZE (1)
31 
JitterNetworkAnalyser()32 JitterNetworkAnalyser::JitterNetworkAnalyser()
33 {
34     mMinJitterBufferSize = 0;
35     mMaxJitterBufferSize = 0;
36     mBufferIncThreshold = BUFFER_INCREASE_TH;
37     mBufferDecThreshold = BUFFER_DECREASE_TH;
38     mBufferStepSize = BUFFER_IN_DECREASE_SIZE;
39     mBufferWeight = MARGIN_WEIGHT;
40 
41     IMLOGD4("[JitterNetworkAnalyser] incThreshold[%d], decThreshold[%d], stepSize[%d], "
42             "weight[%.3f]",
43             mBufferIncThreshold, mBufferDecThreshold, mBufferStepSize, mBufferWeight);
44     Reset();
45 }
46 
~JitterNetworkAnalyser()47 JitterNetworkAnalyser::~JitterNetworkAnalyser() {}
48 
Reset()49 void JitterNetworkAnalyser::Reset()
50 {
51     mNetworkStatus = NETWORK_STATUS_NORMAL;
52     mGoodStatusEnteringTime = 0;
53     mBadStatusChangedTime = 0;
54 
55     {
56         std::lock_guard<std::mutex> guard(mMutex);
57         mListJitters.clear();
58         mMapDelta.clear();
59         mTimeLateArrivals = 0;
60     }
61 }
62 
SetMinMaxJitterBufferSize(uint32_t nMinBufferSize,uint32_t nMaxBufferSize)63 void JitterNetworkAnalyser::SetMinMaxJitterBufferSize(
64         uint32_t nMinBufferSize, uint32_t nMaxBufferSize)
65 {
66     mMinJitterBufferSize = nMinBufferSize;
67     mMaxJitterBufferSize = nMaxBufferSize;
68 }
69 
SetJitterOptions(uint32_t incThreshold,uint32_t decThreshold,uint32_t stepSize,double weight)70 void JitterNetworkAnalyser::SetJitterOptions(
71         uint32_t incThreshold, uint32_t decThreshold, uint32_t stepSize, double weight)
72 {
73     mBufferIncThreshold = incThreshold;
74     mBufferDecThreshold = decThreshold;
75     mBufferStepSize = stepSize;
76     mBufferWeight = weight;
77 
78     IMLOGD4("[SetJitterOptions] incThreshold[%d], decThreshold[%d], stepSize[%d], weight[%.3f]",
79             mBufferIncThreshold, mBufferDecThreshold, mBufferStepSize, mBufferWeight);
80 }
81 
82 template <typename Map>
getGreatestLess(Map const & m,typename Map::key_type const & k)83 typename Map::const_iterator getGreatestLess(Map const& m, typename Map::key_type const& k)
84 {
85     typename Map::const_iterator it = m.lower_bound(k);
86     if (it != m.begin())
87     {
88         return --it;
89     }
90     return m.end();
91 }
92 
CalculateTransitTimeDifference(uint32_t timestamp,uint32_t arrivalTime)93 int32_t JitterNetworkAnalyser::CalculateTransitTimeDifference(
94         uint32_t timestamp, uint32_t arrivalTime)
95 {
96     std::lock_guard<std::mutex> guard(mMutex);
97 
98     if (mMapDelta.size() == 0)
99     {
100         mMapDelta.insert({timestamp, arrivalTime});
101         return 0;
102     }
103 
104     if (mMapDelta.size() > MAX_JITTER_LIST_SIZE)
105     {
106         mMapDelta.erase(mMapDelta.begin());
107     }
108 
109     mMapDelta.insert({timestamp, arrivalTime});
110 
111     if (getGreatestLess(mMapDelta, timestamp) == mMapDelta.end())
112     {
113         mListJitters.push_back(0);
114         return 0;
115     }
116 
117     int32_t inputTimestampGap = timestamp - getGreatestLess(mMapDelta, timestamp)->first;
118     int32_t inputTimeGap = arrivalTime - getGreatestLess(mMapDelta, timestamp)->second;
119     int32_t jitter = std::abs(inputTimeGap - inputTimestampGap);
120 
121     if (jitter < mMaxJitterBufferSize * PACKET_INTERVAL)
122     {
123         mListJitters.push_back(jitter);
124     }
125 
126     if (mListJitters.size() > MAX_JITTER_LIST_SIZE)
127     {
128         mListJitters.pop_front();
129     }
130 
131     return jitter;
132 }
133 
SetLateArrivals(uint32_t time)134 void JitterNetworkAnalyser::SetLateArrivals(uint32_t time)
135 {
136     mTimeLateArrivals = time;
137 }
138 
CalculateDeviation(double * pMean)139 double JitterNetworkAnalyser::CalculateDeviation(double* pMean)
140 {
141     std::lock_guard<std::mutex> guard(mMutex);
142 
143     if (mListJitters.empty())
144     {
145         *pMean = 0;
146         return 0.0f;
147     }
148 
149     double mean =
150             std::accumulate(mListJitters.begin(), mListJitters.end(), 0.0f) / mListJitters.size();
151 
152     *pMean = mean;
153 
154     double dev = sqrt(std::accumulate(mListJitters.begin(), mListJitters.end(), 0.0f,
155                               [mean](int x, int y)
156                               {
157                                   return x + std::pow(y - mean, 2);
158                               }) /
159             mListJitters.size());
160 
161     return dev;
162 }
163 
GetMaxJitterValue()164 int32_t JitterNetworkAnalyser::GetMaxJitterValue()
165 {
166     std::lock_guard<std::mutex> guard(mMutex);
167 
168     if (mListJitters.empty())
169     {
170         return 0;
171     }
172 
173     return *std::max_element(mListJitters.begin(), mListJitters.end());
174 }
175 
GetNextJitterBufferSize(uint32_t nCurrJitterBufferSize,uint32_t currentTime)176 uint32_t JitterNetworkAnalyser::GetNextJitterBufferSize(
177         uint32_t nCurrJitterBufferSize, uint32_t currentTime)
178 {
179     uint32_t nextJitterBuffer = nCurrJitterBufferSize;
180     NETWORK_STATUS networkStatus;
181 
182     double dev, mean;
183     double calcJitterSize = 0;
184     int32_t maxJitter = GetMaxJitterValue();
185     dev = CalculateDeviation(&mean);
186     calcJitterSize = (double)maxJitter * mBufferWeight;
187 
188     if (calcJitterSize >= nCurrJitterBufferSize * PACKET_INTERVAL ||
189             maxJitter >= nCurrJitterBufferSize * PACKET_INTERVAL)
190     {
191         networkStatus = NETWORK_STATUS_BAD;
192     }
193     else if (calcJitterSize < (nCurrJitterBufferSize - 1) * PACKET_INTERVAL &&
194             maxJitter < (nCurrJitterBufferSize - 1) * PACKET_INTERVAL - 10)
195     {
196         networkStatus = NETWORK_STATUS_GOOD;
197     }
198     else
199     {
200         networkStatus = NETWORK_STATUS_NORMAL;
201     }
202 
203     IMLOGD_PACKET6(IM_PACKET_LOG_JITTER,
204             "[GetNextJitterBufferSize] size[%4.2f], mean[%4.2f], dev[%4.2f], max[%d], curr[%d], "
205             "status[%d]",
206             calcJitterSize, mean, dev, maxJitter, nCurrJitterBufferSize, networkStatus);
207 
208     switch (networkStatus)
209     {
210         case NETWORK_STATUS_BAD:
211         {
212             if (mBadStatusChangedTime == 0 ||
213                     (currentTime - mBadStatusChangedTime) >= mBufferIncThreshold)
214             {
215                 nextJitterBuffer = (calcJitterSize + PACKET_INTERVAL) / PACKET_INTERVAL;
216 
217                 if (nextJitterBuffer > mMaxJitterBufferSize)
218                 {
219                     nextJitterBuffer = mMaxJitterBufferSize;
220                 }
221 
222                 if (nextJitterBuffer < mMinJitterBufferSize)
223                 {
224                     nextJitterBuffer = mMinJitterBufferSize;
225                 }
226 
227                 IMLOGD_PACKET2(IM_PACKET_LOG_JITTER,
228                         "[GetNextJitterBufferSize] increase curr[%d], next[%d]",
229                         nCurrJitterBufferSize, nextJitterBuffer);
230                 mBadStatusChangedTime = currentTime;
231             }
232 
233             break;
234         }
235         case NETWORK_STATUS_GOOD:
236         {
237             if (mNetworkStatus != NETWORK_STATUS_GOOD)
238             {
239                 mGoodStatusEnteringTime = currentTime;
240             }
241             else
242             {
243                 uint32_t nTimeDiff = currentTime - mGoodStatusEnteringTime;
244 
245                 if (nTimeDiff >= mBufferDecThreshold &&
246                         (mTimeLateArrivals == 0 ||
247                                 currentTime - mTimeLateArrivals > mBufferDecThreshold))
248                 {
249                     if (nCurrJitterBufferSize > mMinJitterBufferSize)
250                     {
251                         nextJitterBuffer = nCurrJitterBufferSize - mBufferStepSize;
252                     }
253 
254                     IMLOGD_PACKET2(IM_PACKET_LOG_JITTER,
255                             "[GetNextJitterBufferSize] decrease curr[%d], next[%d]",
256                             nCurrJitterBufferSize, nextJitterBuffer);
257                     networkStatus = NETWORK_STATUS_NORMAL;
258                 }
259             }
260 
261             break;
262         }
263         default:
264             nextJitterBuffer = nCurrJitterBufferSize;
265             break;
266     }
267 
268     mNetworkStatus = networkStatus;
269     return nextJitterBuffer;
270 }
271