1 /* This is the test control routine the NetX RTSP module. All tests are dispatched from this routine. */
2
3 #include "tx_api.h"
4 #include "nx_api.h"
5 #include "nx_rtsp_server.h"
6 #include "nx_rtp_sender.h"
7 #include "demo_rtsp_over_rtp.h"
8
9
10 /* Define the stack size for demo tasks. */
11 #define DEMO_TEST_STACK_SIZE 2048
12 #define DEMO_RTSP_SERVER_STACK_SIZE 2048
13 static UCHAR test_thread_stack[DEMO_TEST_STACK_SIZE];
14 static UCHAR rtsp_server_stack[DEMO_RTSP_SERVER_STACK_SIZE];
15
16 /* Define rtp cname which is typically used in rtcp sender report. */
17 #define DEMO_RTP_CNAME "AzureRTOS@microsoft.com"
18
19 /* Define multicast corresponding parameters. !Note: these parameters in sdp shall be changed with the same values. */
20 #ifdef DEMO_MULTICAST_ENABLED
21
22 #ifndef DEMO_MULTICAST_IP_ADDRESS
23 #define DEMO_MULTICAST_IP_ADDRESS IP_ADDRESS(224, 1, 0, 55)
24 #endif /* DEMO_MULTICAST_IP_ADDRESS */
25
26 #ifndef DEMO_MULTICAST_RTP_PORT
27 #define DEMO_MULTICAST_RTP_PORT 6002
28 #endif /* DEMO_MULTICAST_RTP_PORT */
29
30 #ifndef DEMO_MULTICAST_RTCP_PORT
31 #define DEMO_MULTICAST_RTCP_PORT 6003
32 #endif /* DEMO_MULTICAST_RTCP_PORT */
33
34 #endif /* DEMO_MULTICAST_ENABLED */
35
36 /* The RTSP server listening port. */
37 #ifndef DEMO_RTSP_SERVER_PORT
38 #define DEMO_RTSP_SERVER_PORT 554
39 #endif /* DEMO_RTSP_SERVER_PORT */
40
41 /* The RTSP server thread priority. */
42 #ifndef DEMO_RTSP_SERVER_PRIORITY
43 #define DEMO_RTSP_SERVER_PRIORITY 3
44 #endif /* DEMO_RTSP_SERVER_PRIORITY */
45
46 /* File name shown in rtsp SETUP request */
47 #ifndef DEMO_RTSP_VIDEO_FILE_NAME
48 #define DEMO_RTSP_VIDEO_FILE_NAME "trackID=0"
49 #endif /* DEMO_RTSP_VIDEO_FILE_NAME */
50
51 #ifndef DEMO_RTSP_AUDIO_FILE_NAME
52 #define DEMO_RTSP_AUDIO_FILE_NAME "trackID=1"
53 #endif /* DEMO_RTSP_AUDIO_FILE_NAME */
54
55 /* Define RTP payload type for medias. !Note: payload type in sdp shall be changed with the same values */
56 #ifndef DEMO_RTP_PAYLOAD_TYPE_VIDEO
57 #if (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_MJPEG)
58 #define DEMO_RTP_PAYLOAD_TYPE_VIDEO 26
59 #else
60 #define DEMO_RTP_PAYLOAD_TYPE_VIDEO 96 /* Use dynamic type range from 96 to 127 */
61 #endif /* (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_MJPEG) */
62 #endif /* DEMO_RTP_PAYLOAD_TYPE_VIDEO */
63
64 #ifndef DEMO_RTP_PAYLOAD_TYPE_AUDIO
65 #if (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_AAC)
66 #define DEMO_RTP_PAYLOAD_TYPE_AUDIO 97
67 #else
68 #define DEMO_RTP_PAYLOAD_TYPE_AUDIO 11
69 #endif /* (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_AAC) */
70 #endif /* DEMO_RTP_PAYLOAD_TYPE_AUDIO */
71
72 /* Define video & audio play fps. !Note: this macro shall be the same as the real FPS to guarantee video playing normally */
73 #ifndef DEMO_VIDEO_FRAME_PER_SECOND
74 #define DEMO_VIDEO_FRAME_PER_SECOND 30
75 #endif /* DEMO_VIDEO_FRAME_PER_SECOND */
76
77 #ifndef DEMO_AUDIO_FRAME_PER_SECOND
78 #define DEMO_AUDIO_FRAME_PER_SECOND 43 /* Reference the comment of DEMO_RTP_AUDIO_SAMPLING_PERIOD
79 to understand how this macro is calculated and defined. */
80 #endif /* DEMO_AUDIO_FRAME_PER_SECOND */
81
82 #ifndef DEMO_AUDIO_SAMPLE_SIZE
83 #define DEMO_AUDIO_SAMPLE_SIZE 16 /* Indicate the size in bits for each audio sample. */
84 #endif /* DEMO_AUDIO_SAMPLE_SIZE */
85
86 #ifndef DEMO_AUDIO_CHANNEL_NUM
87 #define DEMO_AUDIO_CHANNEL_NUM 1
88 #endif /* DEMO_AUDIO_CHANNEL_NUM */
89
90 /* The sampling periods define rtp timestamp increase rate for medias. */
91 #define DEMO_RTP_VIDEO_SAMPLING_PERIOD (90000 / DEMO_VIDEO_FRAME_PER_SECOND)
92 #define DEMO_RTP_AUDIO_SAMPLING_PERIOD (44100 / DEMO_AUDIO_FRAME_PER_SECOND) /* Assume the default AAC sampling rate is 44100.
93 Normally, a single ACC frame contains 1024 samples;
94 So, there are 44100 / 1024 = 43 frames per second.
95 Therefore, sampling period is 44100 / 43 = 1025. */
96
97 /* Define frame play internal for medias */
98 #define DEMO_RTP_VIDEO_PLAY_INTERVAL (1000 / DEMO_VIDEO_FRAME_PER_SECOND)
99 #define DEMO_RTP_AUDIO_PLAY_INTERVAL (1000 / DEMO_AUDIO_FRAME_PER_SECOND)
100
101 #ifndef DEMO_PLAY_TIMER_INTERVAL
102 #define DEMO_PLAY_TIMER_INTERVAL 10 /* Per miliseconds */
103 #endif /* DEMO_PLAY_TIMER_INTERVAL */
104
105 /* Declare the prototypes for the test entry points. */
106 TX_THREAD test_thread;
107 NX_RTSP_SERVER rtsp_0;
108 NX_RTP_SENDER rtp_0;
109
110 /* Declare events to use in threads. */
111 TX_EVENT_FLAGS_GROUP demo_test_events;
112
113 /* Declare the timer to trigger events (e.g., playing video/audio). */
114 TX_TIMER demo_timer;
115
116 /* Declare the sample structure to support multiple clients interaction. */
117 typedef struct SAMPLE_CLIENT_STRUCT
118 {
119 NX_RTSP_CLIENT *rtsp_client_ptr;
120
121 /* RTP sessions */
122 NX_RTP_SESSION rtp_session_video;
123 NX_RTP_SESSION rtp_session_audio;
124
125 /* Count the number of clients setup in the specific rtp session */
126 USHORT rtp_session_video_client_count;
127 USHORT rtp_session_audio_client_count;
128
129 /* RTP timestamp and NTP timestamp */
130 ULONG rtp_session_video_timestamp;
131 ULONG rtp_session_audio_timestamp;
132
133 #ifdef DEMO_PLAY_BY_TIMER
134 /* Accumulated ticks for determining when to play a video/audio frame */
135 volatile ULONG video_play_time_ms;
136 volatile ULONG audio_play_time_ms;
137 #endif /* DEMO_PLAY_BY_TIMER */
138 } SAMPLE_CLIENT;
139
140 #ifdef DEMO_MULTICAST_ENABLED
141 SAMPLE_CLIENT sample_client_multicast;
142 #else
143 SAMPLE_CLIENT sample_client[NX_RTSP_SERVER_MAX_CLIENTS];
144 #endif /* DEMO_MULTICAST_ENABLED */
145
146 /* Define an error counter. */
147 ULONG error_counter;
148
149
150 /* Internal functions prototype. */
151 static UINT rtsp_describe_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length);
152 static UINT rtsp_setup_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr);
153 static UINT rtsp_play_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length);
154 static UINT rtsp_teardown_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length);
155 static UINT rtsp_pause_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length);
156 static UINT rtsp_set_parameter_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length);
157 static UINT rtsp_disconnect_callback(NX_RTSP_CLIENT *rtsp_client_ptr);
158
159 static UINT test_rtcp_receiver_report_callback(NX_RTP_SESSION *session, NX_RTCP_RECEIVER_REPORT *report);
160 static UINT test_rtcp_sdes_callback(NX_RTCP_SDES_INFO *sdes_info);
161
162 static VOID (*demo_media_data_init_callback)(VOID) = DEMO_MEDIA_DATA_INIT;
163 static UINT (*demo_video_data_read_callback)(ULONG *ntp_msw, ULONG *ntp_lsw, UCHAR **data_ptr, ULONG *data_size) = DEMO_VIDEO_DATA_READ;
164 static UINT (*demo_audio_data_read_callback)(ULONG *ntp_msw, ULONG *ntp_lsw, UCHAR **data_ptr, ULONG *data_size) = DEMO_AUDIO_DATA_READ;
165
166
167 #ifdef DEMO_PLAY_BY_TIMER
demo_timer_entry(ULONG address)168 static VOID demo_timer_entry(ULONG address)
169 {
170 SAMPLE_CLIENT *client_ptr;
171
172 #ifdef DEMO_MULTICAST_ENABLED
173 client_ptr = &sample_client_multicast;
174 #else
175 for (UINT i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
176 {
177 client_ptr = &sample_client[i];
178 #endif /* DEMO_MULTICAST_ENABLED */
179
180 if (client_ptr -> rtp_session_video_client_count)
181 {
182 client_ptr -> video_play_time_ms += DEMO_PLAY_TIMER_INTERVAL;
183 if (client_ptr -> video_play_time_ms >= DEMO_RTP_VIDEO_PLAY_INTERVAL)
184 {
185
186 /* Send the video ready event. */
187 tx_event_flags_set(&demo_test_events, DEMO_VIDEO_DATA_READY_EVENT, TX_OR);
188 }
189 }
190 if (client_ptr -> rtp_session_audio_client_count)
191 {
192 client_ptr -> audio_play_time_ms += DEMO_PLAY_TIMER_INTERVAL;
193 if (client_ptr -> audio_play_time_ms >= DEMO_RTP_AUDIO_PLAY_INTERVAL)
194 {
195
196 /* Send the audio ready event. */
197 tx_event_flags_set(&demo_test_events, DEMO_AUDIO_DATA_READY_EVENT, TX_OR);
198 }
199 }
200 #ifndef DEMO_MULTICAST_ENABLED
201 }
202 #endif /* DEMO_MULTICAST_ENABLED */
203 }
204 #endif /* DEMO_PLAY_BY_TIMER */
205
206 /* Define what the initial system looks like. */
sample_entry(NX_IP * ip_ptr,NX_PACKET_POOL * pool_ptr,VOID * dns_ptr,UINT (* unix_time_callback)(ULONG * unix_time))207 void sample_entry(NX_IP *ip_ptr, NX_PACKET_POOL *pool_ptr, VOID *dns_ptr, UINT (*unix_time_callback)(ULONG *unix_time))
208 {
209 UINT i = 0;
210 UINT status;
211 ULONG events = 0;
212 UCHAR initialized = NX_FALSE;
213 ULONG ntp_msw, ntp_lsw;
214 UCHAR *data;
215 ULONG data_length;
216 #if (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_PCM)
217 NX_PACKET *send_packet = NX_NULL;
218 #endif /* (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_PCM) */
219 #ifndef DEMO_MULTICAST_ENABLED
220 SAMPLE_CLIENT *client_ptr;
221 #else
222 SAMPLE_CLIENT *client_ptr = &sample_client_multicast;
223
224
225 /* Enable IGMP. */
226 status = nx_igmp_enable(ip_ptr);
227
228 /* Join multicast group. */
229 status += nx_ipv4_multicast_interface_join(ip_ptr, DEMO_MULTICAST_IP_ADDRESS, 0);
230 if (status)
231 error_counter++;
232 #endif /* DEMO_MULTICAST_ENABLED */
233
234 status = nx_ip_fragment_enable(ip_ptr);
235 if (status)
236 error_counter++;
237
238 /* Create RTP sender */
239 nx_rtp_sender_create(&rtp_0, ip_ptr, pool_ptr, DEMO_RTP_CNAME, sizeof(DEMO_RTP_CNAME) - 1);
240 nx_rtp_sender_rtcp_receiver_report_callback_set(&rtp_0, test_rtcp_receiver_report_callback);
241 nx_rtp_sender_rtcp_sdes_callback_set(&rtp_0, test_rtcp_sdes_callback);
242
243 /* Create RTSP server. */
244 nx_rtsp_server_create(&rtsp_0, "RTSP Server", sizeof("RTSP Server") - 1, ip_ptr, pool_ptr,
245 rtsp_server_stack, DEMO_RTSP_SERVER_STACK_SIZE, DEMO_RTSP_SERVER_PRIORITY, DEMO_RTSP_SERVER_PORT, rtsp_disconnect_callback);
246
247 /* Set callback functions. */
248 nx_rtsp_server_describe_callback_set(&rtsp_0, rtsp_describe_callback);
249 nx_rtsp_server_setup_callback_set(&rtsp_0, rtsp_setup_callback);
250 nx_rtsp_server_play_callback_set(&rtsp_0, rtsp_play_callback);
251 nx_rtsp_server_teardown_callback_set(&rtsp_0, rtsp_teardown_callback);
252 nx_rtsp_server_pause_callback_set(&rtsp_0, rtsp_pause_callback);
253 nx_rtsp_server_set_parameter_callback_set(&rtsp_0, rtsp_set_parameter_callback);
254
255 /* Start RTSP server. */
256 nx_rtsp_server_start(&rtsp_0);
257
258 printf("RTSP server started!\r\n");
259
260 /* Create event for the play thread */
261 status = tx_event_flags_create(&demo_test_events, "Demo events");
262 if (status)
263 error_counter++;
264
265 #ifdef DEMO_PLAY_BY_TIMER
266 /* Create the global timeout timer. */
267 status = tx_timer_create(&demo_timer, "Demo Timer", demo_timer_entry, 0,
268 (DEMO_PLAY_TIMER_INTERVAL * NX_IP_PERIODIC_RATE / 1000),
269 (DEMO_PLAY_TIMER_INTERVAL * NX_IP_PERIODIC_RATE / 1000),
270 TX_AUTO_ACTIVATE);
271 if (status)
272 error_counter++;
273 #endif /* DEMO_PLAY_BY_TIMER */
274
275 /* Enter server test. */
276 while (1)
277 {
278
279 tx_event_flags_get(&demo_test_events, DEMO_ALL_EVENTS, TX_OR_CLEAR, &events, TX_WAIT_FOREVER);
280
281 /*********************************************
282 ************** DEMO_PLAY_EVENT ***************
283 *********************************************/
284 if (events & DEMO_PLAY_EVENT)
285 {
286 if (initialized == NX_FALSE)
287 {
288
289 /* Call user registered callback function to initialize. */
290 if (demo_media_data_init_callback)
291 {
292 demo_media_data_init_callback();
293 }
294
295 #ifdef DEMO_PLAY_BY_TIMER
296 /* Set an initial value to eliminate too many ticks accumulation. */
297 #ifdef DEMO_MULTICAST_ENABLED
298 client_ptr -> video_play_time_ms = 0;
299 client_ptr -> audio_play_time_ms = 0;
300 #else
301 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
302 {
303 client_ptr = &sample_client[i];
304 sample_client[i].video_play_time_ms = 0;
305 sample_client[i].audio_play_time_ms = 0;
306 }
307 #endif /* DEMO_MULTICAST_ENABLED */
308 #endif /* DEMO_PLAY_BY_TIMER */
309 }
310
311 /* Set the initialized flag */
312 initialized = NX_TRUE;
313 }
314
315 /*********************************************
316 ************ DEMO_TEARDOWN_EVENT *************
317 *********************************************/
318 if (events & DEMO_TEARDOWN_EVENT)
319 {
320 #ifdef DEMO_MULTICAST_ENABLED
321 if ((client_ptr -> rtp_session_video_client_count == 0) &&
322 (client_ptr -> rtp_session_audio_client_count == 0))
323 {
324 initialized = NX_FALSE;
325 }
326
327 #ifdef DEMO_PLAY_BY_TIMER
328 client_ptr -> video_play_time_ms = 0;
329 client_ptr -> audio_play_time_ms = 0;
330 #endif /* DEMO_PLAY_BY_TIMER */
331 #else
332 /* Check all client count to determine whether to clear the initialized flag */
333 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
334 {
335 client_ptr = &sample_client[i];
336 if ((client_ptr -> rtp_session_video_client_count) ||
337 (client_ptr -> rtp_session_audio_client_count))
338 {
339 break;
340 }
341 }
342 if (i == NX_RTSP_SERVER_MAX_CLIENTS)
343 {
344 initialized = NX_FALSE;
345
346 #ifdef DEMO_PLAY_BY_TIMER
347 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
348 {
349 client_ptr -> video_play_time_ms = 0;
350 client_ptr -> audio_play_time_ms = 0;
351 }
352 #endif /* DEMO_PLAY_BY_TIMER */
353 }
354 #endif
355 }
356
357 /*********************************************
358 ******** DEMO_VIDEO_DATA_READY_EVENT *********
359 *********************************************/
360 if (events & DEMO_VIDEO_DATA_READY_EVENT)
361 {
362
363 /* Check if a play event has already triggered. */
364 if (initialized == NX_TRUE)
365 {
366
367 /* Check if the user has redefined DEMO_VIDEO_DATA_READ which registers video data read callback function. */
368 if (demo_video_data_read_callback == NX_NULL)
369 {
370 printf("User must implement video data read function and redefine DEMO_VIDEO_DATA_READ\r\n");
371 continue;
372 }
373
374 /* Read video data and transmit it */
375 data_length = 0;
376 if ((demo_video_data_read_callback(&ntp_msw, &ntp_lsw, &data, &data_length) == NX_SUCCESS) && (data_length > 0))
377 {
378 #ifndef DEMO_MULTICAST_ENABLED
379 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
380 {
381 client_ptr = &sample_client[i];
382 #endif /* DEMO_MULTICAST_ENABLED */
383
384 /* Make sure at least one client having setup the connection. */
385 if (client_ptr -> rtp_session_video_client_count == 0)
386 {
387 continue;
388 }
389
390 #if (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264)
391 status = nx_rtp_sender_session_h264_send(&(client_ptr -> rtp_session_video), data, data_length,
392 client_ptr -> rtp_session_video_timestamp, ntp_msw, ntp_lsw, NX_TRUE);
393 #else
394 status = nx_rtp_sender_session_jpeg_send(&(client_ptr -> rtp_session_video), data, data_length,
395 client_ptr -> rtp_session_video_timestamp, ntp_msw, ntp_lsw, NX_TRUE);
396 #endif /* (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264) */
397 if (status)
398 {
399 printf("Fail to send video frame: %d, %d\r\n", i, status);
400 }
401
402 /* Update rtp timestamp video sampling period. */
403 client_ptr -> rtp_session_video_timestamp += DEMO_RTP_VIDEO_SAMPLING_PERIOD;
404
405 #ifdef DEMO_PLAY_BY_TIMER
406 if (client_ptr -> video_play_time_ms >= DEMO_RTP_VIDEO_PLAY_INTERVAL)
407 {
408 client_ptr -> video_play_time_ms -= DEMO_RTP_VIDEO_PLAY_INTERVAL;
409 }
410 #endif /* DEMO_PLAY_BY_TIMER */
411 #ifndef DEMO_MULTICAST_ENABLED
412 }
413 #endif /* DEMO_MULTICAST_ENABLED */
414 }
415 }
416 }
417
418 /*********************************************
419 ******** DEMO_AUDIO_DATA_READY_EVENT *********
420 *********************************************/
421 if (events & DEMO_AUDIO_DATA_READY_EVENT)
422 {
423
424 /* Check if a play event has already triggered. */
425 if (initialized == NX_TRUE)
426 {
427
428 /* Check if the user has redefined DEMO_AUDIO_DATA_READ which registers audio data read callback function. */
429 if (demo_audio_data_read_callback == NX_NULL)
430 {
431 printf("User must implement audio data read function and redefine DEMO_AUDIO_DATA_READ\r\n");
432 continue;
433 }
434
435 /* Read audio data and transmit it */
436 data_length = 0;
437 if ((demo_audio_data_read_callback(&ntp_msw, &ntp_lsw, &data, &data_length) == NX_SUCCESS) && (data_length > 0))
438 {
439 #ifndef DEMO_MULTICAST_ENABLED
440 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
441 {
442 client_ptr = &sample_client[i];
443 #endif /* DEMO_MULTICAST_ENABLED */
444
445 /* Make sure at least one client having setup the connection. */
446 if (client_ptr -> rtp_session_audio_client_count == 0)
447 {
448 continue;
449 }
450
451 #if (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_AAC)
452 status = nx_rtp_sender_session_aac_send(&(client_ptr -> rtp_session_audio), data, data_length,
453 client_ptr -> rtp_session_audio_timestamp, ntp_msw, ntp_lsw, NX_TRUE);
454 if (status)
455 {
456 printf("Fail to send audio frame: %d, %d\r\n", i, status);
457 }
458
459 client_ptr -> rtp_session_audio_timestamp += DEMO_RTP_AUDIO_SAMPLING_PERIOD;
460 #else
461 /* Allocate a rtp packet. */
462 nx_rtp_sender_session_packet_allocate(&(client_ptr -> rtp_session_audio), &send_packet, NX_WAIT_FOREVER);
463
464 /* Copy payload data into the packet. */
465 status = nx_packet_data_append(send_packet, (void *)data, data_length,
466 client_ptr -> rtp_session_audio.nx_rtp_sender -> nx_rtp_sender_packet_pool_ptr, NX_WAIT_FOREVER);
467 if (status)
468 {
469 nx_packet_release(send_packet);
470 }
471
472 /* Send audio data frame through rtp */
473 status = nx_rtp_sender_session_packet_send(&(client_ptr -> rtp_session_audio), send_packet,
474 client_ptr -> rtp_session_audio_timestamp, ntp_msw, ntp_lsw, NX_FALSE);
475 if (status)
476 {
477 nx_packet_release(send_packet);
478 printf("Fail to send audio data: %d, %d\r\n", i, status);
479 }
480
481 /* Update rtp timestamp by the number of sampling bytes. */
482 client_ptr -> rtp_session_audio_timestamp += (data_length / (DEMO_AUDIO_SAMPLE_SIZE / 8));
483 #endif /* (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_AAC) */
484
485 #ifdef DEMO_PLAY_BY_TIMER
486 if (client_ptr -> audio_play_time_ms >= DEMO_RTP_AUDIO_PLAY_INTERVAL)
487 {
488 client_ptr -> audio_play_time_ms -= DEMO_RTP_AUDIO_PLAY_INTERVAL;
489 }
490 #endif /* DEMO_PLAY_BY_TIMER */
491 #ifndef DEMO_MULTICAST_ENABLED
492 }
493 #endif /* DEMO_MULTICAST_ENABLED */
494 }
495 }
496 }
497 }
498 }
499
500
501 /* SDP string options. */
502 #ifdef DEMO_MULTICAST_ENABLED
503 #if (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264)
504 #define DEMO_SDP \
505 "v=0\r\ns=H264 video with AAC audio, streamed by the NetX RTSP Server\r\n"\
506 "m=video 6002 RTP/AVP 96\r\n"\
507 "c=IN IP4 224.1.0.55/128\r\n"\
508 "a=rtpmap:96 H264/90000\r\n"\
509 "a=fmtp:96 profile-level-id=42A01E; packetization-mode=1\r\n"\
510 "a=control:trackID=0\r\n"\
511 "m=audio 6002 RTP/AVP 97\r\n"\
512 "c=IN IP4 224.1.0.55/128\r\n"\
513 "a=rtpmap:97 mpeg4-generic/44100/1\r\n"\
514 "a=fmtp:97 mode=AAC-hbr; SizeLength=13\r\n"\
515 "a=control:trackID=1\r\n"
516 #else
517 #define DEMO_SDP \
518 "v=0\r\ns=MJPEG video with AAC audio, streamed by the NetX RTSP Server\r\n"\
519 "m=video 6002 RTP/AVP 26\r\n"\
520 "c=IN IP4 224.1.0.55/128\r\n"\
521 "a=rtpmap:26 JPEG/90000\r\n"\
522 "a=control:trackID=0\r\n"\
523 "m=audio 6002 RTP/AVP 11\r\n"\
524 "c=IN IP4 224.1.0.55/128\r\n"\
525 "a=rtpmap:11 L16/44100/1\r\n"\
526 "a=fmtp:11 emphasis=50-15\r\n"\
527 "a=ptime:5\r\n"\
528 "a=control:trackID=1\r\n"
529 #endif /* (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264) */
530 #else
531 #if (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264)
532 #define DEMO_SDP \
533 "v=0\r\ns=H264 video with AAC audio, streamed by the NetX RTSP Server\r\n"\
534 "m=video 0 RTP/AVP 96\r\n"\
535 "a=rtpmap:96 H264/90000\r\n"\
536 "a=fmtp:96 profile-level-id=42A01E; packetization-mode=1\r\n"\
537 "a=control:trackID=0\r\n"\
538 "m=audio 0 RTP/AVP 97\r\n"\
539 "a=rtpmap:97 mpeg4-generic/44100/1\r\n"\
540 "a=fmtp:97 mode=AAC-hbr; SizeLength=13\r\n"\
541 "a=control:trackID=1\r\n"
542 #else
543 #define DEMO_SDP \
544 "v=0\r\ns=MJPEG video with AAC audio, streamed by the NetX RTSP Server\r\n"\
545 "m=video 0 RTP/AVP 26\r\n"\
546 "a=rtpmap:26 JPEG/90000\r\n"\
547 "a=control:trackID=0\r\n"\
548 "m=audio 0 RTP/AVP 11\r\n"\
549 "a=rtpmap:11 L16/44100/1\r\n"\
550 "a=fmtp:11 emphasis=50-15\r\n"\
551 "a=ptime:5\r\n"\
552 "a=control:trackID=1\r\n"
553 #endif /* (DEMO_VIDEO_FORMAT == DEMO_VIDEO_FORMAT_H264) */
554 #endif /* DEMO_MULTICAST_ENABLED */
555
556
rtsp_describe_callback(NX_RTSP_CLIENT * rtsp_client_ptr,UCHAR * uri,UINT uri_length)557 static UINT rtsp_describe_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length)
558 {
559 UINT status;
560
561
562 status = nx_rtsp_server_sdp_set(rtsp_client_ptr, (UCHAR *)DEMO_SDP, sizeof(DEMO_SDP));
563 printf("RTSP request received: DESCRIBE.\r\n");
564 return(status);
565 }
566
rtsp_setup_callback(NX_RTSP_CLIENT * rtsp_client_ptr,UCHAR * uri,UINT uri_length,NX_RTSP_TRANSPORT * transport_ptr)567 static UINT rtsp_setup_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, NX_RTSP_TRANSPORT *transport_ptr)
568 {
569 UINT status;
570 UINT rtp_port, rtcp_port;
571 SAMPLE_CLIENT *client_ptr = NX_NULL;
572 #ifndef DEMO_MULTICAST_ENABLED
573 UINT i;
574 #endif /* DEMO_MULTICAST_ENABLED */
575
576
577 /* Print information from the client */
578 printf("RTSP request received: SETUP.\r\nuri: %s\r\nclient RTP port %d, RTCP port %d, IP %lu.%lu.%lu.%lu\r\n", uri,
579 transport_ptr -> client_rtp_port, transport_ptr -> client_rtcp_port,
580 (transport_ptr -> client_ip_address.nxd_ip_address.v4 >> 24),
581 (transport_ptr -> client_ip_address.nxd_ip_address.v4 >> 16) & 0xFF,
582 (transport_ptr -> client_ip_address.nxd_ip_address.v4 >> 8) & 0xFF,
583 (transport_ptr -> client_ip_address.nxd_ip_address.v4 & 0xFF));
584
585 /* Get the created and found ports */
586 status = nx_rtp_sender_port_get(&rtp_0, &rtp_port, &rtcp_port);
587 if (status)
588 {
589 return(status);
590 }
591 transport_ptr -> server_rtp_port = rtp_port;
592 transport_ptr -> server_rtcp_port = rtcp_port;
593
594 #ifdef DEMO_MULTICAST_ENABLED
595 /* Judge and change to multicast if received ip address is 0 */
596 if (transport_ptr -> client_ip_address.nxd_ip_address.v4 != 0)
597 {
598 return(NX_NOT_SUCCESSFUL);
599 }
600
601 /* Assign multicast ip address and rtp/rtcp ports */
602 transport_ptr -> client_ip_address.nxd_ip_version = NX_IP_VERSION_V4;
603 transport_ptr -> client_ip_address.nxd_ip_address.v4 = DEMO_MULTICAST_IP_ADDRESS;
604 transport_ptr -> client_rtp_port = DEMO_MULTICAST_RTP_PORT;
605 transport_ptr -> client_rtcp_port = DEMO_MULTICAST_RTCP_PORT;
606 transport_ptr -> multicast_ttl = NX_RTP_SENDER_TIME_TO_LIVE;
607
608 /* Directly use sample_client_multicast */
609 client_ptr = &sample_client_multicast;
610 #else
611 /* Find and store the RTSP client pointer. */
612 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
613 {
614
615 /* Check if the client is already linked. */
616 if (sample_client[i].rtsp_client_ptr == rtsp_client_ptr)
617 {
618 client_ptr = &(sample_client[i]);
619 break;
620 }
621
622 if ((client_ptr == NX_NULL) && (sample_client[i].rtsp_client_ptr == NX_NULL))
623 {
624
625 /* Record the unused position. */
626 client_ptr = &(sample_client[i]);
627 }
628 }
629
630 /* Check and return error if reach max connected clients limitation. */
631 if (client_ptr == NX_NULL)
632 {
633 return(NX_NOT_SUCCESSFUL);
634 }
635
636 /* Link the client pointer if it is newly assigned. */
637 if (i == NX_RTSP_SERVER_MAX_CLIENTS)
638 {
639 client_ptr -> rtsp_client_ptr = rtsp_client_ptr;
640 }
641
642 #endif /* DEMO_MULTICAST_ENABLED */
643
644 if (strstr((const char *)uri, DEMO_RTSP_VIDEO_FILE_NAME))
645 {
646 printf("Setup Video (track 0)..\r\n");
647
648 #ifdef DEMO_MULTICAST_ENABLED
649 if (client_ptr -> rtp_session_video_client_count == 0)
650 {
651 #endif /* DEMO_MULTICAST_ENABLED */
652
653 /* Setup rtp sender video session */
654 status = nx_rtp_sender_session_create(&rtp_0, &(client_ptr -> rtp_session_video), DEMO_RTP_PAYLOAD_TYPE_VIDEO,
655 transport_ptr -> interface_index, &(transport_ptr -> client_ip_address),
656 transport_ptr -> client_rtp_port, transport_ptr -> client_rtcp_port);
657 if (status)
658 {
659 printf("Fail to create video session\r\n");
660
661 /* Reset the client pointer if error status happens */
662 client_ptr -> rtsp_client_ptr = NX_NULL;
663 return(status);
664 }
665
666 /* Obtain generated ssrc */
667 status = nx_rtp_sender_session_ssrc_get(&(client_ptr -> rtp_session_video), &(transport_ptr -> rtp_ssrc));
668 if (status)
669 {
670
671 /* Reset the client pointer if error status happens */
672 client_ptr -> rtsp_client_ptr = NX_NULL;
673 return(status);
674 }
675
676 /* Reset corresponding variables */
677 client_ptr -> rtp_session_video_timestamp = (ULONG)NX_RAND();
678 #ifdef DEMO_MULTICAST_ENABLED
679 }
680 #endif /* DEMO_MULTICAST_ENABLED */
681
682 /* Increase the number of setup client. */
683 client_ptr -> rtp_session_video_client_count++;
684 }
685 else if (strstr((const char *)uri, DEMO_RTSP_AUDIO_FILE_NAME))
686 {
687 printf("Setup Audio (track 1)..\r\n");
688
689 #ifdef DEMO_MULTICAST_ENABLED
690 if (client_ptr -> rtp_session_audio_client_count == 0)
691 {
692 #endif /* DEMO_MULTICAST_ENABLED */
693
694 /* Setup rtp sender audio session */
695 status = nx_rtp_sender_session_create(&rtp_0, &(client_ptr -> rtp_session_audio), DEMO_RTP_PAYLOAD_TYPE_AUDIO,
696 transport_ptr -> interface_index, &(transport_ptr -> client_ip_address),
697 transport_ptr -> client_rtp_port, transport_ptr -> client_rtcp_port);
698 if (status)
699 {
700 printf("Fail to create audio session\r\n");
701
702 /* Reset the client pointer if error status happens */
703 client_ptr -> rtsp_client_ptr = NX_NULL;
704 return(status);
705 }
706
707 /* Obtain generated ssrc */
708 status = nx_rtp_sender_session_ssrc_get(&(client_ptr -> rtp_session_audio), &(transport_ptr -> rtp_ssrc));
709 if (status)
710 {
711
712 /* Reset the client pointer if error status happens */
713 client_ptr -> rtsp_client_ptr = NX_NULL;
714 return(status);
715 }
716
717 /* Reset corresponding variables */
718 client_ptr -> rtp_session_audio_timestamp = (ULONG)NX_RAND();
719
720 #if (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_PCM)
721 nx_rtp_sender_session_sample_factor_set(&(client_ptr -> rtp_session_audio), (DEMO_AUDIO_SAMPLE_SIZE / 8) * DEMO_AUDIO_CHANNEL_NUM);
722 #endif /* (DEMO_AUDIO_FORMAT == DEMO_AUDIO_FORMAT_PCM) */
723 #ifdef DEMO_MULTICAST_ENABLED
724 }
725 #endif /* DEMO_MULTICAST_ENABLED */
726
727 /* Increase the number of setup client. */
728 client_ptr -> rtp_session_audio_client_count++;
729 }
730 else
731 {
732 printf("Invalid track ID!\r\n");
733 return(NX_NOT_SUCCESSFUL);
734 }
735
736 return(NX_SUCCESS);
737 }
738
rtsp_play_callback(NX_RTSP_CLIENT * rtsp_client_ptr,UCHAR * uri,UINT uri_length,UCHAR * range_ptr,UINT range_length)739 static UINT rtsp_play_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length)
740 {
741 UINT status;
742 UINT video_seq, audio_seq, video_rtptime, audio_rtptime;
743 SAMPLE_CLIENT *client_ptr;
744 #ifndef DEMO_MULTICAST_ENABLED
745 UINT i;
746 #endif
747
748
749 printf("RTSP request received: PLAY.\r\n");
750
751 #ifndef DEMO_MULTICAST_ENABLED
752 /* Search and find the RTSP client. */
753 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
754 {
755 if (sample_client[i].rtsp_client_ptr == rtsp_client_ptr)
756 {
757 client_ptr = &sample_client[i];
758 break;
759 }
760 }
761 if (i == NX_RTSP_SERVER_MAX_CLIENTS)
762 {
763 printf("Fail to find rtsp client!\r\n");
764 return(NX_NOT_SUCCESSFUL);
765 }
766 #else
767 /* Directly use sample_client_multicast */
768 client_ptr = &sample_client_multicast;
769 #endif /* DEMO_MULTICAST_ENABLED */
770
771 if (client_ptr -> rtp_session_video_client_count)
772 {
773
774 /* Retrieve the sequence number through rtp sender functions */
775 nx_rtp_sender_session_sequence_number_get(&(client_ptr -> rtp_session_video), &video_seq);
776
777 /* Assign recorded timestamps */
778 video_rtptime = client_ptr -> rtp_session_video_timestamp;
779
780 /* Set rtp information into rtsp client */
781 status = nx_rtsp_server_rtp_info_set(rtsp_client_ptr, DEMO_RTSP_VIDEO_FILE_NAME, sizeof(DEMO_RTSP_VIDEO_FILE_NAME) - 1, video_seq, video_rtptime);
782 if (status)
783 {
784 return(status);
785 }
786 }
787
788 if (client_ptr -> rtp_session_audio_client_count)
789 {
790
791 /* Retrieve the sequence number through rtp sender functions */
792 nx_rtp_sender_session_sequence_number_get(&(client_ptr -> rtp_session_audio), &audio_seq);
793
794 /* Assign recorded timestamps */
795 audio_rtptime = client_ptr -> rtp_session_audio_timestamp;
796
797 /* Set rtp information into rtsp client */
798 status = nx_rtsp_server_rtp_info_set(rtsp_client_ptr, DEMO_RTSP_AUDIO_FILE_NAME, sizeof(DEMO_RTSP_AUDIO_FILE_NAME) - 1, audio_seq, audio_rtptime);
799 if (status)
800 {
801 return(status);
802 }
803 }
804
805 /* Trigger the play event */
806 tx_event_flags_set(&demo_test_events, DEMO_PLAY_EVENT, TX_OR);
807
808 return(NX_SUCCESS);
809 }
810
rtsp_teardown_callback(NX_RTSP_CLIENT * rtsp_client_ptr,UCHAR * uri,UINT uri_length)811 static UINT rtsp_teardown_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length)
812 {
813 SAMPLE_CLIENT *client_ptr;
814 #ifndef DEMO_MULTICAST_ENABLED
815 UINT i;
816
817
818 printf("RTSP request received: TEARDOWN.\r\n");
819
820 /* Find the RTSP client pointer. */
821 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
822 {
823 if (sample_client[i].rtsp_client_ptr == rtsp_client_ptr)
824 {
825 client_ptr = &(sample_client[i]);
826 break;
827 }
828 }
829 if (i == NX_RTSP_SERVER_MAX_CLIENTS)
830 {
831 printf("Fail to find rtsp client!\r\n");
832 return(NX_NOT_SUCCESSFUL);
833 }
834 #else
835 /* Directly use sample_client_multicast */
836 client_ptr = &sample_client_multicast;
837 #endif /* DEMO_MULTICAST_ENABLED */
838
839 /* Decrease session client count */
840 if (client_ptr -> rtp_session_video_client_count > 0)
841 {
842 client_ptr -> rtp_session_video_client_count--;
843 #ifdef DEMO_MULTICAST_ENABLED
844 if (client_ptr -> rtp_session_video_client_count == 0)
845 #endif
846 {
847 client_ptr -> rtsp_client_ptr = NX_NULL;
848 nx_rtp_sender_session_delete(&(client_ptr -> rtp_session_video));
849 }
850 }
851 if (client_ptr -> rtp_session_audio_client_count > 0)
852 {
853 client_ptr -> rtp_session_audio_client_count--;
854 #ifdef DEMO_MULTICAST_ENABLED
855 if (client_ptr -> rtp_session_audio_client_count == 0)
856 #endif
857 {
858 client_ptr -> rtsp_client_ptr = NX_NULL;
859 nx_rtp_sender_session_delete(&(client_ptr -> rtp_session_audio));
860 }
861 }
862
863 /* Trigger the tear down event */
864 tx_event_flags_set(&demo_test_events, DEMO_TEARDOWN_EVENT, TX_OR);
865
866 return(NX_SUCCESS);
867 }
868
rtsp_pause_callback(NX_RTSP_CLIENT * rtsp_client_ptr,UCHAR * uri,UINT uri_length,UCHAR * range_ptr,UINT range_length)869 static UINT rtsp_pause_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *range_ptr, UINT range_length)
870 {
871 printf("RTSP request received: PAUSE.\r\n");
872
873 return(NX_SUCCESS);
874 }
875
rtsp_set_parameter_callback(NX_RTSP_CLIENT * rtsp_client_ptr,UCHAR * uri,UINT uri_length,UCHAR * parameter_ptr,ULONG parameter_length)876 static UINT rtsp_set_parameter_callback(NX_RTSP_CLIENT *rtsp_client_ptr, UCHAR *uri, UINT uri_length, UCHAR *parameter_ptr, ULONG parameter_length)
877 {
878 printf("RTSP request received: SET PARAMETER.\r\n");
879
880 return(NX_SUCCESS);
881 }
882
rtsp_disconnect_callback(NX_RTSP_CLIENT * rtsp_client_ptr)883 static UINT rtsp_disconnect_callback(NX_RTSP_CLIENT *rtsp_client_ptr)
884 {
885
886 /* Trigger the tear down event */
887 tx_event_flags_set(&demo_test_events, DEMO_TEARDOWN_EVENT, TX_OR);
888
889 return(NX_SUCCESS);
890 }
891
test_rtcp_receiver_report_callback(NX_RTP_SESSION * session,NX_RTCP_RECEIVER_REPORT * report)892 static UINT test_rtcp_receiver_report_callback(NX_RTP_SESSION *session, NX_RTCP_RECEIVER_REPORT *report)
893 {
894 #ifndef DEMO_MULTICAST_ENABLED
895 UINT i;
896
897 /* Search the rtsp client table and find which session it is*/
898 for (i = 0; i < NX_RTSP_SERVER_MAX_CLIENTS; i++)
899 {
900 if (session == &(sample_client[i].rtp_session_video))
901 {
902 break;
903 }
904 else if (session == &(sample_client[i].rtp_session_audio))
905 {
906 break;
907 }
908 }
909 if (i == NX_RTSP_SERVER_MAX_CLIENTS)
910 {
911
912 /* Unkown session, return directly. */
913 return(NX_SUCCESS);
914 }
915 #endif /* DEMO_MULTICAST_ENABLED */
916
917 /*
918 We can add user implementation code here..
919
920 Note!: since this callback is invoked from the IP thread, the application should not block in this callback.
921
922 Tip: in this callback, we can obtain and record below information:
923 1) report -> receiver_ssrc: the ssrc of the receiver who sends the rr report
924 2) report -> fraction_loss: the fraction lost of the receiver
925 3) report -> packet_loss: the cumulative number of packets lost of the receiver
926 4) report -> extended_max: the extended highest sequence number received of the receiver
927 5) report -> jitter: the inter-arrival jitter of the receiver
928 6) report -> last_sr: the last SR timestamp of the receiver
929 7) report -> delay: the delay since last SR timestamp of the receiver.
930 */
931
932 /* Update the timeout of RTSP server since the RTCP message proves liveness. */
933 #ifdef DEMO_MULTICAST_ENABLED
934 nx_rtsp_server_keepalive_update(sample_client_multicast.rtsp_client_ptr);
935 #else
936 nx_rtsp_server_keepalive_update(sample_client[i].rtsp_client_ptr);
937 #endif /* DEMO_MULTICAST_ENABLED */
938
939 return(NX_SUCCESS);
940 }
941
test_rtcp_sdes_callback(NX_RTCP_SDES_INFO * sdes_info)942 static UINT test_rtcp_sdes_callback(NX_RTCP_SDES_INFO *sdes_info)
943 {
944 /*
945 We can add user implementation code here..
946
947 Note!: since this callback is invoked from the IP thread, the application should not block in this callback.
948
949 Tip: in this callback, we can obtain and record below information:
950 1) sdes_info -> ssrc: the ssrc of the receiver who sends the sdes packet
951 2) sdes_info -> cname_length: the length of the cname field
952 3) sdes_info -> cname: the cname field
953 */
954
955 return NX_SUCCESS;
956 }
957