summaryrefslogtreecommitdiff
path: root/service/src/com/android/telephony/imsmedia/lib/libimsmedia/core/include/audio/MediaQualityAnalyzer.h
blob: feff489235d221953abec79e8b70e13f8c9f8c55 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
/**
 * Copyright (C) 2022 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef MEDIA_QUALITY_ANALYZER_H_INCLUDED
#define MEDIA_QUALITY_ANALYZER_H_INCLUDED

#include <CallQuality.h>
#include <ImsMediaDefine.h>
#include <IImsMediaThread.h>
#include <ImsMediaCondition.h>
#include <RtcpXrEncoder.h>
#include <BaseSessionCallback.h>
#include <AudioConfig.h>
#include <MediaQualityThreshold.h>
#include <MediaQualityStatus.h>
#include <list>
#include <vector>
#include <mutex>
#include <algorithm>

class HysteresisTimeChecker
{
public:
    HysteresisTimeChecker(int32_t time = 0)
    {
        hysteresisTime = time;
        countHysteresisTime = hysteresisTime;
        notifiedDirection = 1;
        firstNotified = false;
        previousValue = 0;
    }

    void initialize(int32_t time)
    {
        hysteresisTime = time;
        countHysteresisTime = hysteresisTime;
        notifiedDirection = 1;
        firstNotified = false;
        previousValue = 0;
    }

    ~HysteresisTimeChecker() {}

    bool checkNotifiable(std::vector<int32_t> thresholds, int32_t currentValue)
    {
        if (thresholds.empty())
        {
            return false;
        }

        bool notifiable = false;

        // cross the threshold case
        auto iterCrossed = find_if(thresholds.begin(), thresholds.end(),
                [=](int32_t thres)
                {
                    return ((currentValue >= thres && previousValue < thres) ||
                            (currentValue < thres && previousValue >= thres));
                });

        if (iterCrossed != thresholds.end())
        {
            uint32_t currentDirection = (currentValue - previousValue) > 0 ? 1 : 0;

            if (countHysteresisTime >= hysteresisTime || currentDirection == notifiedDirection)
            {
                if (!firstNotified)
                {
                    firstNotified = true;
                }

                previousValue = currentValue;
                countHysteresisTime = 0;
                notifiedDirection = currentDirection;
                notifiable = true;
            }

            countHysteresisTime++;
        }
        else
        {
            if (firstNotified)
            {
                countHysteresisTime = 1;
            }
        }

        return notifiable;
    }

    int32_t hysteresisTime;
    int32_t countHysteresisTime;
    int32_t previousValue;
    uint32_t notifiedDirection;
    bool firstNotified;
};

class MediaQualityAnalyzer : public IImsMediaThread
{
public:
    MediaQualityAnalyzer();
    virtual ~MediaQualityAnalyzer();

    /**
     * @brief Set the session callback to send the event
     */
    void setCallback(BaseSessionCallback* callback);

    /**
     * @brief Sets the audio codec type
     * @param config The AudioConfig to set
     */
    void setConfig(AudioConfig* config);

    /**
     * @brief Set the MediaQualityThreshold
     */
    void setMediaQualityThreshold(const MediaQualityThreshold& threshold);

    /**
     * @brief Check the audio config has different codec values
     *
     * @param config The AudioConfig to compare
     */
    bool isSameConfig(AudioConfig* config);

    /**
     * @brief Start for calculating statistics from collected datas
     */
    void start();

    /**
     * @brief Stop calculating the statistics from collected datas and send a report
     */
    void stop();

    /**
     * @brief Collect information of sending or receiving the rtp or the rtcp packet datas.
     *
     * @param streamType The stream type. Tx, Rx, Rtcp.
     * @param packet The packet data struct.
     */
    void collectInfo(const int32_t streamType, RtpPacket* packet);

    /**
     * @brief Collect optional information of sending or receiving the rtp or rtcp packet datas.
     *
     * @param optionType The optional type to collect. The TTL or the Round Trip delay.
     * @param seq The sequence number of the packet to collect.
     * @param value The optional value to collect.
     */
    void collectOptionalInfo(const int32_t optionType, const int32_t seq, const int32_t value);

    /**
     * @brief Collects Rtp status determined from the jitter buffer.
     *
     * @param seq The packet sequence number to collect.
     * @param status The status of the packet. Check in @link{kRtpPacketStatus}
     * @param time The time marked when the frame was played in milliseconds unit
     */
    void collectRxRtpStatus(const int32_t seq, const kRtpPacketStatus status, const uint32_t time);

    /**
     * @brief Collects jitter buffer size.
     *
     * @param currSize The current size of the jitter buffer.
     * @param maxSize The maximum jitter buffer size.
     */
    void collectJitterBufferSize(const int32_t currSize, const int32_t maxSize);

    /**
     * @brief generate  Rtcp-Xr report blocks with given report block enabled in bitmask type
     *
     * @param nReportBlocks The bitmask of report block to creates
     * @param data The byte array of total report blocks
     * @param size The size of total report blocks together
     * @return true The report block is not zero and data is valid
     * @return false The report block is zero or got error during create the report block
     */
    bool getRtcpXrReportBlock(const uint32_t nReportBlocks, uint8_t* data, uint32_t& size);

    /**
     * @brief Get the CallQuality member instance
     */
    CallQuality getCallQuality();

    /**
     * @brief Get number of rx packets in the list
     */
    uint32_t getRxPacketSize();

    /**
     * @brief Get number of tx packets in the list
     */
    uint32_t getTxPacketSize();

    /**
     * @brief Get number of lost packets in the list
     */
    uint32_t getLostPacketSize();

    /**
     * @brief Send message event to event handler
     *
     * @param event The event type
     * @param paramA The 1st parameter
     * @param paramB The 2nd parameter
     */
    void SendEvent(uint32_t event, uint64_t paramA, uint64_t paramB = 0);

protected:
    /**
     * @brief Process the data stacked in the list
     *
     * @param timeCount The count increased every second
     */
    void processData(const int32_t timeCount);
    void processMediaQuality();
    void notifyCallQuality();
    void notifyMediaQualityStatus();
    void AddEvent(uint32_t event, uint64_t paramA, uint64_t paramB);
    void processEvent(uint32_t event, uint64_t paramA, uint64_t paramB);
    virtual void* run();
    void reset();
    void clearPacketList(std::list<RtpPacket*>& list, const int32_t seq);
    void clearLostPacketList(const int32_t seq);
    uint32_t getCallQuality(double lossRate);
    int32_t convertAudioCodecType(const int32_t codec, const int32_t bandwidth);

    BaseSessionCallback* mCallback;
    std::unique_ptr<RtcpXrEncoder> mRtcpXrEncoder;
    /** The list of the packets received ordered by arrival time */
    std::list<RtpPacket*> mListRxPacket;
    /** The list of the lost packets object */
    std::list<LostPacket*> mListLostPacket;
    /** The list of the packets sent */
    std::list<RtpPacket*> mListTxPacket;
    /** The time of call started in milliseconds unit*/
    int32_t mTimeStarted;
    /** The ssrc of the receiving Rtp stream to identify */
    int32_t mSSRC;
    /** The codec type of the audio session retrieved from the AudioConfig.h */
    int32_t mCodecType;
    /** The codec attribute of the audio session, it could be bandwidth in evs codec */
    int32_t mCodecAttribute;
    /** Whether RTP is activated for the receiver or not */
    bool mIsRxRtpEnabled;
    /** Whether RTCP is activated for both sender and receiver */
    bool mIsRtcpEnabled;
    /** The begin of the rx rtp packet sequence number for Rtcp-Xr report */
    int32_t mBeginSeq;
    /** The end of the rx rtp packet sequence number for Rtcp-Xr report */
    int32_t mEndSeq;
    /** The call quality structure to report */
    CallQuality mCallQuality;
    /** The sum of the relative jitter of rx packet for call quality */
    int64_t mCallQualitySumRelativeJitter;
    /** The sum of the round trip delay of the session for call quality */
    uint64_t mSumRoundTripTime;
    /** The number of the round trip delay of the session for call quality */
    uint32_t mCountRoundTripTime;
    /** The current jitter buffer size in milliseconds unit */
    uint32_t mCurrentBufferSize;
    /** The maximum jitter buffer size in milliseconds unit */
    uint32_t mMaxBufferSize;
    /** The number of rx packet received for call quality calculation */
    uint32_t mCallQualityNumRxPacket;
    /** The number of lost rx packet for call quality calculation */
    uint32_t mCallQualityNumLostPacket;

    // MediaQualityThreshold parameters
    std::vector<int32_t> mBaseRtpInactivityTimes;
    std::vector<int32_t> mCurrentRtpInactivityTimes;
    int32_t mRtcpInactivityTime;
    int32_t mRtpHysteresisTime;
    int32_t mPacketLossDuration;
    std::vector<int32_t> mPacketLossThreshold;
    std::vector<int32_t> mJitterThreshold;
    bool mNotifyStatus;

    // Counter for inactivity check
    int32_t mCountRtpInactivity;
    int32_t mCountRtcpInactivity;

    /** The MediaQualityStatus structure to report */
    MediaQualityStatus mQualityStatus;

    /** The number of received packet to check packet loss notification */
    uint32_t mNumRxPacket;
    /** The number of lost packet to check packet loss notification */
    uint32_t mNumLostPacket;
    /** The cumulated jitter value when any rx packet received */
    double mJitterRxPacket;
    /** The number of rtcp packet received */
    uint32_t mNumRtcpPacketReceived;

    HysteresisTimeChecker mPacketLossChecker;
    HysteresisTimeChecker mJitterChecker;

    // event parameters
    std::list<uint32_t> mListevent;
    std::list<uint64_t> mListParamA;
    std::list<uint64_t> mListParamB;
    std::mutex mEventMutex;
    ImsMediaCondition mConditionExit;
};

#endif