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