mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-07-05 00:06:16 -04:00
1260 lines
48 KiB
C
1260 lines
48 KiB
C
|
|
/* 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(¶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;
|
||
|
|
}
|