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 <TextJitterBuffer.h>
18 #include <ImsMediaTrace.h>
19 
TextJitterBuffer()20 TextJitterBuffer::TextJitterBuffer() :
21         BaseJitterBuffer()
22 {
23 }
24 
~TextJitterBuffer()25 TextJitterBuffer::~TextJitterBuffer() {}
26 
Add(ImsMediaSubType subtype,uint8_t * buffer,uint32_t size,uint32_t timestamp,bool mark,uint32_t seqNum,ImsMediaSubType,uint32_t arrivalTime)27 void TextJitterBuffer::Add(ImsMediaSubType subtype, uint8_t* buffer, uint32_t size,
28         uint32_t timestamp, bool mark, uint32_t seqNum, ImsMediaSubType /*dataType*/,
29         uint32_t arrivalTime)
30 {
31     if (subtype == MEDIASUBTYPE_REFRESHED)
32     {
33         mSsrc = size;
34         IMLOGI1("[Add] ssrc[%u]", mSsrc);
35         Reset();
36         return;
37     }
38 
39     IMLOGD_PACKET6(IM_PACKET_LOG_JITTER,
40             "[Add] seq[%u], mark[%u], TS[%u], size[%u], lastPlayedSeq[%u], arrivalTime[%u]", seqNum,
41             mark, timestamp, size, mLastPlayedSeqNum, arrivalTime);
42 
43     std::lock_guard<std::mutex> guard(mMutex);
44 
45     if (mFirstFrameReceived && USHORT_SEQ_ROUND_COMPARE(mLastPlayedSeqNum, seqNum))
46     {
47         IMLOGD_PACKET2(IM_PACKET_LOG_JITTER, "[Add] receive old frame, seq[%u], LastPlayedSeq[%u]",
48                 seqNum, mLastPlayedSeqNum);
49         return;
50     }
51 
52     DataEntry currEntry = DataEntry();
53     currEntry.subtype = subtype;
54     currEntry.pbBuffer = buffer;
55     currEntry.nBufferSize = size;
56     currEntry.nTimestamp = timestamp;
57     currEntry.bMark = mark;
58     currEntry.nSeqNum = seqNum;
59     currEntry.bHeader = true;
60     currEntry.bValid = true;
61     currEntry.arrivalTime = arrivalTime;
62 
63     if (mDataQueue.GetCount() == 0)  // jitter buffer is empty
64     {
65         mDataQueue.Add(&currEntry);
66     }
67     else
68     {
69         DataEntry* pEntry = nullptr;
70         mDataQueue.GetLast(&pEntry);
71 
72         if (pEntry == nullptr)
73         {
74             return;
75         }
76 
77         if (USHORT_SEQ_ROUND_COMPARE(pEntry->nSeqNum, seqNum))  // a >= b
78         {
79             uint32_t i = 0;
80             mDataQueue.SetReadPosFirst();
81 
82             while (mDataQueue.GetNext(&pEntry))
83             {
84                 if (seqNum == pEntry->nSeqNum)
85                 {
86                     IMLOGD_PACKET1(IM_PACKET_LOG_JITTER, "[Add] Redundant seq[%u]", seqNum);
87                     break;
88                 }
89                 else if (!USHORT_SEQ_ROUND_COMPARE(seqNum, pEntry->nSeqNum))
90                 {
91                     IMLOGD_PACKET2(IM_PACKET_LOG_JITTER, "[Add] InsertAt[%u] seq[%u]", i, seqNum);
92                     mDataQueue.InsertAt(i, &currEntry);
93                     break;
94                 }
95                 i++;
96             }
97         }
98         else  // a < b
99         {
100             IMLOGD_PACKET1(
101                     IM_PACKET_LOG_JITTER, "[Add] current data is the latest seq[%u]", seqNum);
102             mDataQueue.Add(&currEntry);
103         }
104     }
105 }
106 
Get(ImsMediaSubType * subtype,uint8_t ** data,uint32_t * dataSize,uint32_t * timestamp,bool * mark,uint32_t * seqNum,uint32_t,ImsMediaSubType *)107 bool TextJitterBuffer::Get(ImsMediaSubType* subtype, uint8_t** data, uint32_t* dataSize,
108         uint32_t* timestamp, bool* mark, uint32_t* seqNum, uint32_t /*currentTime*/,
109         ImsMediaSubType* /*pDataType*/)
110 {
111     std::lock_guard<std::mutex> guard(mMutex);
112     DataEntry* pEntry;
113 
114     if (mDataQueue.Get(&pEntry) == true && pEntry != nullptr)
115     {
116         if (subtype)
117             *subtype = pEntry->subtype;
118         if (data)
119             *data = pEntry->pbBuffer;
120         if (dataSize)
121             *dataSize = pEntry->nBufferSize;
122         if (timestamp)
123             *timestamp = pEntry->nTimestamp;
124         if (mark)
125             *mark = pEntry->bMark;
126         if (seqNum)
127             *seqNum = pEntry->nSeqNum;
128 
129         IMLOGD_PACKET5(IM_PACKET_LOG_JITTER,
130                 "[Get] OK - seq[%u], mark[%u], TS[%u], size[%u], queue[%u]", pEntry->nSeqNum,
131                 pEntry->bMark, pEntry->nTimestamp, pEntry->nBufferSize, mDataQueue.GetCount());
132 
133         return true;
134     }
135     else
136     {
137         if (subtype)
138             *subtype = MEDIASUBTYPE_UNDEFINED;
139         if (data)
140             *data = nullptr;
141         if (dataSize)
142             *dataSize = 0;
143         if (timestamp)
144             *timestamp = 0;
145         if (mark)
146             *mark = false;
147         if (seqNum)
148             *seqNum = 0;
149 
150         IMLOGD_PACKET0(IM_PACKET_LOG_JITTER, "[Get] fail");
151 
152         return false;
153     }
154 }
155 
Delete()156 void TextJitterBuffer::Delete()
157 {
158     DataEntry* pEntry;
159     std::lock_guard<std::mutex> guard(mMutex);
160     mDataQueue.Get(&pEntry);
161 
162     if (pEntry == nullptr)
163     {
164         return;
165     }
166 
167     if (!mFirstFrameReceived)
168     {
169         mFirstFrameReceived = true;
170     }
171 
172     mLastPlayedSeqNum = pEntry->nSeqNum;
173     mLastPlayedTimestamp = pEntry->nTimestamp;
174     mDataQueue.Delete();
175 }