diff options
| author | 2025-03-31 19:16:50 -0400 | |
|---|---|---|
| committer | 2025-03-31 19:16:50 -0400 | |
| commit | c8b3ed01a41c0215a4a33ce8468b162463129600 (patch) | |
| tree | b29fad1faf0d172e2e46be9a73f9b3bc73f8b29a /src/libsink | |
| parent | 2f34d806e42b6d6299ef46284466b98536485839 (diff) | |
| download | camu-c8b3ed01a41c0215a4a33ce8468b162463129600.tar.gz camu-c8b3ed01a41c0215a4a33ce8468b162463129600.tar.bz2 camu-c8b3ed01a41c0215a4a33ce8468b162463129600.zip | |
Overall style change, small fixes
- Tweak sink switch_to() order.
Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/libsink')
| -rw-r--r-- | src/libsink/sink.c | 147 |
1 files changed, 69 insertions, 78 deletions
diff --git a/src/libsink/sink.c b/src/libsink/sink.c index 5038566..5bf9597 100644 --- a/src/libsink/sink.c +++ b/src/libsink/sink.c @@ -22,7 +22,7 @@ enum { enum { // Created. - BUFFER_INIT, + BUFFER_INIT = 0, // Set but not configured. BUFFER_QUEUED, // Ready to receive data. @@ -115,14 +115,11 @@ static inline bool entry_video_buffer_held(struct camu_sink_entry *entry) static void queue_cmd(struct camu_sink *sink, struct camu_sink_cmd cmd) { -#ifdef CAMU_SINK_NO_VIDEO - if (cmd.value.i == CAMU_SINK_VIDEO) return; -#endif camu_queue_push(sink->queue, cmd); nn_signal_send(&sink->queue_signal); } -static void request_video_refresh(struct camu_sink *sink) +static void refresh_video_output(struct camu_sink *sink) { #ifndef CAMU_SINK_NO_VIDEO sink->callback(sink->userdata, CAMU_SINK_REFRESH_VIDEO, 0, NULL); @@ -207,7 +204,7 @@ static void remove_entry_video_buffer(struct camu_sink_entry *entry) // It's possible for some of an entry's buffers to be ENDED while others are still ADDED. // This means entry->ended and BUFFER_ENDED have two distinct considerations. -// entry->ended: Completely ignored, needs special consideration in CLIENT_REMOVE_BUFFERS. +// entry->ended: Completely ignored and needs special consideration in CLIENT_REMOVE_BUFFERS. // BUFFER_ENDED: No-op'd in remove_entry_buffers() and add_or_queue_entry() but otherwise unchanged. static void remove_entry_buffers(struct camu_sink_entry *entry) { @@ -584,7 +581,7 @@ static void maybe_add_to_previous(struct camu_sink *sink, struct camu_sink_entry 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)) { + if (dangling_target || target->ended || (AUDIO_STATE(previous) != BUFFER_ADDED && VIDEO_STATE(previous) != BUFFER_ADDED)) { remove_entry_buffers(previous); return; } @@ -608,7 +605,7 @@ static void do_add_entry(struct camu_sink_entry *entry) }); if (VIDEO_EMPTY(entry)) { // Clear the screen if skipping from a video to an audio-only entry. - request_video_refresh(entry->sink); + refresh_video_output(entry->sink); } queue_cmd(entry->sink, (struct camu_sink_cmd){ .op = (AUDIO_EMPTY(entry) || entry->paused) ? STOP : START, @@ -629,7 +626,7 @@ void add_audio_if_set_and_buffered(struct camu_sink_entry *entry) break; case BUFFER_SET_OR_BUFFERED: AUDIO_STATE(entry) = BUFFER_ADDED; - if (VIDEO_ADDED_OR_EMPTY(entry)) { + if (VIDEO_ADDED_OR_EMPTY(entry) || VIDEO_IS_SINGLE_FRAME(entry)) { do_add_entry(entry); } break; @@ -639,6 +636,7 @@ void add_audio_if_set_and_buffered(struct camu_sink_entry *entry) void add_video_if_set_and_buffered(struct camu_sink_entry *entry) { // Single frame entries will be added/removed with ended set. + if (entry->ended) al_assert(VIDEO_IS_SINGLE_FRAME(entry)); al_assert(VIDEO_STATE(entry) != BUFFER_INIT); al_assert(VIDEO_STATE(entry) != BUFFER_QUEUED); al_assert(VIDEO_STATE(entry) != BUFFER_ADDED); @@ -649,8 +647,9 @@ void add_video_if_set_and_buffered(struct camu_sink_entry *entry) break; case BUFFER_SET_OR_BUFFERED: VIDEO_STATE(entry) = BUFFER_ADDED; - if (VIDEO_IS_SINGLE_FRAME(entry)) add_entry_video_buffer(entry); - if (AUDIO_ADDED_OR_EMPTY(entry)) { + if (VIDEO_IS_SINGLE_FRAME(entry)) { + add_entry_video_buffer(entry); + } else if (AUDIO_ADDED_OR_EMPTY(entry)) { do_add_entry(entry); } break; @@ -661,11 +660,12 @@ 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)); - if (sink->current) { - struct camu_sink_entry *current = sink->current; + bool ensure_removed = false; + struct camu_sink_entry *current = sink->current; + if (current) { struct camu_sink_entry *detached = sink->detached; al_assert(current != target); - bool ensure_removed = detached || current->ended; + ensure_removed = detached || current->ended; if (detached) { al_assert(detached == current); sink->detached = NULL; @@ -676,43 +676,47 @@ static void switch_to(struct camu_sink *sink, struct camu_sink_entry *target) } else if (!current->ended) { maybe_add_to_previous(sink, current, target); } - if (ensure_removed) { - if (VIDEO_IS_SINGLE_FRAME(current)) { - remove_entry_video_buffer(current); + } + + bool stop_video = false; + bool dangling_target = target == (struct camu_sink_entry *)0xb00b; + if (!dangling_target) { + if (!target->ended) { + remove_previous_if_contains(sink, target); + add_or_queue_entry(target); + } else { + if (VIDEO_IS_SINGLE_FRAME(target)) { + add_video_if_set_and_buffered(target); } - al_assert(AUDIO_NOT_ADDED(current)); - al_assert(VIDEO_NOT_ADDED(current)); + stop_video = true; } } - if (target == (struct camu_sink_entry *)0xb00b) { - sink->current = NULL; - queue_cmd(sink, (struct camu_sink_cmd){ - .op = STOP, - .value.i = CAMU_SINK_VIDEO - }); - request_video_refresh(sink); - return; + if (ensure_removed) { + if (VIDEO_IS_SINGLE_FRAME(current)) { + remove_entry_video_buffer(current); + } + al_assert(AUDIO_NOT_ADDED(current)); + al_assert(VIDEO_NOT_ADDED(current)); } - if (!target->ended) { - remove_previous_if_contains(sink, target); - add_or_queue_entry(target); - } else { - if (VIDEO_IS_SINGLE_FRAME(target)) { - add_video_if_set_and_buffered(target); - } else { - queue_cmd(sink, (struct camu_sink_cmd){ - .op = STOP, - .value.i = CAMU_SINK_VIDEO - }); + if (!dangling_target) { + sink->current = target; + sink->current->audio.ignore_paused = false; + if (!sink->current->paused) { + camu_audio_buffer_resync(&sink->current->audio.buf); } + } else { + sink->current = NULL; + stop_video = true; } - sink->current = target; - sink->current->audio.ignore_paused = false; - if (!sink->current->paused) { - camu_audio_buffer_resync(&sink->current->audio.buf); + if (stop_video) { + queue_cmd(sink, (struct camu_sink_cmd){ + .op = STOP, + .value.i = CAMU_SINK_VIDEO + }); + refresh_video_output(sink); } } @@ -798,7 +802,7 @@ static void audio_buffer_callback(void *userdata, u8 op) nn_mutex_lock(&sink->lock); // This buffer's state could be ADDED, SET_OR_BUFFERED, or CONFIGURED. // Having threaded outputs means anything could have happened while waiting on the lock. - // If we were waiting in CLIENT_REMOVE_BUFFERS, state could very well be CONFIGURED. + // If we were waiting in CLIENT_REMOVE_BUFFERS, state could very well be CONFIGURED here. if (AUDIO_STATE(entry) == BUFFER_ADDED) { remove_entry_audio_buffer(entry); } @@ -824,13 +828,12 @@ static void video_buffer_callback(void *userdata, u8 op) struct camu_sink_entry *entry = (struct camu_sink_entry *)userdata; struct camu_sink *sink = entry->sink; switch (op) { - case CAMU_BUFFER_BUFFERED: { + case CAMU_BUFFER_BUFFERED: lia_vcr_set_buffered(entry->video.track); nn_mutex_lock(&sink->lock); add_video_if_set_and_buffered(entry); nn_mutex_unlock(&sink->lock); break; - } case CAMU_BUFFER_CORK: lia_vcr_cork(entry->video.track); break; @@ -903,7 +906,8 @@ static void evaluate_and_set_buffer_params(struct camu_sink *sink, struct camu_s if (!AUDIO_EMPTY(entry) && !ignore_video) { f64 audio = camu_mixer_get_latency(sink->audio.mixer); s32 frames = audio / entry->video.buf.avg_frame_duration; - frames -= sink->video.renderer->get_latency(sink->video.renderer); + struct camu_renderer *renderer = sink->video.renderer; + if (renderer) frames -= renderer->get_latency(renderer); camu_video_buffer_set_latency(&entry->video.buf, -frames); } // If we're local we don't have to worry about syncing audio-only entries. @@ -915,7 +919,8 @@ static void evaluate_and_set_buffer_params(struct camu_sink *sink, struct camu_s f64 audio = camu_mixer_get_latency(sink->audio.mixer); if (!VIDEO_EMPTY(entry)) { s32 frames = audio / entry->video.buf.avg_frame_duration; - frames += sink->video.renderer->get_latency(sink->video.renderer); + struct camu_renderer *renderer = sink->video.renderer; + if (renderer) frames += renderer->get_latency(renderer); camu_video_buffer_set_latency(&entry->video.buf, frames); } bool ignore_video = VIDEO_EMPTY(entry) || VIDEO_IS_SINGLE_FRAME(entry); @@ -1062,7 +1067,7 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str if (!AUDIO_ENDED_OR_EMPTY(entry)) { // Remove for re-add in CLIENT_RECONNECTED. remove_entry_audio_buffer(entry); - // Remove again for BUFFER_BUFFERED. + // Remove again for another add in BUFFER_BUFFERED. remove_entry_audio_buffer(entry); } // Slight optimization. A duplicate frame will still be sent but discarded in the video buffer. @@ -1187,8 +1192,7 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str } // @TODO: Mark for removal here instead. - bool removed; - al_array_remove_checked(sink->entries, entry, removed); + bool removed = al_array_remove(sink->entries, entry); remove_from_queue_by_opaque(sink, entry); if (entry == sink->target) { @@ -1230,17 +1234,6 @@ 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); @@ -1343,7 +1336,7 @@ 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)); + trace("set("ENTRY_FMT"), %s[local], created: %s.", ENTRY_ARG(entry), lia_pause_op_name(pause), BOOLSTR(create)); if (current && !current->ended) { current->audio.ignore_paused = true; if (!current->paused) { @@ -1360,7 +1353,7 @@ static bool set_command_callback(void *userdata, struct nn_rpc_connection *conn, #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)); + trace("set("ENTRY_FMT"), %s, created: %s, target: "ENTRY_FMT".", ENTRY_ARG(entry), lia_pause_op_name(pause), BOOLSTR(create), ENTRY_ARG(prev_target)); switch (pause) { case LIANA_PAUSE_NONE: if (prev_target) { @@ -1452,7 +1445,7 @@ static bool pause_command_callback(void *userdata, struct nn_rpc_connection *con if (!entry) goto out; al_assert(entry->sequence == sequence); nn_mutex_lock(&sink->lock); - trace("pause("ENTRY_FMT"), %s, audio_state: %hhu, video_state: %hhu.", ENTRY_ARG(entry), pause_op_name(pause), AUDIO_STATE(entry), VIDEO_STATE(entry)); + trace("pause("ENTRY_FMT"), %s, audio_state: %hhu, video_state: %hhu.", ENTRY_ARG(entry), lia_pause_op_name(pause), AUDIO_STATE(entry), VIDEO_STATE(entry)); #ifdef CAMU_SINK_LOCAL (void)at; sink_local_pause(sink, entry); @@ -1508,7 +1501,7 @@ static bool seek_command_callback(void *userdata, struct nn_rpc_connection *conn if (!entry) goto out; trace("seek("ENTRY_FMT"), reset_id: %u.", ENTRY_ARG(entry), reset_id); entry->reset_id = reset_id; - // The rest of the seek is handled in client_callback()'s. + // The rest of the seek is handled in CLIENT_REMOVE_BUFFERS/RESUME_AT/RECONNECTED. lia_client_seek(&entry->client, pos, at); out: @@ -1613,13 +1606,12 @@ void camu_sink_toggle_pause(struct camu_sink *sink) nn_mutex_lock(&sink->lock); struct camu_sink_entry *current = sink->current; nn_mutex_unlock(&sink->lock); - if (current) { - queue_cmd(sink, (struct camu_sink_cmd){ - .op = TOGGLE_PAUSE, - .value.f = camu_clock_get_pts(¤t->clock, 0.0, false), - .opaque = current - }); - } + if (!current) return; + queue_cmd(sink, (struct camu_sink_cmd){ + .op = TOGGLE_PAUSE, + .value.f = camu_clock_get_pts(¤t->clock, 0.0, false), + .opaque = current + }); } void camu_sink_seek(struct camu_sink *sink, void *value, u8 mode) @@ -1663,12 +1655,11 @@ void camu_sink_reseek(struct camu_sink *sink) nn_mutex_lock(&sink->lock); struct camu_sink_entry *current = sink->current; nn_mutex_unlock(&sink->lock); - if (current) { - queue_cmd(sink, (struct camu_sink_cmd){ - .op = RESEEK, - .opaque = current - }); - } + if (!current) return; + queue_cmd(sink, (struct camu_sink_cmd){ + .op = RESEEK, + .opaque = current + }); } void camu_sink_shuffle(struct camu_sink *sink) |