summaryrefslogtreecommitdiff
path: root/src/libsink
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2025-03-03 12:53:14 -0500
committerAndrew Opalach <andrew@akon.city> 2025-03-03 12:53:14 -0500
commit1224a43bbde9ef2297c7ee638b1928a07488cc3d (patch)
tree8cfb0ffe2f35c9c12bc20ab65185f08946eda243 /src/libsink
parent000ce1f671d1f05b76202fd128e272e4ac9da683 (diff)
downloadcamu-1224a43bbde9ef2297c7ee638b1928a07488cc3d.tar.gz
camu-1224a43bbde9ef2297c7ee638b1928a07488cc3d.tar.bz2
camu-1224a43bbde9ef2297c7ee638b1928a07488cc3d.zip
Fix vcr memory leak, subtitle upload/render sync
- Some sink behavior fixes. - Fix clock sync when seeking. - Add relative seek bind. Signed-off-by: Andrew Opalach <andrew@akon.city>
Diffstat (limited to 'src/libsink')
-rw-r--r--src/libsink/sink.c61
-rw-r--r--src/libsink/sink.h1
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(&current->clock, 0.0, false);
- if (pts == -1.0) {
-#ifndef CAMU_SINK_NO_VIDEO
- pts = al_atomic_load(f64)(&current->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);