1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** NetX Component                                                        */
16 /**                                                                       */
17 /**   Real Time Transport Protocol (RTP)                                  */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define NX_RTP_SENDER_SOURCE_CODE
23 
24 /* Include necessary system files.  */
25 
26 #include    "tx_api.h"
27 #include    "nx_api.h"
28 #include    "nx_ip.h"
29 #ifdef FEATURE_NX_IPV6
30 #include    "nx_ipv6.h"
31 #endif /* FEATURE_NX_IPV6 */
32 #include    "nx_udp.h"
33 #include    "nx_rtp_sender.h"
34 
35 
36 /* Define JPEG quantization table parameters. */
37 #define NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_MAX_NUM       (4)
38 #define NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH        (64)
39 
40 /* Define H264 parameters. */
41 #define NX_RTP_SENDER_H264_NRI_MASK_BITS                    (0x60)  /* The mask bits of relative transport priority. */
42 #define NX_RTP_SENDER_H264_TYPE_MASK_BITS                   (0x1F)  /* The mask bits of NAL unit type.*/
43 #define NX_RTP_SENDER_H264_TYPE_SEI                         (6)
44 #define NX_RTP_SENDER_H264_TYPE_SPS                         (7)
45 #define NX_RTP_SENDER_H264_TYPE_PPS                         (8)
46 #define NX_RTP_SENDER_H264_TYPE_FU_A                        (28)
47 #define NX_RTP_SENDER_H264_FU_A_S_MASK_BIT                  (0x80)
48 #define NX_RTP_SENDER_H264_FU_A_E_MASK_BIT                  (0x40)
49 
50 /* Define AAC parameters. */
51 #define NX_RTP_SENDER_AAC_HBR_MODE_MAX_DATA_SIZE            (8191) /* RFC 3640, p25, section 3.3.6. */
52 #define NX_RTP_SENDER_AAC_FRAME_DATA_LENGTH_HIGH_BITS_MASK  (0x1FE0)
53 #define NX_RTP_SENDER_AAC_FRAME_DATA_LENGTH_LOW_BITS_MASK   (0x1F)
54 
55 /* Declare rtp sender internal functions */
56 static UINT _nx_rtp_sender_cleanup(NX_RTP_SENDER *rtp_sender);
57 static UINT _nx_rtp_sender_session_find(NX_RTP_SENDER *rtp_sender, UINT ssrc, NX_RTP_SESSION **session);
58 static VOID _nx_rtp_sender_session_link(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session);
59 static UINT _nx_rtp_sender_session_unlink(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session);
60 
61 static UINT _nx_rtcp_packet_process(NX_RTP_SENDER *rtp_sender, NX_PACKET *packet_ptr);
62 static UINT _nx_rtcp_packet_rr_process(NX_RTP_SENDER *rtp_sender, NX_RTCP_HEADER *header);
63 static UINT _nx_rtcp_packet_sdes_process(NX_RTP_SENDER *rtp_sender, NX_RTCP_HEADER *header);
64 static UINT _nx_rtcp_sr_data_append(NX_RTP_SESSION *session, NX_PACKET *packet_ptr);
65 static UINT _nx_rtcp_sdes_data_append(NX_RTP_SESSION *session, NX_PACKET *packet_ptr);
66 static UINT _nx_rtcp_packet_send(NX_RTP_SESSION *session);
67 static VOID _nx_rtcp_packet_receive_notify(NX_UDP_SOCKET *socket_ptr);
68 
69 
70 /**************************************************************************/
71 /*                                                                        */
72 /*  FUNCTION                                               RELEASE        */
73 /*                                                                        */
74 /*    _nxe_rtp_sender_create                             PORTABLE C       */
75 /*                                                           6.3.0        */
76 /*  AUTHOR                                                                */
77 /*                                                                        */
78 /*    Haiqing Zhao, Microsoft Corporation                                 */
79 /*                                                                        */
80 /*  DESCRIPTION                                                           */
81 /*                                                                        */
82 /*    This function checks errors in the RTP sender create function call. */
83 /*                                                                        */
84 /*  INPUT                                                                 */
85 /*                                                                        */
86 /*    rtp_sender                           Pointer to RTP Sender instance */
87 /*    ip_ptr                               Pointer to IP instance         */
88 /*    pool_ptr                             Pointer to the packet pool     */
89 /*    cname                                Pointer to the name string     */
90 /*                                           shown in rtcp SDES report    */
91 /*    cname_length                         The length of the name string  */
92 /*                                                                        */
93 /*  OUTPUT                                                                */
94 /*                                                                        */
95 /*    status                               Completion status              */
96 /*    NX_PTR_ERROR                         Invalid pointer input          */
97 /*                                                                        */
98 /*  CALLS                                                                 */
99 /*                                                                        */
100 /*    _nx_rtp_sender_create                Create rtp sender              */
101 /*                                                                        */
102 /*  CALLED BY                                                             */
103 /*                                                                        */
104 /*    Application Code                                                    */
105 /*                                                                        */
106 /*  RELEASE HISTORY                                                       */
107 /*                                                                        */
108 /*    DATE              NAME                      DESCRIPTION             */
109 /*                                                                        */
110 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
111 /*                                                                        */
112 /**************************************************************************/
_nxe_rtp_sender_create(NX_RTP_SENDER * rtp_sender,NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,CHAR * cname,UCHAR cname_length)113 UINT _nxe_rtp_sender_create(NX_RTP_SENDER *rtp_sender, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, CHAR *cname, UCHAR cname_length)
114 {
115 
116 UINT status;
117 
118 
119     /* Check for invalid input pointers. */
120     if ((rtp_sender == NX_NULL) || (ip_ptr == NX_NULL) || (pool_ptr == NX_NULL) || (rtp_sender -> nx_rtp_sender_id == NX_RTP_SENDER_ID))
121     {
122         return(NX_PTR_ERROR);
123     }
124 
125     /* Call actual RTP sender create service. */
126     status = _nx_rtp_sender_create(rtp_sender, ip_ptr, pool_ptr, cname, cname_length);
127 
128     /* Return status. */
129     return(status);
130 }
131 
132 /**************************************************************************/
133 /*                                                                        */
134 /*  FUNCTION                                               RELEASE        */
135 /*                                                                        */
136 /*    _nx_rtp_sender_create                               PORTABLE C      */
137 /*                                                           6.3.0        */
138 /*  AUTHOR                                                                */
139 /*                                                                        */
140 /*    Haiqing Zhao, Microsoft Corporation                                 */
141 /*                                                                        */
142 /*  DESCRIPTION                                                           */
143 /*                                                                        */
144 /*    This function creates a RTP sender on the specified IP.             */
145 /*                                                                        */
146 /*  INPUT                                                                 */
147 /*                                                                        */
148 /*    rtp_sender                           Pointer to RTP Sender instance */
149 /*    ip_ptr                               Pointer to IP instance         */
150 /*    pool_ptr                             Pointer to the packet pool     */
151 /*    cname                                Pointer to the name string     */
152 /*                                           shown in rtcp SDES report    */
153 /*    cname_length                         The length of the name string  */
154 /*                                                                        */
155 /*  OUTPUT                                                                */
156 /*                                                                        */
157 /*    status                               Completion status              */
158 /*                                                                        */
159 /*  CALLS                                                                 */
160 /*                                                                        */
161 /*    memset                               Reset memory                   */
162 /*    tx_mutex_create                      Create RTP sender mutex        */
163 /*    tx_mutex_delete                      Delete RTP sender mutex        */
164 /*    nx_udp_socket_create                 Create RTP sender UDP socket   */
165 /*    nx_udp_socket_delete                 Delete RTP sender UDP socket   */
166 /*    nx_udp_free_port_find                Find a free UDP port for RTP   */
167 /*                                           or RTCP socket               */
168 /*    nx_udp_socket_bind                   Bind a UDP port for RTP        */
169 /*                                           or RTCP socket               */
170 /*    nx_udp_socket_unbind                 Unbind UDP port for RTP socket */
171 /*    _nx_rtp_sender_cleanup               Clean-up resources             */
172 /*    nx_udp_socket_receive_notify         Set callback function for UDP  */
173 /*                                           data receive notify          */
174 /*                                                                        */
175 /*  CALLED BY                                                             */
176 /*                                                                        */
177 /*    Application Code                                                    */
178 /*                                                                        */
179 /*  RELEASE HISTORY                                                       */
180 /*                                                                        */
181 /*    DATE              NAME                      DESCRIPTION             */
182 /*                                                                        */
183 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
184 /*                                                                        */
185 /**************************************************************************/
_nx_rtp_sender_create(NX_RTP_SENDER * rtp_sender,NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,CHAR * cname,UCHAR cname_length)186 UINT _nx_rtp_sender_create(NX_RTP_SENDER *rtp_sender, NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, CHAR *cname, UCHAR cname_length)
187 {
188 
189 UINT status;
190 UINT free_port;
191 
192 
193     /* Reset the rtp_sender data structure. */
194     memset(rtp_sender, 0, sizeof(NX_RTP_SENDER));
195 
196     /* Create mutex protection. */
197     status = tx_mutex_create(&(rtp_sender -> nx_rtp_sender_protection), "RTP sender protection", TX_INHERIT);
198     if (status)
199     {
200         return(status);
201     }
202 
203     /* Create RTP UDP socket. */
204     status = nx_udp_socket_create(ip_ptr, &(rtp_sender -> nx_rtp_sender_rtp_socket), "RTP Socket",
205                                   NX_RTP_SENDER_TYPE_OF_SERVICE, NX_RTP_SENDER_FRAGMENT_OPTION,
206                                   NX_RTP_SENDER_TIME_TO_LIVE, NX_RTP_SENDER_QUEUE_DEPTH);
207     if (status)
208     {
209 
210         /* Delete already created resources and return error status. */
211         tx_mutex_delete(&(rtp_sender -> nx_rtp_sender_protection));
212         return(status);
213     }
214 
215     /* Create RTCP UDP socket. */
216     status = nx_udp_socket_create(ip_ptr, &(rtp_sender -> nx_rtp_sender_rtcp_socket), "RTCP Socket",
217                                   NX_RTP_SENDER_TYPE_OF_SERVICE, NX_RTP_SENDER_FRAGMENT_OPTION,
218                                   NX_RTP_SENDER_TIME_TO_LIVE, NX_RTP_SENDER_QUEUE_DEPTH);
219     if (status)
220     {
221 
222         /* Delete already created resources and return error status. */
223         tx_mutex_delete(&(rtp_sender -> nx_rtp_sender_protection));
224         nx_udp_socket_delete(&(rtp_sender -> nx_rtp_sender_rtp_socket));
225         return(status);
226     }
227 
228     /* Start from the suggested default port number. */
229     rtp_sender -> nx_rtp_sender_rtp_port = NX_RTP_SENDER_INITIAL_RTP_PORT;
230 
231     while (1)
232     {
233 
234         /* Try to find an available port for RTP. */
235         status = nx_udp_free_port_find(ip_ptr, rtp_sender -> nx_rtp_sender_rtp_port, &free_port);
236         if (status)
237         {
238             break;
239         }
240         else if (rtp_sender -> nx_rtp_sender_rtp_port > free_port)
241         {
242 
243             /* Return since there will be no even number port obtained. */
244             status = NX_NO_FREE_PORTS;
245             break;
246         }
247 
248         /* Check if free_port is an odd number. */
249         if ((free_port & 1) != 0)
250         {
251 
252             /* Check if the found free port reaches maximum. */
253             if (free_port == NX_MAX_PORT)
254             {
255 
256                 /* Return since there will be no even number port obtained. */
257                 status = NX_NO_FREE_PORTS;
258                 break;
259             }
260 
261             /* Free UDP port is not the one we expected for RTP. Move to the next port number and try again. */
262             rtp_sender -> nx_rtp_sender_rtp_port = (USHORT)(free_port + 1);
263         }
264         else
265         {
266 
267             /* Set RTP port. */
268             rtp_sender -> nx_rtp_sender_rtp_port = (USHORT)free_port;
269         }
270 
271         /* Both RTP and RTCP ports are available. Now do a real RTP bind. */
272         status = nx_udp_socket_bind(&(rtp_sender -> nx_rtp_sender_rtp_socket), rtp_sender -> nx_rtp_sender_rtp_port, NX_NO_WAIT);
273         if (status == NX_SUCCESS)
274         {
275 
276             /* RTP socket was bound successfully. Now try RTCP socket. */
277 
278             /* Set RTCP port to be the next odd port of RTP port and bind. */
279             rtp_sender -> nx_rtp_sender_rtcp_port = (USHORT)(rtp_sender -> nx_rtp_sender_rtp_port + 1);
280             status = nx_udp_socket_bind(&(rtp_sender -> nx_rtp_sender_rtcp_socket), rtp_sender -> nx_rtp_sender_rtcp_port, NX_NO_WAIT);
281             if (status == NX_SUCCESS)
282             {
283 
284                 /* Jump out since both ports are found. */
285                 break;
286             }
287 
288             /* RTCP port is unavailable. Unbind the RTP port and try again. */
289             nx_udp_socket_unbind(&(rtp_sender -> nx_rtp_sender_rtp_socket));
290         }
291 
292         /* Move and check next possible even port. */
293         rtp_sender -> nx_rtp_sender_rtp_port = (USHORT)(rtp_sender -> nx_rtp_sender_rtp_port + 2);
294         if (rtp_sender -> nx_rtp_sender_rtp_port == 0)
295         {
296             status = NX_NO_FREE_PORTS;
297             break;
298         }
299     }
300 
301     /* Clean-up generated resources if fails to find a rtp/rtcp port pair. */
302     if (status)
303     {
304         _nx_rtp_sender_cleanup(rtp_sender);
305         return(status);
306     }
307 
308     /* Store pool pointer. */
309     rtp_sender -> nx_rtp_sender_packet_pool_ptr = pool_ptr;
310 
311     /* Set application-specific filed indicating the socket is associated with this RTP sender instance. */
312     rtp_sender -> nx_rtp_sender_rtcp_socket.nx_udp_socket_reserved_ptr = (void *)rtp_sender;
313 
314     /* Install RTCP callback. */
315     nx_udp_socket_receive_notify(&(rtp_sender -> nx_rtp_sender_rtcp_socket), _nx_rtcp_packet_receive_notify);
316 
317     /* Update rtp variables. */
318     rtp_sender -> nx_rtp_sender_id = NX_RTP_SENDER_ID;
319     rtp_sender -> nx_rtp_sender_ip_ptr = ip_ptr;
320     rtp_sender -> nx_rtp_sender_cname = cname;
321     rtp_sender -> nx_rtp_sender_cname_length = cname_length;
322 
323     return(NX_SUCCESS);
324 }
325 
326 /**************************************************************************/
327 /*                                                                        */
328 /*  FUNCTION                                               RELEASE        */
329 /*                                                                        */
330 /*    _nxe_rtp_sender_delete                             PORTABLE C       */
331 /*                                                           6.3.0        */
332 /*  AUTHOR                                                                */
333 /*                                                                        */
334 /*    Haiqing Zhao, Microsoft Corporation                                 */
335 /*                                                                        */
336 /*  DESCRIPTION                                                           */
337 /*                                                                        */
338 /*    This function checks errors in the RTP sender delete function call. */
339 /*                                                                        */
340 /*  INPUT                                                                 */
341 /*                                                                        */
342 /*    rtp_sender                           Pointer to RTP Sender instance */
343 /*                                                                        */
344 /*  OUTPUT                                                                */
345 /*                                                                        */
346 /*    status                               Completion status              */
347 /*    NX_PTR_ERROR                         Invalid pointer input          */
348 /*                                                                        */
349 /*  CALLS                                                                 */
350 /*                                                                        */
351 /*    _nx_rtp_sender_delete                Delete RTP sender              */
352 /*                                                                        */
353 /*  CALLED BY                                                             */
354 /*                                                                        */
355 /*    Application Code                                                    */
356 /*                                                                        */
357 /*  RELEASE HISTORY                                                       */
358 /*                                                                        */
359 /*    DATE              NAME                      DESCRIPTION             */
360 /*                                                                        */
361 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
362 /*                                                                        */
363 /**************************************************************************/
_nxe_rtp_sender_delete(NX_RTP_SENDER * rtp_sender)364 UINT _nxe_rtp_sender_delete(NX_RTP_SENDER *rtp_sender)
365 {
366 
367 UINT status;
368 
369 
370     /* Check for invalid input pointers. */
371     if ((rtp_sender == NX_NULL) || (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID))
372     {
373         return(NX_PTR_ERROR);
374     }
375 
376     /* Call actual RTP sender delete service. */
377     status = _nx_rtp_sender_delete(rtp_sender);
378 
379     /* Return status. */
380     return(status);
381 }
382 
383 /**************************************************************************/
384 /*                                                                        */
385 /*  FUNCTION                                               RELEASE        */
386 /*                                                                        */
387 /*    _nx_rtp_sender_delete                              PORTABLE C       */
388 /*                                                           6.3.0        */
389 /*  AUTHOR                                                                */
390 /*                                                                        */
391 /*    Haiqing Zhao, Microsoft Corporation                                 */
392 /*                                                                        */
393 /*  DESCRIPTION                                                           */
394 /*                                                                        */
395 /*    This function deletes a previous created RTP sender                 */
396 /*                                                                        */
397 /*  INPUT                                                                 */
398 /*                                                                        */
399 /*    rtp_sender                           Pointer to RTP Sender instance */
400 /*                                                                        */
401 /*  OUTPUT                                                                */
402 /*                                                                        */
403 /*    status                               Completion status              */
404 /*    NX_DELETE_ERROR                      Fail to delete RTP sender      */
405 /*                                                                        */
406 /*  CALLS                                                                 */
407 /*                                                                        */
408 /*    tx_mutex_get                         Obtain protection mutex        */
409 /*    tx_mutex_put                         Release protection mutex       */
410 /*    _nx_rtp_sender_cleanup               Clean-up resources             */
411 /*                                                                        */
412 /*  CALLED BY                                                             */
413 /*                                                                        */
414 /*    Application Code                                                    */
415 /*                                                                        */
416 /*  RELEASE HISTORY                                                       */
417 /*                                                                        */
418 /*    DATE              NAME                      DESCRIPTION             */
419 /*                                                                        */
420 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
421 /*                                                                        */
422 /**************************************************************************/
_nx_rtp_sender_delete(NX_RTP_SENDER * rtp_sender)423 UINT _nx_rtp_sender_delete(NX_RTP_SENDER *rtp_sender)
424 {
425 
426     /* Obtain the mutex. */
427     tx_mutex_get(&(rtp_sender -> nx_rtp_sender_protection), TX_WAIT_FOREVER);
428 
429     /* rtp sender can only be deleted when all sessions have been deleted. */
430     if (rtp_sender -> nx_rtp_sender_session_created_ptr)
431     {
432 
433         /* Release the mutex and return error status. */
434         tx_mutex_put(&(rtp_sender -> nx_rtp_sender_protection));
435         return(NX_DELETE_ERROR);
436     }
437 
438     /* Set the id to be 0 to make sure other api functions (except create) cannot execute after deleting. */
439     rtp_sender -> nx_rtp_sender_id = 0;
440 
441     /* Release the mutex */
442     tx_mutex_put(&(rtp_sender -> nx_rtp_sender_protection));
443 
444     /* Clean-up all generated resources. */
445     _nx_rtp_sender_cleanup(rtp_sender);
446 
447     return(NX_SUCCESS);
448 }
449 
450 /**************************************************************************/
451 /*                                                                        */
452 /*  FUNCTION                                               RELEASE        */
453 /*                                                                        */
454 /*    _nxe_rtp_sender_port_get                           PORTABLE C       */
455 /*                                                           6.3.0        */
456 /*  AUTHOR                                                                */
457 /*                                                                        */
458 /*    Haiqing Zhao, Microsoft Corporation                                 */
459 /*                                                                        */
460 /*  DESCRIPTION                                                           */
461 /*                                                                        */
462 /*    This function checks errors in the RTP sender port get function     */
463 /*    call.                                                               */
464 /*                                                                        */
465 /*  INPUT                                                                 */
466 /*                                                                        */
467 /*    rtp_sender                           Pointer to RTP Sender instance */
468 /*    rtp_port                             Pointer to returned RTP port   */
469 /*    rtcp_port                            Pointer to returned RTCP port  */
470 /*                                                                        */
471 /*  OUTPUT                                                                */
472 /*                                                                        */
473 /*    status                               Completion status              */
474 /*    NX_PTR_ERROR                         Invalid pointer input          */
475 /*                                                                        */
476 /*  CALLS                                                                 */
477 /*                                                                        */
478 /*    _nx_rtp_sender_port_get              Get the bound RTP port and     */
479 /*                                           RTCP port in RTP sender      */
480 /*                                                                        */
481 /*  CALLED BY                                                             */
482 /*                                                                        */
483 /*    Application Code                                                    */
484 /*                                                                        */
485 /*  RELEASE HISTORY                                                       */
486 /*                                                                        */
487 /*    DATE              NAME                      DESCRIPTION             */
488 /*                                                                        */
489 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
490 /*                                                                        */
491 /**************************************************************************/
_nxe_rtp_sender_port_get(NX_RTP_SENDER * rtp_sender,UINT * rtp_port,UINT * rtcp_port)492 UINT _nxe_rtp_sender_port_get(NX_RTP_SENDER *rtp_sender, UINT *rtp_port, UINT *rtcp_port)
493 {
494 
495 UINT status;
496 
497 
498     /* Check for invalid input pointers. */
499     if ((rtp_sender == NX_NULL) || (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID) ||
500         (rtp_port == NX_NULL) || (rtcp_port == NX_NULL))
501     {
502         return(NX_PTR_ERROR);
503     }
504 
505     /* Call actual RTP sender port get service. */
506     status = _nx_rtp_sender_port_get(rtp_sender, rtp_port, rtcp_port);
507 
508     /* Return status. */
509     return(status);
510 }
511 
512 /**************************************************************************/
513 /*                                                                        */
514 /*  FUNCTION                                               RELEASE        */
515 /*                                                                        */
516 /*    _nx_rtp_sender_port_get                            PORTABLE C       */
517 /*                                                           6.3.0        */
518 /*  AUTHOR                                                                */
519 /*                                                                        */
520 /*    Haiqing Zhao, Microsoft Corporation                                 */
521 /*                                                                        */
522 /*  DESCRIPTION                                                           */
523 /*                                                                        */
524 /*    This function returns bound RTP and RTCP port pair in RTP sender.   */
525 /*                                                                        */
526 /*  INPUT                                                                 */
527 /*                                                                        */
528 /*    rtp_sender                           Pointer to RTP Sender instance */
529 /*    rtp_port                             Pointer to returned RTP port   */
530 /*    rtcp_port                            Pointer to returned RTCP port  */
531 /*                                                                        */
532 /*  OUTPUT                                                                */
533 /*                                                                        */
534 /*    NX_SUCCESS                           Completion status              */
535 /*                                                                        */
536 /*  CALLS                                                                 */
537 /*                                                                        */
538 /*    _nx_rtp_sender_port_get              Get the bound RTP port and     */
539 /*                                           RTCP port in RTP sender      */
540 /*                                                                        */
541 /*  CALLED BY                                                             */
542 /*                                                                        */
543 /*    Application Code                                                    */
544 /*                                                                        */
545 /*  RELEASE HISTORY                                                       */
546 /*                                                                        */
547 /*    DATE              NAME                      DESCRIPTION             */
548 /*                                                                        */
549 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
550 /*                                                                        */
551 /**************************************************************************/
_nx_rtp_sender_port_get(NX_RTP_SENDER * rtp_sender,UINT * rtp_port,UINT * rtcp_port)552 UINT _nx_rtp_sender_port_get(NX_RTP_SENDER *rtp_sender, UINT *rtp_port, UINT *rtcp_port)
553 {
554 
555     /* Set RTP port and RTCP port. */
556     *rtp_port = rtp_sender -> nx_rtp_sender_rtp_port;
557     *rtcp_port = rtp_sender -> nx_rtp_sender_rtcp_port;
558 
559     /* All done. Return success code. */
560     return(NX_SUCCESS);
561 }
562 
563 /**************************************************************************/
564 /*                                                                        */
565 /*  FUNCTION                                               RELEASE        */
566 /*                                                                        */
567 /*    _nxe_rtp_sender_session_create                     PORTABLE C       */
568 /*                                                           6.3.0        */
569 /*  AUTHOR                                                                */
570 /*                                                                        */
571 /*    Haiqing Zhao, Microsoft Corporation                                 */
572 /*                                                                        */
573 /*  DESCRIPTION                                                           */
574 /*                                                                        */
575 /*    This function checks errors in the RTP sender session create        */
576 /*    function call.                                                      */
577 /*                                                                        */
578 /*  INPUT                                                                 */
579 /*                                                                        */
580 /*    rtp_sender                           Pointer to RTP Sender instance */
581 /*    session                              Pointer to RTP session         */
582 /*    payload_type                         Payload type number            */
583 /*    interface_index                      IP interface index             */
584 /*    receiver_ip_address                  The receiver's IP address      */
585 /*    receiver_rtp_port_number             The receiver's RTP port        */
586 /*    receiver_rtcp_port_number            The receiver's RTCP port       */
587 /*                                                                        */
588 /*  OUTPUT                                                                */
589 /*                                                                        */
590 /*    status                               Completion status              */
591 /*    NX_PTR_ERROR                         Invalid pointer input          */
592 /*                                                                        */
593 /*  CALLS                                                                 */
594 /*                                                                        */
595 /*    _nx_rtp_sender_session_create        Create RTP session with        */
596 /*                                           specific arguments           */
597 /*                                                                        */
598 /*  CALLED BY                                                             */
599 /*                                                                        */
600 /*    Application Code                                                    */
601 /*                                                                        */
602 /*  RELEASE HISTORY                                                       */
603 /*                                                                        */
604 /*    DATE              NAME                      DESCRIPTION             */
605 /*                                                                        */
606 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
607 /*                                                                        */
608 /**************************************************************************/
_nxe_rtp_sender_session_create(NX_RTP_SENDER * rtp_sender,NX_RTP_SESSION * session,ULONG payload_type,UINT interface_index,NXD_ADDRESS * receiver_ip_address,UINT receiver_rtp_port_number,UINT receiver_rtcp_port_number)609 UINT _nxe_rtp_sender_session_create(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session, ULONG payload_type,
610                                     UINT interface_index, NXD_ADDRESS *receiver_ip_address,
611                                     UINT receiver_rtp_port_number, UINT receiver_rtcp_port_number)
612 {
613 
614 UINT status;
615 
616 
617     /* Check for invalid input pointers. */
618     if ((rtp_sender == NX_NULL) || (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID) ||
619         (session == NX_NULL) || (session -> nx_rtp_session_id == NX_RTP_SESSION_ID) ||
620         (receiver_ip_address == NX_NULL))
621     {
622         return(NX_PTR_ERROR);
623     }
624 
625     if (interface_index >= NX_MAX_PHYSICAL_INTERFACES)
626     {
627         return(NX_INVALID_INTERFACE);
628     }
629 
630     /* Call actual RTP sender session create service. */
631     status = _nx_rtp_sender_session_create(rtp_sender, session, payload_type,
632                                            interface_index, receiver_ip_address,
633                                            receiver_rtp_port_number, receiver_rtcp_port_number);
634 
635     /* Return status. */
636     return(status);
637 }
638 
639 /**************************************************************************/
640 /*                                                                        */
641 /*  FUNCTION                                               RELEASE        */
642 /*                                                                        */
643 /*    _nx_rtp_sender_session_create                      PORTABLE C       */
644 /*                                                           6.4.0        */
645 /*  AUTHOR                                                                */
646 /*                                                                        */
647 /*    Haiqing Zhao, Microsoft Corporation                                 */
648 /*                                                                        */
649 /*  DESCRIPTION                                                           */
650 /*                                                                        */
651 /*    This function creates a RTP session with specific arguments.        */
652 /*                                                                        */
653 /*  INPUT                                                                 */
654 /*                                                                        */
655 /*    rtp_sender                           Pointer to RTP Sender instance */
656 /*    session                              Pointer to RTP session         */
657 /*    payload_type                         Payload type number            */
658 /*    interface_index                      IP interface index             */
659 /*    receiver_ip_address                  The receiver's IP address      */
660 /*    receiver_rtp_port_number             The receiver's RTP port        */
661 /*    receiver_rtcp_port_number            The receiver's RTCP port       */
662 /*                                                                        */
663 /*  OUTPUT                                                                */
664 /*                                                                        */
665 /*    NX_SUCCESS                           Completion status              */
666 /*    NX_INVALID_PARAMETERS                Payload type out of range      */
667 /*    NX_IP_ADDRESS_ERROR                  Unsupported IP version         */
668 /*                                                                        */
669 /*  CALLS                                                                 */
670 /*                                                                        */
671 /*    memset                               Reset memory                   */
672 /*    COPY_IPV6_ADDRESS                    Make a copy of an IPv6 address */
673 /*    NX_RAND                              Generate a random number       */
674 /*    tx_mutex_get                         Obtain protection mutex        */
675 /*    tx_mutex_put                         Release protection mutex       */
676 /*    _nx_rtp_sender_session_link          Link the created session into  */
677 /*                                           RTP sender control block     */
678 /*                                                                        */
679 /*  CALLED BY                                                             */
680 /*                                                                        */
681 /*    Application Code                                                    */
682 /*                                                                        */
683 /*  RELEASE HISTORY                                                       */
684 /*                                                                        */
685 /*    DATE              NAME                      DESCRIPTION             */
686 /*                                                                        */
687 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
688 /*  12-31-2023     Haiqing Zhao            Modified comments(s),          */
689 /*                                           supported VLAN,              */
690 /*                                           resulting in version 6.4.0   */
691 /*                                                                        */
692 /**************************************************************************/
_nx_rtp_sender_session_create(NX_RTP_SENDER * rtp_sender,NX_RTP_SESSION * session,ULONG payload_type,UINT interface_index,NXD_ADDRESS * receiver_ip_address,UINT receiver_rtp_port_number,UINT receiver_rtcp_port_number)693 UINT _nx_rtp_sender_session_create(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session, ULONG payload_type,
694                                    UINT interface_index, NXD_ADDRESS *receiver_ip_address,
695                                    UINT receiver_rtp_port_number, UINT receiver_rtcp_port_number)
696 {
697 
698     /* Check and validate rtp payload type with valid range from 0 to 127 (7 bits). */
699     if (payload_type > 127)
700     {
701         return(NX_INVALID_PARAMETERS);
702     }
703 
704     /* Reset rtp session members. */
705     memset(session, 0, sizeof(NX_RTP_SESSION));
706 
707     /* Record peer's ip address and rtp/rtcp port pair. */
708     session -> nx_rtp_session_peer_ip_address.nxd_ip_version = receiver_ip_address -> nxd_ip_version;
709 
710     /* Store the receiver's ip interface index into the session. */
711     session -> nx_rtp_session_interface_index = interface_index;
712 
713     if (receiver_ip_address -> nxd_ip_version == NX_IP_VERSION_V4)
714     {
715 #ifndef NX_DISABLE_IPV4
716         session -> nx_rtp_session_peer_ip_address.nxd_ip_address.v4 = receiver_ip_address -> nxd_ip_address.v4;
717 
718         /* Compute the maximum frame packet length based on mtu size. */
719         session -> nx_rtp_session_max_packet_size = rtp_sender -> nx_rtp_sender_ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_mtu_size
720                                                   - sizeof(NX_UDP_HEADER) - NX_RTP_HEADER_LENGTH - sizeof(NX_IPV4_HEADER);
721 #else
722         return(NX_IP_ADDRESS_ERROR);
723 #endif /* NX_DISABLE_IPV4 */
724     }
725     else if (receiver_ip_address -> nxd_ip_version == NX_IP_VERSION_V6)
726     {
727 #ifdef FEATURE_NX_IPV6
728         COPY_IPV6_ADDRESS(receiver_ip_address -> nxd_ip_address.v6, session -> nx_rtp_session_peer_ip_address.nxd_ip_address.v6);
729 
730         /* Compute the maximum frame packet length based on mtu size. */
731         session -> nx_rtp_session_max_packet_size = rtp_sender -> nx_rtp_sender_ip_ptr -> nx_ip_interface[interface_index].nx_interface_ip_mtu_size
732                                                   - sizeof(NX_UDP_HEADER) - NX_RTP_HEADER_LENGTH - sizeof(NX_IPV6_HEADER);
733 #else
734         return(NX_IP_ADDRESS_ERROR);
735 #endif /* #ifdef FEATURE_NX_IPV6 */
736     }
737     else
738     {
739         return(NX_IP_ADDRESS_ERROR);
740     }
741 
742     /* Store the receiver's rtp/rtcp ports number. */
743     session -> nx_rtp_session_peer_rtp_port = (USHORT)receiver_rtp_port_number;
744     session -> nx_rtp_session_peer_rtcp_port = (USHORT)receiver_rtcp_port_number;
745 
746     /* Record session payload type. */
747     session -> nx_rtp_session_payload_type = (UCHAR)(payload_type);
748 
749     /* Generate random values for the ssrc and sequence number. */
750     session -> nx_rtp_session_ssrc = (ULONG)NX_RAND();
751     session -> nx_rtp_session_sequence_number = (USHORT)NX_RAND();
752 
753     /* Record the rtp sender pointer in the session. */
754     session -> nx_rtp_sender = rtp_sender;
755 
756     /* Obtain the mutex */
757     tx_mutex_get(&(rtp_sender -> nx_rtp_sender_protection), TX_WAIT_FOREVER);
758 
759     _nx_rtp_sender_session_link(rtp_sender, session);
760 
761     /* Release the mutex and return success status. */
762     tx_mutex_put(&(rtp_sender -> nx_rtp_sender_protection));
763 
764 #ifdef NX_ENABLE_VLAN
765     /* Initialize session vlan priority. */
766     session -> nx_rtp_session_vlan_priority = NX_VLAN_PRIORITY_INVALID;
767 #endif /* NX_ENABLE_VLAN */
768 
769     /* Set session magic number to indicate the session is created successfully. */
770     session -> nx_rtp_session_id = NX_RTP_SESSION_ID;
771 
772     return(NX_SUCCESS);
773 }
774 
775 /**************************************************************************/
776 /*                                                                        */
777 /*  FUNCTION                                               RELEASE        */
778 /*                                                                        */
779 /*    _nxe_rtp_sender_session_delete                     PORTABLE C       */
780 /*                                                           6.3.0        */
781 /*  AUTHOR                                                                */
782 /*                                                                        */
783 /*    Haiqing Zhao, Microsoft Corporation                                 */
784 /*                                                                        */
785 /*  DESCRIPTION                                                           */
786 /*                                                                        */
787 /*    This function checks errors in the rtp sender session delete        */
788 /*    function call.                                                      */
789 /*                                                                        */
790 /*  INPUT                                                                 */
791 /*                                                                        */
792 /*    session                              Pointer to RTP session         */
793 /*                                                                        */
794 /*  OUTPUT                                                                */
795 /*                                                                        */
796 /*    status                               Completion status              */
797 /*    NX_PTR_ERROR                         Invalid pointer input          */
798 /*                                                                        */
799 /*  CALLS                                                                 */
800 /*                                                                        */
801 /*    _nx_rtp_sender_session_delete        Delete RTP session             */
802 /*                                                                        */
803 /*  CALLED BY                                                             */
804 /*                                                                        */
805 /*    Application Code                                                    */
806 /*                                                                        */
807 /*  RELEASE HISTORY                                                       */
808 /*                                                                        */
809 /*    DATE              NAME                      DESCRIPTION             */
810 /*                                                                        */
811 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
812 /*                                                                        */
813 /**************************************************************************/
_nxe_rtp_sender_session_delete(NX_RTP_SESSION * session)814 UINT _nxe_rtp_sender_session_delete(NX_RTP_SESSION *session)
815 {
816 
817 UINT status;
818 
819 
820     /* Check for invalid input pointers. */
821     if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID))
822     {
823         return(NX_PTR_ERROR);
824     }
825 
826     /* Call actual RTP sender session delete service. */
827     status = _nx_rtp_sender_session_delete(session);
828 
829     /* Return status. */
830     return(status);
831 }
832 
833 /**************************************************************************/
834 /*                                                                        */
835 /*  FUNCTION                                               RELEASE        */
836 /*                                                                        */
837 /*    _nx_rtp_sender_session_delete                      PORTABLE C       */
838 /*                                                           6.3.0        */
839 /*  AUTHOR                                                                */
840 /*                                                                        */
841 /*    Haiqing Zhao, Microsoft Corporation                                 */
842 /*                                                                        */
843 /*  DESCRIPTION                                                           */
844 /*                                                                        */
845 /*    This function deletes a RTP session.                                */
846 /*                                                                        */
847 /*  INPUT                                                                 */
848 /*                                                                        */
849 /*    session                              Pointer to RTP session         */
850 /*                                                                        */
851 /*  OUTPUT                                                                */
852 /*                                                                        */
853 /*    NX_SUCCESS                           Completion status              */
854 /*                                                                        */
855 /*  CALLS                                                                 */
856 /*                                                                        */
857 /*    tx_mutex_get                         Obtain protection mutex        */
858 /*    tx_mutex_put                         Release protection mutex       */
859 /*    _nx_rtp_sender_session_unlink        Unlink the session from        */
860 /*                                           RTP sender control block     */
861 /*                                                                        */
862 /*  CALLED BY                                                             */
863 /*                                                                        */
864 /*    Application Code                                                    */
865 /*                                                                        */
866 /*  RELEASE HISTORY                                                       */
867 /*                                                                        */
868 /*    DATE              NAME                      DESCRIPTION             */
869 /*                                                                        */
870 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
871 /*                                                                        */
872 /**************************************************************************/
_nx_rtp_sender_session_delete(NX_RTP_SESSION * session)873 UINT _nx_rtp_sender_session_delete(NX_RTP_SESSION *session)
874 {
875 
876     /* Reset the rtp session id. */
877     session -> nx_rtp_session_id = 0;
878 
879     /* Obtain the mutex. */
880     tx_mutex_get(&(session -> nx_rtp_sender -> nx_rtp_sender_protection), TX_WAIT_FOREVER);
881 
882     _nx_rtp_sender_session_unlink(session -> nx_rtp_sender, session);
883 
884     /* Release the mutex and return success status. */
885     tx_mutex_put(&(session -> nx_rtp_sender -> nx_rtp_sender_protection));
886     return(NX_SUCCESS);
887 }
888 
889 /**************************************************************************/
890 /*                                                                        */
891 /*  FUNCTION                                               RELEASE        */
892 /*                                                                        */
893 /*    _nxe_rtp_sender_rtcp_receiver_report_callback_set   PORTABLE C      */
894 /*                                                           6.3.0        */
895 /*  AUTHOR                                                                */
896 /*                                                                        */
897 /*    Ting Zhu, Microsoft Corporation                                     */
898 /*                                                                        */
899 /*  DESCRIPTION                                                           */
900 /*                                                                        */
901 /*    This function checks errors in rtcp receiver report callback set    */
902 /*    function call.                                                      */
903 /*                                                                        */
904 /*  INPUT                                                                 */
905 /*                                                                        */
906 /*    rtp_sender                            Pointer to RTP sender         */
907 /*    rtcp_rr_cb                            Application specified         */
908 /*                                            callback function           */
909 /*                                                                        */
910 /*  OUTPUT                                                                */
911 /*                                                                        */
912 /*    status                                Completion status             */
913 /*                                                                        */
914 /*  CALLS                                                                 */
915 /*                                                                        */
916 /*    _nx_rtp_sender_rtcp_receiver_report_callback_set                    */
917 /*                                          Set RTCP RR packet receive    */
918 /*                                            notify function             */
919 /*                                                                        */
920 /*  CALLED BY                                                             */
921 /*                                                                        */
922 /*    Application Code                                                    */
923 /*                                                                        */
924 /*  RELEASE HISTORY                                                       */
925 /*                                                                        */
926 /*    DATE              NAME                      DESCRIPTION             */
927 /*                                                                        */
928 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
929 /*                                                                        */
930 /**************************************************************************/
_nxe_rtp_sender_rtcp_receiver_report_callback_set(NX_RTP_SENDER * rtp_sender,UINT (* rtcp_rr_cb)(NX_RTP_SESSION *,NX_RTCP_RECEIVER_REPORT *))931 UINT _nxe_rtp_sender_rtcp_receiver_report_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_rr_cb)(NX_RTP_SESSION *, NX_RTCP_RECEIVER_REPORT *))
932 {
933 
934 UINT status;
935 
936 
937     /* Validate user input parameter. */
938     if ((rtp_sender == NX_NULL) || (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID))
939     {
940         return(NX_PTR_ERROR);
941     }
942 
943     /* Call actual RTP sender rtcp receiver report callback service. */
944     status = _nx_rtp_sender_rtcp_receiver_report_callback_set(rtp_sender, rtcp_rr_cb);
945 
946     /* Return status. */
947     return(status);
948 }
949 
950 /**************************************************************************/
951 /*                                                                        */
952 /*  FUNCTION                                               RELEASE        */
953 /*                                                                        */
954 /*    _nx_rtp_sender_rtcp_receiver_report_callback_set    PORTABLE C      */
955 /*                                                           6.3.0        */
956 /*  AUTHOR                                                                */
957 /*                                                                        */
958 /*    Ting Zhu, Microsoft Corporation                                     */
959 /*                                                                        */
960 /*  DESCRIPTION                                                           */
961 /*                                                                        */
962 /*    This function sets a callback routine for RTCP RR packet receive    */
963 /*    notification. If a NULL pointer is supplied the receive notify      */
964 /*    function is disabled. Note that this callback function is invoked   */
965 /*    from the IP thread, Application shall not block the thread.         */
966 /*                                                                        */
967 /*  INPUT                                                                 */
968 /*                                                                        */
969 /*    rtp_sender                            Pointer to RTP sender         */
970 /*    rtcp_rr_cb                            Application specified         */
971 /*                                            callback function           */
972 /*                                                                        */
973 /*  OUTPUT                                                                */
974 /*                                                                        */
975 /*    status                                Completion status             */
976 /*                                                                        */
977 /*  CALLS                                                                 */
978 /*                                                                        */
979 /*    None                                                                */
980 /*                                                                        */
981 /*  CALLED BY                                                             */
982 /*                                                                        */
983 /*    Application Code                                                    */
984 /*                                                                        */
985 /*  RELEASE HISTORY                                                       */
986 /*                                                                        */
987 /*    DATE              NAME                      DESCRIPTION             */
988 /*                                                                        */
989 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
990 /*                                                                        */
991 /**************************************************************************/
_nx_rtp_sender_rtcp_receiver_report_callback_set(NX_RTP_SENDER * rtp_sender,UINT (* rtcp_rr_cb)(NX_RTP_SESSION *,NX_RTCP_RECEIVER_REPORT *))992 UINT _nx_rtp_sender_rtcp_receiver_report_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_rr_cb)(NX_RTP_SESSION *, NX_RTCP_RECEIVER_REPORT *))
993 {
994     rtp_sender -> nx_rtp_sender_rtcp_receiver_report_cb = rtcp_rr_cb;
995 
996     return(NX_SUCCESS);
997 }
998 
999 /**************************************************************************/
1000 /*                                                                        */
1001 /*  FUNCTION                                               RELEASE        */
1002 /*                                                                        */
1003 /*    _nxe_rtp_sender_rtcp_sdes_callback_set              PORTABLE C      */
1004 /*                                                           6.3.0        */
1005 /*  AUTHOR                                                                */
1006 /*                                                                        */
1007 /*    Ting Zhu, Microsoft Corporation                                     */
1008 /*                                                                        */
1009 /*  DESCRIPTION                                                           */
1010 /*                                                                        */
1011 /*    This function checks errors in rtcp sdes callback set function call.*/
1012 /*                                                                        */
1013 /*  INPUT                                                                 */
1014 /*                                                                        */
1015 /*    rtp_sender                            Pointer to RTP sender         */
1016 /*    rtcp_sdes_cb                          Application specified         */
1017 /*                                            callback function           */
1018 /*                                                                        */
1019 /*  OUTPUT                                                                */
1020 /*                                                                        */
1021 /*    status                                Completion status             */
1022 /*                                                                        */
1023 /*  CALLS                                                                 */
1024 /*                                                                        */
1025 /*    _nx_rtp_sender_rtcp_sdes_callback_set Set RTCP SDES packet receive  */
1026 /*                                            notify function             */
1027 /*                                                                        */
1028 /*  CALLED BY                                                             */
1029 /*                                                                        */
1030 /*    Application Code                                                    */
1031 /*                                                                        */
1032 /*  RELEASE HISTORY                                                       */
1033 /*                                                                        */
1034 /*    DATE              NAME                      DESCRIPTION             */
1035 /*                                                                        */
1036 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
1037 /*                                                                        */
1038 /**************************************************************************/
_nxe_rtp_sender_rtcp_sdes_callback_set(NX_RTP_SENDER * rtp_sender,UINT (* rtcp_sdes_cb)(NX_RTCP_SDES_INFO *))1039 UINT _nxe_rtp_sender_rtcp_sdes_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_sdes_cb)(NX_RTCP_SDES_INFO *))
1040 {
1041 
1042 UINT status;
1043 
1044 
1045     /* Validate user input parameter. */
1046     if ((rtp_sender == NX_NULL) || (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID))
1047     {
1048         return(NX_PTR_ERROR);
1049     }
1050 
1051     /* Call actual RTP sender rtcp sdes callback service. */
1052     status = _nx_rtp_sender_rtcp_sdes_callback_set(rtp_sender, rtcp_sdes_cb);
1053 
1054     /* Return status. */
1055     return(status);
1056 }
1057 
1058 /**************************************************************************/
1059 /*                                                                        */
1060 /*  FUNCTION                                               RELEASE        */
1061 /*                                                                        */
1062 /*    _nx_rtp_sender_rtcp_sdes_callback_set               PORTABLE C      */
1063 /*                                                           6.3.0        */
1064 /*  AUTHOR                                                                */
1065 /*                                                                        */
1066 /*    Ting Zhu, Microsoft Corporation                                     */
1067 /*                                                                        */
1068 /*  DESCRIPTION                                                           */
1069 /*                                                                        */
1070 /*    This function sets a callback routine for RTCP SDES packet receive  */
1071 /*    notification. If a NULL pointer is supplied the receive notify      */
1072 /*    function is disabled. Note that this callback function is invoked   */
1073 /*    from the IP thread, Application shall not block the thread.         */
1074 /*                                                                        */
1075 /*  INPUT                                                                 */
1076 /*                                                                        */
1077 /*    rtp_sender                            Pointer to RTP sender         */
1078 /*    rtcp_sdes_cb                          Application specified         */
1079 /*                                            callback function           */
1080 /*                                                                        */
1081 /*  OUTPUT                                                                */
1082 /*                                                                        */
1083 /*    status                                Completion status             */
1084 /*                                                                        */
1085 /*  CALLS                                                                 */
1086 /*                                                                        */
1087 /*    None                                                                */
1088 /*                                                                        */
1089 /*  CALLED BY                                                             */
1090 /*                                                                        */
1091 /*    Application Code                                                    */
1092 /*                                                                        */
1093 /*  RELEASE HISTORY                                                       */
1094 /*                                                                        */
1095 /*    DATE              NAME                      DESCRIPTION             */
1096 /*                                                                        */
1097 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
1098 /*                                                                        */
1099 /**************************************************************************/
_nx_rtp_sender_rtcp_sdes_callback_set(NX_RTP_SENDER * rtp_sender,UINT (* rtcp_sdes_cb)(NX_RTCP_SDES_INFO *))1100 UINT _nx_rtp_sender_rtcp_sdes_callback_set(NX_RTP_SENDER *rtp_sender, UINT (*rtcp_sdes_cb)(NX_RTCP_SDES_INFO *))
1101 {
1102     rtp_sender -> nx_rtp_sender_rtcp_sdes_cb = rtcp_sdes_cb;
1103 
1104     return(NX_SUCCESS);
1105 }
1106 
1107 /**************************************************************************/
1108 /*                                                                        */
1109 /*  FUNCTION                                               RELEASE        */
1110 /*                                                                        */
1111 /*    _nxe_rtp_sender_session_packet_allocate            PORTABLE C       */
1112 /*                                                           6.3.0        */
1113 /*  AUTHOR                                                                */
1114 /*                                                                        */
1115 /*    Haiqing Zhao, Microsoft Corporation                                 */
1116 /*                                                                        */
1117 /*  DESCRIPTION                                                           */
1118 /*                                                                        */
1119 /*    This function checks errors in the RTP sender session packet        */
1120 /*    allocate function call.                                             */
1121 /*                                                                        */
1122 /*  INPUT                                                                 */
1123 /*                                                                        */
1124 /*    session                              Pointer to RTP session         */
1125 /*    packet_ptr                           Pointer to allocated packet    */
1126 /*    wait_option                          Suspension option              */
1127 /*                                                                        */
1128 /*  OUTPUT                                                                */
1129 /*                                                                        */
1130 /*    status                               Completion status              */
1131 /*    NX_PTR_ERROR                         Invalid pointer input          */
1132 /*                                                                        */
1133 /*  CALLS                                                                 */
1134 /*                                                                        */
1135 /*    _nx_rtp_sender_session_packet_allocate                              */
1136 /*                                         Allocate a packet for the user */
1137 /*                                                                        */
1138 /*  CALLED BY                                                             */
1139 /*                                                                        */
1140 /*    Application Code                                                    */
1141 /*                                                                        */
1142 /*  RELEASE HISTORY                                                       */
1143 /*                                                                        */
1144 /*    DATE              NAME                      DESCRIPTION             */
1145 /*                                                                        */
1146 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
1147 /*                                                                        */
1148 /**************************************************************************/
_nxe_rtp_sender_session_packet_allocate(NX_RTP_SESSION * session,NX_PACKET ** packet_ptr,ULONG wait_option)1149 UINT _nxe_rtp_sender_session_packet_allocate(NX_RTP_SESSION *session, NX_PACKET **packet_ptr, ULONG wait_option)
1150 {
1151 
1152 UINT status;
1153 
1154 
1155     /* Check for invalid input pointers. */
1156     if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (packet_ptr == NX_NULL))
1157     {
1158         return(NX_PTR_ERROR);
1159     }
1160 
1161     /* Call actual RTP sender session packet allocate service. */
1162     status = _nx_rtp_sender_session_packet_allocate(session, packet_ptr, wait_option);
1163 
1164     /* Return status. */
1165     return(status);
1166 }
1167 
1168 /**************************************************************************/
1169 /*                                                                        */
1170 /*  FUNCTION                                               RELEASE        */
1171 /*                                                                        */
1172 /*    _nx_rtp_sender_session_packet_allocate             PORTABLE C       */
1173 /*                                                           6.3.0        */
1174 /*  AUTHOR                                                                */
1175 /*                                                                        */
1176 /*    Haiqing Zhao, Microsoft Corporation                                 */
1177 /*                                                                        */
1178 /*  DESCRIPTION                                                           */
1179 /*                                                                        */
1180 /*    This function allocate a RTP packet from the packet pool given      */
1181 /*    by rtp_sender_create, and returns this packet to the user.          */
1182 /*                                                                        */
1183 /*  INPUT                                                                 */
1184 /*                                                                        */
1185 /*    session                              Pointer to RTP session         */
1186 /*    packet_ptr                           Pointer to allocated packet    */
1187 /*    wait_option                          Suspension option              */
1188 /*                                                                        */
1189 /*  OUTPUT                                                                */
1190 /*                                                                        */
1191 /*    status                               Completion status              */
1192 /*                                                                        */
1193 /*  CALLS                                                                 */
1194 /*                                                                        */
1195 /*    nx_packet_allocate                   Allocate a new packet          */
1196 /*                                                                        */
1197 /*  CALLED BY                                                             */
1198 /*                                                                        */
1199 /*    Application Code                                                    */
1200 /*                                                                        */
1201 /*  RELEASE HISTORY                                                       */
1202 /*                                                                        */
1203 /*    DATE              NAME                      DESCRIPTION             */
1204 /*                                                                        */
1205 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
1206 /*                                                                        */
1207 /**************************************************************************/
_nx_rtp_sender_session_packet_allocate(NX_RTP_SESSION * session,NX_PACKET ** packet_ptr,ULONG wait_option)1208 UINT _nx_rtp_sender_session_packet_allocate(NX_RTP_SESSION *session, NX_PACKET **packet_ptr, ULONG wait_option)
1209 {
1210 
1211 UINT status;
1212 
1213 
1214     /* Allocate and get the packet from IP default packet pool. */
1215     status = nx_packet_allocate(session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, packet_ptr, NX_RTP_PACKET, wait_option);
1216 
1217     return(status);
1218 }
1219 
1220 /**************************************************************************/
1221 /*                                                                        */
1222 /*  FUNCTION                                               RELEASE        */
1223 /*                                                                        */
1224 /*    _nxe_rtp_sender_session_packet_send                PORTABLE C       */
1225 /*                                                           6.3.0        */
1226 /*  AUTHOR                                                                */
1227 /*                                                                        */
1228 /*    Haiqing Zhao, Microsoft Corporation                                 */
1229 /*                                                                        */
1230 /*  DESCRIPTION                                                           */
1231 /*                                                                        */
1232 /*    This function checks errors in the RTP sender session packet send   */
1233 /*    function call.                                                      */
1234 /*                                                                        */
1235 /*  INPUT                                                                 */
1236 /*                                                                        */
1237 /*    session                              Pointer to RTP session         */
1238 /*    packet_ptr                           Pointer to packet data to send */
1239 /*    timestamp                            RTP timestamp for current data */
1240 /*    ntp_msw                              Most significant word of       */
1241 /*                                           network time                 */
1242 /*    ntp_lsw                              Least significant word of      */
1243 /*                                           network time                 */
1244 /*    marker                               Marker bit for significant     */
1245 /*                                           event such as frame boundary */
1246 /*                                                                        */
1247 /*  OUTPUT                                                                */
1248 /*                                                                        */
1249 /*    status                               Completion status              */
1250 /*    NX_PTR_ERROR                         Invalid pointer input          */
1251 /*                                                                        */
1252 /*  CALLS                                                                 */
1253 /*                                                                        */
1254 /*    _nx_rtp_sender_session_packet_send   Send packet data               */
1255 /*                                                                        */
1256 /*  CALLED BY                                                             */
1257 /*                                                                        */
1258 /*    Application Code                                                    */
1259 /*                                                                        */
1260 /*  RELEASE HISTORY                                                       */
1261 /*                                                                        */
1262 /*    DATE              NAME                      DESCRIPTION             */
1263 /*                                                                        */
1264 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
1265 /*                                                                        */
1266 /**************************************************************************/
_nxe_rtp_sender_session_packet_send(NX_RTP_SESSION * session,NX_PACKET * packet_ptr,ULONG timestamp,ULONG ntp_msw,ULONG ntp_lsw,UINT marker)1267 UINT _nxe_rtp_sender_session_packet_send(NX_RTP_SESSION *session, NX_PACKET *packet_ptr, ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
1268 {
1269 
1270 UINT status;
1271 
1272 
1273     /* Check for invalid input pointers. */
1274     if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (packet_ptr == NX_NULL))
1275     {
1276         return(NX_PTR_ERROR);
1277     }
1278 
1279     /* Check for an invalid packet prepend pointer.  */
1280     if ((INT)(packet_ptr -> nx_packet_prepend_ptr - packet_ptr -> nx_packet_data_start) < (INT)(NX_RTP_PACKET))
1281     {
1282         return(NX_UNDERFLOW);
1283     }
1284 
1285     /* Call actual RTP sender session packet send service. */
1286     status = _nx_rtp_sender_session_packet_send(session, packet_ptr, timestamp, ntp_msw, ntp_lsw, marker);
1287 
1288     /* Return status. */
1289     return(status);
1290 }
1291 
1292 /**************************************************************************/
1293 /*                                                                        */
1294 /*  FUNCTION                                               RELEASE        */
1295 /*                                                                        */
1296 /*    _nx_rtp_sender_session_packet_send                 PORTABLE C       */
1297 /*                                                           6.4.0        */
1298 /*  AUTHOR                                                                */
1299 /*                                                                        */
1300 /*    Haiqing Zhao, Microsoft Corporation                                 */
1301 /*                                                                        */
1302 /*  DESCRIPTION                                                           */
1303 /*                                                                        */
1304 /*    This function sends passed packet data in RTP format, and calls     */
1305 /*    RTP sender rctp send function as the entry to send RTCP report      */
1306 /*                                                                        */
1307 /*  INPUT                                                                 */
1308 /*                                                                        */
1309 /*    session                              Pointer to RTP session         */
1310 /*    packet_ptr                           Pointer to packet data to send */
1311 /*    timestamp                            RTP timestamp for current data */
1312 /*    ntp_msw                              Most significant word of       */
1313 /*                                           network time                 */
1314 /*    ntp_lsw                              Least significant word of      */
1315 /*                                           network time                 */
1316 /*    marker                               Marker bit for significant     */
1317 /*                                           event such as frame boundary */
1318 /*                                                                        */
1319 /*  OUTPUT                                                                */
1320 /*                                                                        */
1321 /*    status                               Completion status              */
1322 /*                                                                        */
1323 /*  CALLS                                                                 */
1324 /*                                                                        */
1325 /*    NX_CHANGE_USHORT_ENDIAN              Adjust USHORT variable endian  */
1326 /*    _nx_rtcp_packet_send                 Send RTCP report               */
1327 /*    nxd_udp_socket_source_send           Send RTP packet through UDP    */
1328 /*                                                                        */
1329 /*  CALLED BY                                                             */
1330 /*                                                                        */
1331 /*    Application Code                                                    */
1332 /*                                                                        */
1333 /*  RELEASE HISTORY                                                       */
1334 /*                                                                        */
1335 /*    DATE              NAME                      DESCRIPTION             */
1336 /*                                                                        */
1337 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
1338 /*  12-31-2023     Haiqing Zhao            Modified comments(s),          */
1339 /*                                           supported VLAN,              */
1340 /*                                           resulting in version 6.4.0   */
1341 /*                                                                        */
1342 /**************************************************************************/
_nx_rtp_sender_session_packet_send(NX_RTP_SESSION * session,NX_PACKET * packet_ptr,ULONG timestamp,ULONG ntp_msw,ULONG ntp_lsw,UINT marker)1343 UINT _nx_rtp_sender_session_packet_send(NX_RTP_SESSION *session, NX_PACKET *packet_ptr, ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
1344 {
1345 
1346 UINT           status;
1347 NX_RTP_HEADER *rtp_header_ptr;
1348 NX_PACKET     *send_packet;
1349 NX_PACKET     *data_packet = packet_ptr;
1350 UCHAR         *data_ptr = data_packet -> nx_packet_prepend_ptr;
1351 UINT           sample_factor = session -> nx_rtp_session_sample_factor;
1352 ULONG          fragment_size = session -> nx_rtp_session_max_packet_size;
1353 ULONG          remaining_bytes = packet_ptr -> nx_packet_length;
1354 ULONG          payload_data_length;
1355 ULONG          copy_size;
1356 UINT           fragmentation = NX_FALSE;
1357 
1358 
1359     /* Transfer marker bit into rtp header field. */
1360     if (marker)
1361     {
1362         marker = (UINT)NX_RTP_HEADER_MARKER_BIT;
1363     }
1364 
1365     /* Compare and set the fragmentation flag. */
1366     if (packet_ptr -> nx_packet_length > fragment_size)
1367     {
1368         fragmentation = NX_TRUE;
1369     }
1370 
1371     while (remaining_bytes)
1372     {
1373         if (fragmentation == NX_FALSE)
1374         {
1375 
1376             /* No fragmentation needed, set send packet to user passed packet directly. */
1377             send_packet = packet_ptr;
1378         }
1379         else
1380         {
1381 
1382             /* Allocate a rtp packet for fragmentation. */
1383             status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
1384             if (status)
1385             {
1386                 return(status);
1387             }
1388 
1389             /* Copy data. */
1390             while (send_packet -> nx_packet_length < fragment_size)
1391             {
1392 
1393                 /* Compute how many data bytes to copy in the current packet. */
1394                 copy_size = (ULONG)(data_packet -> nx_packet_append_ptr - data_ptr);
1395                 if ((send_packet -> nx_packet_length + copy_size) > fragment_size)
1396                 {
1397 
1398                     /* Compute copy size with the remaining packet space in the send packet. */
1399                     copy_size = fragment_size - send_packet -> nx_packet_length;
1400                 }
1401 
1402                 /* Copy data into the send packet. */
1403                 status = nx_packet_data_append(send_packet, data_ptr, copy_size, session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
1404                 if (status)
1405                 {
1406 
1407                     /* Release the allocated send packet and return error status. */
1408                     nx_packet_release(send_packet);
1409                     return(status);
1410                 }
1411 
1412                 /* Move the data pointer after a success copy. */
1413                 data_ptr += copy_size;
1414 
1415                 /* Make sure all data in current packet finish copying. */
1416                 if (data_ptr >= data_packet -> nx_packet_append_ptr)
1417                 {
1418                     if (data_packet -> nx_packet_next == NX_NULL)
1419                     {
1420 
1421                         /* Jump out current while loop when finding all data packets finish copying. */
1422                         break;
1423                     }
1424                     else
1425                     {
1426 
1427                         /* Move to the next packet. */
1428                         data_packet = data_packet -> nx_packet_next;
1429 
1430                         /* Move the data pointer to the initial position of the next packet. */
1431                         data_ptr = data_packet -> nx_packet_prepend_ptr;
1432                     }
1433                 }
1434             }
1435         }
1436 
1437         /* Obtain payload data length and decrease remaining bytes with it. */
1438         payload_data_length = send_packet -> nx_packet_length;
1439         remaining_bytes -= payload_data_length;
1440 
1441         /* Add rtp header information.
1442              0                   1                   2                   3
1443              0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
1444             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1445             |V=2|P|X|  CC   |M|     PT      | sequence number               |
1446             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1447             |                           timestamp                           |
1448             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1449             |           synchronization source (SSRC) identifier            |
1450             +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
1451         */
1452 
1453         /* Update the overall packet length, assign rtp_header pointer to the initial position. */
1454         send_packet -> nx_packet_length += NX_RTP_HEADER_LENGTH;
1455         send_packet -> nx_packet_prepend_ptr -= NX_RTP_HEADER_LENGTH;
1456         rtp_header_ptr = (NX_RTP_HEADER *)(send_packet -> nx_packet_prepend_ptr);
1457 
1458         /* Fill field 0 which contains following 4 sub-fields (3 of them are considered no need to support so far).
1459         1) The RTP protocol version number is always 2.
1460         2) The padding feature is ignored (i.e not supported) by using lower level padding if required (e.g. tls)
1461         3) The extension bit/feature is set to zero (i.e. not supported)
1462         4) The contributing source identifiers count is set to zero (i.e. not supported) */
1463         rtp_header_ptr -> nx_rtp_header_field0 = (NX_RTP_VERSION << 6);
1464 
1465         /* Fill the second byte by the payload type recorded in the session context. */
1466         rtp_header_ptr -> nx_rtp_header_field1 = session -> nx_rtp_session_payload_type;
1467 
1468         /* Set the marker bit which is intended to allow significant events such as frame boundaries to be marked in the packet stream.
1469            This is a user selectable flag and allow the user to choose whether to set it. */
1470         if ((remaining_bytes == 0) || (sample_factor))
1471         {
1472             rtp_header_ptr -> nx_rtp_header_field1 |= (UCHAR)marker;
1473         }
1474 
1475         /* Fill the sequence number from the session context, convert it from host byte order to network byte order. Increase recorded sequence number by 1. */
1476         rtp_header_ptr -> nx_rtp_header_sequence_number = session -> nx_rtp_session_sequence_number;
1477         NX_CHANGE_USHORT_ENDIAN(rtp_header_ptr -> nx_rtp_header_sequence_number);
1478         session -> nx_rtp_session_sequence_number++;
1479 
1480         /* Fill the timestamp passed as an argument from the user, convert it from host byte order to network byte order. */
1481         rtp_header_ptr -> nx_rtp_header_timestamp = timestamp;
1482         NX_CHANGE_ULONG_ENDIAN(rtp_header_ptr -> nx_rtp_header_timestamp);
1483 
1484         /* Fill the ssrc from the session context, convert it from host byte order to network byte order. */
1485         rtp_header_ptr -> nx_rtp_header_ssrc = session -> nx_rtp_session_ssrc;
1486         NX_CHANGE_ULONG_ENDIAN(rtp_header_ptr -> nx_rtp_header_ssrc);
1487 
1488         /* Store timestamps for rtcp send report. */
1489         session -> nx_rtp_session_rtp_timestamp = timestamp;
1490         session -> nx_rtp_session_ntp_timestamp_msw = ntp_msw;
1491         session -> nx_rtp_session_ntp_timestamp_lsw = ntp_lsw;
1492 
1493         _nx_rtcp_packet_send(session);
1494 
1495 #ifdef NX_ENABLE_VLAN
1496         /* If user has configured vlan priority with valid value, set vlan priority for the rtp data packet to sent.  */
1497         if (session -> nx_rtp_session_vlan_priority != NX_VLAN_PRIORITY_INVALID)
1498         {
1499             status = nx_packet_vlan_priority_set(send_packet, session -> nx_rtp_session_vlan_priority);
1500             if (status)
1501             {
1502                 return(status);
1503             }
1504         }
1505 #endif /* NX_ENABLE_VLAN */
1506 
1507         /* Send out rtp packet */
1508         status = nxd_udp_socket_source_send(&(session -> nx_rtp_sender -> nx_rtp_sender_rtp_socket), send_packet,
1509                                             &(session -> nx_rtp_session_peer_ip_address), session -> nx_rtp_session_peer_rtp_port,
1510                                             session -> nx_rtp_session_interface_index);
1511         if (status)
1512         {
1513             if (fragmentation)
1514             {
1515 
1516                 /* Release the send packet when fragmentation applied. */
1517                 nx_packet_release(send_packet);
1518             }
1519             else
1520             {
1521 
1522                 /* Reset the user packet prepend pointer and the total packet length. */
1523                 packet_ptr -> nx_packet_prepend_ptr += NX_RTP_HEADER_LENGTH;
1524                 packet_ptr -> nx_packet_length -= NX_RTP_HEADER_LENGTH;
1525             }
1526 
1527             /* Return error status and let the user to determine when to release the packet. */
1528             return(status);
1529         }
1530 
1531         /* Update sender report statistic. */
1532         session -> nx_rtp_session_packet_count++;
1533         session -> nx_rtp_session_octet_count += payload_data_length;
1534 
1535         /* Update timestamp when sample-based mode enabled and there are more data bytes to transmit. */
1536         if (sample_factor && remaining_bytes)
1537         {
1538             timestamp += payload_data_length / sample_factor;
1539         }
1540     }
1541 
1542     if (fragmentation)
1543     {
1544 
1545         /* Release the user passed packet when fragmentation applied. */
1546         nx_packet_release(packet_ptr);
1547     }
1548 
1549     return(NX_SUCCESS);
1550 }
1551 
1552 /**************************************************************************/
1553 /*                                                                        */
1554 /*  FUNCTION                                               RELEASE        */
1555 /*                                                                        */
1556 /*    _nxe_rtp_sender_session_sequence_number_get        PORTABLE C       */
1557 /*                                                           6.3.0        */
1558 /*  AUTHOR                                                                */
1559 /*                                                                        */
1560 /*    Haiqing Zhao, Microsoft Corporation                                 */
1561 /*                                                                        */
1562 /*  DESCRIPTION                                                           */
1563 /*                                                                        */
1564 /*    This function checks errors in the RTP sender session sequence      */
1565 /*    number get function call.                                           */
1566 /*                                                                        */
1567 /*  INPUT                                                                 */
1568 /*                                                                        */
1569 /*    session                              Pointer to RTP session         */
1570 /*    sequence_number                      Pointer to the sequence number */
1571 /*                                                                        */
1572 /*  OUTPUT                                                                */
1573 /*                                                                        */
1574 /*    status                               Completion status              */
1575 /*    NX_PTR_ERROR                         Invalid pointer input          */
1576 /*                                                                        */
1577 /*  CALLS                                                                 */
1578 /*                                                                        */
1579 /*    _nx_rtp_sender_session_sequence_number_get                          */
1580 /*                                         Get the sequence number value  */
1581 /*                                                                        */
1582 /*  CALLED BY                                                             */
1583 /*                                                                        */
1584 /*    Application Code                                                    */
1585 /*                                                                        */
1586 /*  RELEASE HISTORY                                                       */
1587 /*                                                                        */
1588 /*    DATE              NAME                      DESCRIPTION             */
1589 /*                                                                        */
1590 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
1591 /*                                                                        */
1592 /**************************************************************************/
_nxe_rtp_sender_session_sequence_number_get(NX_RTP_SESSION * session,UINT * sequence_number)1593 UINT _nxe_rtp_sender_session_sequence_number_get(NX_RTP_SESSION *session, UINT *sequence_number)
1594 {
1595 
1596 UINT status;
1597 
1598 
1599     /* Check for invalid input pointers. */
1600     if ((session == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (sequence_number == NX_NULL))
1601     {
1602         return(NX_PTR_ERROR);
1603     }
1604 
1605     /* Call actual RTP sender session sequence number get service. */
1606     status = _nx_rtp_sender_session_sequence_number_get(session, sequence_number);
1607 
1608     /* Return status. */
1609     return(status);
1610 }
1611 
1612 /**************************************************************************/
1613 /*                                                                        */
1614 /*  FUNCTION                                               RELEASE        */
1615 /*                                                                        */
1616 /*    _nx_rtp_sender_session_sequence_number_get         PORTABLE C       */
1617 /*                                                           6.3.0        */
1618 /*  AUTHOR                                                                */
1619 /*                                                                        */
1620 /*    Haiqing Zhao, Microsoft Corporation                                 */
1621 /*                                                                        */
1622 /*  DESCRIPTION                                                           */
1623 /*                                                                        */
1624 /*    This function provides the current sequence number value.           */
1625 /*                                                                        */
1626 /*  INPUT                                                                 */
1627 /*                                                                        */
1628 /*    session                              Pointer to RTP session         */
1629 /*    sequence_number                      Pointer to the sequence number */
1630 /*                                                                        */
1631 /*  OUTPUT                                                                */
1632 /*                                                                        */
1633 /*    NX_SUCCESS                           Completion status              */
1634 /*                                                                        */
1635 /*  CALLS                                                                 */
1636 /*                                                                        */
1637 /*    None                                                                */
1638 /*                                                                        */
1639 /*  CALLED BY                                                             */
1640 /*                                                                        */
1641 /*    Application Code                                                    */
1642 /*                                                                        */
1643 /*  RELEASE HISTORY                                                       */
1644 /*                                                                        */
1645 /*    DATE              NAME                      DESCRIPTION             */
1646 /*                                                                        */
1647 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
1648 /*                                                                        */
1649 /**************************************************************************/
_nx_rtp_sender_session_sequence_number_get(NX_RTP_SESSION * session,UINT * sequence_number)1650 UINT _nx_rtp_sender_session_sequence_number_get(NX_RTP_SESSION *session, UINT *sequence_number)
1651 {
1652 
1653     /* Assign return value with the current sequence number of the session. */
1654     *sequence_number = session -> nx_rtp_session_sequence_number;
1655 
1656     return(NX_SUCCESS);
1657 }
1658 
1659 /**************************************************************************/
1660 /*                                                                        */
1661 /*  FUNCTION                                               RELEASE        */
1662 /*                                                                        */
1663 /*    _nxe_rtp_sender_session_sample_factor_set          PORTABLE C       */
1664 /*                                                           6.3.0        */
1665 /*  AUTHOR                                                                */
1666 /*                                                                        */
1667 /*    Haiqing Zhao, Microsoft Corporation                                 */
1668 /*                                                                        */
1669 /*  DESCRIPTION                                                           */
1670 /*                                                                        */
1671 /*    This function checks errors in the RTP sender session sampling      */
1672 /*    factor set function call.                                           */
1673 /*                                                                        */
1674 /*  INPUT                                                                 */
1675 /*                                                                        */
1676 /*    session                              Pointer to RTP session         */
1677 /*    factor                               The sampling factor            */
1678 /*                                                                        */
1679 /*  OUTPUT                                                                */
1680 /*                                                                        */
1681 /*    status                               Completion status              */
1682 /*    NX_PTR_ERROR                         Invalid pointer input          */
1683 /*                                                                        */
1684 /*  CALLS                                                                 */
1685 /*                                                                        */
1686 /*    _nx_rtp_sender_session_sample_factor_set                          */
1687 /*                                         Set the sampling factor value  */
1688 /*                                                                        */
1689 /*  CALLED BY                                                             */
1690 /*                                                                        */
1691 /*    Application Code                                                    */
1692 /*                                                                        */
1693 /*  RELEASE HISTORY                                                       */
1694 /*                                                                        */
1695 /*    DATE              NAME                      DESCRIPTION             */
1696 /*                                                                        */
1697 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
1698 /*                                                                        */
1699 /**************************************************************************/
_nxe_rtp_sender_session_sample_factor_set(NX_RTP_SESSION * session,UINT factor)1700 UINT _nxe_rtp_sender_session_sample_factor_set(NX_RTP_SESSION *session, UINT factor)
1701 {
1702 
1703 UINT status;
1704 
1705 
1706     /* Check for invalid input pointers. */
1707     if ((session == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID))
1708     {
1709         return(NX_PTR_ERROR);
1710     }
1711 
1712     /* Call actual RTP sender session sampling factor set service. */
1713     status = _nx_rtp_sender_session_sample_factor_set(session, factor);
1714 
1715     /* Return status. */
1716     return(status);
1717 }
1718 
1719 /**************************************************************************/
1720 /*                                                                        */
1721 /*  FUNCTION                                               RELEASE        */
1722 /*                                                                        */
1723 /*    _nx_rtp_sender_session_sample_factor_set           PORTABLE C       */
1724 /*                                                           6.3.0        */
1725 /*  AUTHOR                                                                */
1726 /*                                                                        */
1727 /*    Haiqing Zhao, Microsoft Corporation                                 */
1728 /*                                                                        */
1729 /*  DESCRIPTION                                                           */
1730 /*                                                                        */
1731 /*    This function sets the sample factor value for sample-based payload */
1732 /*    in rtp. The sample factor determines the timestamp increasing rate  */
1733 /*    in the function _nx_rtp_sender_session_packet_send when the         */
1734 /*    fragmentation feature triggered in sample-based mode since timestamp*/
1735 /*    shall be increased in a pace for each fragmentation packet.         */
1736 /*                                                                        */
1737 /*    The default sample factor value 0, representing frame-based mode.   */
1738 /*    User can use this function to set a non-zero sample factor, with    */
1739 /*    automatically triggering sample-based mode.                         */
1740 /*    Examples about how the sample factor is computed for audio:         */
1741 /*    1) sample bits:  8, channel number: 1, factor = 1 * (8/8) = 1       */
1742 /*    2) sample bits: 16, channel number: 1, factor = 1 * (16/8) = 2      */
1743 /*    3) sample bits: 16, channel number: 2, factor = 2 * (16/8) = 4      */
1744 /*                                                                        */
1745 /*  INPUT                                                                 */
1746 /*                                                                        */
1747 /*    session                              Pointer to RTP session         */
1748 /*    factor                               The sampling factor            */
1749 /*                                                                        */
1750 /*  OUTPUT                                                                */
1751 /*                                                                        */
1752 /*    NX_SUCCESS                           Completion status              */
1753 /*                                                                        */
1754 /*  CALLS                                                                 */
1755 /*                                                                        */
1756 /*    None                                                                */
1757 /*                                                                        */
1758 /*  CALLED BY                                                             */
1759 /*                                                                        */
1760 /*    Application Code                                                    */
1761 /*                                                                        */
1762 /*  RELEASE HISTORY                                                       */
1763 /*                                                                        */
1764 /*    DATE              NAME                      DESCRIPTION             */
1765 /*                                                                        */
1766 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
1767 /*                                                                        */
1768 /**************************************************************************/
_nx_rtp_sender_session_sample_factor_set(NX_RTP_SESSION * session,UINT factor)1769 UINT _nx_rtp_sender_session_sample_factor_set(NX_RTP_SESSION *session, UINT factor)
1770 {
1771 
1772     /* Store the factor value into the session. */
1773     session -> nx_rtp_session_sample_factor = factor;
1774 
1775     return(NX_SUCCESS);
1776 }
1777 
1778 /**************************************************************************/
1779 /*                                                                        */
1780 /*  FUNCTION                                               RELEASE        */
1781 /*                                                                        */
1782 /*    _nxe_rtp_sender_session_ssrc_get                   PORTABLE C       */
1783 /*                                                           6.3.0        */
1784 /*  AUTHOR                                                                */
1785 /*                                                                        */
1786 /*    Haiqing Zhao, Microsoft Corporation                                 */
1787 /*                                                                        */
1788 /*  DESCRIPTION                                                           */
1789 /*                                                                        */
1790 /*    This function checks errors in the RTP sender session ssrc get      */
1791 /*    function call.                                                      */
1792 /*                                                                        */
1793 /*  INPUT                                                                 */
1794 /*                                                                        */
1795 /*    session                              Pointer to RTP session         */
1796 /*    ssrc                                 Pointer to ssrc                */
1797 /*                                                                        */
1798 /*  OUTPUT                                                                */
1799 /*                                                                        */
1800 /*    status                               Completion status              */
1801 /*    NX_PTR_ERROR                         Invalid pointer input          */
1802 /*                                                                        */
1803 /*  CALLS                                                                 */
1804 /*                                                                        */
1805 /*    _nx_rtp_sender_session_ssrc_get      Get ssrc value                 */
1806 /*                                                                        */
1807 /*  CALLED BY                                                             */
1808 /*                                                                        */
1809 /*    Application Code                                                    */
1810 /*                                                                        */
1811 /*  RELEASE HISTORY                                                       */
1812 /*                                                                        */
1813 /*    DATE              NAME                      DESCRIPTION             */
1814 /*                                                                        */
1815 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
1816 /*                                                                        */
1817 /**************************************************************************/
_nxe_rtp_sender_session_ssrc_get(NX_RTP_SESSION * session,ULONG * ssrc)1818 UINT _nxe_rtp_sender_session_ssrc_get(NX_RTP_SESSION *session, ULONG *ssrc)
1819 {
1820 
1821 UINT status;
1822 
1823 
1824     /* Check for invalid input pointers. */
1825     if ((session == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (ssrc == NX_NULL))
1826     {
1827         return(NX_PTR_ERROR);
1828     }
1829 
1830     /* Call actual RTP sender session ssrc get service. */
1831     status = _nx_rtp_sender_session_ssrc_get(session, ssrc);
1832 
1833     /* Return status. */
1834     return(status);
1835 }
1836 
1837 /**************************************************************************/
1838 /*                                                                        */
1839 /*  FUNCTION                                               RELEASE        */
1840 /*                                                                        */
1841 /*    _nx_rtp_sender_session_ssrc_get                    PORTABLE C       */
1842 /*                                                           6.3.0        */
1843 /*  AUTHOR                                                                */
1844 /*                                                                        */
1845 /*    Haiqing Zhao, Microsoft Corporation                                 */
1846 /*                                                                        */
1847 /*  DESCRIPTION                                                           */
1848 /*                                                                        */
1849 /*    This function provides the current ssrc value.                      */
1850 /*                                                                        */
1851 /*  INPUT                                                                 */
1852 /*                                                                        */
1853 /*    session                              Pointer to RTP session         */
1854 /*    ssrc                                 Pointer to ssrc                */
1855 /*                                                                        */
1856 /*  OUTPUT                                                                */
1857 /*                                                                        */
1858 /*    NX_SUCCESS                           Completion status              */
1859 /*                                                                        */
1860 /*  CALLS                                                                 */
1861 /*                                                                        */
1862 /*    None                                                                */
1863 /*                                                                        */
1864 /*  CALLED BY                                                             */
1865 /*                                                                        */
1866 /*    Application Code                                                    */
1867 /*                                                                        */
1868 /*  RELEASE HISTORY                                                       */
1869 /*                                                                        */
1870 /*    DATE              NAME                      DESCRIPTION             */
1871 /*                                                                        */
1872 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
1873 /*                                                                        */
1874 /**************************************************************************/
_nx_rtp_sender_session_ssrc_get(NX_RTP_SESSION * session,ULONG * ssrc)1875 UINT _nx_rtp_sender_session_ssrc_get(NX_RTP_SESSION *session, ULONG *ssrc)
1876 {
1877 
1878     /* Assign return value with the current ssrc of the session */
1879     *ssrc = session -> nx_rtp_session_ssrc;
1880 
1881     return(NX_SUCCESS);
1882 }
1883 
1884 /**************************************************************************/
1885 /*                                                                        */
1886 /*  FUNCTION                                               RELEASE        */
1887 /*                                                                        */
1888 /*    _nxe_rtp_sender_session_vlan_priority_set          PORTABLE C       */
1889 /*                                                           6.4.0        */
1890 /*  AUTHOR                                                                */
1891 /*                                                                        */
1892 /*    Haiqing Zhao, Microsoft Corporation                                 */
1893 /*                                                                        */
1894 /*  DESCRIPTION                                                           */
1895 /*                                                                        */
1896 /*    This function checks errors in the RTP sender session vlan priority */
1897 /*    set function call.                                                  */
1898 /*                                                                        */
1899 /*  INPUT                                                                 */
1900 /*                                                                        */
1901 /*    session                              Pointer to RTP session         */
1902 /*    vlan_priority                        The vlan priority              */
1903 /*                                                                        */
1904 /*  OUTPUT                                                                */
1905 /*                                                                        */
1906 /*    status                               Completion status              */
1907 /*    NX_PTR_ERROR                         Invalid pointer input          */
1908 /*                                                                        */
1909 /*  CALLS                                                                 */
1910 /*                                                                        */
1911 /*    _nx_rtp_sender_session_vlan_priority_set                            */
1912 /*                                         Set the vlan priority value    */
1913 /*                                                                        */
1914 /*  CALLED BY                                                             */
1915 /*                                                                        */
1916 /*    Application Code                                                    */
1917 /*                                                                        */
1918 /*  RELEASE HISTORY                                                       */
1919 /*                                                                        */
1920 /*    DATE              NAME                      DESCRIPTION             */
1921 /*                                                                        */
1922 /*  12-31-2023     Haiqing Zhao            Initial Version 6.4.0          */
1923 /*                                                                        */
1924 /**************************************************************************/
_nxe_rtp_sender_session_vlan_priority_set(NX_RTP_SESSION * session,UINT vlan_priority)1925 UINT _nxe_rtp_sender_session_vlan_priority_set(NX_RTP_SESSION *session, UINT vlan_priority)
1926 {
1927 
1928 #ifdef NX_ENABLE_VLAN
1929 UINT status;
1930 
1931 
1932     /* Check for invalid input pointers. */
1933     if ((session == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID))
1934     {
1935         return(NX_PTR_ERROR);
1936     }
1937 
1938     /* Call actual RTP sender session vlan priority set service. */
1939     status = _nx_rtp_sender_session_vlan_priority_set(session, vlan_priority);
1940 
1941     /* Return status. */
1942     return(status);
1943 #else
1944     NX_PARAMETER_NOT_USED(session);
1945     NX_PARAMETER_NOT_USED(vlan_priority);
1946 
1947     return(NX_NOT_SUPPORTED);
1948 #endif /* NX_ENABLE_VLAN */
1949 }
1950 
1951 /**************************************************************************/
1952 /*                                                                        */
1953 /*  FUNCTION                                               RELEASE        */
1954 /*                                                                        */
1955 /*    _nxe_rtp_sender_session_vlan_priority_set          PORTABLE C       */
1956 /*                                                           6.4.0        */
1957 /*  AUTHOR                                                                */
1958 /*                                                                        */
1959 /*    Haiqing Zhao, Microsoft Corporation                                 */
1960 /*                                                                        */
1961 /*  DESCRIPTION                                                           */
1962 /*                                                                        */
1963 /*    This function sets the vlan priority value for the RTP data packets */
1964 /*    transferred in the specific session.                                */
1965 /*                                                                        */
1966 /*  INPUT                                                                 */
1967 /*                                                                        */
1968 /*    session                              Pointer to RTP session         */
1969 /*    vlan_priority                        The vlan priority              */
1970 /*                                                                        */
1971 /*  OUTPUT                                                                */
1972 /*                                                                        */
1973 /*    status                               Completion status              */
1974 /*    NX_PTR_ERROR                         Invalid pointer input          */
1975 /*                                                                        */
1976 /*  CALLS                                                                 */
1977 /*                                                                        */
1978 /*    _nx_rtp_sender_session_vlan_priority_set                            */
1979 /*                                         Set the vlan priority value    */
1980 /*                                                                        */
1981 /*  CALLED BY                                                             */
1982 /*                                                                        */
1983 /*    Application Code                                                    */
1984 /*                                                                        */
1985 /*  RELEASE HISTORY                                                       */
1986 /*                                                                        */
1987 /*    DATE              NAME                      DESCRIPTION             */
1988 /*                                                                        */
1989 /*  12-31-2023     Haiqing Zhao            Initial Version 6.4.0          */
1990 /*                                                                        */
1991 /**************************************************************************/
_nx_rtp_sender_session_vlan_priority_set(NX_RTP_SESSION * session,UINT vlan_priority)1992 UINT _nx_rtp_sender_session_vlan_priority_set(NX_RTP_SESSION *session, UINT vlan_priority)
1993 {
1994 #ifdef NX_ENABLE_VLAN
1995 
1996     /* Store the vlan priority value into the session. */
1997     session -> nx_rtp_session_vlan_priority = vlan_priority;
1998 
1999     return(NX_SUCCESS);
2000 #else
2001     NX_PARAMETER_NOT_USED(session);
2002     NX_PARAMETER_NOT_USED(vlan_priority);
2003 
2004     return(NX_NOT_SUPPORTED);
2005 #endif /* NX_ENABLE_VLAN */
2006 }
2007 
2008 /**************************************************************************/
2009 /*                                                                        */
2010 /*  FUNCTION                                               RELEASE        */
2011 /*                                                                        */
2012 /*    _nx_rtp_sender_cleanup                             PORTABLE C       */
2013 /*                                                           6.3.0        */
2014 /*  AUTHOR                                                                */
2015 /*                                                                        */
2016 /*    Haiqing Zhao, Microsoft Corporation                                 */
2017 /*                                                                        */
2018 /*  DESCRIPTION                                                           */
2019 /*                                                                        */
2020 /*    This function cleans up resources created in rtp sender.            */
2021 /*                                                                        */
2022 /*  INPUT                                                                 */
2023 /*                                                                        */
2024 /*    rtp_sender                           Pointer to RTP sender instance */
2025 /*                                                                        */
2026 /*  OUTPUT                                                                */
2027 /*                                                                        */
2028 /*    NX_SUCCESS                           Completion status              */
2029 /*                                                                        */
2030 /*  CALLS                                                                 */
2031 /*                                                                        */
2032 /*    nx_udp_socket_unbind                 Unbind RTP/RTCP sockets        */
2033 /*    nx_udp_socket_delete                 Delete RTP/RTCP sockets        */
2034 /*    tx_mutex_delete                      Delete RTP sender mutex        */
2035 /*                                                                        */
2036 /*  CALLED BY                                                             */
2037 /*                                                                        */
2038 /*    _nx_rtp_sender_create                Create RTP sender              */
2039 /*    _nx_rtp_sender_delete                Delete RTP sender              */
2040 /*                                                                        */
2041 /*  RELEASE HISTORY                                                       */
2042 /*                                                                        */
2043 /*    DATE              NAME                      DESCRIPTION             */
2044 /*                                                                        */
2045 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
2046 /*                                                                        */
2047 /**************************************************************************/
_nx_rtp_sender_cleanup(NX_RTP_SENDER * rtp_sender)2048 UINT _nx_rtp_sender_cleanup(NX_RTP_SENDER *rtp_sender)
2049 {
2050 
2051     /* Unbind and delete created rtp and rtcp sockets */
2052     nx_udp_socket_unbind(&(rtp_sender -> nx_rtp_sender_rtp_socket));
2053     nx_udp_socket_delete(&(rtp_sender -> nx_rtp_sender_rtp_socket));
2054     nx_udp_socket_unbind(&(rtp_sender -> nx_rtp_sender_rtcp_socket));
2055     nx_udp_socket_delete(&(rtp_sender -> nx_rtp_sender_rtcp_socket));
2056 
2057     /* Delete generated mutex */
2058     tx_mutex_delete(&(rtp_sender -> nx_rtp_sender_protection));
2059 
2060     return(NX_SUCCESS);
2061 }
2062 
2063 /**************************************************************************/
2064 /*                                                                        */
2065 /*  FUNCTION                                               RELEASE        */
2066 /*                                                                        */
2067 /*    _nx_rtp_sender_session_find                         PORTABLE C      */
2068 /*                                                           6.3.0        */
2069 /*  AUTHOR                                                                */
2070 /*                                                                        */
2071 /*    Ting Zhu, Microsoft Corporation                                     */
2072 /*                                                                        */
2073 /*  DESCRIPTION                                                           */
2074 /*                                                                        */
2075 /*    This function finds a RTP session through the specified ssrc.       */
2076 /*                                                                        */
2077 /*  INPUT                                                                 */
2078 /*                                                                        */
2079 /*    rtp_sender                            Pointer to RTP sender         */
2080 /*    ssrc                                  The specified session ssrc    */
2081 /*    session                               Pointer to RTP session        */
2082 /*                                            destination                 */
2083 /*                                                                        */
2084 /*  OUTPUT                                                                */
2085 /*                                                                        */
2086 /*    status                                Completion status             */
2087 /*                                                                        */
2088 /*  CALLS                                                                 */
2089 /*                                                                        */
2090 /*    None                                                                */
2091 /*                                                                        */
2092 /*  CALLED BY                                                             */
2093 /*                                                                        */
2094 /*    _nx_rtcp_packet_rr_process            Handle RTCP RR packet         */
2095 /*                                                                        */
2096 /*  RELEASE HISTORY                                                       */
2097 /*                                                                        */
2098 /*    DATE              NAME                      DESCRIPTION             */
2099 /*                                                                        */
2100 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
2101 /*                                                                        */
2102 /**************************************************************************/
_nx_rtp_sender_session_find(NX_RTP_SENDER * rtp_sender,UINT ssrc,NX_RTP_SESSION ** session)2103 UINT _nx_rtp_sender_session_find(NX_RTP_SENDER *rtp_sender, UINT ssrc, NX_RTP_SESSION **session)
2104 {
2105 
2106 NX_RTP_SESSION *start = rtp_sender -> nx_rtp_sender_session_created_ptr;
2107 
2108 
2109     while (start)
2110     {
2111         if (start -> nx_rtp_session_ssrc == ssrc)
2112         {
2113             *session = start;
2114             return(NX_SUCCESS);
2115         }
2116         start = start -> nx_rtp_session_next;
2117     }
2118 
2119     return(NX_NOT_FOUND);
2120 }
2121 
2122 /**************************************************************************/
2123 /*                                                                        */
2124 /*  FUNCTION                                               RELEASE        */
2125 /*                                                                        */
2126 /*    _nx_rtp_sender_session_link                         PORTABLE C      */
2127 /*                                                           6.3.0        */
2128 /*  AUTHOR                                                                */
2129 /*                                                                        */
2130 /*    Ting Zhu, Microsoft Corporation                                     */
2131 /*                                                                        */
2132 /*  DESCRIPTION                                                           */
2133 /*                                                                        */
2134 /*    This function links a RTP session to the RTP sender control block.  */
2135 /*                                                                        */
2136 /*  INPUT                                                                 */
2137 /*                                                                        */
2138 /*    rtp_sender                            Pointer to RTP sender         */
2139 /*    session                               Pointer to RTP session        */
2140 /*                                                                        */
2141 /*  OUTPUT                                                                */
2142 /*                                                                        */
2143 /*    None                                                                */
2144 /*                                                                        */
2145 /*  CALLS                                                                 */
2146 /*                                                                        */
2147 /*    None                                                                */
2148 /*                                                                        */
2149 /*  CALLED BY                                                             */
2150 /*                                                                        */
2151 /*    _nx_rtp_sender_session_create         Create RTP session            */
2152 /*                                                                        */
2153 /*  RELEASE HISTORY                                                       */
2154 /*                                                                        */
2155 /*    DATE              NAME                      DESCRIPTION             */
2156 /*                                                                        */
2157 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
2158 /*                                                                        */
2159 /**************************************************************************/
_nx_rtp_sender_session_link(NX_RTP_SENDER * rtp_sender,NX_RTP_SESSION * session)2160 VOID _nx_rtp_sender_session_link(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session)
2161 {
2162 
2163 NX_RTP_SESSION *tail;
2164 
2165 
2166     if (rtp_sender -> nx_rtp_sender_session_created_ptr)
2167     {
2168 
2169         /* Search the tail ptr. */
2170         tail = rtp_sender -> nx_rtp_sender_session_created_ptr;
2171 
2172         while (tail -> nx_rtp_session_next)
2173         {
2174             tail = tail -> nx_rtp_session_next;
2175         }
2176 
2177         /* Put the session at the end of the list. */
2178         tail -> nx_rtp_session_next = session;
2179     }
2180     else
2181     {
2182 
2183         /* The created session list is empty, simply add the session. */
2184         rtp_sender -> nx_rtp_sender_session_created_ptr = session;
2185     }
2186 }
2187 
2188 /**************************************************************************/
2189 /*                                                                        */
2190 /*  FUNCTION                                               RELEASE        */
2191 /*                                                                        */
2192 /*    _nx_rtp_sender_session_unlink                       PORTABLE C      */
2193 /*                                                           6.3.0        */
2194 /*  AUTHOR                                                                */
2195 /*                                                                        */
2196 /*    Ting Zhu, Microsoft Corporation                                     */
2197 /*                                                                        */
2198 /*  DESCRIPTION                                                           */
2199 /*                                                                        */
2200 /*    This function unlinks a RTP session from the RTP sender control     */
2201 /*    block.                                                              */
2202 /*                                                                        */
2203 /*  INPUT                                                                 */
2204 /*                                                                        */
2205 /*    rtp_sender                            Pointer to RTP sender         */
2206 /*    session                               Pointer to RTP session        */
2207 /*                                                                        */
2208 /*  OUTPUT                                                                */
2209 /*                                                                        */
2210 /*    status                                Completion status             */
2211 /*                                                                        */
2212 /*  CALLS                                                                 */
2213 /*                                                                        */
2214 /*    None                                                                */
2215 /*                                                                        */
2216 /*  CALLED BY                                                             */
2217 /*                                                                        */
2218 /*    _nx_rtp_sender_session_delete         Delete RTP session            */
2219 /*                                                                        */
2220 /*  RELEASE HISTORY                                                       */
2221 /*                                                                        */
2222 /*    DATE              NAME                      DESCRIPTION             */
2223 /*                                                                        */
2224 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
2225 /*                                                                        */
2226 /**************************************************************************/
_nx_rtp_sender_session_unlink(NX_RTP_SENDER * rtp_sender,NX_RTP_SESSION * session)2227 UINT _nx_rtp_sender_session_unlink(NX_RTP_SENDER *rtp_sender, NX_RTP_SESSION *session)
2228 {
2229 
2230 NX_RTP_SESSION *current;
2231 NX_RTP_SESSION *pre;
2232 
2233 
2234     /* Find the session and unlink it from the list. */
2235     if (rtp_sender -> nx_rtp_sender_session_created_ptr == session)
2236     {
2237         rtp_sender -> nx_rtp_sender_session_created_ptr = session -> nx_rtp_session_next;
2238     }
2239     else
2240     {
2241         pre = rtp_sender -> nx_rtp_sender_session_created_ptr;
2242         current = pre -> nx_rtp_session_next;
2243 
2244         while (current)
2245         {
2246             if (current == session)
2247             {
2248                 pre -> nx_rtp_session_next = current -> nx_rtp_session_next;
2249                 break;
2250             }
2251 
2252             pre = current;
2253             current = pre -> nx_rtp_session_next;
2254         }
2255     }
2256 
2257     return(NX_SUCCESS);
2258 }
2259 
2260 /**************************************************************************/
2261 /*                                                                        */
2262 /*  FUNCTION                                               RELEASE        */
2263 /*                                                                        */
2264 /*    _nx_rtcp_packet_process                             PORTABLE C      */
2265 /*                                                           6.3.0        */
2266 /*  AUTHOR                                                                */
2267 /*                                                                        */
2268 /*    Ting Zhu, Microsoft Corporation                                     */
2269 /*                                                                        */
2270 /*  DESCRIPTION                                                           */
2271 /*                                                                        */
2272 /*    This function handles reception of RTCP packet.                     */
2273 /*                                                                        */
2274 /*  INPUT                                                                 */
2275 /*                                                                        */
2276 /*    rtp_sender                            Pointer to RTP sender         */
2277 /*    packet_ptr                            Pointer to packet             */
2278 /*                                                                        */
2279 /*  OUTPUT                                                                */
2280 /*                                                                        */
2281 /*    status                                Completion status             */
2282 /*                                                                        */
2283 /*  CALLS                                                                 */
2284 /*                                                                        */
2285 /*    _nx_rtcp_packet_rr_process            Handle RR packet              */
2286 /*    _nx_rtcp_packet_sdes_process          Handle SDES packet            */
2287 /*                                                                        */
2288 /*  CALLED BY                                                             */
2289 /*                                                                        */
2290 /*    _nx_rtcp_packet_receive_notify        RTCP packet receive notify    */
2291 /*                                             service                    */
2292 /*                                                                        */
2293 /*  RELEASE HISTORY                                                       */
2294 /*                                                                        */
2295 /*    DATE              NAME                      DESCRIPTION             */
2296 /*                                                                        */
2297 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
2298 /*                                                                        */
2299 /**************************************************************************/
_nx_rtcp_packet_process(NX_RTP_SENDER * rtp_sender,NX_PACKET * packet_ptr)2300 UINT _nx_rtcp_packet_process(NX_RTP_SENDER *rtp_sender, NX_PACKET *packet_ptr)
2301 {
2302 
2303 UINT            status = NX_SUCCESS;
2304 NX_RTCP_HEADER *header;
2305 NX_RTCP_HEADER *next;
2306 UCHAR          *end;
2307 
2308 
2309     if (rtp_sender -> nx_rtp_sender_id != NX_RTP_SENDER_ID)
2310     {
2311 
2312         /* Not valid RTP sender. */
2313         return(NX_PTR_ERROR);
2314     }
2315 
2316 #ifndef NX_DISABLE_PACKET_CHAIN
2317     if (packet_ptr -> nx_packet_next)
2318     {
2319 
2320         /* Chained packet, not supported. */
2321         return(NX_NOT_SUPPORTED);
2322     }
2323 #endif /* NX_DISABLE_PACKET_CHAIN */
2324 
2325     header = (NX_RTCP_HEADER *)(packet_ptr -> nx_packet_prepend_ptr);
2326     end = packet_ptr -> nx_packet_append_ptr;
2327 
2328     if ((UCHAR *)header + sizeof(NX_RTCP_HEADER) > end)
2329     {
2330         return(NX_INVALID_PACKET);
2331     }
2332 
2333     /* Check the first RTCP packet header:
2334        1) The Padding bit should be zero for the first packet of a compound RTCP packet.
2335        2) The payload type field of the first RTCP packet in a compound packet must be equal to SR or RR.
2336      */
2337     if (((header -> nx_rtcp_byte0 & NX_RTCP_PAD_MASK) != NX_RTCP_PAD_VALUE) ||
2338         ((header -> nx_rtcp_packet_type & NX_RTCP_TYPE_MASK) != NX_RTCP_TYPE_SR))
2339     {
2340 
2341         /* Wrong packet format. */
2342         return(NX_INVALID_PACKET);
2343     }
2344 
2345     do
2346     {
2347         NX_CHANGE_USHORT_ENDIAN(header -> nx_rtcp_length);
2348 
2349         next = (NX_RTCP_HEADER *)((ULONG *)header + header -> nx_rtcp_length + 1);
2350 
2351         /* RTP version field must equal 2. */
2352         if (((header -> nx_rtcp_byte0 & NX_RTCP_VERSION_MASK) != NX_RTCP_VERSION_VALUE) || ((UCHAR *)next > end))
2353         {
2354             status = NX_INVALID_PACKET;
2355             break;
2356         }
2357 
2358         switch (header -> nx_rtcp_packet_type)
2359         {
2360         case NX_RTCP_TYPE_RR:
2361 
2362             /* Process rr packet. */
2363             status = _nx_rtcp_packet_rr_process(rtp_sender, header);
2364             break;
2365 
2366         case NX_RTCP_TYPE_SDES:
2367 
2368             /* Process sdes packet. */
2369             status = _nx_rtcp_packet_sdes_process(rtp_sender, header);
2370             break;
2371         }
2372 
2373         if (status != NX_SUCCESS)
2374         {
2375             break;
2376         }
2377 
2378         header = next;
2379     } while ((UCHAR *)header + sizeof(NX_RTCP_HEADER) <= end);
2380 
2381     return(status);
2382 }
2383 
2384 /**************************************************************************/
2385 /*                                                                        */
2386 /*  FUNCTION                                               RELEASE        */
2387 /*                                                                        */
2388 /*    _nx_rtcp_packet_rr_process                          PORTABLE C      */
2389 /*                                                           6.3.0        */
2390 /*  AUTHOR                                                                */
2391 /*                                                                        */
2392 /*    Ting Zhu, Microsoft Corporation                                     */
2393 /*                                                                        */
2394 /*  DESCRIPTION                                                           */
2395 /*                                                                        */
2396 /*    This function handles RTCP RR packet.                               */
2397 /*                                                                        */
2398 /*  INPUT                                                                 */
2399 /*                                                                        */
2400 /*    rtp_sender                            Pointer to RTP sender         */
2401 /*    header                                Pointer to RTCP packet header */
2402 /*                                                                        */
2403 /*  OUTPUT                                                                */
2404 /*                                                                        */
2405 /*    status                                Completion status             */
2406 /*                                                                        */
2407 /*  CALLS                                                                 */
2408 /*                                                                        */
2409 /*    _nx_rtp_sender_session_find           Find rtp session              */
2410 /*    tx_mutex_get                          Get mutex                     */
2411 /*    tx_mutex_put                          Release mutex                 */
2412 /*    nx_rtp_sender_rtcp_receiver_report_cb Application's RTCP RR packet  */
2413 /*                                            notify callback             */
2414 /*                                                                        */
2415 /*  CALLED BY                                                             */
2416 /*                                                                        */
2417 /*    _nx_rtcp_packet_process                Handle RTCP packet           */
2418 /*                                                                        */
2419 /*  RELEASE HISTORY                                                       */
2420 /*                                                                        */
2421 /*    DATE              NAME                      DESCRIPTION             */
2422 /*                                                                        */
2423 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
2424 /*                                                                        */
2425 /**************************************************************************/
_nx_rtcp_packet_rr_process(NX_RTP_SENDER * rtp_sender,NX_RTCP_HEADER * header)2426 UINT _nx_rtcp_packet_rr_process(NX_RTP_SENDER *rtp_sender, NX_RTCP_HEADER *header)
2427 {
2428 
2429 UINT                    status;
2430 NX_RTCP_RR             *rtcp_rr;
2431 NX_RTCP_RECEIVER_REPORT report;
2432 UINT                    (*rr_callback)(struct NX_RTP_SESSION_STRUCT *, NX_RTCP_RECEIVER_REPORT *);
2433 NX_RTP_SESSION         *session;
2434 
2435 
2436     rr_callback = rtp_sender -> nx_rtp_sender_rtcp_receiver_report_cb;
2437     if (rr_callback == NX_NULL)
2438     {
2439 
2440         /* No RTCP receiver report callback set. */
2441         return(NX_SUCCESS);
2442     }
2443 
2444     if ((header -> nx_rtcp_byte0 & NX_RTCP_COUNT_MASK) &&
2445         ((sizeof(NX_RTCP_RR) >> 2) <= (UINT)((header -> nx_rtcp_length + 1))))
2446     {
2447         rtcp_rr = (NX_RTCP_RR *)header;
2448 
2449         /* Take care of endian-ness. */
2450         NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_ssrc);
2451 
2452         /* Obtain the mutex. */
2453         status = tx_mutex_get(&(rtp_sender -> nx_rtp_sender_protection), TX_NO_WAIT);
2454 
2455         if (status != NX_SUCCESS)
2456         {
2457             return(status);
2458         }
2459 
2460         if (_nx_rtp_sender_session_find(rtp_sender, rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_ssrc, &session) == NX_SUCCESS)
2461         {
2462             NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_ssrc);
2463             NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_loss);
2464             NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_extended_max);
2465             NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_jitter);
2466             NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_last_sr);
2467             NX_CHANGE_ULONG_ENDIAN(rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_delay);
2468 
2469             /* Copy the values out for the callback function. */
2470             report.receiver_ssrc = rtcp_rr -> nx_rtcp_rr_ssrc;
2471             report.fraction_loss = rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_loss >> 24;
2472             report.packet_loss = ((((INT)rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_loss) << 8) >> 8);
2473             report.extended_max = rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_extended_max;
2474             report.jitter = rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_jitter;
2475             report.last_sr = rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_last_sr;
2476             report.delay = rtcp_rr -> nx_rtcp_rr_report.nx_rtcp_report_delay;
2477 
2478             /* Invoke the callback function to process data inside the RTCP RR packet. */
2479             rr_callback(session, &report);
2480         }
2481 
2482         /* Release the mutex. */
2483         tx_mutex_put(&(rtp_sender -> nx_rtp_sender_protection));
2484     }
2485 
2486     return(NX_SUCCESS);
2487 }
2488 
2489 /**************************************************************************/
2490 /*                                                                        */
2491 /*  FUNCTION                                               RELEASE        */
2492 /*                                                                        */
2493 /*    _nx_rtcp_packet_sdes_process                        PORTABLE C      */
2494 /*                                                           6.3.0        */
2495 /*  AUTHOR                                                                */
2496 /*                                                                        */
2497 /*    Ting Zhu, Microsoft Corporation                                     */
2498 /*                                                                        */
2499 /*  DESCRIPTION                                                           */
2500 /*                                                                        */
2501 /*    This function handles RTCP SDES packet.                             */
2502 /*                                                                        */
2503 /*  INPUT                                                                 */
2504 /*                                                                        */
2505 /*    rtp_sender                            Pointer to RTP sender         */
2506 /*    header                                Pointer to RTCP packet header */
2507 /*                                                                        */
2508 /*  OUTPUT                                                                */
2509 /*                                                                        */
2510 /*    status                                Completion status             */
2511 /*                                                                        */
2512 /*  CALLS                                                                 */
2513 /*                                                                        */
2514 /*    nx_rtp_sender_rtcp_sdes_cb            Application's RTCP SDES       */
2515 /*                                            packet notify callback      */
2516 /*                                                                        */
2517 /*  CALLED BY                                                             */
2518 /*                                                                        */
2519 /*    _nx_rtcp_packet_process                Handle RTCP packet           */
2520 /*                                                                        */
2521 /*  RELEASE HISTORY                                                       */
2522 /*                                                                        */
2523 /*    DATE              NAME                      DESCRIPTION             */
2524 /*                                                                        */
2525 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
2526 /*                                                                        */
2527 /**************************************************************************/
_nx_rtcp_packet_sdes_process(NX_RTP_SENDER * rtp_sender,NX_RTCP_HEADER * header)2528 UINT _nx_rtcp_packet_sdes_process(NX_RTP_SENDER *rtp_sender, NX_RTCP_HEADER *header)
2529 {
2530 
2531 UINT                (*sdes_callback)(NX_RTCP_SDES_INFO *);
2532 NX_RTCP_SDES_CHUNK *chunk;
2533 NX_RTCP_SDES_ITEM  *item;
2534 UCHAR              *end;
2535 NX_RTCP_SDES_INFO   sdes_info;
2536 INT                 count;
2537 
2538 
2539     sdes_callback = rtp_sender -> nx_rtp_sender_rtcp_sdes_cb;
2540     if (sdes_callback == NX_NULL)
2541     {
2542 
2543         /* No RTCP receiver report callback set. */
2544         return(NX_SUCCESS);
2545     }
2546 
2547     chunk = (NX_RTCP_SDES_CHUNK *)((UCHAR *)header + sizeof(NX_RTCP_HEADER));
2548     count = (header -> nx_rtcp_byte0 & NX_RTCP_COUNT_MASK);
2549 
2550     end = (UCHAR *)((ULONG *)header + header -> nx_rtcp_length + 1);
2551 
2552     while (((UCHAR *)chunk + sizeof(NX_RTCP_SDES_CHUNK) <= end) && (count-- > 0))
2553     {
2554         item = &chunk -> nx_rtcp_sdes_item[0];
2555 
2556         NX_CHANGE_ULONG_ENDIAN(chunk -> nx_rtcp_sdes_ssrc);
2557 
2558         while (((UCHAR *)item + sizeof(NX_RTCP_SDES_ITEM) <= end) && item -> nx_rtcp_sdes_type)
2559         {
2560 
2561             if (item -> nx_rtcp_sdes_data + item -> nx_rtcp_sdes_length > end)
2562             {
2563                 return(NX_INVALID_PACKET);
2564             }
2565 
2566             if (item -> nx_rtcp_sdes_type == NX_RTCP_SDES_TYPE_CNAME)
2567             {
2568 
2569                 /* Copy the values out for the callback function. */
2570                 sdes_info.ssrc = chunk -> nx_rtcp_sdes_ssrc;
2571                 sdes_info.cname_length = item -> nx_rtcp_sdes_length;
2572 
2573                 /* CNAME string is UTF-8 encoded and is not null terminated. */
2574                 sdes_info.cname = &item -> nx_rtcp_sdes_data[0];
2575 
2576                 /* Invoke the callback function to process data inside the RTCP SDES packet. */
2577                 sdes_callback(&sdes_info);
2578 
2579                 break;
2580             }
2581 
2582             /* Advance to the next item. */
2583             item = (NX_RTCP_SDES_ITEM *)((UCHAR *)item + 2 + item -> nx_rtcp_sdes_length);
2584         }
2585 
2586         /* RFC 3550, chapter 6.5.
2587            The list of items in each chunk MUST be terminated by one or more null octets,
2588            the first of which is interpreted as an item type of zero to denote the end of the list. */
2589         chunk = (NX_RTCP_SDES_CHUNK *)((UCHAR *)chunk + (((UCHAR *)item - (UCHAR *)chunk) >> 2) + 1);
2590     }
2591 
2592     return(NX_SUCCESS);
2593 }
2594 
2595 
2596 /**************************************************************************/
2597 /*                                                                        */
2598 /*  FUNCTION                                               RELEASE        */
2599 /*                                                                        */
2600 /*    _nx_rtcp_sr_data_append                             PORTABLE C      */
2601 /*                                                           6.3.0        */
2602 /*  AUTHOR                                                                */
2603 /*                                                                        */
2604 /*    Ting Zhu, Microsoft Corporation                                     */
2605 /*                                                                        */
2606 /*  DESCRIPTION                                                           */
2607 /*                                                                        */
2608 /*    This function generates an RTCP SR packet and copies it to the end  */
2609 /*    of the specifed RTCP packet.                                        */
2610 /*                                                                        */
2611 /*  INPUT                                                                 */
2612 /*                                                                        */
2613 /*    session                               Pointer to RTP session        */
2614 /*    packet_ptr                            Pointer to RTCP packet        */
2615 /*                                                                        */
2616 /*  OUTPUT                                                                */
2617 /*                                                                        */
2618 /*    status                                Completion status             */
2619 /*                                                                        */
2620 /*  CALLS                                                                 */
2621 /*                                                                        */
2622 /*    nx_packet_data_append                 Copy the specified data to    */
2623 /*                                            the end of specified packet */
2624 /*                                                                        */
2625 /*  CALLED BY                                                             */
2626 /*                                                                        */
2627 /*    _nx_rtcp_packet_send                  Send RTCP packet              */
2628 /*                                                                        */
2629 /*  RELEASE HISTORY                                                       */
2630 /*                                                                        */
2631 /*    DATE              NAME                      DESCRIPTION             */
2632 /*                                                                        */
2633 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
2634 /*                                                                        */
2635 /**************************************************************************/
_nx_rtcp_sr_data_append(NX_RTP_SESSION * session,NX_PACKET * packet_ptr)2636 UINT _nx_rtcp_sr_data_append(NX_RTP_SESSION *session, NX_PACKET *packet_ptr)
2637 {
2638 
2639 NX_RTCP_SR rtcp_sr;
2640 
2641 
2642     /* Pack SR packet. */
2643     rtcp_sr.nx_rtcp_sr_header.nx_rtcp_byte0 = (NX_RTP_VERSION << 6);                   /* Version 2 */
2644     rtcp_sr.nx_rtcp_sr_header.nx_rtcp_packet_type = NX_RTCP_TYPE_SR;
2645     rtcp_sr.nx_rtcp_sr_header.nx_rtcp_length = sizeof(NX_RTCP_SR) / sizeof(ULONG) - 1; /* RTCP SR size. */
2646     rtcp_sr.nx_rtcp_sr_ssrc = session -> nx_rtp_session_ssrc;
2647     rtcp_sr.nx_rtcp_sr_ntp_timestamp_msw = session -> nx_rtp_session_ntp_timestamp_msw;
2648     rtcp_sr.nx_rtcp_sr_ntp_timestamp_lsw = session -> nx_rtp_session_ntp_timestamp_lsw;
2649     rtcp_sr.nx_rtcp_sr_rtp_timestamp = session -> nx_rtp_session_rtp_timestamp;
2650     rtcp_sr.nx_rtcp_sr_rtp_packet_count = session -> nx_rtp_session_packet_count;
2651     rtcp_sr.nx_rtcp_sr_rtp_octet_count = session -> nx_rtp_session_octet_count;
2652 
2653     /* Take care of endian-ness. */
2654     NX_CHANGE_USHORT_ENDIAN(rtcp_sr.nx_rtcp_sr_header.nx_rtcp_length);
2655     NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_ssrc);
2656     NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_ntp_timestamp_msw);
2657     NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_ntp_timestamp_lsw);
2658     NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_rtp_timestamp);
2659     NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_rtp_packet_count);
2660     NX_CHANGE_ULONG_ENDIAN(rtcp_sr.nx_rtcp_sr_rtp_octet_count);
2661 
2662     /* Append SR packet.  */
2663     nx_packet_data_append(packet_ptr, &rtcp_sr, sizeof(rtcp_sr), session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
2664 
2665     return(NX_SUCCESS);
2666 }
2667 
2668 /**************************************************************************/
2669 /*                                                                        */
2670 /*  FUNCTION                                               RELEASE        */
2671 /*                                                                        */
2672 /*    _nx_rtcp_sdes_data_append                           PORTABLE C      */
2673 /*                                                           6.3.0        */
2674 /*  AUTHOR                                                                */
2675 /*                                                                        */
2676 /*    Ting Zhu, Microsoft Corporation                                     */
2677 /*                                                                        */
2678 /*  DESCRIPTION                                                           */
2679 /*                                                                        */
2680 /*    This function generates an RTCP SDES packet and copies it to the    */
2681 /*    end of the specifed RTCP packet.                                    */
2682 /*                                                                        */
2683 /*  INPUT                                                                 */
2684 /*                                                                        */
2685 /*    session                               Pointer to RTP session        */
2686 /*    packet_ptr                            Pointer to RTCP packet        */
2687 /*                                                                        */
2688 /*  OUTPUT                                                                */
2689 /*                                                                        */
2690 /*    status                                Completion status             */
2691 /*                                                                        */
2692 /*  CALLS                                                                 */
2693 /*                                                                        */
2694 /*    nx_packet_data_append                 Copy the specified data to    */
2695 /*                                            the end of specified packet */
2696 /*                                                                        */
2697 /*  CALLED BY                                                             */
2698 /*                                                                        */
2699 /*    _nx_rtcp_packet_send                  Send RTCP packet              */
2700 /*                                                                        */
2701 /*  RELEASE HISTORY                                                       */
2702 /*                                                                        */
2703 /*    DATE              NAME                      DESCRIPTION             */
2704 /*                                                                        */
2705 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
2706 /*                                                                        */
2707 /**************************************************************************/
_nx_rtcp_sdes_data_append(NX_RTP_SESSION * session,NX_PACKET * packet_ptr)2708 UINT _nx_rtcp_sdes_data_append(NX_RTP_SESSION *session, NX_PACKET *packet_ptr)
2709 {
2710 
2711 UINT               status;
2712 NX_RTCP_HEADER     header;
2713 NX_RTCP_SDES_CHUNK sdes_chunk;
2714 NX_PACKET_POOL    *packet_pool = session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr;
2715 NX_RTP_SENDER     *sender = session -> nx_rtp_sender;
2716 ULONG              pad = 0;
2717 UCHAR              pad_value[] = {0, 0, 0};
2718 UINT               length;
2719 
2720 
2721 /*
2722 SDES packet format:
2723         0                   1                   2                   3
2724         0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
2725        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2726 header |V=2|P|    SC   |  PT=SDES=202  |             length            |
2727        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
2728 chunk  |                          SSRC/CSRC_1                          |
2729   1    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2730        |                           SDES items                          |
2731        |                              ...                              |
2732        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
2733 chunk  |                          SSRC/CSRC_2                          |
2734   2    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2735        |                           SDES items                          |
2736        |                              ...                              |
2737        +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
2738 
2739 SDES item format for CNAME:
2740        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2741        |    CNAME=1    |     length    | user and domain name        ...
2742        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
2743 */
2744 
2745     /* packet size = rtcp header size + 4 bytes ssrc + 1 byte type + 1 byte length + data length. */
2746     length = sizeof(NX_RTCP_HEADER) + 6 + sender -> nx_rtp_sender_cname_length;
2747 
2748     if (length & 0x3)
2749     {
2750         pad = 4 - (length & 0x3);
2751     }
2752 
2753     /* Pack SDES packet header. */
2754     header.nx_rtcp_byte0 = (NX_RTP_VERSION << 6) | 1; /* Sender Desc with 1 item */
2755     header.nx_rtcp_packet_type = NX_RTCP_TYPE_SDES;
2756     header.nx_rtcp_length = (USHORT)(((length + pad) / sizeof(ULONG)) - 1);
2757 
2758     NX_CHANGE_USHORT_ENDIAN(header.nx_rtcp_length);
2759 
2760     /* Append SDES packet header. */
2761     status = nx_packet_data_append(packet_ptr, &header, sizeof(header), packet_pool, NX_RTP_SENDER_PACKET_TIMEOUT);
2762     if (status)
2763     {
2764         return(status);
2765     }
2766 
2767     /* Pack CNAME item. */
2768     sdes_chunk.nx_rtcp_sdes_ssrc = session -> nx_rtp_session_ssrc;
2769     sdes_chunk.nx_rtcp_sdes_item[0].nx_rtcp_sdes_type = NX_RTCP_SDES_TYPE_CNAME;
2770     sdes_chunk.nx_rtcp_sdes_item[0].nx_rtcp_sdes_length = sender -> nx_rtp_sender_cname_length;
2771 
2772     NX_CHANGE_ULONG_ENDIAN(sdes_chunk.nx_rtcp_sdes_ssrc);
2773 
2774     /* Append 4 bytes ssrc + 1 byte item type + 1 byte data length. */
2775     status = nx_packet_data_append(packet_ptr, &sdes_chunk, 6, packet_pool, NX_RTP_SENDER_PACKET_TIMEOUT);
2776     if (status)
2777     {
2778         return(status);
2779     }
2780 
2781     /* Append cname string. */
2782     status = nx_packet_data_append(packet_ptr, sender -> nx_rtp_sender_cname, sender -> nx_rtp_sender_cname_length, packet_pool, NX_RTP_SENDER_PACKET_TIMEOUT);
2783     if (status)
2784     {
2785         return(status);
2786     }
2787 
2788     if (pad)
2789     {
2790         status = nx_packet_data_append(packet_ptr, pad_value, pad, packet_pool, NX_RTP_SENDER_PACKET_TIMEOUT);
2791         if (status)
2792         {
2793             return(status);
2794         }
2795     }
2796 
2797     return(NX_SUCCESS);
2798 }
2799 
2800 /**************************************************************************/
2801 /*                                                                        */
2802 /*  FUNCTION                                               RELEASE        */
2803 /*                                                                        */
2804 /*    _nx_rtcp_packet_send                                PORTABLE C      */
2805 /*                                                           6.3.0        */
2806 /*  AUTHOR                                                                */
2807 /*                                                                        */
2808 /*    Ting Zhu, Microsoft Corporation                                     */
2809 /*                                                                        */
2810 /*  DESCRIPTION                                                           */
2811 /*                                                                        */
2812 /*    This function sends a compound RTCP packet through the UDP layer to */
2813 /*    the supplied IP address and rtcp port.                              */
2814 /*                                                                        */
2815 /*  INPUT                                                                 */
2816 /*                                                                        */
2817 /*    session                               Pointer to RTP session        */
2818 /*                                                                        */
2819 /*  OUTPUT                                                                */
2820 /*                                                                        */
2821 /*    status                                Completion status             */
2822 /*                                                                        */
2823 /*  CALLS                                                                 */
2824 /*                                                                        */
2825 /*    tx_time_get                           Get current system clock      */
2826 /*    nx_packet_allocate                    Allocate packet               */
2827 /*    nx_packet_release                     Release packet                */
2828 /*    nxd_udp_socket_source_send            Send a UDP packet             */
2829 /*    _nx_rtcp_sr_data_append               Append SR packet              */
2830 /*    _nx_rtcp_sdes_data_append             Append SDES packet            */
2831 /*                                                                        */
2832 /*  CALLED BY                                                             */
2833 /*                                                                        */
2834 /*    _nx_rtp_sender_session_packet_send    Send rtp packet               */
2835 /*                                                                        */
2836 /*  RELEASE HISTORY                                                       */
2837 /*                                                                        */
2838 /*    DATE              NAME                      DESCRIPTION             */
2839 /*                                                                        */
2840 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
2841 /*                                                                        */
2842 /**************************************************************************/
_nx_rtcp_packet_send(NX_RTP_SESSION * session)2843 UINT _nx_rtcp_packet_send(NX_RTP_SESSION *session)
2844 {
2845 
2846 UINT       status = NX_SUCCESS;
2847 NX_PACKET *packet_ptr;
2848 UINT       current_time = tx_time_get();
2849 
2850 
2851     if (session -> nx_rtp_session_rtcp_time &&
2852         ((current_time - session -> nx_rtp_session_rtcp_time) / TX_TIMER_TICKS_PER_SECOND < NX_RTCP_INTERVAL))
2853     {
2854         return(NX_SUCCESS);
2855     }
2856 
2857     status = nx_packet_allocate(session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, &packet_ptr, NX_UDP_PACKET, NX_RTP_SENDER_PACKET_TIMEOUT);
2858 
2859     if (status != NX_SUCCESS)
2860     {
2861         return(status);
2862     }
2863 
2864     /* Chain rtcp packets into one compound packet. */
2865     status = _nx_rtcp_sr_data_append(session, packet_ptr);
2866 
2867     if (status == NX_SUCCESS)
2868     {
2869         status = _nx_rtcp_sdes_data_append(session, packet_ptr);
2870     }
2871 
2872     if (status == NX_SUCCESS)
2873     {
2874 
2875         /* Send the packet. */
2876         status = nxd_udp_socket_source_send(&session -> nx_rtp_sender -> nx_rtp_sender_rtcp_socket, packet_ptr,
2877                                             &(session -> nx_rtp_session_peer_ip_address), session -> nx_rtp_session_peer_rtcp_port,
2878                                             session -> nx_rtp_session_interface_index);
2879     }
2880 
2881     /* Check the status.  */
2882     if (status == NX_SUCCESS)
2883     {
2884         session -> nx_rtp_session_rtcp_time = tx_time_get();
2885     }
2886     else
2887     {
2888         nx_packet_release(packet_ptr);
2889     }
2890 
2891     return(status);
2892 }
2893 
2894 /**************************************************************************/
2895 /*                                                                        */
2896 /*  FUNCTION                                               RELEASE        */
2897 /*                                                                        */
2898 /*    _nx_rtcp_packet_receive_notify                      PORTABLE C      */
2899 /*                                                           6.3.0        */
2900 /*  AUTHOR                                                                */
2901 /*                                                                        */
2902 /*    Ting Zhu, Microsoft Corporation                                     */
2903 /*                                                                        */
2904 /*  DESCRIPTION                                                           */
2905 /*                                                                        */
2906 /*    This function serves as RTCP packet receive notify routine, which   */
2907 /*    is called whenever a packet is received on the rtcp port.           */
2908 /*                                                                        */
2909 /*  INPUT                                                                 */
2910 /*                                                                        */
2911 /*    socket_ptr                            Pointer to RTCP port          */
2912 /*                                                                        */
2913 /*  OUTPUT                                                                */
2914 /*                                                                        */
2915 /*    status                                Completion status             */
2916 /*                                                                        */
2917 /*  CALLS                                                                 */
2918 /*                                                                        */
2919 /*    nx_udp_socket_receive                 Check for UDP packet on the   */
2920 /*                                            specified port              */
2921 /*    nx_packet_release                     Release packet                */
2922 /*    _nx_rtcp_packet_process               Handle rtcp packet            */
2923 /*                                                                        */
2924 /*  CALLED BY                                                             */
2925 /*                                                                        */
2926 /*    _nx_rtp_sender_create                 Create RTP sender             */
2927 /*                                                                        */
2928 /*  RELEASE HISTORY                                                       */
2929 /*                                                                        */
2930 /*    DATE              NAME                      DESCRIPTION             */
2931 /*                                                                        */
2932 /*  10-31-2023     Ting Zhu                 Initial Version 6.3.0         */
2933 /*                                                                        */
2934 /**************************************************************************/
_nx_rtcp_packet_receive_notify(NX_UDP_SOCKET * socket_ptr)2935 VOID _nx_rtcp_packet_receive_notify(NX_UDP_SOCKET *socket_ptr)
2936 {
2937 
2938 /* Drain the packet */
2939 NX_PACKET *packet_ptr;
2940 NX_RTP_SENDER *rtp_sender;
2941 
2942 
2943     /* Get packet(s) from the passed socket. */
2944     if (nx_udp_socket_receive(socket_ptr, &packet_ptr, NX_NO_WAIT) != NX_SUCCESS)
2945     {
2946         return;
2947     }
2948 
2949     /* Check and determine whether to process received rtcp packet. */
2950     rtp_sender = (NX_RTP_SENDER *)socket_ptr -> nx_udp_socket_reserved_ptr;
2951     if ((rtp_sender) &&
2952         (rtp_sender -> nx_rtp_sender_rtcp_receiver_report_cb || rtp_sender -> nx_rtp_sender_rtcp_sdes_cb))
2953     {
2954         _nx_rtcp_packet_process(rtp_sender, packet_ptr);
2955     }
2956 
2957     /* Release the packet and return. */
2958     nx_packet_release(packet_ptr);
2959     return;
2960 }
2961 
2962 /**************************************************************************/
2963 /*                                                                        */
2964 /*  FUNCTION                                               RELEASE        */
2965 /*                                                                        */
2966 /*    _nxe_rtp_sender_session_jpeg_send                  PORTABLE C       */
2967 /*                                                           6.3.0        */
2968 /*  AUTHOR                                                                */
2969 /*                                                                        */
2970 /*    Haiqing Zhao, Microsoft Corporation                                 */
2971 /*                                                                        */
2972 /*  DESCRIPTION                                                           */
2973 /*                                                                        */
2974 /*    This function checks errors in the RTP sender session jpeg send     */
2975 /*    function call.                                                      */
2976 /*                                                                        */
2977 /*  INPUT                                                                 */
2978 /*                                                                        */
2979 /*    session                              Pointer to RTP session         */
2980 /*    frame_data                           Pointer to data buffer to send */
2981 /*    frame_data_size                      Size of data to send           */
2982 /*    timestamp                            RTP timestamp for current data */
2983 /*    ntp_msw                              Most significant word of       */
2984 /*                                           network time                 */
2985 /*    ntp_lsw                              Least significant word of      */
2986 /*                                           network time                 */
2987 /*    marker                               Marker bit for significant     */
2988 /*                                           event such as frame boundary */
2989 /*                                                                        */
2990 /*  OUTPUT                                                                */
2991 /*                                                                        */
2992 /*    status                               Completion status              */
2993 /*    NX_PTR_ERROR                         Invalid pointer input          */
2994 /*                                                                        */
2995 /*  CALLS                                                                 */
2996 /*                                                                        */
2997 /*    _nx_rtp_sender_session_jpeg_send     Send packet data               */
2998 /*                                                                        */
2999 /*  CALLED BY                                                             */
3000 /*                                                                        */
3001 /*    Application Code                                                    */
3002 /*                                                                        */
3003 /*  RELEASE HISTORY                                                       */
3004 /*                                                                        */
3005 /*    DATE              NAME                      DESCRIPTION             */
3006 /*                                                                        */
3007 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
3008 /*                                                                        */
3009 /**************************************************************************/
_nxe_rtp_sender_session_jpeg_send(NX_RTP_SESSION * session,UCHAR * frame_data,ULONG frame_data_size,ULONG timestamp,ULONG ntp_msw,ULONG ntp_lsw,UINT marker)3010 UINT _nxe_rtp_sender_session_jpeg_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
3011                                        ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
3012 {
3013 
3014 UINT status;
3015 
3016 
3017     /* Check for invalid input pointers. */
3018     if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (frame_data == NX_NULL))
3019     {
3020         return(NX_PTR_ERROR);
3021     }
3022 
3023     /* Call actual RTP sender session packet send service. */
3024     status = _nx_rtp_sender_session_jpeg_send(session, frame_data, frame_data_size, timestamp, ntp_msw, ntp_lsw, marker);
3025 
3026     /* Return status. */
3027     return(status);
3028 }
3029 
3030 /**************************************************************************/
3031 /*                                                                        */
3032 /*  FUNCTION                                               RELEASE        */
3033 /*                                                                        */
3034 /*    _nx_rtp_sender_session_jpeg_send                   PORTABLE C       */
3035 /*                                                           6.3.0        */
3036 /*  AUTHOR                                                                */
3037 /*                                                                        */
3038 /*    Haiqing Zhao, Microsoft Corporation                                 */
3039 /*                                                                        */
3040 /*  DESCRIPTION                                                           */
3041 /*                                                                        */
3042 /*    This function parses and makes the passed data in RTP/JPEG format,  */
3043 /*    and then calls RTP session send function to send these data in RTP  */
3044 /*    packet.                                                             */
3045 /*    The function references RFC 2435 as the standard with below notes:  */
3046 /*    1) A complete jpeg scan file inside frame data buffer is required.  */
3047 /*    2) Use dynamic quantization table mapping.                          */
3048 /*    3) The provided jpeg scan file shall be 8-bit sample precision,     */
3049 /*       YUV420 or YUV422 type, and encoded with standard huffman tables. */
3050 /*    4) Restart marker is not supported.                                 */
3051 /*                                                                        */
3052 /*  INPUT                                                                 */
3053 /*                                                                        */
3054 /*    session                              Pointer to RTP session         */
3055 /*    frame_data                           Pointer to data buffer to send */
3056 /*    frame_data_size                      Size of data to send           */
3057 /*    timestamp                            RTP timestamp for current data */
3058 /*    ntp_msw                              Most significant word of       */
3059 /*                                           network time                 */
3060 /*    ntp_lsw                              Least significant word of      */
3061 /*                                           network time                 */
3062 /*    marker                               Marker bit for significant     */
3063 /*                                           event such as frame boundary */
3064 /*                                                                        */
3065 /*  OUTPUT                                                                */
3066 /*                                                                        */
3067 /*    status                               Completion status              */
3068 /*                                                                        */
3069 /*  CALLS                                                                 */
3070 /*                                                                        */
3071 /*    _nx_rtp_sender_session_packet_allocate                              */
3072 /*                                         Allocate a packet for the user */
3073 /*    nx_packet_data_append                Copy the specified data to     */
3074 /*                                            the end of specified packet */
3075 /*    nx_packet_data_release               Release the packet             */
3076 /*    _nx_rtp_sender_session_packet_send   Send RTP packet                */
3077 /*                                                                        */
3078 /*  CALLED BY                                                             */
3079 /*                                                                        */
3080 /*    Application Code                                                    */
3081 /*                                                                        */
3082 /*  RELEASE HISTORY                                                       */
3083 /*                                                                        */
3084 /*    DATE              NAME                      DESCRIPTION             */
3085 /*                                                                        */
3086 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
3087 /*                                                                        */
3088 /**************************************************************************/
_nx_rtp_sender_session_jpeg_send(NX_RTP_SESSION * session,UCHAR * frame_data,ULONG frame_data_size,ULONG timestamp,ULONG ntp_msw,ULONG ntp_lsw,UINT marker)3089 UINT _nx_rtp_sender_session_jpeg_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
3090                                       ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
3091 {
3092 
3093 UINT       status;
3094 UCHAR     *data_ptr;
3095 UCHAR     *data_end_ptr;
3096 UCHAR      jpeg_header[8];
3097 UCHAR      quantization_header[4];
3098 USHORT     section_length;
3099 UCHAR      type = 255; /* type field for main jpeg header. */
3100 UCHAR      marker_code; /* jpeg marker code to indicate different sections. */
3101 USHORT     width = 0, height = 0; /* resolution information for main jpeg header. */
3102 ULONG      q_table_num = 0;
3103 ULONG      q_overall_table_num = 0;
3104 UCHAR     *q_table_ptr[NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_MAX_NUM];
3105 ULONG      data_payload_length = 0;
3106 ULONG      transferred_data_size = 0;
3107 ULONG      single_frame_length;
3108 ULONG      copy_length;
3109 UINT       temp_rtp_marker = NX_FALSE;
3110 NX_PACKET *send_packet = NX_NULL;
3111 
3112 
3113     /* In current design, the marker bit shall be always 1 (i.e. a complete jpeg scan file required to be passed). */
3114     if (marker != NX_TRUE)
3115     {
3116         return(NX_NOT_SUPPORTED);
3117     }
3118 
3119     /* Initialize local variables for searching. */
3120     data_ptr = frame_data;
3121     data_end_ptr = frame_data + frame_data_size;
3122 
3123     /* Check jpeg constant file header. */
3124     if ((frame_data_size < 2) || ((data_ptr[0] != 0xFF) || (data_ptr[1] != 0xD8)))
3125     {
3126         return(NX_NOT_SUCCESSFUL);
3127     }
3128 
3129     /* Skip the 2 bytes jpeg file header. */
3130     data_ptr += 2;
3131 
3132     do
3133     {
3134 
3135         /* Check there are enough bytes remaining in the data buffer for 2 bytes section marker and 2 bytes section length. */
3136         if ((data_ptr + 4) > data_end_ptr)
3137         {
3138             return(NX_SIZE_ERROR);
3139         }
3140 
3141         /* Check the first byte for section marker. */
3142         if (data_ptr[0] != 0xFF)
3143         {
3144             return(NX_NOT_SUCCESSFUL);
3145         }
3146 
3147         /* Update the marker code. */
3148         marker_code = data_ptr[1];
3149 
3150         /* Update and skip the whole 2 bytes section marker. */
3151         data_ptr += 2;
3152 
3153         /* Compute data length in this section. */
3154         section_length = (USHORT)((data_ptr[0] << 8) | data_ptr[1]);
3155 
3156         /* Check there are enough bytes remaining in the data buffer. */
3157         if ((data_ptr + section_length) > data_end_ptr)
3158         {
3159             return(NX_SIZE_ERROR);
3160         }
3161 
3162         /* Now it is time to parse the marker code and its corresponding section. */
3163         switch (marker_code)
3164         {
3165 
3166             /* SOF0: image baseline information. */
3167             case 0xC0:
3168             {
3169 
3170                 /* For a standard RTP/JPEG image baseline information, this section length shall be
3171                    at least 17, in order to contain enough baseline information for the image. */
3172                 if (section_length < 17)
3173                 {
3174                     return(NX_SIZE_ERROR);
3175                 }
3176 
3177                 /* Skip 2 bytes section length. */
3178                 data_ptr += 2;
3179 
3180                 /* 8-bit sample precision is required. */
3181                 if (data_ptr[0] != 8)
3182                 {
3183                     return(NX_NOT_SUPPORTED);
3184                 }
3185 
3186                 /* Check the number of image components which shall be 3 for YUV. */
3187                 if (data_ptr[5] != 3)
3188                 {
3189                     return(NX_NOT_SUPPORTED);
3190                 }
3191 
3192                 /* Check the quantization table number for all YUV dimensions. */
3193                 if ((data_ptr[8] != 0x00) || (data_ptr[11] != 0x01) || (data_ptr[14] != 0x01))
3194                 {
3195                     return(NX_NOT_SUPPORTED);
3196                 }
3197 
3198                 /* Check the horizontal and vertical sampling factor for both U dimension and V dimension. */
3199                 if ((data_ptr[10] != 0x11) || (data_ptr[13] != 0x11))
3200                 {
3201                     return(NX_NOT_SUPPORTED);
3202                 }
3203 
3204                 /* Determine the RTP/JPEG type in jpeg main header through different vertical sampling factor of Y dimension. */
3205                 if (data_ptr[7] == 0x21)
3206                 {
3207                     type = 0; /* YUV420. */
3208                 }
3209                 else if (data_ptr[7] == 0x22)
3210                 {
3211                     type = 1; /* YUV422. */
3212                 }
3213                 else
3214                 {
3215                     return(NX_NOT_SUPPORTED);
3216                 }
3217 
3218                 /* Compute width and height. */
3219                 height = (USHORT)((data_ptr[1] << 8) | data_ptr[2]);
3220                 width = (USHORT)((data_ptr[3] << 8) | data_ptr[4]);
3221 
3222                 /* Skip the current section. */
3223                 data_ptr += 15; /* 15 bytes section data. */
3224                 break;
3225             }
3226 
3227             /* DQT: define quantization table. */
3228             case 0xDB:
3229             {
3230 
3231                 /* Skip 2 bytes section length. */
3232                 data_ptr += 2;
3233 
3234                 /* Compute the number of quantization tables (each table shall contain 65 bytes). */
3235                 q_table_num = section_length / (NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH + 1);
3236 
3237                 /* Check current table number. */
3238                 if ((q_table_num == 0) || ((q_table_num + q_overall_table_num) > NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_MAX_NUM))
3239                 {
3240                     return(NX_NOT_SUCCESSFUL);
3241                 }
3242 
3243                 for (UINT i = q_overall_table_num; i < (q_overall_table_num + q_table_num); i++)
3244                 {
3245 
3246                     /* Skip the first no meaning byte. */
3247                     data_ptr++;
3248 
3249                     /* Record the current table position. */
3250                     q_table_ptr[i] = data_ptr;
3251 
3252                     /* Move to the next table position. */
3253                     data_ptr += NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH;
3254                 }
3255 
3256                 /* Update overall number of tables. This variable is introduced because there may be more than 1 DQT come. */
3257                 q_overall_table_num += q_table_num;
3258                 break;
3259             }
3260 
3261             /* SOS: the start of the scan. */
3262             case 0xDA:
3263             {
3264 
3265                 /* Skip the scan header. */
3266                 data_ptr += section_length;
3267 
3268                 /* Move the end pointer to the last 2 byte to make the check easier */
3269                 data_end_ptr -= 2;
3270 
3271                 /* Search and try to find EOI in current packet. */
3272                 while (data_ptr < data_end_ptr)
3273                 {
3274                     if ((data_end_ptr[0] == 0xFF) && (data_end_ptr[1] == 0xD9))
3275                     {
3276                         break;
3277                     }
3278                     else
3279                     {
3280                         data_end_ptr--;
3281                     }
3282                 }
3283 
3284                 /* Check if EOI has been found. */
3285                 if (data_ptr < data_end_ptr)
3286                 {
3287                     data_payload_length = (ULONG)(data_end_ptr - data_ptr);
3288                 }
3289                 else /* data_ptr == data_end_ptr */
3290                 {
3291 
3292                     /* If EOI has not been found, consider all remaining data are scan data. */
3293                     data_payload_length = frame_data_size - (ULONG)(data_ptr - frame_data);
3294                 }
3295 
3296                 /* When SOS found, the while loop will also be jumped out. */
3297                 break;
3298             }
3299 
3300             /* EOI */
3301             case 0xD9:
3302             {
3303 
3304                 /* SOS shall be found before EOI. */
3305                 return(NX_NOT_SUCCESSFUL);
3306             }
3307 
3308             /* Unsupported SOFs or other markers. */
3309             case 0xC1: /* Extended sequential DCT */
3310             case 0xC2: /* Progressive DCT */
3311             case 0xC3: /* Lossless (sequential) */
3312             case 0xC5: /* Differential sequential DCT */
3313             case 0xC6: /* Differential progressive DCT */
3314             case 0xC7: /* Differential lossless (sequential) */
3315             case 0xC8: /* Reserved for JPEG extensions */
3316             case 0xC9: /* Extended sequential DCT */
3317             case 0xCA: /* Progressive DCT */
3318             case 0xCB: /* Lossless (sequential) */
3319             case 0xCC: /* Define arithmetic coding conditionings */
3320             case 0xCD: /* Differential sequential DCT */
3321             case 0xCE: /* Differential progressive DCT */
3322             case 0xCF: /* Differential lossless (sequential) */
3323             case 0xDD: /* DRI */
3324             {
3325                 return(NX_NOT_SUPPORTED);
3326             }
3327 
3328             /* Possible sections in default:
3329             1) APP0 ~ APPn: define exchange format and image identifications.
3330             2) Huffman table: it is assumed that standard Huffman table applied. */
3331             default:
3332             {
3333 
3334                 /* Marker code 0x01 is not supported. Marker codes inside 0x02 ~ 0xBF are reserved. */
3335                 if (marker_code < 0xC0)
3336                 {
3337                     return(NX_NOT_SUPPORTED);
3338                 }
3339 
3340                 /* Move the data_ptr and offset to skip the whole section. */
3341                 data_ptr += section_length;
3342                 break;
3343             }
3344         }
3345 
3346     } while (marker_code != 0xDA); /* Jump out when find SOS. */
3347 
3348     /* Check the type has been confirmed, and quantization. */
3349     if (((type != 0) && (type != 1)) || (q_overall_table_num == 0))
3350     {
3351         return(NX_NOT_SUCCESSFUL);
3352     }
3353 
3354     /* Check there is any scan data to send. */
3355     if (data_payload_length == 0)
3356     {
3357         return(NX_SIZE_ERROR);
3358     }
3359 
3360     /* Allocate a packet for the first data packet to transmit. */
3361     status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
3362     if (status)
3363     {
3364         return(NX_NOT_SUCCESSFUL);
3365     }
3366 
3367     /* Initialize main JPEG header, and append it into the send packet. */
3368     jpeg_header[0] = 0; /* Always 0 since no interpretation is specified. */
3369     jpeg_header[1] = 0; /* High byte of 24 bytes size offset. */
3370     jpeg_header[2] = 0; /* Middle byte 24 bytes size offset. */
3371     jpeg_header[3] = 0; /* Low byte of 24 bytes size offset. */
3372     jpeg_header[4] = type;
3373     jpeg_header[5] = 255; /* Q values 255 indicates the quantization table header appears after the main JPEG header,
3374                              and the quantization table is allowed to be changeable among different frames. */
3375     jpeg_header[6] = (UCHAR)(width >> 3);  /* Maximum width: 2040 pixels. */
3376     jpeg_header[7] = (UCHAR)(height >> 3); /* Maximum height: 2040 pixels. */
3377 
3378     status = nx_packet_data_append(send_packet, (void *)jpeg_header, sizeof(jpeg_header),
3379                                    session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
3380     if (status)
3381     {
3382         nx_packet_release(send_packet);
3383         return(NX_NOT_SUCCESSFUL);
3384     }
3385 
3386     /* Update quantization table header, and append it into the send packet. */
3387     quantization_header[0] = 0; /* MBZ. */
3388     quantization_header[1] = 0; /* Precision: 8 bits. */
3389     quantization_header[2] = (UCHAR)((NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH * q_overall_table_num) >> 8); /* High byte if tables length. */
3390     quantization_header[3] = (UCHAR)(NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH * q_overall_table_num); /* Low byte if tables length. */
3391 
3392     status = nx_packet_data_append(send_packet, (void *)quantization_header, sizeof(quantization_header),
3393                                    session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
3394     if (status)
3395     {
3396         nx_packet_release(send_packet);
3397         return(NX_NOT_SUCCESSFUL);
3398     }
3399 
3400     /* Copy quantization table(s) into the packet. It is assume that these table(s) are not in different packets of a chain packet. */
3401     for (UINT i = 0; i < q_overall_table_num; i++)
3402     {
3403         status = nx_packet_data_append(send_packet, (void *)(q_table_ptr[i]), NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH,
3404                                        session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
3405         if (status)
3406         {
3407             nx_packet_release(send_packet);
3408             return(NX_NOT_SUCCESSFUL);
3409         }
3410     }
3411 
3412     /* Compute the current single frame length and check if mtu size match the requirement for putting all jpeg header info into one packet. */
3413     single_frame_length = sizeof(jpeg_header) + sizeof(quantization_header) + NX_RTP_SENDER_JPEG_QUANTIZATION_TABLE_LENGTH * q_overall_table_num;
3414     if (single_frame_length > session -> nx_rtp_session_max_packet_size)
3415     {
3416         nx_packet_release(send_packet);
3417         return(NX_NOT_SUPPORTED);
3418     }
3419 
3420     /* Begin data frame(s) transmit. */
3421     while (1)
3422     {
3423 
3424         /* Check and execute packet fragmentation. */
3425         copy_length = session -> nx_rtp_session_max_packet_size - single_frame_length;
3426         if (data_payload_length <= copy_length)
3427         {
3428             copy_length = data_payload_length;
3429             temp_rtp_marker = NX_TRUE;
3430         }
3431 
3432         /* Copy payload data into the packet. */
3433         status = nx_packet_data_append(send_packet, (void *)data_ptr, copy_length,
3434                                        session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
3435         if (status)
3436         {
3437             nx_packet_release(send_packet);
3438             return(status);
3439         }
3440 
3441         /* Send the data packet. */
3442         status = _nx_rtp_sender_session_packet_send(session, send_packet, timestamp, ntp_msw, ntp_lsw, temp_rtp_marker);
3443         if (status)
3444         {
3445             nx_packet_release(send_packet);
3446             return(status);
3447         }
3448 
3449         /* Decrease transmitted data payload length and check whether all data finish transmitting. */
3450         data_payload_length -= copy_length;
3451         if (data_payload_length == 0)
3452         {
3453 
3454             /* Jump out the while loop when all data finish transmitting. */
3455             break;
3456         }
3457 
3458         /* Move data pointer to the begin of remaining data. */
3459         data_ptr += copy_length;
3460 
3461         /* Update 24-bit transferred data offset with bytes order. */
3462         transferred_data_size += copy_length;
3463         jpeg_header[1] = (UCHAR)(transferred_data_size >> 16);
3464         jpeg_header[2] = (UCHAR)(transferred_data_size >> 8);
3465         jpeg_header[3] = (UCHAR)(transferred_data_size);
3466 
3467         /* Allocate a packet for next packet. */
3468         status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
3469         if (status)
3470         {
3471             return(status);
3472         }
3473 
3474         /* Copy jpeg header into the packet. */
3475         status = nx_packet_data_append(send_packet, (void *)jpeg_header, sizeof(jpeg_header),
3476                                        session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
3477         if (status)
3478         {
3479             nx_packet_release(send_packet);
3480             return(status);
3481         }
3482 
3483         /* Update single frame length. */
3484         single_frame_length = sizeof(jpeg_header);
3485     }
3486 
3487     /* Return success status. */
3488     return(NX_SUCCESS);
3489 }
3490 
3491 /**************************************************************************/
3492 /*                                                                        */
3493 /*  FUNCTION                                               RELEASE        */
3494 /*                                                                        */
3495 /*    _nxe_rtp_sender_session_h264_send                  PORTABLE C       */
3496 /*                                                           6.3.0        */
3497 /*  AUTHOR                                                                */
3498 /*                                                                        */
3499 /*    Haiqing Zhao, Microsoft Corporation                                 */
3500 /*                                                                        */
3501 /*  DESCRIPTION                                                           */
3502 /*                                                                        */
3503 /*    This function checks errors in the RTP sender session h264 send     */
3504 /*    function call.                                                      */
3505 /*                                                                        */
3506 /*  INPUT                                                                 */
3507 /*                                                                        */
3508 /*    session                              Pointer to RTP session         */
3509 /*    frame_data                           Pointer to data buffer to send */
3510 /*    frame_data_size                      Size of data to send           */
3511 /*    timestamp                            RTP timestamp for current data */
3512 /*    ntp_msw                              Most significant word of       */
3513 /*                                           network time                 */
3514 /*    ntp_lsw                              Least significant word of      */
3515 /*                                           network time                 */
3516 /*    marker                               Marker bit for significant     */
3517 /*                                           event such as frame boundary */
3518 /*                                                                        */
3519 /*  OUTPUT                                                                */
3520 /*                                                                        */
3521 /*    status                               Completion status              */
3522 /*    NX_PTR_ERROR                         Invalid pointer input          */
3523 /*                                                                        */
3524 /*  CALLS                                                                 */
3525 /*                                                                        */
3526 /*    _nx_rtp_sender_session_h264_send     Send h264 frame data           */
3527 /*                                                                        */
3528 /*  CALLED BY                                                             */
3529 /*                                                                        */
3530 /*    Application Code                                                    */
3531 /*                                                                        */
3532 /*  RELEASE HISTORY                                                       */
3533 /*                                                                        */
3534 /*    DATE              NAME                      DESCRIPTION             */
3535 /*                                                                        */
3536 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
3537 /*                                                                        */
3538 /**************************************************************************/
_nxe_rtp_sender_session_h264_send(NX_RTP_SESSION * session,UCHAR * frame_data,ULONG frame_data_size,ULONG timestamp,ULONG ntp_msw,ULONG ntp_lsw,UINT marker)3539 UINT _nxe_rtp_sender_session_h264_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
3540                                        ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
3541 {
3542 
3543 UINT status;
3544 
3545 
3546     /* Check for invalid input pointers. */
3547     if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (frame_data == NX_NULL))
3548     {
3549         return(NX_PTR_ERROR);
3550     }
3551 
3552     /* Call actual RTP sender session frame send service. */
3553     status = _nx_rtp_sender_session_h264_send(session, frame_data, frame_data_size, timestamp, ntp_msw, ntp_lsw, marker);
3554 
3555     /* Return status. */
3556     return(status);
3557 }
3558 
3559 /**************************************************************************/
3560 /*                                                                        */
3561 /*  FUNCTION                                               RELEASE        */
3562 /*                                                                        */
3563 /*    _nx_rtp_sender_session_h264_send                   PORTABLE C       */
3564 /*                                                           6.3.0        */
3565 /*  AUTHOR                                                                */
3566 /*                                                                        */
3567 /*    Haiqing Zhao, Microsoft Corporation                                 */
3568 /*                                                                        */
3569 /*  DESCRIPTION                                                           */
3570 /*                                                                        */
3571 /*    This function parses and separates the passed data into h264 frames */
3572 /*    or slices, and processes each frame/slice from VCL format to NAL    */
3573 /*    format, and finally calls RTP session send function to send these   */
3574 /*    frame/slice(s) in RTP packet.                                       */
3575 /*    The function references RFC 6184 as the standard with below notes:  */
3576 /*    1) A complete h264 data frame shall be inside the frame data buffer.*/
3577 /*    2) Special frame(s) such as SEI, SPS and PPS can be inside the      */
3578 /*       frame data buffer.                                               */
3579 /*    3) Each H264 frame/slice inside the frame data buffer shall be in   */
3580 /*       VCL (video coding layer) format.                                 */
3581 /*    4) SDP shall indicate that non-interleaved mode is applied (i.e.    */
3582 /*       packetization-mode=1), which supports the use of single NAL unit */
3583 /*       packet and FU-A packets.                                         */
3584 /*                                                                        */
3585 /*  INPUT                                                                 */
3586 /*                                                                        */
3587 /*    session                              Pointer to RTP session         */
3588 /*    frame_data                           Pointer to data buffer to send */
3589 /*    frame_data_size                      Size of data to send           */
3590 /*    timestamp                            RTP timestamp for current data */
3591 /*    ntp_msw                              Most significant word of       */
3592 /*                                           network time                 */
3593 /*    ntp_lsw                              Least significant word of      */
3594 /*                                           network time                 */
3595 /*    marker                               Marker bit for significant     */
3596 /*                                           event such as frame boundary */
3597 /*                                                                        */
3598 /*  OUTPUT                                                                */
3599 /*                                                                        */
3600 /*    status                               Completion status              */
3601 /*                                                                        */
3602 /*  CALLS                                                                 */
3603 /*                                                                        */
3604 /*    _nx_rtp_sender_session_packet_allocate                              */
3605 /*                                         Allocate a packet for the user */
3606 /*    nx_packet_data_append                Copy the specified data to     */
3607 /*                                            the end of specified packet */
3608 /*    nx_packet_data_release               Release the packet             */
3609 /*    _nx_rtp_sender_session_packet_send   Send RTP packet                */
3610 /*                                                                        */
3611 /*  CALLED BY                                                             */
3612 /*                                                                        */
3613 /*    Application Code                                                    */
3614 /*                                                                        */
3615 /*  RELEASE HISTORY                                                       */
3616 /*                                                                        */
3617 /*    DATE              NAME                      DESCRIPTION             */
3618 /*                                                                        */
3619 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
3620 /*                                                                        */
3621 /**************************************************************************/
_nx_rtp_sender_session_h264_send(NX_RTP_SESSION * session,UCHAR * frame_data,ULONG frame_data_size,ULONG timestamp,ULONG ntp_msw,ULONG ntp_lsw,UINT marker)3622 UINT _nx_rtp_sender_session_h264_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
3623                                       ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
3624 {
3625 
3626 UINT       status;
3627 UINT       i;
3628 ULONG      nal_unit_size;
3629 ULONG      max_packet_length;
3630 ULONG      send_packet_length;
3631 UCHAR     *frame_end;
3632 UCHAR     *nal_unit_start;
3633 UCHAR     *data_ptr = frame_data;
3634 UINT       send_marker = NX_FALSE;
3635 UINT       temp_marker = NX_FALSE;
3636 UCHAR      nal_unit_type;
3637 UCHAR      fu_a_header[2];
3638 ULONG      packet_num;
3639 ULONG      last_packet_size;
3640 NX_PACKET *send_packet = NX_NULL;
3641 
3642 
3643     /* In current design, the marker bit shall be always 1 (i.e. a complete h264 frame required to be passed). */
3644     if (marker != NX_TRUE)
3645     {
3646         return(NX_NOT_SUPPORTED);
3647     }
3648 
3649     /* Obtain the maximum frame packet length. */
3650     max_packet_length = session -> nx_rtp_session_max_packet_size;
3651 
3652     /* Check frame minimum length. */
3653     if (frame_data_size <= 4)
3654     {
3655         return(NX_SIZE_ERROR);
3656     }
3657 
3658     /* Record frame end position. */
3659     frame_end = frame_data + frame_data_size - 1;
3660 
3661     /* Is the h264 4 bytes or 3 bytes header found. */
3662     if ((data_ptr[0] == 0x00) && (data_ptr[1] == 0x00) && (data_ptr[2] == 0x00) && (data_ptr[3] == 0x01))
3663     {
3664 
3665         /* Yes, skip the 4 bytes header. */
3666         data_ptr += 4;
3667     }
3668     else if ((data_ptr[0] == 0x00) && (data_ptr[1] == 0x00) && (data_ptr[2] == 0x01))
3669     {
3670 
3671         /* Yes, skip the 3 bytes header. */
3672         data_ptr += 3;
3673     }
3674     else
3675     {
3676 
3677         /* Wrong h264 header, return not successful. */
3678         return(NX_NOT_SUCCESSFUL);
3679     }
3680 
3681     /* There are conditions requiring below while loop to guarantee the procedure of separation and transmission:
3682        1) Special frame(s) such as SEI, SPS and PPS are passed with a data frame.
3683        2) The data frame is composed of several slices
3684     */
3685     while (data_ptr <= (frame_end - 4))
3686     {
3687 
3688         /* Set the start position and reset the single frame size. */
3689         nal_unit_start = data_ptr;
3690         nal_unit_size = 0;
3691 
3692         /* Extract a complete frame from the raw source file through finding the next 4/3 bytes header or the end of data buffer. */
3693         while (1)
3694         {
3695 
3696             /* Check if there is a new slice header found */
3697             if ((data_ptr[0] == 0x00) && (data_ptr[1] == 0x00))
3698             {
3699 
3700                 if ((data_ptr[2] == 0x00) && (data_ptr[3] == 0x01))
3701                 {
3702 
3703                     /* Jump out if 4 bytes header of next frame/slice found. */
3704                     nal_unit_size = (ULONG)(data_ptr - nal_unit_start + 1);
3705                     data_ptr += 4;
3706                     break;
3707                 }
3708                 else if (data_ptr[2] == 0x01)
3709                 {
3710 
3711                     /* Jump out if 3 bytes header of next frame/slice found. */
3712                     nal_unit_size = (ULONG)(data_ptr - nal_unit_start + 1);
3713                     data_ptr += 3;
3714                     break;
3715                 }
3716             }
3717 
3718             /* Skip the check last 4 bytes if no header found is current position. */
3719             if (data_ptr >= (frame_end - 4))
3720             {
3721 
3722                 /* Compute nal unit size and move data pointer to the end. */
3723                 nal_unit_size = (ULONG)(frame_end - nal_unit_start + 1);
3724                 data_ptr = frame_end;
3725 
3726                 /* Set the send marker and jump out. */
3727                 send_marker = NX_TRUE;
3728                 break;
3729             }
3730 
3731             /* Move and check next byte. */
3732             data_ptr++;
3733         }
3734 
3735         /* Initialize NAL unit type with the first byte after the h264 header. */
3736         nal_unit_type = nal_unit_start[0];
3737 
3738         /* Check NAL unit type. */
3739         if (((nal_unit_type & NX_RTP_SENDER_H264_TYPE_MASK_BITS) == NX_RTP_SENDER_H264_TYPE_SEI) ||
3740             ((nal_unit_type & NX_RTP_SENDER_H264_TYPE_MASK_BITS) == NX_RTP_SENDER_H264_TYPE_SPS) ||
3741             ((nal_unit_type & NX_RTP_SENDER_H264_TYPE_MASK_BITS) == NX_RTP_SENDER_H264_TYPE_PPS))
3742         {
3743 
3744             /* Clear the send marker for special frames. */
3745             send_marker = NX_FALSE;
3746         }
3747 
3748         /* Check the frame size and determine if more than 1 packet are needed. */
3749         if (nal_unit_size <= max_packet_length)
3750         {
3751 
3752             /* RTP payload format for single NAL unit packet (in this case, the NAL header byte is the same as VCL header byte):
3753              0                   1                   2                   3
3754              0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
3755             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3756             |F|NRI|  Type   |                                               |
3757             +-+-+-+-+-+-+-+-+                                               |
3758             |                                                               |
3759             |              Bytes 2..n of a single NAL unit                  |
3760             |                                                               |
3761             |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3762             |                               :...OPTIONAL RTP padding        |
3763             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3764             */
3765 
3766             /* Allocate a rtp packet */
3767             status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
3768             if (status)
3769             {
3770                 return(status);
3771             }
3772 
3773             /* Copy payload data into the packet. */
3774             status = nx_packet_data_append(send_packet, (void*)nal_unit_start, nal_unit_size,
3775                                            session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr,
3776                                            NX_RTP_SENDER_PACKET_TIMEOUT);
3777             if (status)
3778             {
3779                 nx_packet_release(send_packet);
3780                 return(status);
3781             }
3782 
3783             /* Send packet data */
3784             status = _nx_rtp_sender_session_packet_send(session, send_packet, timestamp, ntp_msw, ntp_lsw, send_marker);
3785             if (status)
3786             {
3787                 nx_packet_release(send_packet);
3788                 return(status);
3789             }
3790         }
3791         else
3792         {
3793 
3794             /* RTP payload format for FU-A packets (in this case, 1 byte VCL header extends to 2 bytes NAL header):
3795              0                   1                   2                   3
3796              0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
3797             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3798             | FU indicator |    FU header   |                               |
3799             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
3800             |                                                               |
3801             |                         FU payload                            |
3802             |                                                               |
3803             |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3804             |                               :...OPTIONAL RTP padding        |
3805             +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
3806 
3807             1) Format for FU indicator octet:        2) Format for FU header:
3808                +---------------+                        +---------------+
3809                |0|1|2|3|4|5|6|7|                        |0|1|2|3|4|5|6|7|
3810                +-+-+-+-+-+-+-+-+                        +-+-+-+-+-+-+-+-+
3811                |F|NRI|  Type   |                        |S|E|R|  Type   |
3812                +---------------+                        +---------------+
3813             */
3814 
3815             /* Reserve the bytes space for fu-a header. */
3816             max_packet_length -= sizeof(fu_a_header);
3817 
3818             /* Compute the number of packets with the size of the last packet. */
3819             packet_num = ((nal_unit_size - 1) / max_packet_length) + 1;
3820             last_packet_size = nal_unit_size % max_packet_length;
3821 
3822             /* Initialize fu-a header's first byte with the source priority and fu-a type. */
3823             fu_a_header[0] = (UCHAR)((nal_unit_type & NX_RTP_SENDER_H264_NRI_MASK_BITS) | NX_RTP_SENDER_H264_TYPE_FU_A);
3824 
3825             /* Initialize fu-a header's second byte with the source nal unit type. */
3826             fu_a_header[1] = (UCHAR)(nal_unit_type & NX_RTP_SENDER_H264_TYPE_MASK_BITS);
3827 
3828             for (i = 0; i < packet_num; i++)
3829             {
3830 
3831                 /* Check which packet to transmit and execute different corresponding logic. */
3832                 if (i == 0)
3833                 {
3834 
3835                     /* Set the fu-a start bit for the first frame fragment. */
3836                     fu_a_header[1] |= NX_RTP_SENDER_H264_FU_A_S_MASK_BIT;
3837 
3838                     /* Set the send marker as false. */
3839                     temp_marker = NX_FALSE;
3840 
3841                     /* Skip the first NAL unit type byte, and update the send packet length. */
3842                     nal_unit_start++;
3843                     send_packet_length = max_packet_length - 1;
3844                 }
3845                 else if (i == (packet_num - 1))
3846                 {
3847 
3848                     /* Clear the fu-a start bit and set fu-a end bit for the last frame fragment. */
3849                     fu_a_header[1] &= (UCHAR)(~NX_RTP_SENDER_H264_FU_A_S_MASK_BIT);
3850                     fu_a_header[1] |= NX_RTP_SENDER_H264_FU_A_E_MASK_BIT;
3851 
3852                     /* Update send marker by the final data frame flag. */
3853                     temp_marker = send_marker;
3854 
3855                     /* Update packet length based on whether the last packet size is not zero. */
3856                     send_packet_length = last_packet_size ? last_packet_size : max_packet_length;
3857                 }
3858                 else
3859                 {
3860 
3861                     /* Clear the fu-a start bit for middle slices. */
3862                     fu_a_header[1] &= (UCHAR)(~NX_RTP_SENDER_H264_FU_A_S_MASK_BIT);
3863 
3864                     /* Update the send packet length. */
3865                     send_packet_length = max_packet_length;
3866                 }
3867 
3868                 /* Allocate a packet */
3869                 status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
3870                 if (status)
3871                 {
3872                     return(status);
3873                 }
3874 
3875                 /* Copy fu-a header into the packet. */
3876                 status = nx_packet_data_append(send_packet, (void *)fu_a_header, sizeof(fu_a_header),
3877                                                session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr,
3878                                                NX_RTP_SENDER_PACKET_TIMEOUT);
3879                 if (status)
3880                 {
3881                     nx_packet_release(send_packet);
3882                     return(status);
3883                 }
3884 
3885                 /* Copy payload data into the packet. */
3886                 status = nx_packet_data_append(send_packet, (void *)nal_unit_start, send_packet_length,
3887                                                session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr,
3888                                                NX_RTP_SENDER_PACKET_TIMEOUT);
3889                 if (status)
3890                 {
3891                     nx_packet_release(send_packet);
3892                     return(status);
3893                 }
3894 
3895                 /* Send packet data */
3896                 status = _nx_rtp_sender_session_packet_send(session, send_packet, timestamp, ntp_msw, ntp_lsw, temp_marker);
3897                 if (status)
3898                 {
3899                     nx_packet_release(send_packet);
3900                     return(status);
3901                 }
3902 
3903                 /* Move start pointer to following position. */
3904                 nal_unit_start += send_packet_length;
3905             }
3906         }
3907     }
3908 
3909     /* Return success status. */
3910     return(NX_SUCCESS);
3911 }
3912 
3913 /**************************************************************************/
3914 /*                                                                        */
3915 /*  FUNCTION                                               RELEASE        */
3916 /*                                                                        */
3917 /*    _nxe_rtp_sender_session_aac_send                   PORTABLE C       */
3918 /*                                                           6.3.0        */
3919 /*  AUTHOR                                                                */
3920 /*                                                                        */
3921 /*    Haiqing Zhao, Microsoft Corporation                                 */
3922 /*                                                                        */
3923 /*  DESCRIPTION                                                           */
3924 /*                                                                        */
3925 /*    This function checks errors in the RTP sender session aac send      */
3926 /*    function call.                                                      */
3927 /*                                                                        */
3928 /*  INPUT                                                                 */
3929 /*                                                                        */
3930 /*    session                              Pointer to RTP session         */
3931 /*    frame_data                           Pointer to data buffer to send */
3932 /*    frame_data_size                      Size of data to send           */
3933 /*    timestamp                            RTP timestamp for current data */
3934 /*    ntp_msw                              Most significant word of       */
3935 /*                                           network time                 */
3936 /*    ntp_lsw                              Least significant word of      */
3937 /*                                           network time                 */
3938 /*    marker                               Marker bit for significant     */
3939 /*                                           event such as frame boundary */
3940 /*                                                                        */
3941 /*  OUTPUT                                                                */
3942 /*                                                                        */
3943 /*    status                               Completion status              */
3944 /*    NX_PTR_ERROR                         Invalid pointer input          */
3945 /*                                                                        */
3946 /*  CALLS                                                                 */
3947 /*                                                                        */
3948 /*    _nx_rtp_sender_session_aac_send      Send aac frame data            */
3949 /*                                                                        */
3950 /*  CALLED BY                                                             */
3951 /*                                                                        */
3952 /*    Application Code                                                    */
3953 /*                                                                        */
3954 /*  RELEASE HISTORY                                                       */
3955 /*                                                                        */
3956 /*    DATE              NAME                      DESCRIPTION             */
3957 /*                                                                        */
3958 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
3959 /*                                                                        */
3960 /**************************************************************************/
_nxe_rtp_sender_session_aac_send(NX_RTP_SESSION * session,UCHAR * frame_data,ULONG frame_data_size,ULONG timestamp,ULONG ntp_msw,ULONG ntp_lsw,UINT marker)3961 UINT _nxe_rtp_sender_session_aac_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
3962                                       ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
3963 {
3964 
3965 UINT status;
3966 
3967 
3968     /* Check for invalid input pointers. */
3969     if ((session == NX_NULL) || (session -> nx_rtp_sender == NX_NULL) || (session -> nx_rtp_session_id != NX_RTP_SESSION_ID) || (frame_data == NX_NULL))
3970     {
3971         return(NX_PTR_ERROR);
3972     }
3973 
3974     /* Call actual RTP sender session frame send service. */
3975     status = _nx_rtp_sender_session_aac_send(session, frame_data, frame_data_size, timestamp, ntp_msw, ntp_lsw, marker);
3976 
3977     /* Return status. */
3978     return(status);
3979 }
3980 
3981 /**************************************************************************/
3982 /*                                                                        */
3983 /*  FUNCTION                                               RELEASE        */
3984 /*                                                                        */
3985 /*    _nx_rtp_sender_session_aac_send                    PORTABLE C       */
3986 /*                                                           6.3.0        */
3987 /*  AUTHOR                                                                */
3988 /*                                                                        */
3989 /*    Haiqing Zhao, Microsoft Corporation                                 */
3990 /*                                                                        */
3991 /*  DESCRIPTION                                                           */
3992 /*                                                                        */
3993 /*    This function parses and makes the passed data in RTP/AAC format,   */
3994 /*    and then calls RTP session send function to send these data in RTP  */
3995 /*    packet, with AAC-HBR mode.                                          */
3996 /*    The function references RFC 3640 as the standard with below notes:  */
3997 /*    1) A complete aac frame data shall be inside frame data buffer      */
3998 /*    2) SDP shall indicate that aac-hbr mode is applied, with SizeLength */
3999 /*       field to be 13 since 13-bit frame length is applied for          */
4000 /*       computing the length in AU header.                               */
4001 /*                                                                        */
4002 /*  INPUT                                                                 */
4003 /*                                                                        */
4004 /*    session                              Pointer to RTP session         */
4005 /*    frame_data                           Pointer to data buffer to send */
4006 /*    frame_data_size                      Size of data to send           */
4007 /*    timestamp                            RTP timestamp for current data */
4008 /*    ntp_msw                              Most significant word of       */
4009 /*                                           network time                 */
4010 /*    ntp_lsw                              Least significant word of      */
4011 /*                                           network time                 */
4012 /*    marker                               Marker bit for significant     */
4013 /*                                           event such as frame boundary */
4014 /*                                                                        */
4015 /*  OUTPUT                                                                */
4016 /*                                                                        */
4017 /*    status                               Completion status              */
4018 /*                                                                        */
4019 /*  CALLS                                                                 */
4020 /*                                                                        */
4021 /*    _nx_rtp_sender_session_packet_allocate                              */
4022 /*                                         Allocate a packet for the user */
4023 /*    nx_packet_data_append                Copy the specified data to     */
4024 /*                                            the end of specified packet */
4025 /*    nx_packet_data_release               Release the packet             */
4026 /*    _nx_rtp_sender_session_packet_send   Send RTP packet                */
4027 /*                                                                        */
4028 /*  CALLED BY                                                             */
4029 /*                                                                        */
4030 /*    Application Code                                                    */
4031 /*                                                                        */
4032 /*  RELEASE HISTORY                                                       */
4033 /*                                                                        */
4034 /*    DATE              NAME                      DESCRIPTION             */
4035 /*                                                                        */
4036 /*  10-31-2023     Haiqing Zhao            Initial Version 6.3.0          */
4037 /*                                                                        */
4038 /**************************************************************************/
_nx_rtp_sender_session_aac_send(NX_RTP_SESSION * session,UCHAR * frame_data,ULONG frame_data_size,ULONG timestamp,ULONG ntp_msw,ULONG ntp_lsw,UINT marker)4039 UINT _nx_rtp_sender_session_aac_send(NX_RTP_SESSION *session, UCHAR *frame_data, ULONG frame_data_size,
4040                                      ULONG timestamp, ULONG ntp_msw, ULONG ntp_lsw, UINT marker)
4041 {
4042 
4043 UINT       status;
4044 UCHAR      au_header[4] = {0x00, 0x10, 0x00, 0x00}; /* First 2 bytes represent au header length, with default 16 bits. */
4045 ULONG      send_packet_length;
4046 ULONG      max_packet_length = session -> nx_rtp_session_max_packet_size - sizeof(au_header);
4047 NX_PACKET *send_packet = NX_NULL;
4048 UCHAR     *data_ptr;
4049 UINT       temp_marker;
4050 
4051 
4052     /* In current design, the marker bit shall be always 1 (i.e. a complete aac frame required to be passed). */
4053     if (marker != NX_TRUE)
4054     {
4055         return(NX_NOT_SUPPORTED);
4056     }
4057 
4058     /* When frame data exceeds maximum defined value, it requires access unit fragment feature which is not supported so far.
4059        This check is specific for aac-hbr mode. */
4060     if (frame_data_size > NX_RTP_SENDER_AAC_HBR_MODE_MAX_DATA_SIZE)
4061     {
4062         return(NX_NOT_SUPPORTED);
4063     }
4064 
4065     /* Initialize data_ptr to where data bytes begin. */
4066     data_ptr = frame_data;
4067 
4068     while (frame_data_size > 0)
4069     {
4070 
4071         /* Allocate a rtp packet. */
4072         status = _nx_rtp_sender_session_packet_allocate(session, &send_packet, NX_RTP_SENDER_PACKET_TIMEOUT);
4073         if (status)
4074         {
4075             return(status);
4076         }
4077 
4078         /* Check if fragmentation needed, and assign data length. */
4079         if (frame_data_size > max_packet_length)
4080         {
4081             send_packet_length = max_packet_length;
4082             temp_marker = NX_FALSE;
4083         }
4084         else
4085         {
4086             send_packet_length = frame_data_size;
4087             temp_marker = NX_TRUE;
4088         }
4089 
4090         /* Compute the data length inside the current packet. */
4091         au_header[2] = (UCHAR)((send_packet_length & NX_RTP_SENDER_AAC_FRAME_DATA_LENGTH_HIGH_BITS_MASK) >> 5);
4092         au_header[3] = (UCHAR)((send_packet_length & NX_RTP_SENDER_AAC_FRAME_DATA_LENGTH_LOW_BITS_MASK) << 3);
4093 
4094         /* Copy aac header data into the packet. */
4095         status = nx_packet_data_append(send_packet, (void *)au_header, sizeof(au_header),
4096                                        session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
4097         if (status)
4098         {
4099             nx_packet_release(send_packet);
4100             return(status);
4101         }
4102 
4103         /* Copy payload data into the packet. */
4104         status = nx_packet_data_append(send_packet, (void *)data_ptr, send_packet_length,
4105                                        session -> nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_RTP_SENDER_PACKET_TIMEOUT);
4106         if (status)
4107         {
4108             nx_packet_release(send_packet);
4109             return(status);
4110         }
4111 
4112         /* Send AAC frame through rtp; passed marker bit with true when this is the last frame packet. */
4113         status = _nx_rtp_sender_session_packet_send(session, send_packet, timestamp, ntp_msw, ntp_lsw, temp_marker);
4114         if (status)
4115         {
4116             nx_packet_release(send_packet);
4117             return(status);
4118         }
4119 
4120         /* Compute remaining frame length and move data pointer. */
4121         frame_data_size -= send_packet_length;
4122         data_ptr += send_packet_length;
4123     }
4124 
4125     /* Return success status. */
4126     return(NX_SUCCESS);
4127 }
4128