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 }