1 /*
2 * Copyright (C) 2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "fillp_frame.h"
17 #include "fillp_common.h"
18
19 #define FRAME_VIDEO_FRAME_TYPE_STR(_type) (((_type) == VIDEO_I) ? "I" : "P")
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
FillpFrameInit(struct FillpFrameHandle * h)25 void FillpFrameInit(struct FillpFrameHandle *h)
26 {
27 if (h != FILLP_NULL_PTR) {
28 (void)memset_s(h, sizeof(struct FillpFrameHandle), 0, sizeof(struct FillpFrameHandle));
29 }
30 }
31
FillpFrameItemHold(struct FillpFrameItem * frameItem)32 static inline void FillpFrameItemHold(struct FillpFrameItem *frameItem)
33 {
34 FILLP_INT refCnt = SYS_ARCH_ATOMIC_INC(&frameItem->refCnt, 1);
35 FILLP_LOGDBG("item refcnt: %d, seq: %d", refCnt, frameItem->info.seqNum);
36 }
37
FillpFrameItemPut(struct FillpFrameItem * frameItem)38 void FillpFrameItemPut(struct FillpFrameItem *frameItem)
39 {
40 if (frameItem != FILLP_NULL_PTR) {
41 if (SYS_ARCH_ATOMIC_DEC_AND_TEST(&frameItem->refCnt)) {
42 FILLP_LOGDBG("free frame item of seq: %d", frameItem->info.seqNum);
43 SpungeFree(frameItem, SPUNGE_ALLOC_TYPE_CALLOC);
44 }
45 }
46 }
47
FillpFrameItemAlloc(FILLP_CONST struct FrameInfo * frame)48 struct FillpFrameItem *FillpFrameItemAlloc(FILLP_CONST struct FrameInfo *frame)
49 {
50 struct FillpFrameItem *frameItem = FILLP_NULL_PTR;
51
52 if (frame != FILLP_NULL_PTR) {
53 frameItem = SpungeAlloc(1, sizeof(struct FillpFrameItem), SPUNGE_ALLOC_TYPE_CALLOC);
54 if (frameItem == FILLP_NULL_PTR) {
55 FILLP_LOGERR("alloc frame item failed, seq: %d", frame->seqNum);
56 } else {
57 frameItem->info = *frame;
58 /* hold the frame item until the sending of socket app ended */
59 FillpFrameItemHold(frameItem);
60 FILLP_LOGDBG("alloc frame item succeeded, seq: %d", frame->seqNum);
61 }
62 }
63
64 return frameItem;
65 }
66
FillpFrameItemReference(struct FillpPcbItem * item,struct FillpFrameItem * frameItem)67 void FillpFrameItemReference(struct FillpPcbItem *item, struct FillpFrameItem *frameItem)
68 {
69 if (frameItem != FILLP_NULL_PTR) {
70 FillpFrameItemHold(frameItem);
71 item->frame = frameItem;
72 } else {
73 item->frame = FILLP_NULL_PTR;
74 }
75 }
76
FillpFrameAddItemStats(struct FillpFrameHandle * h,FILLP_INT frameType,FILLP_UINT32 size,FILLP_BOOL newFrame)77 static void FillpFrameAddItemStats(struct FillpFrameHandle *h, FILLP_INT frameType,
78 FILLP_UINT32 size, FILLP_BOOL newFrame)
79 {
80 if (frameType == VIDEO_I) {
81 if (newFrame) {
82 h->stats.iFrameCount++;
83 }
84 h->stats.iFrameTotalSize += size;
85 } else {
86 if (newFrame) {
87 h->stats.pFrameCount++;
88 }
89 h->stats.pFrameTotalSize += size;
90 }
91 }
92
FillpFrameAddItem(struct FillpFrameHandle * h,struct FillpPcbItem * item)93 FILLP_INT FillpFrameAddItem(struct FillpFrameHandle *h, struct FillpPcbItem *item)
94 {
95 struct FrameInfo *info = FILLP_NULL_PTR;
96
97 if (item->frame == FILLP_NULL_PTR || !FILLP_FRAME_IS_VIDEO(item->frame->info.frameType)) {
98 return NONE;
99 }
100
101 info = &item->frame->info;
102
103 if (UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_FIRST_PKT)) {
104 FillpFrameAddItemStats(h, info->frameType, item->frame->fragSize,
105 UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_FRAME_FIRST_FRAG_START));
106 }
107
108 /* check FRAME_FLAGS_FIRST_FRAG_START after FRAME_FLAGS_FIRST_FRAG_PKT to statistics the fragment */
109 if (!UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_FRAME_FIRST_FRAG_START)) {
110 return NONE;
111 }
112
113 return info->frameType;
114 }
115
FillpFrameFreeItem(struct FillpPcbItem * item)116 void FillpFrameFreeItem(struct FillpPcbItem *item)
117 {
118 FillpFrameItemPut(item->frame);
119 item->frame = FILLP_NULL_PTR;
120 }
121
FillpFrameTxInitItem(struct FillpFrameHandle * h,struct FillpPcbItem * item,const struct FrameInfo * info,FILLP_UINT32 fragSize,FILLP_BOOL firstPkt)122 void FillpFrameTxInitItem(struct FillpFrameHandle *h, struct FillpPcbItem *item,
123 const struct FrameInfo *info, FILLP_UINT32 fragSize, FILLP_BOOL firstPkt)
124 {
125 if (item->frame != FILLP_NULL_PTR && info != FILLP_NULL_PTR && FILLP_FRAME_IS_VIDEO(info->frameType)) {
126 item->frame->fragSize = fragSize;
127
128 if (firstPkt) {
129 if (h->curFrame.info.size == 0 || (FILLP_UINT32)info->seqNum != h->curFrame.info.seqNum) {
130 FILLP_LOGDBG("start sending a new frame, seq: %d", info->seqNum);
131 UTILS_FLAGS_SET(item->flags, FILLP_ITEM_FLAGS_FRAME_FIRST_FRAG_START);
132 h->curFrame.info.type = info->frameType;
133 h->curFrame.info.seqNum = (FILLP_UINT32)info->seqNum;
134 h->curFrame.info.size = fragSize;
135 h->curFrame.info.fragCnt = 1;
136 } else {
137 h->curFrame.info.size += fragSize;
138 h->curFrame.info.fragCnt++;
139 }
140
141 if (UTILS_FLAGS_CHECK(info->bitMap, FRAME_INFO_BITMAP_FRAME_END)) {
142 UTILS_FLAGS_SET(item->flags, FILLP_ITEM_FLAGS_FRAME_LAST_FRAG_START);
143 FILLP_LOGDBG("frame %d end, total size: %u", info->seqNum, h->curFrame.info.size);
144 }
145
146 UTILS_FLAGS_SET(item->dataOptFlag, FILLP_OPT_FLAG_FRAME_INFO);
147 FILLP_LOGDBG("set the first pkt flag of seq: %d, seqNo %d", info->seqNum, info->subSeqNum);
148 }
149 }
150 }
151
FillpFrameGetPktDataOptLen(FILLP_UINT32 flag,FILLP_UINT32 pktDataOptLen)152 FILLP_UINT32 FillpFrameGetPktDataOptLen(FILLP_UINT32 flag, FILLP_UINT32 pktDataOptLen)
153 {
154 FILLP_UINT32 optLen = pktDataOptLen;
155 if (UTILS_FLAGS_CHECK(flag, FILLP_OPT_FLAG_FRAME_INFO)) {
156 optLen = UTILS_MAX(pktDataOptLen, FILLP_DATA_OFFSET_LEN);
157 optLen += FILLP_OPT_FRAME_INFO_LEN + FILLP_DATA_OPT_HLEN;
158 }
159
160 return optLen;
161 }
162
FillpFrameBuildOption(const struct FillpPcbItem * item,FILLP_UINT8 * option)163 FILLP_UINT16 FillpFrameBuildOption(const struct FillpPcbItem *item, FILLP_UINT8 *option)
164 {
165 const struct FrameInfo *info = FILLP_NULL_PTR;
166 FillpDataOption *dataOpt = FILLP_NULL_PTR;
167 struct FillpFrameDataOption *frameOpt = FILLP_NULL_PTR;
168
169 info = &item->frame->info;
170 dataOpt = (FillpDataOption *)option;
171 dataOpt->type = FILLP_OPT_FRAME_INFO;
172 dataOpt->len = FILLP_OPT_FRAME_INFO_LEN;
173
174 frameOpt = (struct FillpFrameDataOption *)&dataOpt->value[0];
175 frameOpt->frameType = (FILLP_UINT8)info->frameType;
176 frameOpt->level = (FILLP_UINT8)info->level;
177 frameOpt->seqNum = FILLP_HTONS((FILLP_UINT16)info->seqNum);
178 frameOpt->subSeqNum = (FILLP_UINT8)info->subSeqNum;
179 frameOpt->bitMap = (FILLP_UINT8)(item->flags & FILLP_ITEM_FLAGS_FRAME_OPT_BITMAP_MASK);
180 frameOpt->fragSize = FILLP_HTONL(item->frame->fragSize);
181 frameOpt->txTimestamp = FILLP_HTONL((FILLP_UINT32)info->timestamp);
182
183 FILLP_LOGDTL("fill option of frame %s, seq: %d, seqNo: %d, bitmap: 0x%x",
184 FRAME_VIDEO_FRAME_TYPE_STR(info->frameType), info->seqNum, info->subSeqNum, frameOpt->bitMap);
185
186 return (FILLP_UINT16)(FILLP_DATA_OPT_HLEN + FILLP_OPT_FRAME_INFO_LEN);
187 }
188
FillpFrameParseOption(struct FillpFrameHandle * h,struct FillpPcbItem * item,FILLP_UINT8 * option,FILLP_UINT8 optLen)189 FILLP_INT FillpFrameParseOption(struct FillpFrameHandle *h,
190 struct FillpPcbItem *item, FILLP_UINT8 *option, FILLP_UINT8 optLen)
191 {
192 struct FillpFrameDataOption *frameOpt = FILLP_NULL_PTR;
193 struct FillpFrameItem *frameItem = FILLP_NULL_PTR;
194 struct FrameInfo info;
195
196 if (optLen < FILLP_OPT_FRAME_INFO_LEN) {
197 FILLP_LOGERR("invalid frame info len %u, seqNum: %u, pktNum: %u", optLen, item->seqNum, item->pktNum);
198 return FILLP_EINVAL;
199 }
200
201 frameOpt = (struct FillpFrameDataOption *)option;
202
203 (void)memset_s(&info, sizeof(info), 0, sizeof(info));
204 info.frameType = frameOpt->frameType;
205 info.level = frameOpt->level;
206 info.seqNum = FILLP_NTOHS(frameOpt->seqNum);
207 info.subSeqNum = frameOpt->subSeqNum;
208 info.timestamp = FILLP_NTOHL(frameOpt->txTimestamp);
209
210 frameItem = FillpFrameItemAlloc(&info);
211 if (frameItem == FILLP_NULL_PTR) {
212 FILLP_LOGERR("alloc frame item failed, reset the rx status! seq: %d", info.seqNum);
213 h->curFrame.rxStarted = FILLP_FALSE;
214 return FILLP_OK;
215 }
216
217 frameItem->fragSize = FILLP_NTOHL(frameOpt->fragSize);
218 FILLP_LOGDBG("get a fragment, seq: %d, fragment seq: %d, size: %u, timestamp: %ld, bitmap: 0x%x",
219 frameItem->info.seqNum, frameItem->info.subSeqNum, frameItem->fragSize,
220 frameItem->info.timestamp, frameOpt->bitMap);
221
222 item->frame = frameItem;
223 UTILS_FLAGS_RESET(item->flags);
224 UTILS_FLAGS_SET(item->flags, (FILLP_UINT32)frameOpt->bitMap | FILLP_ITEM_FLAGS_FIRST_PKT);
225 return ERR_OK;
226 }
227
FillpFrameRxNewFrag(struct FillpFrame * frame,const struct FillpPcbItem * item)228 static void FillpFrameRxNewFrag(struct FillpFrame *frame, const struct FillpPcbItem *item)
229 {
230 if (UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_FRAME_FIRST_FRAG_START)) {
231 frame->rxStarted = FILLP_TRUE;
232 frame->lastFragRecvd = FILLP_FALSE;
233 frame->info.firstPktRxTime = item->rxTimeStamp;
234 frame->info.lastPktRxTime = item->rxTimeStamp;
235 frame->info.size = 0;
236 frame->info.fragCnt = 0;
237 frame->info.totalItemCnt = 0;
238 frame->info.seqNum = (FILLP_UINT32)item->frame->info.seqNum;
239 frame->info.type = item->frame->info.frameType;
240 frame->info.txTimestamp = (FILLP_UINT32)item->frame->info.timestamp;
241 }
242
243 if (!frame->rxStarted) {
244 FILLP_LOGERR("first fragment is NOT received!!!");
245 return;
246 }
247
248 frame->info.size += item->frame->fragSize;
249 frame->info.fragCnt++;
250
251 if (UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_FRAME_LAST_FRAG_START)) {
252 frame->lastFragRecvd = FILLP_TRUE;
253 }
254
255 frame->curFrag.size = item->frame->fragSize;
256 frame->curFrag.procSize = 0;
257 frame->curFrag.seqNum = (FILLP_UINT32)item->frame->info.subSeqNum;
258 }
259
FillpFrameStatistics(struct FillpFrameHandle * h)260 static inline void FillpFrameStatistics(struct FillpFrameHandle *h)
261 {
262 if (h->curFrame.info.type == VIDEO_I) {
263 h->stats.iFrameTotalSize += h->curFrame.info.size;
264 h->stats.iFrameCount++;
265 } else {
266 h->stats.pFrameTotalSize += h->curFrame.info.size;
267 h->stats.pFrameCount++;
268 }
269 }
270
FillpFrameRxUpdateAndNotify(struct FillpFrameHandle * h,const struct FillpPcbItem * item)271 static void FillpFrameRxUpdateAndNotify(struct FillpFrameHandle *h, const struct FillpPcbItem *item)
272 {
273 h->curFrame.info.totalItemCnt++;
274 h->curFrame.info.firstPktRxTime = UTILS_MIN(h->curFrame.info.firstPktRxTime, item->rxTimeStamp);
275 h->curFrame.info.lastPktRxTime = UTILS_MAX(h->curFrame.info.lastPktRxTime, item->rxTimeStamp);
276
277 h->curFrame.curFrag.procSize += item->dataLen;
278 if (h->curFrame.curFrag.size == h->curFrame.curFrag.procSize) {
279 if (h->curFrame.lastFragRecvd) {
280 FILLP_LOGINF("recv a %s frame, seq: %u, frame size: %u, fragment cnt: %u, total pkt cnt: %u,"
281 " first pkt rx time: %lld, last pkt rx time: %lld",
282 FRAME_VIDEO_FRAME_TYPE_STR(h->curFrame.info.type), h->curFrame.info.seqNum,
283 h->curFrame.info.size, h->curFrame.info.fragCnt, h->curFrame.info.totalItemCnt,
284 h->curFrame.info.firstPktRxTime, h->curFrame.info.lastPktRxTime);
285 if (h->rxCb != FILLP_NULL_PTR) {
286 h->rxCb(h->rxCbArg, &h->curFrame.info);
287 }
288
289 FillpFrameStatistics(h);
290 h->curFrame.rxStarted = FILLP_FALSE;
291 } else {
292 FILLP_LOGDBG("recv a fragment of %s frame, seq: %u, fragment seq: %u, size: %u",
293 FRAME_VIDEO_FRAME_TYPE_STR(h->curFrame.info.type),
294 h->curFrame.info.seqNum, h->curFrame.curFrag.seqNum, h->curFrame.curFrag.size);
295 }
296 }
297 }
298
FillpFrameRx(struct FillpFrameHandle * h,const struct FillpPcbItem * item)299 void FillpFrameRx(struct FillpFrameHandle *h, const struct FillpPcbItem *item)
300 {
301 if (item->frame != FILLP_NULL_PTR && UTILS_FLAGS_CHECK(item->flags, FILLP_ITEM_FLAGS_FIRST_PKT)) {
302 FillpFrameRxNewFrag(&h->curFrame, item);
303 }
304
305 if (!h->curFrame.rxStarted) {
306 return;
307 }
308
309 FillpFrameRxUpdateAndNotify(h, item);
310 }
311
312 #ifdef __cplusplus
313 }
314 #endif
315
316