module-rtp: add packet timer

When multiple packets need to be flushed (because sess.latency is set
and larger than ptime) use a timer to space the packets uniformly in
the current quantum to avoid bursts.

See !1873
This commit is contained in:
Wim Taymans 2024-01-30 10:06:27 +01:00
parent 3958bed5c3
commit 78055736a2
2 changed files with 85 additions and 11 deletions

View file

@ -85,7 +85,11 @@ struct impl {
unsigned receiving:1;
unsigned first:1;
struct pw_loop *data_loop;
struct spa_source *timer;
int (*receive_rtp)(struct impl *impl, uint8_t *buffer, ssize_t len);
void (*flush_timeout)(struct impl *impl, uint64_t expirations);
};
#include "module-rtp/audio.c"
@ -271,6 +275,12 @@ static float samples_to_msec(struct impl *impl, uint32_t samples)
return samples * 1000.0f / impl->rate;
}
static void on_flush_timeout(void *d, uint64_t expirations)
{
struct impl *impl = d;
impl->flush_timeout(d, expirations);
}
struct rtp_stream *rtp_stream_new(struct pw_core *core,
enum pw_direction direction, struct pw_properties *props,
const struct rtp_stream_events *events, void *data)
@ -286,16 +296,26 @@ struct rtp_stream *rtp_stream_new(struct pw_core *core,
enum pw_stream_flags flags;
float latency_msec;
int res;
struct pw_data_loop *data_loop;
struct pw_context *context;
impl = calloc(1, sizeof(*impl));
if (impl == NULL) {
res = -errno;
goto out;
return NULL;
}
impl->first = true;
spa_hook_list_init(&impl->listener_list);
impl->stream_events = stream_events;
context = pw_core_get_context(core);
data_loop = pw_context_get_data_loop(context);
impl->data_loop = pw_data_loop_get_loop(data_loop);
impl->timer = pw_loop_add_timer(impl->data_loop, on_flush_timeout, impl);
if (impl->timer == NULL) {
res = -errno;
pw_log_error("can't create timer");
goto out;
}
if ((str = pw_properties_get(props, "sess.media")) == NULL)
str = "audio";
@ -561,6 +581,9 @@ void rtp_stream_destroy(struct rtp_stream *s)
if (impl->stream)
pw_stream_destroy(impl->stream);
if (impl->timer)
pw_loop_destroy_source(impl->data_loop, impl->timer);
spa_hook_list_clean(&impl->listener_list);
free(impl);
}