pipewire/test/modules/module-rtp/test-jitter-buffer.c

1260 lines
48 KiB
C
Raw Normal View History

/* PipeWire */
/* SPDX-FileCopyrightText: Copyright © 2026 Carlos Rafael Giani */
/* SPDX-License-Identifier: MIT */
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <arpa/inet.h>
#include "config.h"
#include <pipewire/pipewire.h>
#include <module-rtp/rtp.h>
#include <module-rtp/jitter-buffer.h>
#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(&params, 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), &params);
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;
}