• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef MEDIA_QUALITY_ANALYZER_H_INCLUDED
18 #define MEDIA_QUALITY_ANALYZER_H_INCLUDED
19 
20 #include <CallQuality.h>
21 #include <ImsMediaDefine.h>
22 #include <IImsMediaThread.h>
23 #include <ImsMediaCondition.h>
24 #include <RtcpXrEncoder.h>
25 #include <BaseSessionCallback.h>
26 #include <AudioConfig.h>
27 #include <MediaQualityThreshold.h>
28 #include <MediaQualityStatus.h>
29 #include <list>
30 #include <vector>
31 #include <mutex>
32 #include <algorithm>
33 
34 class HysteresisTimeChecker
35 {
36 public:
37     HysteresisTimeChecker(int32_t time = 0)
38     {
39         hysteresisTime = time;
40         countHysteresisTime = hysteresisTime;
41         notifiedDirection = 1;
42         firstNotified = false;
43         previousValue = 0;
44     }
45 
initialize(int32_t time)46     void initialize(int32_t time)
47     {
48         hysteresisTime = time;
49         countHysteresisTime = hysteresisTime;
50         notifiedDirection = 1;
51         firstNotified = false;
52         previousValue = 0;
53     }
54 
~HysteresisTimeChecker()55     ~HysteresisTimeChecker() {}
56 
checkNotifiable(std::vector<int32_t> thresholds,int32_t currentValue)57     bool checkNotifiable(std::vector<int32_t> thresholds, int32_t currentValue)
58     {
59         if (thresholds.empty())
60         {
61             return false;
62         }
63 
64         bool notifiable = false;
65 
66         // cross the threshold case
67         auto iterCrossed = find_if(thresholds.begin(), thresholds.end(),
68                 [=](int32_t thres)
69                 {
70                     return ((currentValue >= thres && previousValue < thres) ||
71                             (currentValue < thres && previousValue >= thres));
72                 });
73 
74         if (iterCrossed != thresholds.end())
75         {
76             uint32_t currentDirection = (currentValue - previousValue) > 0 ? 1 : 0;
77 
78             if (countHysteresisTime >= hysteresisTime || currentDirection == notifiedDirection)
79             {
80                 if (!firstNotified)
81                 {
82                     firstNotified = true;
83                 }
84 
85                 previousValue = currentValue;
86                 countHysteresisTime = 0;
87                 notifiedDirection = currentDirection;
88                 notifiable = true;
89             }
90 
91             countHysteresisTime++;
92         }
93         else
94         {
95             if (firstNotified)
96             {
97                 countHysteresisTime = 1;
98             }
99         }
100 
101         return notifiable;
102     }
103 
104     int32_t hysteresisTime;
105     int32_t countHysteresisTime;
106     int32_t previousValue;
107     uint32_t notifiedDirection;
108     bool firstNotified;
109 };
110 
111 class MediaQualityAnalyzer : public IImsMediaThread
112 {
113 public:
114     MediaQualityAnalyzer();
115     virtual ~MediaQualityAnalyzer();
116 
117     /**
118      * @brief Set the session callback to send the event
119      */
120     void setCallback(BaseSessionCallback* callback);
121 
122     /**
123      * @brief Sets the audio codec type
124      * @param config The AudioConfig to set
125      */
126     void setConfig(AudioConfig* config);
127 
128     /**
129      * @brief Set the MediaQualityThreshold
130      */
131     void setMediaQualityThreshold(const MediaQualityThreshold& threshold);
132 
133     /**
134      * @brief Check the audio config has different codec values
135      *
136      * @param config The AudioConfig to compare
137      */
138     bool isSameConfig(AudioConfig* config);
139 
140     /**
141      * @brief Start for calculating statistics from collected datas
142      */
143     void start();
144 
145     /**
146      * @brief Stop calculating the statistics from collected datas and send a report
147      */
148     void stop();
149 
150     /**
151      * @brief Collect information of sending or receiving the rtp or the rtcp packet datas.
152      *
153      * @param streamType The stream type. Tx, Rx, Rtcp.
154      * @param packet The packet data struct.
155      */
156     void collectInfo(const int32_t streamType, RtpPacket* packet);
157 
158     /**
159      * @brief Collect optional information of sending or receiving the rtp or rtcp packet datas.
160      *
161      * @param optionType The optional type to collect. The TTL or the Round Trip delay.
162      * @param seq The sequence number of the packet to collect.
163      * @param value The optional value to collect.
164      */
165     void collectOptionalInfo(const int32_t optionType, const int32_t seq, const int32_t value);
166 
167     /**
168      * @brief Collects Rtp status determined from the jitter buffer.
169      *
170      * @param seq The packet sequence number to collect.
171      * @param status The status of the packet. Check in @link{kRtpPacketStatus}
172      * @param time The time marked when the frame was played in milliseconds unit
173      */
174     void collectRxRtpStatus(const int32_t seq, const kRtpPacketStatus status, const uint32_t time);
175 
176     /**
177      * @brief Collects jitter buffer size.
178      *
179      * @param currSize The current size of the jitter buffer.
180      * @param maxSize The maximum jitter buffer size.
181      */
182     void collectJitterBufferSize(const int32_t currSize, const int32_t maxSize);
183 
184     /**
185      * @brief generate  Rtcp-Xr report blocks with given report block enabled in bitmask type
186      *
187      * @param nReportBlocks The bitmask of report block to creates
188      * @param data The byte array of total report blocks
189      * @param size The size of total report blocks together
190      * @return true The report block is not zero and data is valid
191      * @return false The report block is zero or got error during create the report block
192      */
193     bool getRtcpXrReportBlock(const uint32_t nReportBlocks, uint8_t* data, uint32_t& size);
194 
195     /**
196      * @brief Get the CallQuality member instance
197      */
198     CallQuality getCallQuality();
199 
200     /**
201      * @brief Get number of rx packets in the list
202      */
203     uint32_t getRxPacketSize();
204 
205     /**
206      * @brief Get number of tx packets in the list
207      */
208     uint32_t getTxPacketSize();
209 
210     /**
211      * @brief Get number of lost packets in the list
212      */
213     uint32_t getLostPacketSize();
214 
215     /**
216      * @brief Send message event to event handler
217      *
218      * @param event The event type
219      * @param paramA The 1st parameter
220      * @param paramB The 2nd parameter
221      */
222     void SendEvent(uint32_t event, uint64_t paramA, uint64_t paramB = 0);
223 
224 protected:
225     /**
226      * @brief Process the data stacked in the list
227      *
228      * @param timeCount The count increased every second
229      */
230     void processData(const int32_t timeCount);
231     void processMediaQuality();
232     void notifyCallQuality();
233     void notifyMediaQualityStatus();
234     void AddEvent(uint32_t event, uint64_t paramA, uint64_t paramB);
235     void processEvent(uint32_t event, uint64_t paramA, uint64_t paramB);
236     virtual void* run();
237     void reset();
238     void clearPacketList(std::list<RtpPacket*>& list, const int32_t seq);
239     void clearLostPacketList(const int32_t seq);
240     uint32_t getCallQuality(double lossRate);
241     int32_t convertAudioCodecType(const int32_t codec, const int32_t bandwidth);
242 
243     BaseSessionCallback* mCallback;
244     std::unique_ptr<RtcpXrEncoder> mRtcpXrEncoder;
245     /** The list of the packets received ordered by arrival time */
246     std::list<RtpPacket*> mListRxPacket;
247     /** The list of the lost packets object */
248     std::list<LostPacket*> mListLostPacket;
249     /** The list of the packets sent */
250     std::list<RtpPacket*> mListTxPacket;
251     /** The time of call started in milliseconds unit*/
252     int32_t mTimeStarted;
253     /** The ssrc of the receiving Rtp stream to identify */
254     int32_t mSSRC;
255     /** The codec type of the audio session retrieved from the AudioConfig.h */
256     int32_t mCodecType;
257     /** The codec attribute of the audio session, it could be bandwidth in evs codec */
258     int32_t mCodecAttribute;
259     /** Whether RTP is activated for the receiver or not */
260     bool mIsRxRtpEnabled;
261     /** Whether RTCP is activated for both sender and receiver */
262     bool mIsRtcpEnabled;
263     /** The begin of the rx rtp packet sequence number for Rtcp-Xr report */
264     int32_t mBeginSeq;
265     /** The end of the rx rtp packet sequence number for Rtcp-Xr report */
266     int32_t mEndSeq;
267     /** The call quality structure to report */
268     CallQuality mCallQuality;
269     /** The sum of the relative jitter of rx packet for call quality */
270     int64_t mCallQualitySumRelativeJitter;
271     /** The sum of the round trip delay of the session for call quality */
272     uint64_t mSumRoundTripTime;
273     /** The number of the round trip delay of the session for call quality */
274     uint32_t mCountRoundTripTime;
275     /** The current jitter buffer size in milliseconds unit */
276     uint32_t mCurrentBufferSize;
277     /** The maximum jitter buffer size in milliseconds unit */
278     uint32_t mMaxBufferSize;
279     /** The number of rx packet received for call quality calculation */
280     uint32_t mCallQualityNumRxPacket;
281     /** The number of lost rx packet for call quality calculation */
282     uint32_t mCallQualityNumLostPacket;
283 
284     // MediaQualityThreshold parameters
285     std::vector<int32_t> mBaseRtpInactivityTimes;
286     std::vector<int32_t> mCurrentRtpInactivityTimes;
287     int32_t mRtcpInactivityTime;
288     int32_t mRtpHysteresisTime;
289     int32_t mPacketLossDuration;
290     std::vector<int32_t> mPacketLossThreshold;
291     std::vector<int32_t> mJitterThreshold;
292     bool mNotifyStatus;
293 
294     // Counter for inactivity check
295     int32_t mCountRtpInactivity;
296     int32_t mCountRtcpInactivity;
297 
298     /** The MediaQualityStatus structure to report */
299     MediaQualityStatus mQualityStatus;
300 
301     /** The number of received packet to check packet loss notification */
302     uint32_t mNumRxPacket;
303     /** The number of lost packet to check packet loss notification */
304     uint32_t mNumLostPacket;
305     /** The cumulated jitter value when any rx packet received */
306     double mJitterRxPacket;
307     /** The number of rtcp packet received */
308     uint32_t mNumRtcpPacketReceived;
309 
310     HysteresisTimeChecker mPacketLossChecker;
311     HysteresisTimeChecker mJitterChecker;
312 
313     // event parameters
314     std::list<uint32_t> mListevent;
315     std::list<uint64_t> mListParamA;
316     std::list<uint64_t> mListParamB;
317     std::mutex mEventMutex;
318     ImsMediaCondition mConditionExit;
319 };
320 
321 #endif