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