diff options
| author | 2025-03-18 10:56:12 -0400 | |
|---|---|---|
| committer | 2025-03-18 10:56:12 -0400 | |
| commit | 191d98d306d48ba36d5a5a2eb3583b805a03b2c3 (patch) | |
| tree | 3c917adaf66e6d348046beee510a9a1ed1dc1a41 /src/libsink | |
| parent | f0accac221a53633380f15b4953ca4f4fdfbeca7 (diff) | |
| download | camu-191d98d306d48ba36d5a5a2eb3583b805a03b2c3.tar.gz camu-191d98d306d48ba36d5a5a2eb3583b805a03b2c3.tar.bz2 camu-191d98d306d48ba36d5a5a2eb3583b805a03b2c3.zip | |
Cleanup
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/libsink')
| -rw-r--r-- | src/libsink/sink.c | 136 | ||||
| -rw-r--r-- | src/libsink/sink.h | 9 |
2 files changed, 70 insertions, 75 deletions
diff --git a/src/libsink/sink.c b/src/libsink/sink.c index e5f9351..d3647f1 100644 --- a/src/libsink/sink.c +++ b/src/libsink/sink.c @@ -60,9 +60,9 @@ enum { #define ENTRY_MAX_AGE 3 // printf format for entries. -#if defined C89ATOMIC_64BIT +#if defined AL_WE_64BIT #define ENTRY_FMT "#%u(0x%llx)" -#elif defined C89ATOMIC_32BIT +#elif defined AL_WE_32BIT #define ENTRY_FMT "#%u(0x%lx)" #endif #define ENTRY_ARG(entry) \ @@ -76,16 +76,16 @@ enum { #define AUDIO_EMPTY(entry) BUFFER_EMPTY(&(entry)->audio) #define VIDEO_EMPTY(entry) BUFFER_EMPTY(&(entry)->video) +#define AUDIO_NOT_ADDED(entry) ((entry)->audio.state != BUFFER_ADDED) +#define VIDEO_NOT_ADDED(entry) ((entry)->video.state != BUFFER_ADDED) + #define AUDIO_ADDED_OR_EMPTY(entry) ((entry)->audio.state == BUFFER_ADDED || BUFFER_EMPTY(&(entry)->audio)) #define VIDEO_ADDED_OR_EMPTY(entry) ((entry)->video.state == BUFFER_ADDED || BUFFER_EMPTY(&(entry)->video)) #define AUDIO_ENDED_OR_EMPTY(entry) ((entry)->audio.state == BUFFER_ENDED || BUFFER_EMPTY(&(entry)->audio)) #define VIDEO_ENDED_OR_EMPTY(entry) ((entry)->video.state == BUFFER_ENDED || BUFFER_EMPTY(&(entry)->video)) -#define AUDIO_NOT_ADDED(entry) ((entry)->audio.state != BUFFER_ADDED) -#define VIDEO_NOT_ADDED(entry) ((entry)->video.state != BUFFER_ADDED) - -#define VIDEO_IS_SINGLE_FRAME(entry) camu_video_buffer_is_single_frame(&(entry)->video.buf) +#define VIDEO_IS_SINGLE_FRAME(entry) (entry)->video.buf.single_frame #if defined CAMU_SCREEN_THREADED && defined CAMU_MIXER_THREADED #define BLOCKING_SLEEP(delay) nn_thread_sleep(delay) @@ -126,6 +126,8 @@ static void request_video_refresh(struct camu_sink *sink) { #ifndef CAMU_SINK_NO_VIDEO sink->callback(sink->userdata, CAMU_SINK_REFRESH_VIDEO, 0, NULL); +#else + (void)sink; #endif } @@ -148,16 +150,19 @@ static inline void add_entry_video_buffer(struct camu_sink_entry *entry) #ifndef CAMU_SINK_NO_VIDEO struct camu_sink *sink = entry->sink; sink->callback(sink->userdata, CAMU_SINK_ADD_BUFFER, CAMU_SINK_VIDEO, &entry->video.buf); +#else + (void)entry; #endif } -static void remove_entry_audio_buffer(struct camu_sink *sink, struct camu_sink_entry *entry) +static void remove_entry_audio_buffer(struct camu_sink_entry *entry) { al_assert(AUDIO_STATE(entry) != BUFFER_ENDED); al_assert(AUDIO_STATE(entry) != BUFFER_INIT); switch (AUDIO_STATE(entry)) { case BUFFER_ADDED: AUDIO_STATE(entry) = BUFFER_SET_OR_BUFFERED; + struct camu_sink *sink = entry->sink; #ifdef CAMU_MIXER_THREADED_START_STOP sink->callback(sink->userdata, CAMU_SINK_REMOVE_BUFFER, CAMU_SINK_AUDIO, &entry->audio.buf); #else @@ -177,7 +182,7 @@ static void remove_entry_audio_buffer(struct camu_sink *sink, struct camu_sink_e } } -static void remove_entry_video_buffer(struct camu_sink *sink, struct camu_sink_entry *entry) +static void remove_entry_video_buffer(struct camu_sink_entry *entry) { // Don't assert !entry->ended here because of single frame handling. al_assert(VIDEO_STATE(entry) != BUFFER_ENDED); @@ -186,6 +191,7 @@ static void remove_entry_video_buffer(struct camu_sink *sink, struct camu_sink_e case BUFFER_ADDED: VIDEO_STATE(entry) = BUFFER_SET_OR_BUFFERED; #ifndef CAMU_SINK_NO_VIDEO + struct camu_sink *sink = entry->sink; sink->callback(sink->userdata, CAMU_SINK_REMOVE_BUFFER, CAMU_SINK_VIDEO, &entry->video.buf); #endif break; @@ -202,16 +208,15 @@ static void remove_entry_video_buffer(struct camu_sink *sink, struct camu_sink_e // It's possible for some of an entries buffers to be ENDED while others are still // ADDED and playing. We handle that by making remove_entry_buffers() and // add_audio/video_if_set_and_buffered() no-ops for ENDED buffers. -static void remove_entry_buffers(struct camu_sink *sink, struct camu_sink_entry *entry) +static void remove_entry_buffers(struct camu_sink_entry *entry) { - trace("remove_entry_buffers("ENTRY_FMT"), audio_state: %hhu, video_state: %hhu.", - ENTRY_ARG(entry), AUDIO_STATE(entry), VIDEO_STATE(entry)); + trace("remove_entry_buffers("ENTRY_FMT"), audio_state: %hhu, video_state: %hhu.", ENTRY_ARG(entry), AUDIO_STATE(entry), VIDEO_STATE(entry)); al_assert(!entry->ended); if (AUDIO_STATE(entry) != BUFFER_ENDED) { - remove_entry_audio_buffer(sink, entry); + remove_entry_audio_buffer(entry); } if (VIDEO_STATE(entry) != BUFFER_ENDED) { - remove_entry_video_buffer(sink, entry); + remove_entry_video_buffer(entry); } } @@ -278,12 +283,9 @@ static inline s32 get_sequence_for_command(struct camu_sink *sink) { // SEQUENCE_ANY resolves order on the server. s32 sequence = LIANA_SEQUENCE_ANY; -#if 0 - // Setting an explicit sequence makes skip and pause act on "what you see". - // This is unlikely to be expected behavior in the common case. The user might - // feel like their input was eaten if skipping after a different skip happens - // on the server but is yet to be reflected on their end. - if (sink->target) { + // If we're local this could only lead to feeling like your inputs were eaten. +#ifndef CAMU_SINK_LOCAL + if (sink->target && sink->target != (struct camu_sink_entry *)0xb00b) { sequence = sink->target->sequence; } else if (sink->current) { sequence = sink->current->sequence; @@ -463,14 +465,16 @@ static void queue_signal_callback(void *userdata) static void mixer_callback(void *userdata, u8 op) { + struct camu_sink *sink = (struct camu_sink *)userdata; if (op == CAMU_MIXER_EMPTY) { info("Mixer empty."); #ifndef LIANA_LIST_SCUFFED_LOOP - struct camu_sink *sink = (struct camu_sink *)userdata; queue_cmd(sink, (struct camu_sink_cmd){ .op = STOP, .value.i = CAMU_SINK_AUDIO }); +#else + (void)sink; #endif } } @@ -548,7 +552,7 @@ static void maybe_remove_previous(struct camu_sink *sink) trace("maybe_remove_previous(), previous_count: %u.", sink->previous.count); struct camu_sink_entry *previous; al_array_foreach(sink->previous, i, previous) { - remove_entry_buffers(sink, previous); + remove_entry_buffers(previous); } sink->previous.count = 0; } @@ -577,14 +581,13 @@ static void maybe_remove_from_previous(struct camu_sink *sink, struct camu_sink_ static void maybe_add_to_previous(struct camu_sink *sink, struct camu_sink_entry *previous, struct camu_sink_entry *target) { - trace("maybe_add_to_previous("ENTRY_FMT"), "ENTRY_FMT"), audio_state: %hhu, video_state: %hhu.", - ENTRY_ARG(previous), ENTRY_ARG(target), AUDIO_STATE(previous), VIDEO_STATE(previous)); + trace("maybe_add_to_previous("ENTRY_FMT", "ENTRY_FMT"), audio_state: %hhu, video_state: %hhu.", ENTRY_ARG(previous), ENTRY_ARG(target), AUDIO_STATE(previous), VIDEO_STATE(previous)); al_assert(previous != target); al_assert(!previous->ended); // If none of the entry's buffers are added, we don't care about adding it to previous. bool dangling_target = target == (struct camu_sink_entry *)0xb00b; if (dangling_target || target->ended || !(AUDIO_STATE(previous) == BUFFER_ADDED || VIDEO_STATE(previous) == BUFFER_ADDED)) { - remove_entry_buffers(sink, previous); + remove_entry_buffers(previous); return; } al_array_push(sink->previous, previous); @@ -602,7 +605,7 @@ static void do_add_entry(struct camu_sink_entry *entry) } maybe_remove_previous(entry->sink); queue_cmd(entry->sink, (struct camu_sink_cmd){ - .op = VIDEO_EMPTY(entry) || VIDEO_IS_SINGLE_FRAME(entry) || entry->paused ? STOP : START, + .op = (VIDEO_EMPTY(entry) || VIDEO_IS_SINGLE_FRAME(entry) || entry->paused) ? STOP : START, .value.i = CAMU_SINK_VIDEO }); if (VIDEO_EMPTY(entry)) { @@ -610,7 +613,7 @@ static void do_add_entry(struct camu_sink_entry *entry) request_video_refresh(entry->sink); } queue_cmd(entry->sink, (struct camu_sink_cmd){ - .op = AUDIO_EMPTY(entry) || entry->paused ? STOP : START, + .op = (AUDIO_EMPTY(entry) || entry->paused) ? STOP : START, .value.i = CAMU_SINK_AUDIO }); } @@ -650,9 +653,7 @@ void add_video_if_set_and_buffered(struct camu_sink_entry *entry) VIDEO_STATE(entry) = BUFFER_SET_OR_BUFFERED; } else if (VIDEO_STATE(entry) == BUFFER_SET_OR_BUFFERED) { VIDEO_STATE(entry) = BUFFER_ADDED; - if (VIDEO_IS_SINGLE_FRAME(entry)) { - add_entry_video_buffer(entry); - } + if (VIDEO_IS_SINGLE_FRAME(entry)) add_entry_video_buffer(entry); if (AUDIO_ADDED_OR_EMPTY(entry)) { do_add_entry(entry); } @@ -661,8 +662,7 @@ void add_video_if_set_and_buffered(struct camu_sink_entry *entry) static void switch_to(struct camu_sink *sink, struct camu_sink_entry *target) { - trace("switch_to("ENTRY_FMT"), current: "ENTRY_FMT".", - ENTRY_ARG(target), ENTRY_ARG(sink->current)); + trace("switch_to("ENTRY_FMT"), current: "ENTRY_FMT".", ENTRY_ARG(target), ENTRY_ARG(sink->current)); if (sink->current) { struct camu_sink_entry *current = sink->current; @@ -677,7 +677,7 @@ static void switch_to(struct camu_sink *sink, struct camu_sink_entry *target) } if (ensure_removed) { if (VIDEO_IS_SINGLE_FRAME(current)) { - remove_entry_video_buffer(sink, current); + remove_entry_video_buffer(current); } al_assert(AUDIO_NOT_ADDED(current)); al_assert(VIDEO_NOT_ADDED(current)); @@ -719,8 +719,7 @@ static void switch_to(struct camu_sink *sink, struct camu_sink_entry *target) static void pause_and_swap_to(struct camu_sink *sink, struct camu_sink_entry *target, u64 at) { struct camu_sink_entry *current = sink->current; - trace("pause_and_swap_to("ENTRY_FMT"), %llu), current: "ENTRY_FMT".", - ENTRY_ARG(target), at, ENTRY_ARG(current)); + trace("pause_and_swap_to("ENTRY_FMT"), current: "ENTRY_FMT".", ENTRY_ARG(target), ENTRY_ARG(current)); al_assert(target != current); if (!current || current->ended) { switch_to(sink, target); @@ -797,7 +796,7 @@ static void audio_buffer_callback(void *userdata, u8 op) // Getting EOF on a buffer that isn't ADDED is very possible if the audio // output is threaded. Even more if we had to wait on the lock above. if (AUDIO_STATE(entry) == BUFFER_ADDED) { - remove_entry_audio_buffer(sink, entry); + remove_entry_audio_buffer(entry); } // This assert likely doesn't matter due to the handling of the ENDED state. al_assert(AUDIO_STATE(entry) == BUFFER_SET_OR_BUFFERED); @@ -846,7 +845,7 @@ static void video_buffer_callback(void *userdata, u8 op) } if (!single_frame) { if (VIDEO_STATE(entry) == BUFFER_ADDED) { - remove_entry_video_buffer(sink, entry); + remove_entry_video_buffer(entry); } al_assert(VIDEO_STATE(entry) == BUFFER_SET_OR_BUFFERED); VIDEO_STATE(entry) = BUFFER_ENDED; @@ -879,8 +878,7 @@ static void clock_callback(void *userdata, u8 op) struct camu_sink *sink = entry->sink; if (op == CAMU_CLOCK_PAUSED) { nn_mutex_lock(&sink->lock); - trace("clock_callback(CAMU_CLOCK_PAUSED, "ENTRY_FMT"), target: "ENTRY_FMT".", - ENTRY_ARG(entry), ENTRY_ARG(sink->target)); + trace("clock_paused("ENTRY_FMT"), target: "ENTRY_FMT".", ENTRY_ARG(entry), ENTRY_ARG(sink->target)); if (entry == sink->current) { if (sink->target) { switch_to(sink, sink->target); @@ -1040,8 +1038,7 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str nn_mutex_lock(&sink->lock); - trace("remove_buffers("ENTRY_FMT", %s), entry == current: %s.", - ENTRY_ARG(entry), BOOLSTR(reconnect), BOOLSTR(entry == sink->current)); + trace("remove_buffers("ENTRY_FMT", %s), entry == current: %s.", ENTRY_ARG(entry), BOOLSTR(reconnect), BOOLSTR(entry == sink->current)); if (reconnect && entry == sink->current) { sink->reconnecting = entry; @@ -1053,11 +1050,11 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str remove_previous_if_contains(sink, entry); if (AUDIO_STATE(entry) == BUFFER_ADDED) { - remove_entry_audio_buffer(sink, entry); + remove_entry_audio_buffer(entry); } bool ignore_video = reconnect && VIDEO_IS_SINGLE_FRAME(entry); if (!ignore_video && VIDEO_STATE(entry) == BUFFER_ADDED) { - remove_entry_video_buffer(sink, entry); + remove_entry_video_buffer(entry); } // Resolve any queued REMOVE_BUFFER requests before blocking. @@ -1107,8 +1104,10 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str } case LIANA_CLIENT_RESUME_AT: { struct lia_timing *time = (struct lia_timing *)opaque; - trace("resume_at("ENTRY_FMT"), %llu, %llu), paused_at: %f.", - ENTRY_ARG(entry), time->seek_pos, time->at, entry->clock.paused_at); + trace("resume_at("ENTRY_FMT"), paused_at: %f.", ENTRY_ARG(entry), entry->clock.paused_at); +#ifdef CAMU_SINK_LOCAL + time->at = 0; +#endif nn_mutex_lock(&sink->lock); #if defined LIANA_LIST_SCUFFED_LOOP if (time->seek_pos == 0) { @@ -1125,8 +1124,7 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str case LIANA_CLIENT_RECONNECTED: { bool unconfigured = *(bool *)opaque; nn_mutex_lock(&sink->lock); - trace("reconnected("ENTRY_FMT"), reconnecting: "ENTRY_FMT".", - ENTRY_ARG(entry), ENTRY_ARG(sink->reconnecting)); + trace("reconnected("ENTRY_FMT"), reconnecting: "ENTRY_FMT".", ENTRY_ARG(entry), ENTRY_ARG(sink->reconnecting)); if (entry == sink->reconnecting) { al_assert(entry == sink->current); if (AUDIO_STATE(entry) > BUFFER_QUEUED) { @@ -1172,7 +1170,7 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str if (VIDEO_STATE(entry) == BUFFER_ADDED) { al_assert(VIDEO_IS_SINGLE_FRAME(entry)); - remove_entry_video_buffer(sink, entry); + remove_entry_video_buffer(entry); while (entry_video_buffer_held(entry)) { BLOCKING_SLEEP(NNWT_TS_FROM_USEC(2000)); } } @@ -1220,6 +1218,17 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str } } +static const char *pause_op_name(u8 pause) +{ + switch (pause) { + case LIANA_PAUSE_NONE: return "PAUSE_NONE"; + case LIANA_PAUSE_RESUME: return "PAUSE_RESUME"; + case LIANA_PAUSE_PAUSE: return "PAUSE_PAUSE"; + case LIANA_PAUSE_BOTH: return "PAUSE_BOTH"; + default: al_assert_and_return(NULL); + }; +} + static struct camu_sink_entry *create_entry(struct camu_sink *sink, u32 id) { struct camu_sink_entry *entry = al_alloc_object(struct camu_sink_entry); @@ -1242,9 +1251,9 @@ static struct camu_sink_entry *create_entry(struct camu_sink *sink, u32 id) entry->video.buf.callback = video_buffer_callback; entry->video.buf.userdata = entry; - entry->client.renderer = sink->video.renderer; entry->client.callback = client_callback; entry->client.userdata = entry; + entry->client.renderer = sink->video.renderer; entry->client.prefs = sink->prefs; al_array_push(sink->entries, entry); @@ -1298,14 +1307,11 @@ static bool set_command_callback(void *userdata, struct nn_rpc_connection *conn, u32 reset_id = nn_packet_read_u32(packet); struct camu_sink_entry *current = sink->current; - struct camu_sink_entry *prev_target = sink->target; struct camu_sink_entry *entry = get_entry_from_id(sink, id); bool create = !entry; - if (create) { - entry = create_entry(sink, id); - } + if (create) entry = create_entry(sink, id); entry->sequence = sequence; - sink->lru = al_u16_inc_wrap(sink->lru); + sink->lru = al_u16_add_wrap(sink->lru, SINK_LRU_MAX); entry->lru = sink->lru; entry->reset_id = reset_id; @@ -1322,9 +1328,6 @@ static bool set_command_callback(void *userdata, struct nn_rpc_connection *conn, lia_client_connect(&entry->client, sink->loop, sink->type, &addr, port, node_id, seek_pos); } - trace("set("ENTRY_FMT", %llu), created: %s, pause: %hhu, current: "ENTRY_FMT", target: "ENTRY_FMT".", - ENTRY_ARG(entry), at, BOOLSTR(create), pause, ENTRY_ARG(current), ENTRY_ARG(prev_target)); - if (op == LIANA_SINK_BUFFER) { goto out; } else if (op == LIANA_SINK_BUFFER_AND_QUEUE) { @@ -1340,7 +1343,9 @@ static bool set_command_callback(void *userdata, struct nn_rpc_connection *conn, } #ifdef CAMU_SINK_LOCAL + (void)at; al_assert(entry != current); + trace("set("ENTRY_FMT"), %s[local], created: %s.", ENTRY_ARG(entry), pause_op_name(pause), BOOLSTR(create)); if (current && !current->ended) { current->audio.ignore_paused = true; if (!current->paused) { @@ -1356,6 +1361,8 @@ static bool set_command_callback(void *userdata, struct nn_rpc_connection *conn, switch_to(sink, entry); #else // For target to be set that must mean current is set, armed to pause, and not ended. + struct camu_sink_entry *prev_target = sink->target; + trace("set("ENTRY_FMT"), %s, created: %s, target: "ENTRY_FMT".", ENTRY_ARG(entry), pause_op_name(pause), BOOLSTR(create), ENTRY_ARG(prev_target)); switch (pause) { case LIANA_PAUSE_NONE: if (prev_target) { @@ -1446,13 +1453,10 @@ static bool pause_command_callback(void *userdata, struct nn_rpc_connection *con struct camu_sink_entry *entry = get_entry_from_id(sink, id); if (!entry) goto out; al_assert(entry->sequence == sequence); - nn_mutex_lock(&sink->lock); - - trace("pause("ENTRY_FMT", %llu), pause: %hhu, audio_state: %hhu, video_state: %hhu.", - ENTRY_ARG(entry), at, pause, AUDIO_STATE(entry), VIDEO_STATE(entry)); - + trace("pause("ENTRY_FMT"), %s, audio_state: %hhu, video_state: %hhu.", ENTRY_ARG(entry), pause_op_name(pause), AUDIO_STATE(entry), VIDEO_STATE(entry)); #ifdef CAMU_SINK_LOCAL + (void)at; sink_local_pause(sink, entry); #else switch (pause) { @@ -1481,7 +1485,6 @@ static bool pause_command_callback(void *userdata, struct nn_rpc_connection *con break; } #endif - nn_mutex_unlock(&sink->lock); out: @@ -1505,13 +1508,8 @@ static bool seek_command_callback(void *userdata, struct nn_rpc_connection *conn struct camu_sink_entry *entry = get_entry_from_id(sink, id); if (!entry) goto out; - entry->reset_id = reset_id; - trace("seek("ENTRY_FMT"), reset_id: %u.", ENTRY_ARG(entry), reset_id); - -#ifdef CAMU_SINK_LOCAL - at = 0; -#endif + entry->reset_id = reset_id; // The rest of the seek is handled in client_callback()'s. lia_client_seek(&entry->client, pos, at); @@ -1630,7 +1628,7 @@ void camu_sink_seek(struct camu_sink *sink, void *value, u8 mode) { nn_mutex_lock(&sink->lock); struct camu_sink_entry *current = sink->current; - u64 duration; + u64 duration = 0; if (current) duration = current->client.duration; f64 pts = camu_clock_get_last_pts(¤t->clock); nn_mutex_unlock(&sink->lock); diff --git a/src/libsink/sink.h b/src/libsink/sink.h index 32fdc26..d1bcd26 100644 --- a/src/libsink/sink.h +++ b/src/libsink/sink.h @@ -7,7 +7,7 @@ #include <nnwt/timer.h> #include "../util/queue.h" - +#include "../liana/client.h" #include "../buffer/clock.h" #include "../buffer/audio.h" #ifndef CAMU_SINK_NO_VIDEO @@ -16,8 +16,6 @@ #include "../buffer/video_null.h" #endif -#include "../liana/client.h" - enum { CAMU_SINK_AUDIO = 0, CAMU_SINK_VIDEO @@ -56,7 +54,7 @@ struct camu_sink_entry { bool paused; struct { u8 state; - // Don't stop the audio output when this entry is paused. + // Don't stop the audio output on BUFFER_PAUSED from this entry. bool ignore_paused; struct camu_audio_buffer buf; struct lia_vcr_track *track; @@ -87,7 +85,6 @@ struct camu_sink { struct nn_timer reconnect_timer; struct nn_signal queue_signal; queue(struct camu_sink_cmd) queue; - str default_list; struct camu_sink_entry *current; struct camu_sink_entry *queued; struct camu_sink_entry *target; @@ -104,7 +101,7 @@ struct camu_sink { struct camu_renderer *renderer; } video; struct lia_prefs prefs; - struct lia_server *local_server; + str default_list; u8 (*callback)(void *, u8, u8, void *); void *userdata; }; |