diff options
Diffstat (limited to 'src/libsink')
| -rw-r--r-- | src/libsink/sink.c | 61 | ||||
| -rw-r--r-- | src/libsink/sink.h | 1 |
2 files changed, 51 insertions, 11 deletions
diff --git a/src/libsink/sink.c b/src/libsink/sink.c index 62bb941..3528e6b 100644 --- a/src/libsink/sink.c +++ b/src/libsink/sink.c @@ -308,8 +308,6 @@ static void handle_sink_cmd(struct camu_sink *sink, struct camu_sink_cmd *cmd) if (sink->video.state == SINK_PLAYING) { sink->callback(sink->userdata, CAMU_SINK_STOP, CAMU_SINK_VIDEO, NULL); sink->video.state = SINK_PAUSED; - } else { - sink->callback(sink->userdata, CAMU_SINK_REFRESH_VIDEO, 0, NULL); } break; #endif @@ -641,6 +639,12 @@ void add_audio_if_set_and_buffered(struct camu_sink_entry *entry) .op = VIDEO_EMPTY(entry) || entry->buffers_paused ? STOP : START, .value.i = CAMU_SINK_VIDEO }); + // This is the only place to clear the screen if skipping from a video + // to an audio-only entry. + if (VIDEO_EMPTY(entry)) { + struct camu_sink *sink = entry->sink; + sink->callback(sink->userdata, CAMU_SINK_REFRESH_VIDEO, 0, NULL); + } } #endif queue_cmd(entry->sink, (struct camu_sink_cmd){ @@ -654,6 +658,7 @@ void add_audio_if_set_and_buffered(struct camu_sink_entry *entry) #ifndef CAMU_SINK_NO_VIDEO void add_video_if_set_and_buffered(struct camu_sink_entry *entry) { + // Single frames will be added/removed with ended set. al_assert(entry->video.state != BUFFER_INIT && (entry->video.state != BUFFER_QUEUED) && (entry->video.state != BUFFER_ADDED)); @@ -676,7 +681,7 @@ void add_video_if_set_and_buffered(struct camu_sink_entry *entry) add_entry_audio_buffer(entry); } - // This entry could be in previous. + // This entry could be in previous, see note in add_audio_if_set_and_buffered(). maybe_remove_previous(entry->sink); queue_cmd(entry->sink, (struct camu_sink_cmd){ @@ -753,6 +758,9 @@ 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; +#ifdef CAMU_SINK_TRACE + al_log_info("sink", "pause_and_swap_to(%llx, %llu), current: %llx", target, at, current); +#endif al_assert(target != current); if (!current || current->ended) { switch_to(sink, target); @@ -875,12 +883,13 @@ static void video_buffer_callback(void *userdata, u8 op) break; case CAMU_BUFFER_EOF: { bool swapped = false; + bool single_frame = VIDEO_IS_SINGLE_FRAME(entry); nn_mutex_lock(&sink->mutex); al_log_info("sink", "Video EOF."); if (!AUDIO_EMPTY(entry)) { camu_audio_buffer_set_no_video(&entry->audio.buf, true); } - if (!VIDEO_IS_SINGLE_FRAME(entry)) { + if (!single_frame) { if (entry->video.state == BUFFER_ADDED) { remove_entry_video_buffer(sink, entry); } @@ -891,7 +900,7 @@ static void video_buffer_callback(void *userdata, u8 op) } } nn_mutex_unlock(&sink->mutex); - if (!swapped) { + if (!swapped && !single_frame) { queue_cmd(sink, (struct camu_sink_cmd){ .op = STOP, .value.i = CAMU_SINK_VIDEO @@ -1086,6 +1095,10 @@ static void client_callback(void *userdata, u8 op, struct camu_codec_stream *str nn_mutex_lock(&sink->mutex); +#ifdef CAMU_SINK_TRACE + al_log_info("sink", "remove_buffers(%s), entry == current: %s", BOOLSTR(reconnect), BOOLSTR(entry == sink->current)); +#endif + if (reconnect) { if (entry == sink->current) { sink->reconnecting = entry; @@ -1177,6 +1190,9 @@ 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; nn_mutex_lock(&sink->mutex); +#ifdef CAMU_SINK_TRACE + al_log_info("sink", "resume_at(%llu, %llu)", time->seek_pos, time->at); +#endif #if defined LIANA_LIST_SCUFFED_LOOP && !defined CAMU_SINK_NO_VIDEO struct camu_video_buffer *buf = &entry->video.buf; if (time->seek_pos == 0 && buf->last_pts >= 0.0) { @@ -1704,11 +1720,39 @@ void camu_sink_seek(struct camu_sink *sink, f64 precent) }); } +// @TODO: We need at standard way to get the entries pts even when paused. +static f64 tmp_get_entry_pts(struct camu_sink_entry *entry) +{ + f64 pts = camu_clock_get_pts(&entry->clock, 0.0, false); + if (pts == -1.0) { +#ifndef CAMU_SINK_NO_VIDEO + pts = al_atomic_load(f64)(&entry->video.buf.pts, AL_ATOMIC_RELAXED); +#endif + } + return pts; +} + +void camu_sink_relative_seek(struct camu_sink *sink, f64 offset) +{ + nn_mutex_lock(&sink->mutex); + struct camu_sink_entry *current = sink->current; + nn_mutex_unlock(&sink->mutex); + if (!current) return; + f64 pts = tmp_get_entry_pts(current) + offset; + f64 duration = current->client.duration / 1000000.0; + queue_cmd(sink, (struct camu_sink_cmd){ + .op = SEEK, + .value.f = pts / duration, + .opaque = current + }); +} + void camu_sink_reseek(struct camu_sink *sink) { nn_mutex_lock(&sink->mutex); struct camu_sink_entry *current = sink->current; nn_mutex_unlock(&sink->mutex); + if (!current) return; queue_cmd(sink, (struct camu_sink_cmd){ .op = RESEEK, .opaque = current @@ -1743,12 +1787,7 @@ void camu_sink_status(struct camu_sink *sink) al_log_info("sink", "Nothing playing."); return; } - f64 pts = camu_clock_get_pts(¤t->clock, 0.0, false); - if (pts == -1.0) { -#ifndef CAMU_SINK_NO_VIDEO - pts = al_atomic_load(f64)(¤t->video.buf.pts, AL_ATOMIC_RELAXED); -#endif - } + f64 pts = tmp_get_entry_pts(current); f64 duration = current->client.duration / 1000000.0; s32 text = 0; u32 minute = (u32)(pts / 60); diff --git a/src/libsink/sink.h b/src/libsink/sink.h index 86c6a04..4e97f3a 100644 --- a/src/libsink/sink.h +++ b/src/libsink/sink.h @@ -119,6 +119,7 @@ void camu_sink_skip(struct camu_sink *sink, s32 n); void camu_sink_shuffle(struct camu_sink *sink); void camu_sink_toggle_pause(struct camu_sink *sink); void camu_sink_seek(struct camu_sink *sink, f64 pos); +void camu_sink_relative_seek(struct camu_sink *sink, f64 offset); void camu_sink_reseek(struct camu_sink *sink); void camu_sink_unset(struct camu_sink *sink); void camu_sink_set_volume(struct camu_sink *sink, f32 volume); |