From 6134465ddc10f8b43bddf74209f0ec8654595041 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Wed, 29 Jan 2025 16:45:30 -0500 Subject: Fixes and optimizations around seek and loop Signed-off-by: Andrew Opalach --- src/libsink/sink.c | 58 +++++++++++++++++++++++++++++++++++++----------------- src/libsink/sink.h | 3 ++- 2 files changed, 42 insertions(+), 19 deletions(-) (limited to 'src/libsink') diff --git a/src/libsink/sink.c b/src/libsink/sink.c index 54f651b..03dd379 100644 --- a/src/libsink/sink.c +++ b/src/libsink/sink.c @@ -610,8 +610,13 @@ void add_audio_if_set_and_buffered(struct camu_sink_entry *entry) bool ignore_video = true; #ifndef CAMU_SINK_NO_VIDEO ignore_video = VIDEO_EMPTY(entry) || VIDEO_IS_SINGLE_FRAME(entry); + if (ignore_video) { + struct camu_sink *sink = entry->sink; + sink->callback(sink->userdata, CAMU_SINK_REFRESH_VIDEO, CAMU_SINK_VIDEO, NULL); + } #endif camu_audio_buffer_set_no_video(&entry->audio.buf, ignore_video); + #ifdef CAMU_SINK_LOCAL // If we're local we don't have to worry about syncing audio-only entries. camu_audio_buffer_set_ignore_desync(&entry->audio.buf, ignore_video); @@ -798,7 +803,7 @@ static void audio_buffer_callback(void *userdata, u8 op) // @TODO: This is not well synced. EOF can happen at any time // while other stuff is happening in the sink. For example // while seeking, if EOF happens right after a REMOVE_BUFFERS, - // we might assert during RECONNECT because the entry is ended. + // we might assert during RECONNECTED because the entry is ended. // // state can be something other than BUFFER_ADDED here // because it could have changed while waiting on the lock above. @@ -1058,7 +1063,6 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str nn_mutex_lock(&sink->mutex); if (reconnect) { - entry->ended = false; if (entry == sink->current) { sink->reconnecting = entry; if (sink->target) { @@ -1084,10 +1088,6 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str if (entry->audio.state == BUFFER_ADDED) { remove_entry_audio_buffer(sink, entry); } - // SET_OR_BUFFERED, ADDED, or ENDED. - if (entry->audio.state > BUFFER_CONFIGURED) { - entry->audio.state = BUFFER_CONFIGURED; - } #ifndef CAMU_SINK_NO_VIDEO bool ignore_video = VIDEO_EMPTY(entry) || (reconnect && VIDEO_IS_SINGLE_FRAME(entry)); @@ -1095,9 +1095,6 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str if (entry->video.state == BUFFER_ADDED) { remove_entry_video_buffer(sink, entry); } - if (entry->video.state > BUFFER_CONFIGURED) { - entry->video.state = BUFFER_CONFIGURED; - } } #endif @@ -1114,6 +1111,29 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str #endif ) { BLOCKING_SLEEP(NNWT_TS_FROM_USEC(2000)); } + // Reset possible ENDED state here in case the entry ended at + // some pointer after unlocking to block above. + nn_mutex_lock(&sink->mutex); + + if (reconnect) { + entry->ended = false; + } + + // SET_OR_BUFFERED, ADDED, or ENDED. + if (entry->audio.state > BUFFER_CONFIGURED) { + entry->audio.state = BUFFER_CONFIGURED; + } + +#ifndef CAMU_SINK_NO_VIDEO + if (!ignore_video) { + if (entry->video.state > BUFFER_CONFIGURED) { + entry->video.state = BUFFER_CONFIGURED; + } + } +#endif + + nn_mutex_unlock(&sink->mutex); + if (reconnect) { if (!AUDIO_EMPTY(entry)) { camu_audio_buffer_reset(&entry->audio.buf); @@ -1132,8 +1152,8 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str nn_mutex_lock(&sink->mutex); #if defined LIANA_LIST_SCUFFED_LOOP && !defined CAMU_SINK_NO_VIDEO struct camu_video_buffer *buf = &entry->video.buf; - if (time->seek_pos == 0Lu && buf->last_pts >= 0.0) { - camu_clock_offset(&entry->clock, buf->last_pts); + if (time->seek_pos == 0 && buf->last_pts >= 0.0) { + camu_clock_loop(&entry->clock, buf->last_pts); } else { camu_clock_seek(&entry->clock, time->seek_pos / 1000000.0, time->at); } @@ -1337,12 +1357,14 @@ static bool set_command_callback(void *userdata, struct nn_rpc_connection *conn, #ifdef CAMU_SINK_LOCAL (void)at; if (current && !current->ended && !camu_clock_is_paused(¤t->clock)) { + current->audio.ignore_paused = true; camu_clock_pause(¤t->clock, 0); } if (!entry->ended && camu_clock_is_paused(&entry->clock)) { // This will resume user-paused entries, but whatever. entry->audio.buffer_paused = false; + entry->audio.ignore_paused = false; camu_clock_resume(&entry->clock, 0); } @@ -1520,14 +1542,14 @@ static void connection_callback(void *userdata, struct nn_rpc_connection *conn) { struct camu_sink *sink = (struct camu_sink *)userdata; sink->conn = conn; - nn_timer_stop(&sink->reconnect_timer); + nn_timer_stop(&sink->periodic_timer); struct nn_packet *packet = nn_rpc_get_packet(&sink->client, CAMU_SERVER_IDENTIFY); nn_packet_write_u8(packet, CAMU_SINK); nn_packet_write_str(packet, &sink->name); nn_rpc_connection_command(sink->conn, packet, idd_callback, sink); } -static void reconnect_timer_callback(void *userdata, struct nn_timer *timer) +static void periodic_timer_callback(void *userdata, struct nn_timer *timer) { struct camu_sink *sink = (struct camu_sink *)userdata; (void)timer; @@ -1541,15 +1563,15 @@ static void connection_closed_callback(void *userdata, struct nn_rpc_connection al_assert(sink->conn == conn); sink->conn = NULL; } - nn_timer_again(&sink->reconnect_timer); + nn_timer_again(&sink->periodic_timer); } bool camu_sink_connect(struct camu_sink *sink, u8 type, str *addr, u16 port, str *name) { al_str_clone(&sink->name, name); sink->type = type; - nn_timer_init(&sink->reconnect_timer, sink->loop, reconnect_timer_callback, sink); - nn_timer_set_repeat(&sink->reconnect_timer, NNWT_TS_FROM_USEC(1000000)); + nn_timer_init(&sink->periodic_timer, sink->loop, periodic_timer_callback, sink); + nn_timer_set_repeat(&sink->periodic_timer, NNWT_TS_FROM_USEC(1000000)); nn_rpc_init(&sink->client, sink->loop, connection_callback, connection_closed_callback, sink); for (u32 i = 0; i < ARRAY_SIZE(commands); i++) { commands[i].userdata = sink; @@ -1660,8 +1682,8 @@ void camu_sink_stop(struct camu_sink *sink) void camu_sink_close(struct camu_sink *sink) { - nn_timer_stop(&sink->reconnect_timer); - nn_timer_disable(&sink->reconnect_timer); + nn_timer_stop(&sink->periodic_timer); + nn_timer_disable(&sink->periodic_timer); if (sink->conn) nn_rpc_conn_disconnect(sink->conn); struct camu_sink_entry *entry; al_array_foreach_rev(sink->entries, i, entry) { diff --git a/src/libsink/sink.h b/src/libsink/sink.h index 68fac15..6845c6d 100644 --- a/src/libsink/sink.h +++ b/src/libsink/sink.h @@ -28,6 +28,7 @@ enum { CAMU_SINK_REMOVE_BUFFER, CAMU_SINK_START, CAMU_SINK_STOP, + CAMU_SINK_REFRESH_VIDEO, CAMU_SINK_CLEAR, CAMU_SINK_MOCK_CLOSE, CAMU_SINK_EXIT @@ -79,7 +80,7 @@ struct camu_sink { struct nn_rpc client; struct nn_rpc_connection *conn; struct nn_mutex mutex; - struct nn_timer reconnect_timer; + struct nn_timer periodic_timer; struct nn_signal queue_signal; queue(struct camu_sink_cmd) queue; str default_list; -- cgit v1.2.3-101-g0448