Asterisk - The Open Source Telephony Project GIT-master-f36a736
test_res_rtp.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2019, Sangoma, Inc.
5 *
6 * Ben Ford <bford@sangoma.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19/*!
20 * \file
21 * \brief RTP/RTCP Unit Tests
22 *
23 * \author Ben Ford <bford@digium.com>
24 *
25 */
26
27/*** MODULEINFO
28 <depend>TEST_FRAMEWORK</depend>
29 <support_level>core</support_level>
30 ***/
31
32#include "asterisk.h"
33
34#include "asterisk/module.h"
35#include "asterisk/test.h"
36#include "asterisk/rtp_engine.h"
39#include <assert.h>
40#include <sched.h>
41
43 TEST_TYPE_NONE = 0, /* No special setup required */
44 TEST_TYPE_NACK, /* Enable NACK */
45 TEST_TYPE_REMB, /* Enable REMB */
46 TEST_TYPE_STD_RTCP, /* Let the stack do RTCP */
47};
48
50{
51 if (sched) {
53 }
54}
55
56static int test_init_rtp_instances(struct ast_rtp_instance **instance1,
57 struct ast_rtp_instance **instance2, struct ast_sched_context *test_sched,
58 enum test_type type)
59{
60 struct ast_sockaddr addr1;
61 struct ast_sockaddr addr2;
63
64 ast_sockaddr_parse(&addr1, "127.0.0.1", 0);
65 ast_sockaddr_parse(&addr2, "127.0.0.1", 0);
66
67 *instance1 = ast_rtp_instance_new("asterisk", test_sched, &addr1, "instance1");
68 *instance2 = ast_rtp_instance_new("asterisk", test_sched, &addr2, "instance2");
69 if (!instance1 || !instance2) {
70 return -1;
71 }
72
73 ast_rtp_instance_set_channel_id(*instance1, "instance1");
74 ast_rtp_instance_set_channel_id(*instance2, "instance2");
75
76 if (type == TEST_TYPE_STD_RTCP) {
78 }
79
81 AST_RTP_PROPERTY_RTCP, rtcp_type);
83 AST_RTP_PROPERTY_RTCP, rtcp_type);
84
85 if (type == TEST_TYPE_NACK) {
90 } else if (type == TEST_TYPE_REMB) {
93 }
94
95 ast_rtp_instance_get_local_address(*instance1, &addr1);
96 ast_rtp_instance_set_remote_address(*instance2, &addr1);
97
98 ast_rtp_instance_get_local_address(*instance2, &addr2);
99 ast_rtp_instance_set_remote_address(*instance1, &addr2);
100
101 ast_rtp_instance_reset_test_engine(*instance1);
102
103 ast_rtp_instance_activate(*instance1);
104 ast_rtp_instance_activate(*instance2);
105
106 return 0;
107}
108
109static void test_write_frames(struct ast_rtp_instance *instance, int seqno, int num)
110{
111 char data[320] = "";
112 struct ast_frame frame_out = {
114 .subclass.format = ast_format_ulaw,
115 .data.ptr = data,
116 .datalen = 160,
117 };
118 int index;
119
121
122 for (index = 0; index < num; index++) {
123 frame_out.seqno = seqno + index;
124 ast_rtp_instance_write(instance, &frame_out);
125 }
126}
127
128static void test_read_frames(struct ast_rtp_instance *instance, int num)
129{
130 struct ast_frame *frame_in;
131 int index;
132
133 for (index = 0; index < num; index++) {
134 frame_in = ast_rtp_instance_read(instance, 0);
135 if (frame_in) {
136 ast_frfree(frame_in);
137 }
138 }
139}
140
141static void test_write_and_read_frames(struct ast_rtp_instance *instance1,
142 struct ast_rtp_instance *instance2, int seqno, int num)
143{
144 test_write_frames(instance1, seqno, num);
145 test_read_frames(instance2, num);
146}
147
148
149/*
150 * Unfortunately, we can't use usleep() to create
151 * packet spacing because there are signals in use
152 * which cause usleep to immediately return. Instead
153 * we have to spin. :(
154 */
155static void SLEEP_SPINNER(int ms)
156{
157 struct timeval a = ast_tvnow();
158
159 while(1) {
160 sched_yield();
161 if (ast_remaining_ms(a, ms) <= 0) {
162 break;
163 }
164 }
165}
166
167/*
168 * This function is NOT really a reliable implementation.
169 * Its purpose is only to aid in code development in res_rtp_asterisk.
170 */
172 struct ast_rtp_instance *instance2, int howlong, int rtcp_interval)
173{
174 char data[320] = "";
175 int pktinterval = 20;
176
177 struct ast_frame frame_out1 = {
179 .subclass.format = ast_format_ulaw,
180 .seqno = 4556,
181 .data.ptr = data,
182 .datalen = 160,
183 .samples = 1,
184 .len = pktinterval,
185 .ts = 4622295,
186 };
187 struct ast_frame frame_out2 = {
189 .subclass.format = ast_format_ulaw,
190 .seqno = 6554,
191 .data.ptr = data,
192 .datalen = 160,
193 .samples = 1,
194 .len = pktinterval,
195 .ts = 8622295,
196 };
197 struct ast_frame *frame_in1;
198 struct ast_frame *frame_in2;
199 int index;
200 int num;
201 int rtcpnum;
202 int reverse = 1;
203 int send_rtcp = 0;
204
205 num = howlong / pktinterval;
206
207 rtcpnum = rtcp_interval / pktinterval;
208
213
214 for (index = 0; index < num; index++) {
215 struct timeval start = ast_tvnow();
216 time_t ms;
217
218 if (index == 1) {
223 }
224 frame_out1.seqno += index;
225 frame_out1.delivery = start;
226 frame_out1.ts += frame_out1.len;
227 ast_rtp_instance_write(instance1, &frame_out1);
228
229 if (send_rtcp && index && (index % rtcpnum == 0)) {
230 ast_rtp_instance_queue_report(instance1);
231 }
232
233 frame_in2 = ast_rtp_instance_read(instance2, 0);
234 ast_frfree(frame_in2);
235 frame_in2 = ast_rtp_instance_read(instance2, 1);
236 ast_frfree(frame_in2);
237
238 if (reverse) {
239 frame_out2.seqno += index;
240 frame_out2.delivery = ast_tvnow();
241 frame_out2.ts += frame_out2.len;
242 ast_rtp_instance_write(instance2, &frame_out2);
243
244 if (send_rtcp && index && (index % rtcpnum == 0)) {
245 ast_rtp_instance_queue_report(instance2);
246 }
247
248 frame_in1 = ast_rtp_instance_read(instance1, 0);
249 ast_frfree(frame_in1);
250 frame_in1 = ast_rtp_instance_read(instance1, 1);
251 ast_frfree(frame_in1);
252
253 }
254
255 ms = frame_out1.len - ast_tvdiff_ms(ast_tvnow(),start);
256 ms += (index % 2 ? 5 : 12);
257 ms += (index % 3 ? 2 : 30);
258 SLEEP_SPINNER(ms);
259 }
260}
261
262AST_TEST_DEFINE(nack_no_packet_loss)
263{
267
268 switch (cmd) {
269 case TEST_INIT:
270 info->name = "nack_no_packet_loss";
271 info->category = "/res/res_rtp/";
272 info->summary = "nack no packet loss unit test";
273 info->description =
274 "Tests sending packets with no packet loss and "
275 "validates that the send buffer stores sent packets "
276 "and the receive buffer is empty";
277 return AST_TEST_NOT_RUN;
278 case TEST_EXECUTE:
279 break;
280 }
281
282 test_sched = ast_sched_context_create();
283
284 if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NACK)) < 0) {
285 ast_log(LOG_ERROR, "Failed to initialize test!\n");
286 return AST_TEST_FAIL;
287 }
288
289 test_write_and_read_frames(instance1, instance2, 1000, 10);
290
291 ast_test_validate(test, ast_rtp_instance_get_send_buffer_count(instance1) == 10,
292 "Send buffer did not have the expected count of 10");
293
294 ast_test_validate(test, ast_rtp_instance_get_recv_buffer_count(instance2) == 0,
295 "Receive buffer did not have the expected count of 0");
296
297 return AST_TEST_PASS;
298}
299
300AST_TEST_DEFINE(nack_nominal)
301{
305
306 switch (cmd) {
307 case TEST_INIT:
308 info->name = "nack_nominal";
309 info->category = "/res/res_rtp/";
310 info->summary = "nack nominal unit test";
311 info->description =
312 "Tests sending packets with some packet loss and "
313 "validates that a NACK request is sent on reaching "
314 "the triggering amount of lost packets";
315 return AST_TEST_NOT_RUN;
316 case TEST_EXECUTE:
317 break;
318 }
319
320 test_sched = ast_sched_context_create();
321
322 if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NACK)) < 0) {
323 ast_log(LOG_ERROR, "Failed to initialize test!\n");
324 return AST_TEST_FAIL;
325 }
326
327 /* Start normally */
328 test_write_and_read_frames(instance1, instance2, 1000, 10);
329
330 /* Set the number of packets to drop when we send them next */
331 ast_rtp_instance_drop_packets(instance2, 10);
332 test_write_and_read_frames(instance1, instance2, 1010, 10);
333
334 /* Send enough packets to reach the NACK trigger */
335 test_write_and_read_frames(instance1, instance2, 1020, ast_rtp_instance_get_recv_buffer_max(instance2) / 2);
336
337 /* This needs to be read as RTCP */
338 test_read_frames(instance1, 1);
339
340 /* We should have the missing packets to read now */
341 test_read_frames(instance2, 10);
342
343 ast_test_validate(test, ast_rtp_instance_get_recv_buffer_count(instance2) == 0,
344 "Receive buffer did not have the expected count of 0");
345
346 return AST_TEST_PASS;
347}
348
349AST_TEST_DEFINE(nack_overflow)
350{
354 int max_packets;
355
356 switch (cmd) {
357 case TEST_INIT:
358 info->name = "nack_overflow";
359 info->category = "/res/res_rtp/";
360 info->summary = "nack overflow unit test";
361 info->description =
362 "Tests that when the buffer hits its capacity, we "
363 "queue all the packets we currently have stored";
364 return AST_TEST_NOT_RUN;
365 case TEST_EXECUTE:
366 break;
367 }
368
369 test_sched = ast_sched_context_create();
370
371 if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NACK)) < 0) {
372 ast_log(LOG_ERROR, "Failed to initialize test!\n");
373 return AST_TEST_FAIL;
374 }
375
376 /* Start normally */
377 test_write_and_read_frames(instance1, instance2, 1000, 10);
378
379 /* Send enough packets to fill the buffer */
380 max_packets = ast_rtp_instance_get_recv_buffer_max(instance2);
381 test_write_and_read_frames(instance1, instance2, 1020, max_packets);
382
383 ast_test_validate(test, ast_rtp_instance_get_recv_buffer_count(instance2) == max_packets,
384 "Receive buffer did not have the expected count of max buffer size");
385
386 /* Send the packet that will overflow the buffer */
387 test_write_and_read_frames(instance1, instance2, 1020 + max_packets, 1);
388
389 ast_test_validate(test, ast_rtp_instance_get_recv_buffer_count(instance2) == 0,
390 "Receive buffer did not have the expected count of 0");
391
392 return AST_TEST_PASS;
393}
394
395AST_TEST_DEFINE(lost_packet_stats_nominal)
396{
400 struct ast_rtp_instance_stats stats = { 0, };
402
403 switch (cmd) {
404 case TEST_INIT:
405 info->name = "lost_packet_stats_nominal";
406 info->category = "/res/res_rtp/";
407 info->summary = "lost packet stats nominal unit test";
408 info->description =
409 "Tests that when some packets are lost, we calculate that "
410 "loss correctly when doing lost packet statistics";
411 return AST_TEST_NOT_RUN;
412 case TEST_EXECUTE:
413 break;
414 }
415
416 test_sched = ast_sched_context_create();
417
418 if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NONE)) < 0) {
419 ast_log(LOG_ERROR, "Failed to initialize test!\n");
420 return AST_TEST_FAIL;
421 }
422
423 /* Start normally */
424 test_write_and_read_frames(instance1, instance2, 1000, 10);
425
426 /* Send some more packets, but with a gap */
427 test_write_and_read_frames(instance1, instance2, 1015, 5);
428
429 /* Send a RR to calculate lost packet statistics. We should be missing 5 packets */
430 ast_rtp_instance_queue_report(instance1);
431 test_write_frames(instance2, 1000, 1);
432
433 /* Check RTCP stats to see if we got the expected packet loss count */
434 ast_rtp_instance_get_stats(instance2, &stats, stat);
435 ast_test_validate(test, stats.rxploss == 5 && stats.local_minrxploss == 5 &&
436 stats.local_maxrxploss == 5, "Condition of 5 lost packets was not met");
437
438 /* Drop 3 before writing 5 more */
439 test_write_and_read_frames(instance1, instance2, 1023, 5);
440
441 ast_rtp_instance_queue_report(instance1);
442 test_write_frames(instance2, 1001, 1);
443 ast_rtp_instance_get_stats(instance2, &stats, stat);
444
445 /* Should now be missing 8 total packets with a change in min */
446 ast_test_validate(test, stats.rxploss == 8 && stats.local_minrxploss == 3 &&
447 stats.local_maxrxploss == 5);
448
449 /* Write 5 more with no gaps */
450 test_write_and_read_frames(instance1, instance2, 1028, 5);
451
452 ast_rtp_instance_queue_report(instance1);
453 test_write_frames(instance2, 1002, 1);
454 ast_rtp_instance_get_stats(instance2, &stats, stat);
455
456 /* Should still only be missing 8 total packets */
457 ast_test_validate(test, stats.rxploss == 8 && stats.local_minrxploss == 3 &&
458 stats.local_maxrxploss == 5);
459
460 /* Now drop 1, write another 5, drop 8, and then write 5 */
461 test_write_and_read_frames(instance1, instance2, 1034, 5);
462 test_write_and_read_frames(instance1, instance2, 1047, 5);
463
464 ast_rtp_instance_queue_report(instance1);
465 test_write_frames(instance2, 1003, 1);
466 ast_rtp_instance_get_stats(instance2, &stats, stat);
467
468 /* Now it should be missing 17 total packets, with a change in max */
469 ast_test_validate(test, stats.rxploss == 17 && stats.local_minrxploss == 3 &&
470 stats.local_maxrxploss == 9);
471
472 return AST_TEST_PASS;
473}
474
475AST_TEST_DEFINE(remb_nominal)
476{
480 RAII_VAR(struct ast_frame *, frame_in, NULL, ast_frfree);
481 /* Use the structure softmix_remb_collector uses to store information for REMB */
482 struct ast_rtp_rtcp_feedback feedback = {
484 .remb.br_exp = 0,
485 .remb.br_mantissa = 1000,
486 };
487 struct ast_frame frame_out = {
489 .subclass.integer = AST_RTP_RTCP_PSFB,
490 .data.ptr = &feedback,
491 .datalen = sizeof(feedback),
492 };
493 struct ast_rtp_rtcp_feedback *received_feedback;
494
495 switch (cmd) {
496 case TEST_INIT:
497 info->name = "remb_nominal";
498 info->category = "/res/res_rtp/";
499 info->summary = "remb nominal unit test";
500 info->description =
501 "Tests sending and receiving a REMB packet";
502 return AST_TEST_NOT_RUN;
503 case TEST_EXECUTE:
504 break;
505 }
506
507 test_sched = ast_sched_context_create();
508
509 if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_REMB)) < 0) {
510 ast_log(LOG_ERROR, "Failed to initialize test!\n");
511 return AST_TEST_FAIL;
512 }
513
514 /* The schedid must be 0 or greater, so let's do that now */
515 ast_rtp_instance_set_schedid(instance1, 0);
516
517 ast_rtp_instance_write(instance1, &frame_out);
518
519 /* Verify the high level aspects of the frame */
520 frame_in = ast_rtp_instance_read(instance2, 0);
521 ast_test_validate(test, frame_in != NULL, "Did not receive a REMB frame");
522 ast_test_validate(test, frame_in->frametype == AST_FRAME_RTCP,
523 "REMB frame did not have the expected frametype");
524 ast_test_validate(test, frame_in->subclass.integer == AST_RTP_RTCP_PSFB,
525 "REMB frame did not have the expected subclass integer");
526
527 /* Verify the actual REMB information itself */
528 received_feedback = frame_in->data.ptr;
529 ast_test_validate(test, received_feedback->fmt == AST_RTP_RTCP_FMT_REMB,
530 "REMB frame did not have the expected feedback format");
531 ast_test_validate(test, received_feedback->remb.br_exp == feedback.remb.br_exp,
532 "REMB received exponent did not match sent exponent");
533 ast_test_validate(test, received_feedback->remb.br_mantissa == feedback.remb.br_mantissa,
534 "REMB received mantissa did not match sent mantissa");
535
536 return AST_TEST_PASS;
537}
538
539AST_TEST_DEFINE(sr_rr_nominal)
540{
544 RAII_VAR(struct ast_frame *, frame_in, NULL, ast_frfree);
545
546 switch (cmd) {
547 case TEST_INIT:
548 info->name = "sr_rr_nominal";
549 info->category = "/res/res_rtp/";
550 info->summary = "SR/RR nominal unit test";
551 info->description =
552 "Tests sending SR/RR and receiving it; includes SDES";
553 return AST_TEST_NOT_RUN;
554 case TEST_EXECUTE:
555 break;
556 }
557
558 test_sched = ast_sched_context_create();
559
560 if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NONE)) < 0) {
561 ast_log(LOG_ERROR, "Failed to initialize test!\n");
562 return AST_TEST_FAIL;
563 }
564
565 test_write_and_read_frames(instance1, instance2, 1000, 10);
566
567 /*
568 * Set the send_report flag so we send a sender report instead of normal RTP. We
569 * also need to ensure that SDES processed.
570 */
571 ast_rtp_instance_queue_report(instance1);
572 test_write_frames(instance1, 1010, 1);
573
574 frame_in = ast_rtp_instance_read(instance2, 0);
575 ast_test_validate(test, frame_in->frametype == AST_FRAME_RTCP,
576 "Sender report frame did not have the expected frametype");
577 ast_test_validate(test, frame_in->subclass.integer == AST_RTP_RTCP_SR,
578 "Sender report frame did not have the expected subclass integer");
579 ast_test_validate(test, ast_rtp_instance_get_sdes_received(instance2) == 1,
580 "SDES was never processed for sender report");
581
582 ast_frfree(frame_in);
583
584 /* Set the send_report flag so we send a receiver report instead of normal RTP */
585 ast_rtp_instance_queue_report(instance1);
586 test_write_frames(instance1, 1010, 1);
587
588 frame_in = ast_rtp_instance_read(instance2, 0);
589 ast_test_validate(test, frame_in->frametype == AST_FRAME_RTCP,
590 "Receiver report frame did not have the expected frametype");
591 ast_test_validate(test, frame_in->subclass.integer == AST_RTP_RTCP_RR,
592 "Receiver report frame did not have the expected subclass integer");
593
594 return AST_TEST_PASS;
595}
596
597AST_TEST_DEFINE(fir_nominal)
598{
602 RAII_VAR(struct ast_frame *, frame_in, NULL, ast_frfree);
603 struct ast_frame frame_out = {
605 .subclass.integer = AST_CONTROL_VIDUPDATE,
606 };
607
608 switch (cmd) {
609 case TEST_INIT:
610 info->name = "fir_nominal";
611 info->category = "/res/res_rtp/";
612 info->summary = "fir nominal unit test";
613 info->description =
614 "Tests sending and receiving a FIR packet";
615 return AST_TEST_NOT_RUN;
616 case TEST_EXECUTE:
617 break;
618 }
619
620 test_sched = ast_sched_context_create();
621
622 if ((test_init_rtp_instances(&instance1, &instance2, test_sched, TEST_TYPE_NONE)) < 0) {
623 ast_log(LOG_ERROR, "Failed to initialize test!\n");
624 return AST_TEST_FAIL;
625 }
626
627 /* Send some packets to learn SSRC */
628 test_write_and_read_frames(instance2, instance1, 1000, 10);
629
630 /* The schedid must be 0 or greater, so let's do that now */
631 ast_rtp_instance_set_schedid(instance1, 0);
632
633 /*
634 * This will not directly write a frame out, but cause Asterisk to see it as a FIR
635 * request, which will then trigger rtp_write_rtcp_fir, which will send out the
636 * appropriate packet.
637 */
638 ast_rtp_instance_write(instance1, &frame_out);
639
640 /*
641 * We only receive one frame, the FIR request. It won't have a subclass integer of
642 * 206 (PSFB) because ast_rtcp_interpret sets it to 18 (AST_CONTROL_VIDUPDATE), so
643 * check for that.
644 */
645 frame_in = ast_rtp_instance_read(instance2, 0);
646 ast_test_validate(test, frame_in != NULL, "Did not receive a FIR frame");
647 ast_test_validate(test, frame_in->frametype == AST_FRAME_CONTROL,
648 "FIR frame did not have the expected frametype");
649 ast_test_validate(test, frame_in->subclass.integer == AST_CONTROL_VIDUPDATE,
650 "FIR frame did not have the expected subclass integer");
651
652 return AST_TEST_PASS;
653}
654
655/*
656 * This test should not normally be run. Its only purpose is to
657 * aid in code development.
658 */
660{
664
665 switch (cmd) {
666 case TEST_INIT:
667 info->name = "mes";
668 info->category = "/res/res_rtp/";
669 info->summary = "Media Experience Score";
670 info->description =
671 "Tests calculation of Media Experience Score (only run by explicit request)";
672 info->explicit_only = 1;
673 return AST_TEST_NOT_RUN;
674 case TEST_EXECUTE:
675 break;
676 }
677
678 test_sched = ast_sched_context_create();
679 ast_sched_start_thread(test_sched);
680
681 if ((test_init_rtp_instances(&instance1, &instance2,
682 test_sched, TEST_TYPE_NONE)) < 0) {
683 ast_log(LOG_ERROR, "Failed to initialize test!\n");
684 return AST_TEST_FAIL;
685 }
686
688 instance1, instance2, 1000, 5000);
689
690 return AST_TEST_PASS;
691}
692
693static int unload_module(void)
694{
696 AST_TEST_UNREGISTER(nack_no_packet_loss);
697 AST_TEST_UNREGISTER(nack_nominal);
698 AST_TEST_UNREGISTER(nack_overflow);
699 AST_TEST_UNREGISTER(lost_packet_stats_nominal);
700 AST_TEST_UNREGISTER(remb_nominal);
701 AST_TEST_UNREGISTER(sr_rr_nominal);
702 AST_TEST_UNREGISTER(fir_nominal);
703 return 0;
704}
705
706static int load_module(void)
707{
708 AST_TEST_REGISTER(nack_no_packet_loss);
709 AST_TEST_REGISTER(nack_nominal);
710 AST_TEST_REGISTER(nack_overflow);
711 AST_TEST_REGISTER(lost_packet_stats_nominal);
712 AST_TEST_REGISTER(remb_nominal);
713 AST_TEST_REGISTER(sr_rr_nominal);
714 AST_TEST_REGISTER(fir_nominal);
717}
718
Asterisk main include file. File version handling, generic pbx functions.
#define ast_log
Definition: astobj2.c:42
static const char type[]
Definition: chan_ooh323.c:109
Data Buffer API.
Media Format Cache API.
struct ast_format * ast_format_ulaw
Built-in cached ulaw format.
Definition: format_cache.c:86
@ AST_FRFLAG_HAS_SEQUENCE_NUMBER
@ AST_FRFLAG_HAS_TIMING_INFO
#define ast_frfree(fr)
@ AST_FRAME_VOICE
@ AST_FRAME_RTCP
@ AST_FRAME_CONTROL
@ AST_CONTROL_VIDUPDATE
#define LOG_ERROR
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
Definition: module.h:581
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
def info(msg)
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
#define NULL
Definition: resample.c:96
Pluggable RTP Architecture.
#define AST_RTP_RTCP_PSFB
Definition: rtp_engine.h:329
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:458
struct ast_rtp_instance * ast_rtp_instance_new(const char *engine_name, struct ast_sched_context *sched, const struct ast_sockaddr *sa, void *data)
Create a new RTP instance.
Definition: rtp_engine.c:487
#define AST_RTP_RTCP_SR
Definition: rtp_engine.h:323
ast_rtp_instance_rtcp
Definition: rtp_engine.h:283
@ AST_RTP_INSTANCE_RTCP_MUX
Definition: rtp_engine.h:289
@ AST_RTP_INSTANCE_RTCP_STANDARD
Definition: rtp_engine.h:287
ast_rtp_instance_stat
Definition: rtp_engine.h:185
@ AST_RTP_INSTANCE_STAT_ALL
Definition: rtp_engine.h:187
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:600
#define AST_RTP_RTCP_RR
Definition: rtp_engine.h:325
void ast_rtp_instance_set_prop(struct ast_rtp_instance *instance, enum ast_rtp_property property, int value)
Set the value of an RTP instance property.
Definition: rtp_engine.c:727
void ast_rtp_instance_get_local_address(struct ast_rtp_instance *instance, struct ast_sockaddr *address)
Get the local address that we are expecting RTP on.
Definition: rtp_engine.c:665
int ast_rtp_instance_get_stats(struct ast_rtp_instance *instance, struct ast_rtp_instance_stats *stats, enum ast_rtp_instance_stat stat)
Retrieve statistics about an RTP instance.
Definition: rtp_engine.c:2622
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition: rtp_engine.c:590
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
Definition: rtp_engine.h:1138
#define AST_RTP_RTCP_FMT_REMB
Definition: rtp_engine.h:339
@ AST_RTP_PROPERTY_RETRANS_RECV
Definition: rtp_engine.h:130
@ AST_RTP_PROPERTY_RETRANS_SEND
Definition: rtp_engine.h:132
@ AST_RTP_PROPERTY_RTCP
Definition: rtp_engine.h:126
@ AST_RTP_PROPERTY_REMB
Definition: rtp_engine.h:134
int ast_rtp_instance_activate(struct ast_rtp_instance *instance)
Indicate to the RTP engine that packets are now expected to be sent/received on the RTP instance.
Definition: rtp_engine.c:2847
void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
Set the channel that owns this RTP instance.
Definition: rtp_engine.c:575
Scheduler Routines (derived from cheops)
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition: sched.c:197
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
Definition: sched.c:238
Data structure associated with a single frame of data.
union ast_frame::@226 data
struct timeval delivery
enum ast_frame_type frametype
unsigned int rxploss
Definition: rtp_engine.h:424
An object that represents data received in a feedback report.
Definition: rtp_engine.h:388
unsigned int fmt
Definition: rtp_engine.h:389
struct ast_rtp_rtcp_feedback_remb remb
Definition: rtp_engine.h:391
Socket address structure.
Definition: netsock2.h:97
Definition: sched.c:76
Test Framework API.
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
#define AST_TEST_REGISTER(cb)
Definition: test.h:127
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
static struct test_val a
static void SLEEP_SPINNER(int ms)
Definition: test_res_rtp.c:155
AST_TEST_DEFINE(nack_no_packet_loss)
Definition: test_res_rtp.c:262
static void test_write_and_read_interleaved_frames(struct ast_rtp_instance *instance1, struct ast_rtp_instance *instance2, int howlong, int rtcp_interval)
Definition: test_res_rtp.c:171
static int test_init_rtp_instances(struct ast_rtp_instance **instance1, struct ast_rtp_instance **instance2, struct ast_sched_context *test_sched, enum test_type type)
Definition: test_res_rtp.c:56
static void test_read_frames(struct ast_rtp_instance *instance, int num)
Definition: test_res_rtp.c:128
test_type
Definition: test_res_rtp.c:42
@ TEST_TYPE_NACK
Definition: test_res_rtp.c:44
@ TEST_TYPE_NONE
Definition: test_res_rtp.c:43
@ TEST_TYPE_STD_RTCP
Definition: test_res_rtp.c:46
@ TEST_TYPE_REMB
Definition: test_res_rtp.c:45
static void ast_sched_context_destroy_wrapper(struct ast_sched_context *sched)
Definition: test_res_rtp.c:49
static int load_module(void)
Definition: test_res_rtp.c:706
static void test_write_and_read_frames(struct ast_rtp_instance *instance1, struct ast_rtp_instance *instance2, int seqno, int num)
Definition: test_res_rtp.c:141
static int unload_module(void)
Definition: test_res_rtp.c:693
static void test_write_frames(struct ast_rtp_instance *instance, int seqno, int num)
Definition: test_res_rtp.c:109
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
Definition: time.h:107
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70