69 if (!instance1 || !instance2) {
76 if (type == TEST_TYPE_STD_RTCP) {
85 if (type == TEST_TYPE_NACK) {
90 }
else if (type == TEST_TYPE_REMB) {
101 ast_rtp_instance_reset_test_engine(*instance1);
109 static void test_write_frames(
struct ast_rtp_instance *instance,
int seqno,
int num)
122 for (index = 0; index < num; index++) {
123 frame_out.
seqno = seqno + index;
133 for (index = 0; index < num; index++) {
136 ast_frfree(frame_in);
144 test_write_frames(instance1, seqno, num);
145 test_read_frames(instance2, num);
155 static void SLEEP_SPINNER(
int ms)
171 static void test_write_and_read_interleaved_frames(
struct ast_rtp_instance *instance1,
175 int pktinterval = 20;
205 num = howlong / pktinterval;
207 rtcpnum = rtcp_interval / pktinterval;
214 for (index = 0; index < num; index++) {
224 frame_out1.
seqno += index;
226 frame_out1.
ts += frame_out1.
len;
229 if (send_rtcp && index && (index % rtcpnum == 0)) {
230 ast_rtp_instance_queue_report(instance1);
234 ast_frfree(frame_in2);
236 ast_frfree(frame_in2);
239 frame_out2.
seqno += index;
241 frame_out2.
ts += frame_out2.
len;
244 if (send_rtcp && index && (index % rtcpnum == 0)) {
245 ast_rtp_instance_queue_report(instance2);
249 ast_frfree(frame_in1);
251 ast_frfree(frame_in1);
256 ms += (index % 2 ? 5 : 12);
257 ms += (index % 3 ? 2 : 30);
270 info->name =
"nack_no_packet_loss";
271 info->category =
"/res/res_rtp/";
272 info->summary =
"nack no packet loss unit test";
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;
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;
289 test_write_and_read_frames(instance1, instance2, 1000, 10);
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");
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");
297 return AST_TEST_PASS;
308 info->name =
"nack_nominal";
309 info->category =
"/res/res_rtp/";
310 info->summary =
"nack nominal unit test";
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;
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;
328 test_write_and_read_frames(instance1, instance2, 1000, 10);
331 ast_rtp_instance_drop_packets(instance2, 10);
332 test_write_and_read_frames(instance1, instance2, 1010, 10);
335 test_write_and_read_frames(instance1, instance2, 1020, ast_rtp_instance_get_recv_buffer_max(instance2) / 2);
338 test_read_frames(instance1, 1);
341 test_read_frames(instance2, 10);
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");
346 return AST_TEST_PASS;
358 info->name =
"nack_overflow";
359 info->category =
"/res/res_rtp/";
360 info->summary =
"nack overflow unit test";
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;
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;
377 test_write_and_read_frames(instance1, instance2, 1000, 10);
380 max_packets = ast_rtp_instance_get_recv_buffer_max(instance2);
381 test_write_and_read_frames(instance1, instance2, 1020, max_packets);
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");
387 test_write_and_read_frames(instance1, instance2, 1020 + max_packets, 1);
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");
392 return AST_TEST_PASS;
405 info->name =
"lost_packet_stats_nominal";
406 info->category =
"/res/res_rtp/";
407 info->summary =
"lost packet stats nominal unit test";
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;
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;
424 test_write_and_read_frames(instance1, instance2, 1000, 10);
427 test_write_and_read_frames(instance1, instance2, 1015, 5);
430 ast_rtp_instance_queue_report(instance1);
431 test_write_frames(instance2, 1000, 1);
439 test_write_and_read_frames(instance1, instance2, 1023, 5);
441 ast_rtp_instance_queue_report(instance1);
442 test_write_frames(instance2, 1001, 1);
450 test_write_and_read_frames(instance1, instance2, 1028, 5);
452 ast_rtp_instance_queue_report(instance1);
453 test_write_frames(instance2, 1002, 1);
461 test_write_and_read_frames(instance1, instance2, 1034, 5);
462 test_write_and_read_frames(instance1, instance2, 1047, 5);
464 ast_rtp_instance_queue_report(instance1);
465 test_write_frames(instance2, 1003, 1);
472 return AST_TEST_PASS;
485 .remb.br_mantissa = 1000,
490 .data.ptr = &feedback,
491 .datalen =
sizeof(feedback),
497 info->name =
"remb_nominal";
498 info->category =
"/res/res_rtp/";
499 info->summary =
"remb nominal unit test";
501 "Tests sending and receiving a REMB packet";
502 return AST_TEST_NOT_RUN;
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;
515 ast_rtp_instance_set_schedid(instance1, 0);
521 ast_test_validate(
test, frame_in != NULL,
"Did not receive a REMB frame");
523 "REMB frame did not have the expected frametype");
525 "REMB frame did not have the expected subclass integer");
528 received_feedback = frame_in->
data.ptr;
530 "REMB frame did not have the expected feedback format");
532 "REMB received exponent did not match sent exponent");
534 "REMB received mantissa did not match sent mantissa");
536 return AST_TEST_PASS;
548 info->name =
"sr_rr_nominal";
549 info->category =
"/res/res_rtp/";
550 info->summary =
"SR/RR nominal unit test";
552 "Tests sending SR/RR and receiving it; includes SDES";
553 return AST_TEST_NOT_RUN;
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;
565 test_write_and_read_frames(instance1, instance2, 1000, 10);
571 ast_rtp_instance_queue_report(instance1);
572 test_write_frames(instance1, 1010, 1);
576 "Sender report frame did not have the expected frametype");
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");
582 ast_frfree(frame_in);
585 ast_rtp_instance_queue_report(instance1);
586 test_write_frames(instance1, 1010, 1);
590 "Receiver report frame did not have the expected frametype");
592 "Receiver report frame did not have the expected subclass integer");
594 return AST_TEST_PASS;
610 info->name =
"fir_nominal";
611 info->category =
"/res/res_rtp/";
612 info->summary =
"fir nominal unit test";
614 "Tests sending and receiving a FIR packet";
615 return AST_TEST_NOT_RUN;
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;
628 test_write_and_read_frames(instance2, instance1, 1000, 10);
631 ast_rtp_instance_set_schedid(instance1, 0);
646 ast_test_validate(
test, frame_in != NULL,
"Did not receive a FIR frame");
648 "FIR frame did not have the expected frametype");
650 "FIR frame did not have the expected subclass integer");
652 return AST_TEST_PASS;
668 info->category =
"/res/res_rtp/";
669 info->summary =
"Media Experience Score";
671 "Tests calculation of Media Experience Score (only run by explicit request)";
672 info->explicit_only = 1;
673 return AST_TEST_NOT_RUN;
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;
687 test_write_and_read_interleaved_frames(
688 instance1, instance2, 1000, 5000);
690 return AST_TEST_PASS;
693 static int unload_module(
void)
695 AST_TEST_UNREGISTER(mes);
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);
706 static int load_module(
void)
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);
715 AST_TEST_REGISTER(mes);
int ast_sched_start_thread(struct ast_sched_context *con)
Start a thread for processing scheduler entries.
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...
Asterisk main include file. File version handling, generic pbx functions.
void ast_rtp_instance_set_channel_id(struct ast_rtp_instance *instance, const char *uniqueid)
Set the channel that owns this RTP instance.
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.
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
int ast_rtp_instance_write(struct ast_rtp_instance *instance, struct ast_frame *frame)
Send a frame out over RTP.
An object that represents data received in a feedback report.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
int64_t ast_tvdiff_ms(struct timeval end, struct timeval start)
Computes the difference (in milliseconds) between two struct timeval instances.
struct ast_rtp_rtcp_feedback_remb remb
Socket address structure.
struct ast_frame_subclass subclass
Scheduler Routines (derived from cheops)
struct ast_sched_context * ast_sched_context_create(void)
Create a scheduler context.
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
#define ast_rtp_instance_set_remote_address(instance, address)
Set the address of the remote endpoint that we are sending RTP to.
union ast_frame::@224 data
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.
int ast_rtp_instance_destroy(struct ast_rtp_instance *instance)
Destroy an RTP instance.
Data structure associated with a single frame of data.
#define AST_RTP_RTCP_PSFB
#define AST_TEST_DEFINE(hdr)
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.
enum ast_frame_type frametype
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.
#define ASTERISK_GPL_KEY
The text the key() function should return.
Pluggable RTP Architecture.
Asterisk module definitions.
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
void ast_sched_context_destroy(struct ast_sched_context *c)
destroys a schedule context
struct ast_frame * ast_rtp_instance_read(struct ast_rtp_instance *instance, int rtcp)
Receive a frame over RTP.
#define AST_RTP_RTCP_FMT_REMB