Asterisk - The Open Source Telephony Project GIT-master-a358458
Enumerations | Functions | Variables
test_res_rtp.c File Reference

RTP/RTCP Unit Tests. More...

#include "asterisk.h"
#include "asterisk/module.h"
#include "asterisk/test.h"
#include "asterisk/rtp_engine.h"
#include "asterisk/data_buffer.h"
#include "asterisk/format_cache.h"
#include <assert.h>
#include <sched.h>
Include dependency graph for test_res_rtp.c:

Go to the source code of this file.

Enumerations

enum  test_type { TEST_TYPE_NONE = 0 , TEST_TYPE_NACK , TEST_TYPE_REMB , TEST_TYPE_STD_RTCP }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
struct ast_moduleAST_MODULE_SELF_SYM (void)
 
static void ast_sched_context_destroy_wrapper (struct ast_sched_context *sched)
 
 AST_TEST_DEFINE (fir_nominal)
 
 AST_TEST_DEFINE (lost_packet_stats_nominal)
 
 AST_TEST_DEFINE (mes)
 
 AST_TEST_DEFINE (nack_no_packet_loss)
 
 AST_TEST_DEFINE (nack_nominal)
 
 AST_TEST_DEFINE (nack_overflow)
 
 AST_TEST_DEFINE (remb_nominal)
 
 AST_TEST_DEFINE (sr_rr_nominal)
 
static int load_module (void)
 
static void SLEEP_SPINNER (int ms)
 
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)
 
static void test_read_frames (struct ast_rtp_instance *instance, int num)
 
static void test_write_and_read_frames (struct ast_rtp_instance *instance1, struct ast_rtp_instance *instance2, int seqno, int num)
 
static void test_write_and_read_interleaved_frames (struct ast_rtp_instance *instance1, struct ast_rtp_instance *instance2, int howlong, int rtcp_interval)
 
static void test_write_frames (struct ast_rtp_instance *instance, int seqno, int num)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "RTP/RTCP test module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
 
static const struct ast_module_infoast_module_info = &__mod_info
 

Detailed Description

RTP/RTCP Unit Tests.

Author
Ben Ford bford.nosp@m.@dig.nosp@m.ium.c.nosp@m.om

Definition in file test_res_rtp.c.

Enumeration Type Documentation

◆ test_type

enum test_type
Enumerator
TEST_TYPE_NONE 
TEST_TYPE_NACK 
TEST_TYPE_REMB 
TEST_TYPE_STD_RTCP 

Definition at line 42 of file test_res_rtp.c.

42 {
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};
@ 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

Function Documentation

◆ __reg_module()

static void __reg_module ( void  )
static

Definition at line 719 of file test_res_rtp.c.

◆ __unreg_module()

static void __unreg_module ( void  )
static

Definition at line 719 of file test_res_rtp.c.

◆ AST_MODULE_SELF_SYM()

struct ast_module * AST_MODULE_SELF_SYM ( void  )

Definition at line 719 of file test_res_rtp.c.

◆ ast_sched_context_destroy_wrapper()

static void ast_sched_context_destroy_wrapper ( struct ast_sched_context sched)
static

Definition at line 49 of file test_res_rtp.c.

50{
51 if (sched) {
53 }
54}
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
Definition: sched.c:271
Definition: sched.c:76

References ast_sched_context_destroy().

Referenced by AST_TEST_DEFINE().

◆ AST_TEST_DEFINE() [1/8]

AST_TEST_DEFINE ( fir_nominal  )

Definition at line 597 of file test_res_rtp.c.

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}
#define ast_log
Definition: astobj2.c:42
#define ast_frfree(fr)
@ AST_FRAME_CONTROL
@ AST_CONTROL_VIDUPDATE
#define LOG_ERROR
def info(msg)
#define NULL
Definition: resample.c:96
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Definition: rtp_engine.c:457
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
Definition: rtp_engine.c:599
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
Definition: rtp_engine.c:589
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.
enum ast_frame_type frametype
@ TEST_INIT
Definition: test.h:200
@ TEST_EXECUTE
Definition: test.h:201
@ AST_TEST_PASS
Definition: test.h:195
@ AST_TEST_FAIL
Definition: test.h:196
@ AST_TEST_NOT_RUN
Definition: test.h:194
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 ast_sched_context_destroy_wrapper(struct ast_sched_context *sched)
Definition: test_res_rtp.c:49
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
#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

References AST_CONTROL_VIDUPDATE, AST_FRAME_CONTROL, ast_frfree, ast_log, ast_rtp_instance_destroy(), ast_rtp_instance_read(), ast_rtp_instance_write(), ast_sched_context_create(), ast_sched_context_destroy_wrapper(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_frame::frametype, sip_to_pjsip::info(), LOG_ERROR, NULL, RAII_VAR, TEST_EXECUTE, TEST_INIT, test_init_rtp_instances(), TEST_TYPE_NONE, and test_write_and_read_frames().

◆ AST_TEST_DEFINE() [2/8]

AST_TEST_DEFINE ( lost_packet_stats_nominal  )

Definition at line 395 of file test_res_rtp.c.

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}
ast_rtp_instance_stat
Definition: rtp_engine.h:182
@ AST_RTP_INSTANCE_STAT_ALL
Definition: rtp_engine.h:184
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:2459
unsigned int rxploss
Definition: rtp_engine.h:419
static void test_write_frames(struct ast_rtp_instance *instance, int seqno, int num)
Definition: test_res_rtp.c:109

References ast_log, ast_rtp_instance_destroy(), ast_rtp_instance_get_stats(), AST_RTP_INSTANCE_STAT_ALL, ast_sched_context_create(), ast_sched_context_destroy_wrapper(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), ast_rtp_instance_stats::local_maxrxploss, ast_rtp_instance_stats::local_minrxploss, LOG_ERROR, NULL, RAII_VAR, ast_rtp_instance_stats::rxploss, TEST_EXECUTE, TEST_INIT, test_init_rtp_instances(), TEST_TYPE_NONE, test_write_and_read_frames(), and test_write_frames().

◆ AST_TEST_DEFINE() [3/8]

AST_TEST_DEFINE ( mes  )

Definition at line 659 of file test_res_rtp.c.

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}
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
Definition: sched.c:197
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

References ast_log, ast_rtp_instance_destroy(), ast_sched_context_create(), ast_sched_context_destroy_wrapper(), ast_sched_start_thread(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), LOG_ERROR, NULL, RAII_VAR, TEST_EXECUTE, TEST_INIT, test_init_rtp_instances(), TEST_TYPE_NONE, and test_write_and_read_interleaved_frames().

◆ AST_TEST_DEFINE() [4/8]

AST_TEST_DEFINE ( nack_no_packet_loss  )

Definition at line 262 of file test_res_rtp.c.

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}

References ast_log, ast_rtp_instance_destroy(), ast_sched_context_create(), ast_sched_context_destroy_wrapper(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), LOG_ERROR, NULL, RAII_VAR, TEST_EXECUTE, TEST_INIT, test_init_rtp_instances(), TEST_TYPE_NACK, and test_write_and_read_frames().

◆ AST_TEST_DEFINE() [5/8]

AST_TEST_DEFINE ( nack_nominal  )

Definition at line 300 of file test_res_rtp.c.

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}
static void test_read_frames(struct ast_rtp_instance *instance, int num)
Definition: test_res_rtp.c:128

References ast_log, ast_rtp_instance_destroy(), ast_sched_context_create(), ast_sched_context_destroy_wrapper(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), LOG_ERROR, NULL, RAII_VAR, TEST_EXECUTE, TEST_INIT, test_init_rtp_instances(), test_read_frames(), TEST_TYPE_NACK, and test_write_and_read_frames().

◆ AST_TEST_DEFINE() [6/8]

AST_TEST_DEFINE ( nack_overflow  )

Definition at line 349 of file test_res_rtp.c.

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}

References ast_log, ast_rtp_instance_destroy(), ast_sched_context_create(), ast_sched_context_destroy_wrapper(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), LOG_ERROR, NULL, RAII_VAR, TEST_EXECUTE, TEST_INIT, test_init_rtp_instances(), TEST_TYPE_NACK, and test_write_and_read_frames().

◆ AST_TEST_DEFINE() [7/8]

AST_TEST_DEFINE ( remb_nominal  )

Definition at line 475 of file test_res_rtp.c.

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}
@ AST_FRAME_RTCP
#define AST_RTP_RTCP_PSFB
Definition: rtp_engine.h:324
#define AST_RTP_RTCP_FMT_REMB
Definition: rtp_engine.h:334
An object that represents data received in a feedback report.
Definition: rtp_engine.h:383
unsigned int fmt
Definition: rtp_engine.h:384
struct ast_rtp_rtcp_feedback_remb remb
Definition: rtp_engine.h:386

References AST_FRAME_RTCP, ast_frfree, ast_log, ast_rtp_instance_destroy(), ast_rtp_instance_read(), ast_rtp_instance_write(), AST_RTP_RTCP_FMT_REMB, AST_RTP_RTCP_PSFB, ast_sched_context_create(), ast_sched_context_destroy_wrapper(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, ast_rtp_rtcp_feedback_remb::br_exp, ast_rtp_rtcp_feedback_remb::br_mantissa, ast_rtp_rtcp_feedback::fmt, ast_frame::frametype, sip_to_pjsip::info(), LOG_ERROR, NULL, RAII_VAR, ast_rtp_rtcp_feedback::remb, TEST_EXECUTE, TEST_INIT, test_init_rtp_instances(), and TEST_TYPE_REMB.

◆ AST_TEST_DEFINE() [8/8]

AST_TEST_DEFINE ( sr_rr_nominal  )

Definition at line 539 of file test_res_rtp.c.

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}
#define AST_RTP_RTCP_SR
Definition: rtp_engine.h:318
#define AST_RTP_RTCP_RR
Definition: rtp_engine.h:320

References AST_FRAME_RTCP, ast_frfree, ast_log, ast_rtp_instance_destroy(), ast_rtp_instance_read(), AST_RTP_RTCP_RR, AST_RTP_RTCP_SR, ast_sched_context_create(), ast_sched_context_destroy_wrapper(), AST_TEST_FAIL, AST_TEST_NOT_RUN, AST_TEST_PASS, sip_to_pjsip::info(), LOG_ERROR, NULL, RAII_VAR, TEST_EXECUTE, TEST_INIT, test_init_rtp_instances(), TEST_TYPE_NONE, test_write_and_read_frames(), and test_write_frames().

◆ load_module()

static int load_module ( void  )
static

Definition at line 706 of file test_res_rtp.c.

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}
@ AST_MODULE_LOAD_SUCCESS
Definition: module.h:70
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

References AST_MODULE_LOAD_SUCCESS, and AST_TEST_REGISTER.

◆ SLEEP_SPINNER()

static void SLEEP_SPINNER ( int  ms)
static

Definition at line 155 of file test_res_rtp.c.

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}
static struct test_val a
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:2281
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159

References a, ast_remaining_ms(), and ast_tvnow().

Referenced by test_write_and_read_interleaved_frames().

◆ test_init_rtp_instances()

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 
)
static

Definition at line 56 of file test_res_rtp.c.

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}
static const char type[]
Definition: chan_ooh323.c:109
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
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:486
ast_rtp_instance_rtcp
Definition: rtp_engine.h:280
@ AST_RTP_INSTANCE_RTCP_MUX
Definition: rtp_engine.h:286
@ AST_RTP_INSTANCE_RTCP_STANDARD
Definition: rtp_engine.h:284
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:726
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:664
#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:1126
@ AST_RTP_PROPERTY_RETRANS_RECV
Definition: rtp_engine.h:127
@ AST_RTP_PROPERTY_RETRANS_SEND
Definition: rtp_engine.h:129
@ AST_RTP_PROPERTY_RTCP
Definition: rtp_engine.h:123
@ AST_RTP_PROPERTY_REMB
Definition: rtp_engine.h:131
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:2684
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:574
Socket address structure.
Definition: netsock2.h:97

References ast_rtp_instance_activate(), ast_rtp_instance_get_local_address(), ast_rtp_instance_new(), AST_RTP_INSTANCE_RTCP_MUX, AST_RTP_INSTANCE_RTCP_STANDARD, ast_rtp_instance_set_channel_id(), ast_rtp_instance_set_prop(), ast_rtp_instance_set_remote_address, AST_RTP_PROPERTY_REMB, AST_RTP_PROPERTY_RETRANS_RECV, AST_RTP_PROPERTY_RETRANS_SEND, AST_RTP_PROPERTY_RTCP, ast_sockaddr_parse(), TEST_TYPE_NACK, TEST_TYPE_REMB, TEST_TYPE_STD_RTCP, and type.

Referenced by AST_TEST_DEFINE().

◆ test_read_frames()

static void test_read_frames ( struct ast_rtp_instance instance,
int  num 
)
static

Definition at line 128 of file test_res_rtp.c.

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}

References ast_frfree, and ast_rtp_instance_read().

Referenced by AST_TEST_DEFINE(), and test_write_and_read_frames().

◆ test_write_and_read_frames()

static void test_write_and_read_frames ( struct ast_rtp_instance instance1,
struct ast_rtp_instance instance2,
int  seqno,
int  num 
)
static

Definition at line 141 of file test_res_rtp.c.

143{
144 test_write_frames(instance1, seqno, num);
145 test_read_frames(instance2, num);
146}

References ast_frame::seqno, test_read_frames(), and test_write_frames().

Referenced by AST_TEST_DEFINE().

◆ test_write_and_read_interleaved_frames()

static void test_write_and_read_interleaved_frames ( struct ast_rtp_instance instance1,
struct ast_rtp_instance instance2,
int  howlong,
int  rtcp_interval 
)
static

Definition at line 171 of file test_res_rtp.c.

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}
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
@ AST_FRAME_VOICE
union ast_frame::@226 data
struct timeval delivery
static void SLEEP_SPINNER(int ms)
Definition: test_res_rtp.c:155
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
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define ast_set_flag(p, flag)
Definition: utils.h:70

References ast_clear_flag, ast_format_ulaw, AST_FRAME_VOICE, AST_FRFLAG_HAS_SEQUENCE_NUMBER, AST_FRFLAG_HAS_TIMING_INFO, ast_frfree, ast_rtp_instance_read(), ast_rtp_instance_write(), ast_set_flag, ast_tvdiff_ms(), ast_tvnow(), ast_frame::data, ast_frame::delivery, ast_frame::frametype, ast_frame::len, ast_frame::seqno, SLEEP_SPINNER(), and ast_frame::ts.

Referenced by AST_TEST_DEFINE().

◆ test_write_frames()

static void test_write_frames ( struct ast_rtp_instance instance,
int  seqno,
int  num 
)
static

Definition at line 109 of file test_res_rtp.c.

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}

References ast_format_ulaw, AST_FRAME_VOICE, AST_FRFLAG_HAS_SEQUENCE_NUMBER, ast_rtp_instance_write(), ast_set_flag, ast_frame::data, ast_frame::frametype, and ast_frame::seqno.

Referenced by AST_TEST_DEFINE(), and test_write_and_read_frames().

◆ unload_module()

static int unload_module ( void  )
static

Definition at line 693 of file test_res_rtp.c.

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}
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

References AST_TEST_UNREGISTER.

Variable Documentation

◆ __mod_info

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "RTP/RTCP test module" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, .support_level = AST_MODULE_SUPPORT_CORE, }
static

Definition at line 719 of file test_res_rtp.c.

◆ ast_module_info

const struct ast_module_info* ast_module_info = &__mod_info
static

Definition at line 719 of file test_res_rtp.c.