module-rtp-sink: Send all remaining packets when stopping

Don't close rtp_fd until all packets have been sent by the timer, if
the timer is running when the stream is stopped.
This commit is contained in:
Jonas Holmberg 2024-04-16 08:29:53 +02:00 committed by Wim Taymans
parent 4cea8eb01f
commit 64d75b6b2e
2 changed files with 36 additions and 7 deletions

View file

@ -224,9 +224,15 @@ static void rtp_audio_flush_packets(struct impl *impl, uint32_t num_packets)
avail = spa_ringbuffer_get_read_index(&impl->ring, &timestamp);
tosend = impl->psamples;
if (avail < tosend)
goto done;
num_packets = SPA_MIN(num_packets, (uint32_t)(avail / tosend));
if (impl->started)
goto done;
else {
/* send last packet before emitting state_changed */
tosend = avail;
num_packets = 1;
}
else
num_packets = SPA_MIN(num_packets, (uint32_t)(avail / tosend));
stride = impl->stride;
@ -264,8 +270,19 @@ static void rtp_audio_flush_packets(struct impl *impl, uint32_t num_packets)
}
spa_ringbuffer_read_update(&impl->ring, timestamp);
done:
if (avail < tosend && impl->timer_running)
set_timer(impl, 0, 0);
if (impl->timer_running) {
if (impl->started) {
if (avail < tosend) {
set_timer(impl, 0, 0);
}
} else if (avail <= 0) {
bool started = false;
/* the stream has been stopped and all packets have been sent */
set_timer(impl, 0, 0);
pw_loop_invoke(impl->main_loop, do_emit_state_changed, SPA_ID_INVALID, &started, sizeof started, false, impl);
}
}
}
static void rtp_audio_flush_timeout(struct impl *impl, uint64_t expirations)

View file

@ -85,6 +85,7 @@ struct impl {
unsigned receiving:1;
unsigned first:1;
struct pw_loop *main_loop;
struct pw_loop *data_loop;
struct spa_source *timer;
bool timer_running;
@ -93,6 +94,15 @@ struct impl {
void (*flush_timeout)(struct impl *impl, uint64_t expirations);
};
static int do_emit_state_changed(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data)
{
struct impl *impl = user_data;
bool *started = (bool *)data;
rtp_stream_emit_state_changed(impl, *started, NULL);
return 0;
}
#include "module-rtp/audio.c"
#include "module-rtp/midi.c"
#include "module-rtp/opus.c"
@ -154,7 +164,9 @@ static int stream_stop(struct impl *impl)
if (!impl->started)
return 0;
rtp_stream_emit_state_changed(impl, false, NULL);
/* if timer is running, the state changed event must be emitted by the timer after all packets have been sent */
if (!impl->timer_running)
rtp_stream_emit_state_changed(impl, false, NULL);
impl->started = false;
return 0;
@ -171,7 +183,6 @@ static void on_stream_state_changed(void *d, enum pw_stream_state old,
break;
case PW_STREAM_STATE_ERROR:
pw_log_error("stream error: %s", error);
rtp_stream_emit_state_changed(impl, false, error);
break;
case PW_STREAM_STATE_STREAMING:
if ((errno = -stream_start(impl)) < 0)
@ -309,6 +320,7 @@ struct rtp_stream *rtp_stream_new(struct pw_core *core,
spa_hook_list_init(&impl->listener_list);
impl->stream_events = stream_events;
context = pw_core_get_context(core);
impl->main_loop = pw_context_get_main_loop(context);
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);