/* PipeWire */ /* SPDX-FileCopyrightText: Copyright © 2026 Carlos Rafael Giani */ /* SPDX-License-Identifier: MIT */ #include #include #include #include #include "config.h" #include #include #include #include "pwtest.h" PW_LOG_TOPIC(mod_topic, "test.rtp-jitter-buffer"); #define PW_LOG_TOPIC_DEFAULT mod_topic enum test_event_type { TEST_EVENT_OUTPUT_PACKET, TEST_EVENT_LOST_PACKETS, }; struct test_event { enum test_event_type type; union { struct { uint16_t seqnum; } output; struct { uint16_t first_seqnum; size_t count; bool open_ended; } lost; }; }; #define MAX_TEST_EVENTS 256 #define MAX_TEST_PACKET_SIZE 2048 #define TEST_PACKET_SIZE 128 #define TEST_HEADER_SIZE 16 #define TEST_TIMESTAMP 123456 #define TEST_PACKET_DURATION (10 * SPA_NSEC_PER_MSEC) struct test_context { struct pw_loop *loop; struct pw_main_loop *main_loop; struct rtp_jitter_buffer jitter_buffer; struct test_event events[MAX_TEST_EVENTS]; size_t num_events; uint8_t packet_bytes[MAX_TEST_PACKET_SIZE]; }; static void send_packet(struct test_context *test_context, uint16_t seqnum) { /* Create a simulated RTP packet. Only write the sequence number * into its header. The rest (SSRC, CSRC, payload type etc.) are * of no interest to the jitter buffer - it only cares about the * sequence number. */ struct rtp_header *header = (struct rtp_header *)(test_context->packet_bytes); header->sequence_number = htons(seqnum); int ret = rtp_jitter_buffer_insert_packet(&(test_context->jitter_buffer), test_context->packet_bytes, (TEST_PACKET_SIZE), (TEST_HEADER_SIZE), (TEST_TIMESTAMP), seqnum); assert(ret == 0); } static int test_output_rtp_packet(void *context, const uint8_t *packet_data, size_t packet_size, size_t header_size, uint32_t timestamp, uint16_t seqnum) { struct test_context *test_context = context; struct rtp_header *header = (struct rtp_header *)packet_data; assert(test_context->num_events < MAX_TEST_EVENTS); /* Check that this function is not simply passed * the value of params.max_packet_size, and that * the other values (header size, timestamp) * are correct as well. */ pwtest_int_eq(packet_size, (size_t)(TEST_PACKET_SIZE)); pwtest_int_eq(header_size, (size_t)(TEST_HEADER_SIZE)); pwtest_int_eq(timestamp, (size_t)(TEST_TIMESTAMP)); /* Compare the seqnum that is given by the caller * with the seqnum in the RTP header to verify that * the packet data is correctly associated with the * information from the function arguments. */ pwtest_int_eq(seqnum, ntohs(header->sequence_number)); test_context->events[test_context->num_events].type = TEST_EVENT_OUTPUT_PACKET; test_context->events[test_context->num_events].output.seqnum = seqnum; pw_log_debug("Output RTP packet with seqnum %" PRIu16, test_context->events[test_context->num_events].output.seqnum); test_context->num_events++; return 0; } static int test_signal_lost_packets(void *context, uint16_t seq_of_first_lost_packet, size_t num_lost_packets, bool open_ended) { struct test_context *test_context = context; assert(test_context->num_events < MAX_TEST_EVENTS); test_context->events[test_context->num_events].type = TEST_EVENT_LOST_PACKETS; test_context->events[test_context->num_events].lost.first_seqnum = seq_of_first_lost_packet; test_context->events[test_context->num_events].lost.count = num_lost_packets; test_context->events[test_context->num_events].lost.open_ended = open_ended; test_context->num_events++; return 0; } static void setup_test_context(struct test_context *test_context, size_t num_slots) { struct rtp_jitter_buffer_params params; assert(test_context != NULL); spa_memzero(test_context, sizeof(struct test_context)); pw_init(0, NULL); test_context->main_loop = pw_main_loop_new(NULL); assert(test_context->main_loop != NULL); test_context->loop = pw_main_loop_get_loop(test_context->main_loop); memset(¶ms, 0, sizeof(params)); params.num_slots = num_slots; /* Set the maximum packet size to a value higher than TEST_PACKET_SIZE * to be able to check in test_output_rtp_packet() that that function * does not simply get the max_packet_size value as the packet size, * but the _actual_ packet size. (Also see test_output_rtp_packet().) */ params.max_packet_size = MAX_TEST_PACKET_SIZE; params.packet_duration = TEST_PACKET_DURATION; params.loop = test_context->loop; params.context = test_context; params.output_rtp_packet = test_output_rtp_packet; params.signal_lost_packets = test_signal_lost_packets; int ret = rtp_jitter_buffer_init(&(test_context->jitter_buffer), ¶ms); assert(ret == 0); } static void teardown_test_context(struct test_context *test_context) { assert(test_context != NULL); rtp_jitter_buffer_shutdown(&(test_context->jitter_buffer)); if (test_context->main_loop != NULL) pw_main_loop_destroy(test_context->main_loop); pw_deinit(); } #define SHIFT_TEST_EVENTS() \ do { \ memmove( \ &(test_context.events[0]), \ &(test_context.events[1]), \ (test_context.num_events - 1) * sizeof(struct test_event)); \ test_context.num_events--; \ } while (0) #define CHECK_LOST_PACKET_EVENT(FIRST_SEQNUM, COUNT, OPEN_ENDED) \ do { \ pwtest_int_ge(test_context.num_events, 1u); \ pwtest_int_eq((int)(test_context.events[0].type), TEST_EVENT_LOST_PACKETS); \ pwtest_int_eq(test_context.events[0].lost.first_seqnum, (FIRST_SEQNUM)); \ pwtest_int_eq(test_context.events[0].lost.count, (size_t)(COUNT)); \ pwtest_int_eq(test_context.events[0].lost.open_ended, (OPEN_ENDED)); \ SHIFT_TEST_EVENTS(); \ } while (0) #define CHECK_OUTPUT_PACKET_EVENT(SEQNUM) \ do { \ pwtest_int_ge(test_context.num_events, 1u); \ pwtest_int_eq((int)(test_context.events[0].type), TEST_EVENT_OUTPUT_PACKET); \ pwtest_int_eq(test_context.events[0].output.seqnum, (SEQNUM)); \ SHIFT_TEST_EVENTS(); \ } while (0) PWTEST(rtp_jitter_buffer_test_consecutive_packets) { /* Simple test with packets that are passed to the jitter buffer * in order, with no gaps. Immediate output is expected, since * the jitter buffer will be in regular mode. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Send packets 100, 101, 102, 103, 104 in order. * All 5 should be immediately output, and the * hold-back mode should remain disabled. */ for (uint16_t i = 0; i < 5; i++) { uint16_t seqnum = 100 + i; send_packet(&test_context, seqnum); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); } pwtest_int_eq(test_context.num_events, 5u); for (uint16_t i = 0; i < 5; i++) { uint16_t seqnum = 100 + i; CHECK_OUTPUT_PACKET_EVENT(seqnum); } teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_simple_reordering) { /* Check that simple out-of-order packet arrival is handled properly. * There should be no gaps signaled, and the packets should be output * in order. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Send 100, 101 in order. */ send_packet(&test_context, 100); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 101); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_OUTPUT_PACKET_EVENT(100); CHECK_OUTPUT_PACKET_EVENT(101); /* Send 103. A gap at 102 is produced -> jitter buffer enables hold-back mode. * No output takes place just yet, since 103 is held back. * The valid seqnum window starts at 102 and ends at packet 103. */ send_packet(&test_context, 103); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_start_seqnum, 102u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_length, 2u); pwtest_int_eq(test_context.num_events, 0u); /* Send 102 to simulate out-of-order arrival. This fills the gap * at 102 (implying that it is not signaled), and should cause * 102 and 103 to be output (in order) and the hold-back mode * to be disabled again. */ send_packet(&test_context, 102); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_OUTPUT_PACKET_EVENT(102); CHECK_OUTPUT_PACKET_EVENT(103); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_partial_output) { /* Test that partial output is done correctly when some * gaps are filled. (Partial means that only part of the * held-back packets are output.) */ struct test_context test_context; setup_test_context(&test_context, 10); /* Establish regular mode with packet 400. */ send_packet(&test_context, 400); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(400); /* Send in packet 402 to produce a gap at 401 and cause the * jitter buffer to enter hold-back mode. */ send_packet(&test_context, 402); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_start_seqnum, 401u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_length, 2u); pwtest_int_eq(test_context.num_events, 0u); /* Send in packets 404 and 405. This keeps the gap at 401, adds * a gap at 403, and keeps the jitter buffer in hold-back mode. */ send_packet(&test_context, 404); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 405); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); /* Send in packet 401, which fills the gap at 401. This allows * the jitter buffer to output packets 401 and 402. But since * another gap exists at 403, hold-back mode remains enabled. */ send_packet(&test_context, 401); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_OUTPUT_PACKET_EVENT(401); CHECK_OUTPUT_PACKET_EVENT(402); /* Send in packet 403, which fills the gap at 403. This allows * the jitter buffer to output packets 403, 404, 405. Those were * the remaining held-back packets, so hold-back mode should be * turned off now. */ send_packet(&test_context, 403); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 3u); CHECK_OUTPUT_PACKET_EVENT(403); CHECK_OUTPUT_PACKET_EVENT(404); CHECK_OUTPUT_PACKET_EVENT(405); /* Verify that regular mode is working properly by sending * in packet 406. */ send_packet(&test_context, 406); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(406); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_explicit_drain_in_regular_mode) { /* Test what happens when explicitly draining the jitter buffer * while in regular mode. Draining should be a no-op in this mode. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Establish regular mode with packets 200 and 201. */ send_packet(&test_context, 200); send_packet(&test_context, 201); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_OUTPUT_PACKET_EVENT(200); CHECK_OUTPUT_PACKET_EVENT(201); /* Drain, and then check the outcome. Check that it was a no-op. */ int ret = rtp_jitter_buffer_drain(&(test_context.jitter_buffer)); assert(ret == 0); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); pwtest_int_eq(test_context.jitter_buffer.last_seqnum, 201); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_explicit_drain_in_hold_back_mode) { /* Test what happens when explicitly draining the jitter buffer * while in hold-back mode. Missing packets should be signaled * as lost packets by this. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Establish regular mode with packet 200. */ send_packet(&test_context, 200); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(200); /* Send in packets 202 and 205 to produce gap at 201, 203, 204 * and cause the jitter buffer to enter hold-back mode. */ send_packet(&test_context, 202); send_packet(&test_context, 205); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); /* Drain explicitly. This should output the following (in this order): * * - 1 lost packet, starting at seqnum 201, not open-ended * - 1 packet output with seqnum 202 * - 2 lost packets, starting at seqnum 203, not open-ended * - 1 packet output with seqnum 205 * * This should also set the jitter buffer back to regular mode. * The last_seqnum should be -1, since after explicit drain, * the jitter buffer has no idea what packets will come next.*/ int ret = rtp_jitter_buffer_drain(&(test_context.jitter_buffer)); assert(ret == 0); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 4u); pwtest_int_eq(test_context.jitter_buffer.last_seqnum, -1); CHECK_LOST_PACKET_EVENT(201, 1u, false); CHECK_OUTPUT_PACKET_EVENT(202); CHECK_LOST_PACKET_EVENT(203, 2u, false); CHECK_OUTPUT_PACKET_EVENT(205); /* Verify that regular mode is working properly by sending * in packet 700. Since after draining, the last_seqnum is * -1, a discontinuity in the sequence numbers is okay. */ send_packet(&test_context, 700); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(700); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_explicit_drain_coalesced_loss) { /* Test that a contiguous set of lost packets is coalesced * into one signal lost packet signal. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Establish regular mode with packet 50. */ send_packet(&test_context, 50); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(50); /* Send in packet 54 to produce gap at 51, 52, 53 and * cause the jitter buffer to enter hold-back mode. */ send_packet(&test_context, 54); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); /* Drain the jitter buffer. The packets 51, 52, 53 are * now considered lost, and should be reported as such. */ int ret = rtp_jitter_buffer_drain(&(test_context.jitter_buffer)); assert(ret == 0); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); pwtest_int_eq(test_context.jitter_buffer.last_seqnum, -1); CHECK_LOST_PACKET_EVENT(51, 3u, false); CHECK_OUTPUT_PACKET_EVENT(54); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_explicit_drain_with_seqnum_wraparound) { /* Test what happens when explicitly draining the jitter * buffer while in hold-back mode and with sequence numbers * wrapping around. Missing packets should be signaled as * lost packets by this. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Establish regular mode with packet 65533. */ send_packet(&test_context, 65533); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(65533); /* Send in packets 65535 and 2 to produce gap at 65534, 0, 1 * and cause the jitter buffer to enter hold-back mode. */ send_packet(&test_context, 65535); send_packet(&test_context, 2); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); /* Drain explicitly. This should output the following (in this order): * * - 1 lost packet, starting at seqnum 65534, not open-ended * - 1 packet output with seqnum 65535 * - 2 lost packets, starting at seqnum 0, not open-ended * - 1 packet output with seqnum 2 * * This should also set the jitter buffer back to regular mode. * The last_seqnum should be -1, since after explicit drain, * the jitter buffer has no idea what packets will come next.*/ int ret = rtp_jitter_buffer_drain(&(test_context.jitter_buffer)); assert(ret == 0); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 4u); pwtest_int_eq(test_context.jitter_buffer.last_seqnum, -1); CHECK_LOST_PACKET_EVENT(65534, 1u, false); CHECK_OUTPUT_PACKET_EVENT(65535); CHECK_LOST_PACKET_EVENT(0, 2u, false); CHECK_OUTPUT_PACKET_EVENT(2); /* Verify that regular mode is working properly by sending * in packet 700. Since after draining, the last_seqnum is * -1, a discontinuity in the sequence numbers is okay. */ send_packet(&test_context, 700); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(700); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_stale_packets_in_regular_mode) { /* Test what happens when stale and old packets are sent into * the jitter buffer in regular mode. They should be dropped * without influencing the behavior of the jitter buffer. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Establish regular mode with packets 100 and 101. */ send_packet(&test_context, 100); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 101); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_OUTPUT_PACKET_EVENT(100); CHECK_OUTPUT_PACKET_EVENT(101); /* Send in packet 101. Since a packet 101 was already seen, * this is a stale packet, and needs to be dropped. */ send_packet(&test_context, 101); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); /* Send in packet 99. Since packets 100 and 101 were already seen, * this is an old packet, and needs to be dropped. */ send_packet(&test_context, 99); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); /* Verify that regular mode is working properly by sending * in packet 102. */ send_packet(&test_context, 102); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(102); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_stale_packets_in_hold_back_mode) { /* Test what happens when stale and old packets are sent into * the jitter buffer in hold-back mode. They should be dropped * without influencing the behavior of the jitter buffer. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Establish hold-back mode with packets 300 and 302. * Hold-back mode gets active because of the gap at 301. */ send_packet(&test_context, 300); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 302); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(300); /* Send in packet 299. Since packets 300 and 302 were already seen, * this is an old packet, and needs to be dropped. */ send_packet(&test_context, 299); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); /* Send in packet 300. Since a packet 300 was already seen, * this is a stale packet, and needs to be dropped. */ send_packet(&test_context, 300); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); /* Send in packet 302. This is another stale packet. The * difference to the packet 300 check above is that the * packet 302 that was previously observed is held back, * and was not output thus far. */ send_packet(&test_context, 302); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); /* Send in packet 301 to test that switching back * to regular mode still works properly. */ send_packet(&test_context, 301); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_OUTPUT_PACKET_EVENT(301); CHECK_OUTPUT_PACKET_EVENT(302); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_flush) { /* Test the flush functionality. This should discard any held-back * packets, without emitting them, and the jitter buffer should * be back in regular mode afterwards. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Establish hold-back mode with packets 500 and 502. * Hold-back mode gets active because of the gap at 501. */ send_packet(&test_context, 500); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 502); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(500); rtp_jitter_buffer_flush(&(test_context.jitter_buffer)); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); pwtest_int_eq(test_context.jitter_buffer.last_seqnum, -1); /* Verify that regular mode is working properly by sending * in packet 700. Since after flushing, the last_seqnum is * -1, a discontinuity in the sequence numbers is okay. */ send_packet(&test_context, 700); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(700); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_seqnum_wraparound_regular) { /* Check that in regular mode, output of in-sequence packets * works properly even when a sequence number wrap-around occurs. */ struct test_context test_context; setup_test_context(&test_context, 10); send_packet(&test_context, 65534); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 65535); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 0); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 1); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 4u); CHECK_OUTPUT_PACKET_EVENT(65534); CHECK_OUTPUT_PACKET_EVENT(65535); CHECK_OUTPUT_PACKET_EVENT(0); CHECK_OUTPUT_PACKET_EVENT(1); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_seqnum_wraparound_with_reordering) { /* Check that in hold-back mode, output of in-sequence packets * works properly even when a sequence number wrap-around occurs. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Send packets 65534 and 65535 in order. */ send_packet(&test_context, 65534); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 65535); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_OUTPUT_PACKET_EVENT(65534); CHECK_OUTPUT_PACKET_EVENT(65535); /* Send in packet 1, causing a gap at 0. */ send_packet(&test_context, 1); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 0u); /* Fill the gap by sending in packet 0, then check that * packets 0 and 1 were now output in order. */ send_packet(&test_context, 0); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_OUTPUT_PACKET_EVENT(0); CHECK_OUTPUT_PACKET_EVENT(1); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_overextension_single_gap_no_end_gap) { /* Check what happens when hold-back mode is active, the * valid seqnum window's maximum length is reached, and then, * a packet with a sequence number that is one past the window * range is added. This new packet would overextend the window, * so the window is shifted forwards. However, it is only * overextended by 1, so only the oldest slot in the window * needs to be drained. In this case, that oldest slot contains * the gap at the very beginning of the window. Also, since * aside from that gap, there are no other ones, and the new * packet (the one that overextends the window) comes directly * after the last packet in the valid seqnum window, the * jitter buffer will have no gaps left to take care of, so * all held back packets can be output. * * This simulates cases where one packet is lost among * a string of packets that all arrive in order. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Produce a sequence of packets with a gap in them. Start at 100, * skip 101, then go all the way to 110. * * First, packet 100 will immediately be output. Then, packet 102 * will enable hold-back mode (due to the gap at 101). The valid * seqnum window then starts at 101, and extends all the way to 110. * 110-101+1 = 10, which equals the max num packets of the jitter * buffer here. In other words, after this, the jitter buffer valid * range is as large as it can maximally be. */ send_packet(&test_context, 100); for (uint16_t i = 102; i <= 110; i++) { send_packet(&test_context, i); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); } pwtest_int_eq(test_context.num_events, 1u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_length, 10u); CHECK_OUTPUT_PACKET_EVENT(100); /* Now insert packet 111. This would overextend the window, so the * jitter buffer has to shift the window and drain the oldest slots * that are no longer part of the shifted window. Since packet 111 * would overextend the window by 1, it means that the one oldest * slot is drained. That oldest slot actually is the gap at 101. * Since that gap was drained (resulting in a packet loss signal * at seqnum 101 of length 1), only packets remain in the valid * seqnum window, no gaps anymore, so the jitter buffer immediately * outputs all of them, in order. */ send_packet(&test_context, 111); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 11u); CHECK_LOST_PACKET_EVENT(101, 1u, false); for (uint16_t i = 102; i <= 111; i++) CHECK_OUTPUT_PACKET_EVENT(i); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_overextension_multiple_gaps_no_end_gap) { /* Check what happens when hold-back mode is active, the * valid seqnum window's maximum length is reached, and then, * a packet with a sequence number that is one past the window * range is added. This new packet would overextend the window, * so the window is shifted forwards. However, it is only * overextended by 1, so only the oldest slot in the window * needs to be drained. In this case, that oldest slot contains * the gap at the very beginning of the window. Since there * are more gaps present, the hold-back mode is not left. * * This simulates cases where more than one packet is lost * among a string of packets that all arrive in order. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Produce a sequence of packets with a gap in them. Start at 100, * skip 101 and 102, and go all the way to 110. * * In the hold-back mode that results from this, the valid range * then starts at 101, and extends all the way to 110. 110-101+1 = 10, * which equals the max num packets of the jitter buffer here. In * other words, after this, the jitter buffer valid range is as large * as it can maximally be. */ send_packet(&test_context, 100); send_packet(&test_context, 103); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); for (uint16_t i = 105; i <= 110; i++) { send_packet(&test_context, i); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); } pwtest_int_eq(test_context.num_events, 1u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_length, 10u); CHECK_OUTPUT_PACKET_EVENT(100); /* Now insert packet 111. This would overextend the window, so the * jitter buffer has to shift the window and drain the oldest slots * that are no longer part of the shifted window. Since packet 111 * would overextend the window by 1, it means that the one oldest * slot is drained. But, at 102, there is also gap, and 102 is now * the new start of the valid seqnum window, so the jitter buffer * cannot output any packets yet. */ send_packet(&test_context, 111); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_start_seqnum, 102u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_length, 10u); CHECK_LOST_PACKET_EVENT(101, 1u, false); /* To see that the behavior remains as expected, fill the gap at 102. * Since 102 is the very beginning of the valid seqnum window, and there * is a packet at 103, the jitter buffer can now output 102 and 103. * Also, the valid seqnum window shrinks accordingly by 2, its length * becoming 8 and its start seqnum becoming 104. */ send_packet(&test_context, 102); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_start_seqnum, 104u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_length, 8u); CHECK_OUTPUT_PACKET_EVENT(102); CHECK_OUTPUT_PACKET_EVENT(103); /* Finally, send in packet 104. By now, 104 is the start of the valid * packet window, and a gap is there. Since this is the last gap in * the jitter buffer, once it is filled, all packets can be output. */ send_packet(&test_context, 104); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 8u); for (uint16_t i = 104; i <= 111; i++) CHECK_OUTPUT_PACKET_EVENT(i); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_overextension_after_partial_output) { /* Check what happens when first, in hold-back mode, a partial * drain happens, and then, the valid seqnum window is overextended. */ struct test_context test_context; setup_test_context(&test_context, 5); /* Add a packet 100, which is output immediately, since the * jitter buffer is in regular mode. */ send_packet(&test_context, 100); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(100); /* Now add packet 102. Since there is a gap at 101, hold-back * mode is enabled. The valid seqnum window starts at 101, * and is of length 2. */ send_packet(&test_context, 102); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_start_seqnum, 101u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_length, 2u); pwtest_int_eq(test_context.num_events, 0u); /* Packets 103 to 105 are inserted. This fills the window to * capacity, since now, it has been extended, and goes from * 101 to 105. That is, it starts at 101, and is of length 5 * which equals the jitter buffer capacity). */ send_packet(&test_context, 103); send_packet(&test_context, 104); send_packet(&test_context, 105); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_start_seqnum, 101u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_length, 5u); pwtest_int_eq(test_context.num_events, 0u); /* Now add packet 101. This fills the gap. All 5 packets * can be output, and the jitter buffer returns to the regular mode. */ send_packet(&test_context, 101); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 5u); CHECK_OUTPUT_PACKET_EVENT(101); CHECK_OUTPUT_PACKET_EVENT(102); CHECK_OUTPUT_PACKET_EVENT(103); CHECK_OUTPUT_PACKET_EVENT(104); CHECK_OUTPUT_PACKET_EVENT(105); /* Re-enter the hold-back mode by adding packet 107 and * intentionally leaving out packet 106. The valid seqnum * window now starts at 106, and is of length 2. */ send_packet(&test_context, 107); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_start_seqnum, 106u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_length, 2u); pwtest_int_eq(test_context.num_events, 0u); /* Packets 108 to 110 are inserted. This fills the window to * capacity, since now, it has been extended, and goes from * 106 to 110. That is, it starts at 106, and is of length 5 * which equals the jitter buffer capacity). */ send_packet(&test_context, 108); send_packet(&test_context, 109); send_packet(&test_context, 110); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_start_seqnum, 106u); pwtest_int_eq(test_context.jitter_buffer.valid_seqnum_window_length, 5u); pwtest_int_eq(test_context.num_events, 0u); /* Packet 111 is added. This overextends the window, since it would * now go from 106 to 111. That is a length of 111-106+1 = 6, which * is beyond the capacity (5). * * The overextension is still low enough that most of the window * contents can be reused. In fact, only the oldest slot (the one * containing the gap at 106) needs to be drained by signaling it * as a packet 106 loss. * * Once packet 106 is signaled as lost, and the corresponding slot * is drained, the leftovers are all packets, no gaps, so all packets * from 107 to 111 are output. * * By combining this with multiple partial drains above, it is verified * that valid_seqnum_window_start_seqnum updates (which happen during * partial drains) do not break the overextension handling. */ send_packet(&test_context, 111); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 6u); CHECK_LOST_PACKET_EVENT(106, 1u, false); CHECK_OUTPUT_PACKET_EVENT(107); CHECK_OUTPUT_PACKET_EVENT(108); CHECK_OUTPUT_PACKET_EVENT(109); CHECK_OUTPUT_PACKET_EVENT(110); CHECK_OUTPUT_PACKET_EVENT(111); /* Verify regular mode recovery. */ send_packet(&test_context, 112); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(112); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_immediate_overextension_after_regular_mode) { /* Check what happens when a gap causes the jitter buffer to switch * to the hold-back mode, but that gap is so large that it immediately * overextends the valid seqnum window. The jitter buffer should * instantly recognize the immediate overextension aqnd signal an open * ended packet loss event. It does not stay in the hold-back mode, * since there is nothing to hold back in that case. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Send 100, 101 in order. */ send_packet(&test_context, 100); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 101); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_OUTPUT_PACKET_EVENT(100); CHECK_OUTPUT_PACKET_EVENT(101); /* Send 200. A massive gap of far more than 10 packets is produced * -> jitter buffer signals an open ended gap, but stays in regular mode. */ send_packet(&test_context, 200); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_LOST_PACKET_EVENT(102, 10u, true); CHECK_OUTPUT_PACKET_EVENT(200); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_immediate_overextension_after_regular_mode_threshold_open_closed_gap) { /* This is similar to rtp_jitter_buffer_test_immediate_overextension_after_regular_mode, * but checks for a corner case. That is: If the gap length equals * the number of slots, then the gap should not be reported as open. * * Test this by producing such a gap. Then further verify by repeating * the test, but by a gap that is 1 packet larger than the number of * slots. The first round should report a closed gap of a size equal * to the number of slot. The second round should report an open gap. */ /* First round. */ { struct test_context test_context; setup_test_context(&test_context, 10); /* Send 10, 11 in order. */ send_packet(&test_context, 10); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 11); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_OUTPUT_PACKET_EVENT(10); CHECK_OUTPUT_PACKET_EVENT(11); /* Send 22. A gap of exactly 10 packets (= the number of slots) * is produced -> jitter buffer signals a closed gap of size * equal to the number of slots. */ send_packet(&test_context, 22); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_LOST_PACKET_EVENT(12, 10u, false); CHECK_OUTPUT_PACKET_EVENT(22); teardown_test_context(&test_context); } /* Second round. */ { struct test_context test_context; setup_test_context(&test_context, 10); /* Send 10, 11 in order. */ send_packet(&test_context, 10); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 11); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_OUTPUT_PACKET_EVENT(10); CHECK_OUTPUT_PACKET_EVENT(11); /* Send 23. A gap of exactly 11 packets (= 1 past the number * of slots) is produced -> jitter buffer signals an open * ended gap of size equal to the number of slots. */ send_packet(&test_context, 23); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); CHECK_LOST_PACKET_EVENT(12, 10u, true); CHECK_OUTPUT_PACKET_EVENT(23); teardown_test_context(&test_context); } return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_full_window_invalidation_non_open_ended_gap) { /* Check what happens when hold-back mode is active, the * valid seqnum window's maximum length is reached, and then, * a packet with a sequence number that is far enough to * overextend the window past its current length. This means * that the shifting method (verified in earlier tests above) * won't work - the window is shifted completely past its * current range, so none of those slots remain valid, * and must all be drained. Furthermore, it means that between * the last seqnum of the old window and the first seqnum of * the new window, there is a gap. The jitter buffer is expected * to do the following: * * 1. Drain the entire current valid seqnum window * 2. Reset the window to only contain the seqnum of the new packet * 3. Signal the gap between the old and the new window * * Here, the window is shifted far enough that none of the * original content can be retained, but not so far that * the gap between the old and new windows becomes too large * to fully cover via PLC. As a result, that gap is signaled * as packet loss, but as a non-open-ended one. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Establish hold-back mode with packets 10 and 12. * Hold-back mode gets active because of the gap at 11. */ send_packet(&test_context, 10); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 12); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(10); /* Send in packet 22. This would overextend the window. Shifting * the current window moves it past packet 12, so the jitter * buffer must be fully drained. Since afterwards, there is * nothing left in the jitter buffer other than the new packet, * the valid seqnum window length becomes 1, and starts at 22. * This means that there are no gaps left, so the contents * (in this case, just the packet 22) can be output immediately. * Also, the gap between the old window and the new window goes * from seqnum 13 (one past the end of the old window) to seqnum * 21 (one before the new packet 22). 21-13+1 = 9, which is * less than the jitter buffer capacity (which is 10), so that * gap is announced as non-open-ended packet loss. */ send_packet(&test_context, 22); pwtest_int_eq(test_context.num_events, 4u); CHECK_LOST_PACKET_EVENT(11, 1u, false); CHECK_OUTPUT_PACKET_EVENT(12); CHECK_LOST_PACKET_EVENT(13, 9u, false); CHECK_OUTPUT_PACKET_EVENT(22); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_full_window_invalidation_open_ended_gap) { /* Check what happens when hold-back mode is active, the * valid seqnum window's maximum length is reached, and then, * a packet with a sequence number that is far enough to * overextend the window past its current length. This means * that the shifting method (verified in earlier tests above) * won't work - the window is shifted completely past its * current range, so none of those slots remain valid, * and must all be drained. Furthermore, it means that between * the last seqnum of the old window and the first seqnum of * the new window, there is a gap. The jitter buffer is expected * to do the following: * * 1. Drain the entire current valid seqnum window * 2. Reset the window to only contain the seqnum of the new packet * 3. Signal the gap between the old and the new window * * Here, the window is shifted far enough that none of the * original content can be retained, and that that the gap * between the old and new windows becomes too large * to fully cover via PLC. As a result, that gap is signaled * as packet loss, but as an open-ended one. */ struct test_context test_context; setup_test_context(&test_context, 10); /* Establish hold-back mode with packets 10 and 12. * Hold-back mode gets active because of the gap at 11. */ send_packet(&test_context, 10); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 12); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(10); /* Send in packet 400. This would overextend the window. Shifting * the current window moves it past packet 12, so the jitter * buffer must be fully drained. Since afterwards, there is * nothing left in the jitter buffer other than the new packet, * the valid seqnum window length becomes 1, and starts at 400. * This means that there are no gaps left, so the contents * (in this case, just the packet 400) can be output immediately. * Also, the gap between the old window and the new window goes * from seqnum 13 (one past the end of the old window) to seqnum * 399 (one before the new packet 400). 399-13+1 = 387, which is * far beyond the jitter buffer capacity (which is 10). That gap * is then signaled as an open ended packet loss with maximum * length 10, meaning that any PLC/fadeout measure must not * exceed the length of 10 packets. (In non-open-ended signals, * the length instead specifies the exact length of the gap.) * This is done to avoid excessive PLC/fadeout calculations, * like in this case, where it otherwise would force PLC for * 387 packets. Callers are encouraged to apply fadeout as well * to not have a hard cutoff after the maximum (10 packets here).*/ send_packet(&test_context, 400); pwtest_int_eq(test_context.num_events, 4u); CHECK_LOST_PACKET_EVENT(11, 1u, false); CHECK_OUTPUT_PACKET_EVENT(12); CHECK_LOST_PACKET_EVENT(13, 10u, true); CHECK_OUTPUT_PACKET_EVENT(400); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST(rtp_jitter_buffer_test_timeout_drain) { /* Check what happens when hold-back mode is enabled and * the gaps are not filled in time. It is expected that the * jitter buffer's timeout expires and forcibly drains * its contents. */ struct test_context test_context; struct timespec ts; setup_test_context(&test_context, 10); /* Establish hold-back mode with packets 60 and 62. * Hold-back mode gets active because of the gap at 61. */ send_packet(&test_context, 60); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); send_packet(&test_context, 62); pwtest_bool_true(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(60); /* The jitter buffer's timeout timer is configured to expire * when the total duration of its capacity passes after the * hold-back mode was enabled. In this test, capacity is 10 * packets, and each packet covers 10ms, then the total duration * is 10*10ms = 100 ms, and that will also be the timeout of * that timer, and the gap that was detected earlier will have * armed that timer. Sleep for 50ms longer than its timeout * duration to make sure it expires and thus provokes the * draining of the jitter buffer. */ ts.tv_sec = 0; ts.tv_nsec = 10 * TEST_PACKET_DURATION + 50 * SPA_NSEC_PER_MSEC; nanosleep(&ts, NULL); /* Iterate the loop to process the timer expiration. */ pw_loop_enter(test_context.loop); pw_loop_iterate(test_context.loop, 0); pw_loop_leave(test_context.loop); /* After draining, the jitter buffer should be back to regular * mode, just as if rtp_jitter_buffer_drain() had been called. */ pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 2u); pwtest_int_eq(test_context.jitter_buffer.last_seqnum, -1); CHECK_LOST_PACKET_EVENT(61, 1u, false); CHECK_OUTPUT_PACKET_EVENT(62); /* Verify that regular mode is working properly by sending * in packet 700. Since after draining, the last_seqnum is * -1, a discontinuity in the sequence numbers is okay. */ send_packet(&test_context, 700); pwtest_bool_false(test_context.jitter_buffer.hold_back_mode); pwtest_int_eq(test_context.num_events, 1u); CHECK_OUTPUT_PACKET_EVENT(700); teardown_test_context(&test_context); return PWTEST_PASS; } PWTEST_SUITE(pw_module_rtp_common_lib) { pwtest_add(rtp_jitter_buffer_test_consecutive_packets, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_simple_reordering, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_partial_output, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_explicit_drain_in_regular_mode, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_explicit_drain_in_hold_back_mode, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_explicit_drain_coalesced_loss, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_explicit_drain_with_seqnum_wraparound, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_stale_packets_in_regular_mode, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_stale_packets_in_hold_back_mode, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_flush, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_seqnum_wraparound_regular, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_seqnum_wraparound_with_reordering, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_overextension_single_gap_no_end_gap, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_overextension_multiple_gaps_no_end_gap, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_overextension_after_partial_output, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_immediate_overextension_after_regular_mode, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_full_window_invalidation_non_open_ended_gap, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_immediate_overextension_after_regular_mode_threshold_open_closed_gap, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_full_window_invalidation_open_ended_gap, PWTEST_NOARG); pwtest_add(rtp_jitter_buffer_test_timeout_drain, PWTEST_NOARG); return PWTEST_PASS; }