summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Opalach <andrew@akon.city> 2024-12-27 11:02:38 -0500
committerAndrew Opalach <andrew@akon.city> 2024-12-27 11:02:38 -0500
commit4af2d16c06a8a67ab225caa61ccd94df3c572bdc (patch)
tree6f5b364ea409c93aa9f0b795f252ac78c7d833f9
parent9026e7f49f11e920eac666bd4159ec459b979623 (diff)
downloadcamu-4af2d16c06a8a67ab225caa61ccd94df3c572bdc.tar.gz
camu-4af2d16c06a8a67ab225caa61ccd94df3c572bdc.tar.bz2
camu-4af2d16c06a8a67ab225caa61ccd94df3c572bdc.zip
Fix some configurations, add sink loop mode
Signed-off-by: Andrew Opalach <andrew@akon.city>
-rw-r--r--src/buffer/audio.c4
-rw-r--r--src/buffer/clock.c11
-rw-r--r--src/buffer/frame_queue.h4
-rw-r--r--src/buffer/peak_buffer.c2
-rw-r--r--src/buffer/peak_buffer.h2
-rw-r--r--src/buffer/video.c1
-rw-r--r--src/cache/handlers/cdio.c17
-rw-r--r--src/fruits/cmv/cmv.c6
-rw-r--r--src/fruits/ctv/ctv.c56
-rw-r--r--src/fruits/droid/ctv/app/src/main/AndroidManifest.xml1
-rw-r--r--src/fruits/droid/ctv/gradle/libs.versions.toml2
-rw-r--r--src/liana/client.c4
-rw-r--r--src/libsink/common.h1
-rw-r--r--src/libsink/sink.c13
-rw-r--r--src/render/queue_libplacebo.c52
-rw-r--r--src/render/queue_tiger.c2
-rw-r--r--src/render/renderer.h2
-rw-r--r--src/render/renderer_libplacebo.c10
-rw-r--r--src/render/renderer_tiger.c3
-rw-r--r--src/screen/screen.c12
-rw-r--r--src/screen/screen.h3
-rw-r--r--src/sink/desktop.c7
-rw-r--r--subprojects/libnaunet.wrap2
-rw-r--r--subprojects/stela.wrap2
24 files changed, 141 insertions, 78 deletions
diff --git a/src/buffer/audio.c b/src/buffer/audio.c
index 5a956ec..c0556e2 100644
--- a/src/buffer/audio.c
+++ b/src/buffer/audio.c
@@ -143,7 +143,7 @@ static bool push_internal(struct camu_audio_buffer *buf, f64 pts, u8 **data, s32
}
size_t have = camu_audio_format_samples_to_bytes(&buf->fmt.req, (size_t)sample_count);
- size_t peak = camu_peak_buffer_size(&buf->peak);
+ size_t peak = camu_peak_buffer_get_size(&buf->peak);
if (space < have + peak) {
al_assert(have < buf->mark.min);
camu_peak_buffer_push(&buf->peak, data[0], have);
@@ -333,7 +333,7 @@ size_t camu_audio_buffer_read(struct camu_audio_buffer *buf, u8 *data, size_t re
if (have < req) { // We don't have enough data to fulfill our request.
if (flow == FLUSHED) { // Stream is flushed.
// Check peak buffer for any remaining data.
- ret = camu_peak_buffer_size(&buf->peak);
+ ret = camu_peak_buffer_get_size(&buf->peak);
if (ret > 0) {
// This doesn't break single reader, single writer because
// pushing data after a flush is not allowed.
diff --git a/src/buffer/clock.c b/src/buffer/clock.c
index cbf63d5..33118aa 100644
--- a/src/buffer/clock.c
+++ b/src/buffer/clock.c
@@ -14,8 +14,11 @@ void camu_clock_init(struct camu_clock *clock, void (*callback)(void *, u8), voi
static f64 calc_tick_offset(f64 tick, u64 now, u64 target)
{
- if (now > target) return tick - (now - target) / 1000000.0;
- else return tick + (target - now) / 1000000.0;
+ if (now > target) {
+ return tick - (now - target) / 1000000.0;
+ } else {
+ return tick + (target - now) / 1000000.0;
+ }
}
void camu_clock_set(struct camu_clock *clock, f64 base)
@@ -107,12 +110,15 @@ f64 camu_clock_get_pts(struct camu_clock *clock, f64 offset)
{
f64 pause = al_atomic_load(f64)(&clock->pause, AL_ATOMIC_ACQUIRE);
if (pause == PAUSED) return -1.0;
+
f64 current = nn_get_tick();
+
f64 tick = al_atomic_load(f64)(&clock->tick, AL_ATOMIC_RELAXED);
if (tick == -1.0) {
tick = al_atomic_compare_and_swap(f64)(&clock->tick, -1.0, current);
if (tick == -1.0) tick = current;
}
+
// pause > 0.0 means running or pause armed.
if (pause > 0.0 && current > pause) {
current = pause;
@@ -121,5 +127,6 @@ f64 camu_clock_get_pts(struct camu_clock *clock, f64 offset)
clock->callback(clock->userdata, CAMU_CLOCK_PAUSED);
}
}
+
return clock->base + (current - (tick + clock->offset)) + offset;
}
diff --git a/src/buffer/frame_queue.h b/src/buffer/frame_queue.h
index e3044f1..e40971d 100644
--- a/src/buffer/frame_queue.h
+++ b/src/buffer/frame_queue.h
@@ -16,10 +16,12 @@ enum {
struct camu_frame_queue {
struct camu_video_buffer *buf;
+#ifdef CAMU_HAVE_FFMPEG
+ bool (*configure_subtitles)(struct camu_frame_queue *, s32, s32, AVCodecParameters *);
+#endif
void (*push)(struct camu_frame_queue *, struct camu_codec_frame *, f64);
#ifdef CAMU_HAVE_FFMPEG
void (*push_av_frame)(struct camu_frame_queue *, AVFrame *, f64);
- bool (*configure_subtitles)(struct camu_frame_queue *, s32, s32, AVCodecParameters *);
void (*push_subtitle)(struct camu_frame_queue *, AVPacket *);
#endif
void (*flush)(struct camu_frame_queue *);
diff --git a/src/buffer/peak_buffer.c b/src/buffer/peak_buffer.c
index eec031a..9687a1f 100644
--- a/src/buffer/peak_buffer.c
+++ b/src/buffer/peak_buffer.c
@@ -13,7 +13,7 @@ void camu_peak_buffer_push(struct camu_peak_buffer *buf, u8 *data, size_t size)
nn_buffer_append(&buf->buf, data, size);
}
-size_t camu_peak_buffer_size(struct camu_peak_buffer *buf)
+size_t camu_peak_buffer_get_size(struct camu_peak_buffer *buf)
{
return nn_buffer_get_size(&buf->buf);
}
diff --git a/src/buffer/peak_buffer.h b/src/buffer/peak_buffer.h
index ebb9939..9bd3316 100644
--- a/src/buffer/peak_buffer.h
+++ b/src/buffer/peak_buffer.h
@@ -9,6 +9,6 @@ struct camu_peak_buffer {
void camu_peak_buffer_init(struct camu_peak_buffer *buf, size_t size);
void camu_peak_buffer_push(struct camu_peak_buffer *buf, u8 *data, size_t size);
-size_t camu_peak_buffer_size(struct camu_peak_buffer *buf);
+size_t camu_peak_buffer_get_size(struct camu_peak_buffer *buf);
u8 *camu_peak_buffer_flush(struct camu_peak_buffer *buf);
void camu_peak_buffer_free(struct camu_peak_buffer *buf);
diff --git a/src/buffer/video.c b/src/buffer/video.c
index 94c452d..245f3d2 100644
--- a/src/buffer/video.c
+++ b/src/buffer/video.c
@@ -47,7 +47,6 @@ bool camu_video_buffer_configure(struct camu_video_buffer *buf, struct camu_code
const char *format_name = camu_pixel_format_name(fmt->format);
if (!format_name) format_name = "unknown";
al_log_info("video_buffer", "Stream: %s (%dx%d) %s.", format_name, fmt->width, fmt->height, "IMAGE");
-
break;
}
#ifdef CAMU_HAVE_FFMPEG
diff --git a/src/cache/handlers/cdio.c b/src/cache/handlers/cdio.c
index b10bbf1..ffaaa62 100644
--- a/src/cache/handlers/cdio.c
+++ b/src/cache/handlers/cdio.c
@@ -14,11 +14,12 @@
static void cdio_log_messages(struct cch_handler_cdio *cdio)
{
char *error_messages = cdio_cddap_errors(cdio->drive);
- char *messages = cdio_cddap_messages(cdio->drive);
if (error_messages) {
al_log_error("cdio", "\n%s", error_messages);
cdio_cddap_free_messages(error_messages);
}
+
+ char *messages = cdio_cddap_messages(cdio->drive);
if (messages) {
al_log_info("cdio", "\n%s", messages);
cdio_cddap_free_messages(messages);
@@ -34,7 +35,8 @@ static bool handler_cdio_can_seek(struct cch_handler *handler)
static nn_thread_result NNWT_THREADCALL cd_read_thread(void *userdata)
{
struct cch_handler_cdio *cdio = (struct cch_handler_cdio *)userdata;
- while (1) {
+
+ for (;;) {
if (!al_atomic_load(s32)(&cdio->running, AL_ATOMIC_RELAXED)) {
// We don't care about how complete the disc read was.
return 0;
@@ -72,11 +74,13 @@ static nn_thread_result NNWT_THREADCALL cd_read_thread(void *userdata)
break;
}
}
+
if (cdio->sector <= cdio->end) {
al_log_warn("cdio", "Disc read cut short (sectors: %zd, end: %zd).", cdio->sector, cdio->end);
// We didn't read the full disc, disable waiters.
cch_threaded_waits_disable_all(&cdio->handler);
}
+
return 0;
}
@@ -148,9 +152,10 @@ static bool open_cd_drive(struct cch_handler_cdio *cdio)
al_log_warn("cdio", "Failed to set drive speed (%d).", ret);
}
- // Not sure what this is based on, but it can seemingly just be wrong.
track_t tracks = cdio_cddap_tracks(drive);
- al_log_info("cdio", "CD with %d tracks loaded.", tracks);
+ track_t first_track = cdio_get_first_track_num(drive->p_cdio);
+ track_t last_track = cdio_get_last_track_num(drive->p_cdio);
+ al_log_info("cdio", "CD with %d tracks loaded (%d-%d).", tracks, first_track, last_track);
al_array_reserve(cdio->handler.entry->chapters, tracks);
lsn_t start = cdio_cddap_disc_firstsector(drive);
@@ -196,7 +201,9 @@ struct cch_entry *cch_handler_cdio_create(void)
entry->handler->free = handler_cdio_free;
entry->handler->entry = entry;
al_str_from(&entry->handler->liana, "cdio");
- if (!open_cd_drive(cdio)) return NULL;
+ if (!open_cd_drive(cdio)) {
+ return NULL;
+ }
al_atomic_store(s32)(&cdio->running, 0, AL_ATOMIC_RELAXED);
nn_buffer_init(&cdio->buffer);
nn_buffer_ensure_space(&cdio->buffer, BYTES_PER_STEP);
diff --git a/src/fruits/cmv/cmv.c b/src/fruits/cmv/cmv.c
index 8509485..6fd1f38 100644
--- a/src/fruits/cmv/cmv.c
+++ b/src/fruits/cmv/cmv.c
@@ -12,7 +12,11 @@
#include "../common.h"
+#ifndef CAMU_SINK_ONLY
+#ifndef _WIN32
static str *CMV_UNIX_PATH = al_str_c("/tmp/cmv_sock");
+#endif
+#endif
struct cmv {
struct nn_event_loop loop;
@@ -87,7 +91,7 @@ s32 wmain(s32 argc, wchar_t **argv)
addr = CAMU_TEST_ADDR;
}
#else
- type = NNWT_SOCKET_TCP; addr = CAMU_SERVER_IP;
+ type = NNWT_SOCKET_TCP; addr = CAMU_TEST_ADDR;
#endif
#ifndef CAMU_SINK_ONLY
diff --git a/src/fruits/ctv/ctv.c b/src/fruits/ctv/ctv.c
index c7bd250..b350c8a 100644
--- a/src/fruits/ctv/ctv.c
+++ b/src/fruits/ctv/ctv.c
@@ -8,7 +8,9 @@
#include "../../mixer/audio_null.h"
#include "../../mixer/audio_miniaudio.h"
#include "../../sink/common.h"
-#include "../../server/common.c"
+#include "../../server/common.h"
+
+#include "../common.h"
struct ctv {
struct nn_event_loop loop;
@@ -44,37 +46,44 @@ static nn_thread_result NNWT_THREADCALL event_loop_thread(void *userdata)
return 0;
}
+static void to_be_removed_inline_create_client(struct ctv *c, GLFMDisplay *display)
+{
+ c->scr.callback = screen_callback;
+ c->scr.userdata = c;
+ camu_screen_init(&c->scr, display);
+ camu_screen_create_window(&c->scr, "ctv");
+ c->renderer = camu_renderer_lp_create();
+ camu_screen_create_renderer(&c->scr, c->renderer);
+
+ camu_mixer_init(&c->mixer, camu_audio_miniaudio_create());
+ c->mixer.audio->configure_stream(c->mixer.audio, NULL);
+ camu_mixer_pick_format(&c->mixer, &c->mixer.fmt);
+
+ nn_event_loop_init(&c->loop);
+
+ camu_sink_init(&c->sink, &c->loop, &c->mixer, c->renderer);
+ al_str_from(&c->sink.default_list, "default");
+ c->sink.callback = sink_callback;
+ c->sink.userdata = c;
+ camu_sink_connect(&c->sink, NNWT_SOCKET_TCP, CAMU_TEST_IP, CAMU_PORT, al_str_c("ctv"));
+
+ nn_thread_create(&c->thread, event_loop_thread, c);
+}
+
static void onSurfaceCreated(GLFMDisplay *display, s32 width, s32 height)
{
struct ctv *c = (struct ctv *)glfmGetUserData(display);
(void)width;
(void)height;
+
GLFMRenderingAPI api = glfmGetRenderingAPI(display);
al_log_info("window_glfm", "Created GLES context of version %s.",
api == GLFMRenderingAPIOpenGLES32 ? "3.2" :
api == GLFMRenderingAPIOpenGLES31 ? "3.1" :
api == GLFMRenderingAPIOpenGLES3 ? "3.0" : "2.0");
- if (!c->created) {
- c->scr.callback = screen_callback;
- c->scr.userdata = c;
- camu_screen_init(&c->scr, display);
- camu_screen_create_window(&c->scr, "ctv");
- c->renderer = camu_renderer_lp_create();
- camu_screen_create_renderer(&c->scr, c->renderer);
-
- camu_mixer_init(&c->mixer, camu_audio_miniaudio_create());
- c->mixer.audio->configure_stream(c->mixer.audio, NULL);
- camu_mixer_pick_format(&c->mixer, &c->mixer.fmt);
-
- nn_event_loop_init(&c->loop);
-
- camu_sink_init(&c->sink, &c->loop, &c->mixer, c->renderer);
- c->sink.callback = sink_callback;
- c->sink.userdata = c;
- camu_sink_connect(&c->sink, NNWT_SOCKET_TCP, CAMU_SERVER_IP, CAMU_PORT, al_str_c("ctv"));
-
- nn_thread_create(&c->thread, event_loop_thread, c);
+ if (!c->created) {
+ to_be_removed_inline_create_client(c, display);
c->created = true;
}
}
@@ -87,8 +96,9 @@ static void onSurfaceDestroyed(GLFMDisplay *display)
static void onDraw(GLFMDisplay *display)
{
struct ctv *c = (struct ctv *)glfmGetUserData(display);
- if (camu_screen_tick(&c->scr)) {
- c->renderer->render(c->renderer, &c->scr);
+ bool force;
+ if (camu_screen_tick(&c->scr, &force)) {
+ c->renderer->render(c->renderer, &c->scr, force);
}
}
diff --git a/src/fruits/droid/ctv/app/src/main/AndroidManifest.xml b/src/fruits/droid/ctv/app/src/main/AndroidManifest.xml
index 00f96c1..cca763f 100644
--- a/src/fruits/droid/ctv/app/src/main/AndroidManifest.xml
+++ b/src/fruits/droid/ctv/app/src/main/AndroidManifest.xml
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<uses-permission android:name="android.permission.INTERNET" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-feature android:name="android.software.leanback"
android:required="false" />
<uses-feature android:name="android.hardware.touchscreen"
diff --git a/src/fruits/droid/ctv/gradle/libs.versions.toml b/src/fruits/droid/ctv/gradle/libs.versions.toml
index c474f95..ea02696 100644
--- a/src/fruits/droid/ctv/gradle/libs.versions.toml
+++ b/src/fruits/droid/ctv/gradle/libs.versions.toml
@@ -1,5 +1,5 @@
[versions]
-agp = "8.7.2"
+agp = "8.7.3"
[libraries]
diff --git a/src/liana/client.c b/src/liana/client.c
index 1ba09cc..e9dd536 100644
--- a/src/liana/client.c
+++ b/src/liana/client.c
@@ -208,10 +208,10 @@ void lia_client_connect(struct lia_client *client, struct nn_event_loop *loop, u
lia_vcr_init(&client->vcr, client->loop, &client->data);
al_str_clone(&client->addr, addr);
client->port = port;
- if (!nn_packet_stream_init(&client->data, type, connection_callback, connection_closed_callback, client)) {
+ if (!nn_packet_stream_init(&client->data, type, CAMU_MULTIPLEX_LIANA,
+ connection_callback, connection_closed_callback, client)) {
connection_closed_callback(client, &client->data);
}
- nn_packet_stream_set_multiplex(&client->data, CAMU_MULTIPLEX_LIANA);
client->renderer = renderer;
nn_packet_stream_connect(&client->data, client->loop, &client->addr, client->port);
}
diff --git a/src/libsink/common.h b/src/libsink/common.h
index 0bb3ded..dc0b207 100644
--- a/src/libsink/common.h
+++ b/src/libsink/common.h
@@ -1,6 +1,7 @@
#pragma once
#define CAMU_SINK_LOCAL
+//#define CAMU_SINK_SCUFFED_LOOP
enum {
CAMU_SINK_SET = 0,
diff --git a/src/libsink/sink.c b/src/libsink/sink.c
index 9b5c05e..12b8bca 100644
--- a/src/libsink/sink.c
+++ b/src/libsink/sink.c
@@ -433,12 +433,12 @@ static void maybe_add_to_previous(struct camu_sink *sink, struct camu_sink_entry
}
}
- // If neither the entries audio or video buffer is ADDED, we don't care about adding it
+ // If neither of the entries audio or video buffer is ADDED, we don't care about adding it
// to previous (waiting for the next added entry to remove it).
#ifndef CAMU_SINK_NO_VIDEO
if (!(previous->audio.state == BUFFER_ADDED || previous->video.state == BUFFER_ADDED) || target->ended) {
#else
- if (!(previous->audio.state == BUFFER_ADDED) || target->ended)
+ if (!(previous->audio.state == BUFFER_ADDED) || target->ended) {
#endif
remove_entry_buffers(sink, previous);
return;
@@ -629,6 +629,15 @@ static void pause_and_swap_to(struct camu_sink *sink, struct camu_sink_entry *ta
static bool end_entry_and_advance_queue(struct camu_sink *sink, struct camu_sink_entry *entry)
{
+#ifdef CAMU_SINK_SCUFFED_LOOP
+ al_log_info("sink", "Looping.");
+ queue_cmd(sink, (struct camu_sink_cmd){
+ .op = SEEK,
+ .value.f = 0.0,
+ .opaque = entry
+ });
+ return true;
+#endif
al_log_info("sink", "Entry ended.");
entry->ended = true;
queue_cmd(sink, (struct camu_sink_cmd){
diff --git a/src/render/queue_libplacebo.c b/src/render/queue_libplacebo.c
index 07ce379..dfaa190 100644
--- a/src/render/queue_libplacebo.c
+++ b/src/render/queue_libplacebo.c
@@ -9,6 +9,31 @@
#include "queue_libplacebo.h"
+#ifdef CAMU_HAVE_FFMPEG
+static bool queue_lp_configure_subtitiles(struct camu_frame_queue *queue, s32 width, s32 height, AVCodecParameters *codecpar)
+{
+ struct camu_frame_queue_lp *lq = (struct camu_frame_queue_lp *)queue;
+ if (!lq->ass) return false;
+ lq->ass_renderer = ass_renderer_init(lq->ass);
+ if (!lq->ass_renderer) {
+ al_log_error("frame_queue_libplacebo", "Failed to initialize ass renderer.");
+ return false;
+ }
+ lq->ass_track = ass_new_track(lq->ass);
+ if (!lq->ass_track) {
+ al_log_error("frame_queue_libplacebo", "Failed to create ass track.");
+ return false;
+ }
+ ass_set_frame_size(lq->ass_renderer, width, height);
+ ass_set_storage_size(lq->ass_renderer, width, height);
+ ass_set_fonts(lq->ass_renderer, NULL, NULL, ASS_FONTPROVIDER_AUTODETECT, NULL, 0);
+ ass_process_codec_private(lq->ass_track, (const char *)codecpar->extradata,
+ codecpar->extradata_size);
+ lq->have_subtitles = true;
+ return true;
+}
+#endif
+
static bool map_frame(pl_gpu gpu, pl_tex *tex, const struct pl_source_frame *src,
struct pl_frame *out_frame)
{
@@ -264,29 +289,6 @@ static void queue_lp_push_av_frame(struct camu_frame_queue *queue, AVFrame *fram
});
}
-static bool queue_lp_configure_subtitiles(struct camu_frame_queue *queue, s32 width, s32 height, AVCodecParameters *codecpar)
-{
- struct camu_frame_queue_lp *lq = (struct camu_frame_queue_lp *)queue;
- if (!lq->ass) return false;
- lq->ass_renderer = ass_renderer_init(lq->ass);
- if (!lq->ass_renderer) {
- al_log_error("frame_queue_libplacebo", "Failed to initialize ass renderer.");
- return false;
- }
- lq->ass_track = ass_new_track(lq->ass);
- if (!lq->ass_track) {
- al_log_error("frame_queue_libplacebo", "Failed to create ass track.");
- return false;
- }
- ass_set_frame_size(lq->ass_renderer, width, height);
- ass_set_storage_size(lq->ass_renderer, width, height);
- ass_set_fonts(lq->ass_renderer, NULL, NULL, ASS_FONTPROVIDER_AUTODETECT, NULL, 0);
- ass_process_codec_private(lq->ass_track, (const char *)codecpar->extradata,
- codecpar->extradata_size);
- lq->have_subtitles = true;
- return true;
-}
-
static void queue_lp_push_subtitle(struct camu_frame_queue *queue, AVPacket *pkt)
{
struct camu_frame_queue_lp *lq = (struct camu_frame_queue_lp *)queue;
@@ -350,10 +352,12 @@ struct camu_frame_queue *camu_frame_queue_lp_create(void)
struct camu_frame_queue_lp *lq = al_alloc_object(struct camu_frame_queue_lp);
al_array_init(lq->overlays);
lq->have_subtitles = false;
+#ifdef CAMU_HAVE_FFMPEG
+ lq->q.configure_subtitles = queue_lp_configure_subtitiles;
+#endif
lq->q.push = queue_lp_push;
#ifdef CAMU_HAVE_FFMPEG
lq->q.push_av_frame = queue_lp_push_av_frame;
- lq->q.configure_subtitles = queue_lp_configure_subtitiles;
lq->q.push_subtitle = queue_lp_push_subtitle;
#endif
lq->q.flush = queue_lp_flush;
diff --git a/src/render/queue_tiger.c b/src/render/queue_tiger.c
index bbc2b6e..d21236d 100644
--- a/src/render/queue_tiger.c
+++ b/src/render/queue_tiger.c
@@ -3,6 +3,8 @@
#include "queue_tiger.h"
+#define GL_UNPACK_ROW_LENGTH 0x0CF2
+
static void upload_texture(struct camu_frame_queue_tiger *tq, u8 *data, s32 width, s32 height, s32 format, s32 linesize)
{
glGenTextures(1, &tq->texture_id);
diff --git a/src/render/renderer.h b/src/render/renderer.h
index b304fdf..7afd8de 100644
--- a/src/render/renderer.h
+++ b/src/render/renderer.h
@@ -33,7 +33,7 @@ struct camu_renderer {
struct camu_frame_queue *(*create_queue)(struct camu_renderer *);
u32 (*get_latency)(struct camu_renderer *);
void (*resize)(struct camu_renderer *, s32 *, s32 *);
- void (*render)(struct camu_renderer *, struct camu_screen *);
+ void (*render)(struct camu_renderer *, struct camu_screen *, bool);
#ifdef CAMU_HAVE_FFMPEG
s32 (*get_buffer2)(struct AVCodecContext *s, AVFrame *frame, s32 flags);
void *opaque;
diff --git a/src/render/renderer_libplacebo.c b/src/render/renderer_libplacebo.c
index 9fedc5f..8359798 100644
--- a/src/render/renderer_libplacebo.c
+++ b/src/render/renderer_libplacebo.c
@@ -6,6 +6,7 @@
#endif
#include "../screen/screen.h"
+#include "../libsink/common.h"
#include "../util/color_palette.h"
#include "renderer_libplacebo.h"
@@ -189,7 +190,7 @@ static u32 renderer_lp_get_latency(struct camu_renderer *renderer)
return (u32)pl_swapchain_latency(lr->swapchain);
}
-static void renderer_lp_render(struct camu_renderer *renderer, struct camu_screen *scr)
+static void renderer_lp_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
{
struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer;
@@ -243,6 +244,13 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree
}
pl_swapchain_submit_frame(lr->swapchain);
+
+#ifdef CAMU_SINK_SCUFFED_LOOP
+ if (scr->videos.size == 0 && !force) {
+ return;
+ }
+#endif
+
pl_swapchain_swap_buffers(lr->swapchain);
}
diff --git a/src/render/renderer_tiger.c b/src/render/renderer_tiger.c
index 74d9238..74db594 100644
--- a/src/render/renderer_tiger.c
+++ b/src/render/renderer_tiger.c
@@ -221,10 +221,11 @@ static mat4x4 model = { 0 };
static GLuint texture0 = 0;
#endif
-static void renderer_tiger_render(struct camu_renderer *renderer, struct camu_screen *scr)
+static void renderer_tiger_render(struct camu_renderer *renderer, struct camu_screen *scr, bool force)
{
#ifdef CAMU_RENDERER_OPENGL
struct camu_renderer_tiger *tr = (struct camu_renderer_tiger *)renderer;
+ (void)force;
tr->make_current(tr->priv);
diff --git a/src/screen/screen.c b/src/screen/screen.c
index 17f4e3b..c323204 100644
--- a/src/screen/screen.c
+++ b/src/screen/screen.c
@@ -38,13 +38,15 @@ static void resize_callback(void *userdata, s32 width, s32 height)
al_array_foreach_ptr(scr->videos, i, video) {
camu_view_calculate(&video->view, scr->width, scr->height);
}
+ scr->force_render = true;
}
static void refresh_callback(void *userdata)
{
struct camu_screen *scr = (struct camu_screen *)userdata;
if (scr->renderer) {
- scr->renderer->render(scr->renderer, scr);
+ // The thread-safety of this is questionable.
+ scr->renderer->render(scr->renderer, scr, true);
}
}
@@ -512,12 +514,16 @@ bool camu_screen_poll(struct camu_screen *scr, bool block)
#endif
}
-bool camu_screen_tick(struct camu_screen *scr)
+bool camu_screen_tick(struct camu_screen *scr, bool *force)
{
s32 state = al_atomic_load(s32)(&scr->state, AL_ATOMIC_RELAXED);
al_assert(state != CAMU_SCREEN_STOPPED);
bool paused = state == CAMU_SCREEN_PAUSED;
- return camu_screen_poll(scr, paused) || !paused;
+ bool render = camu_screen_poll(scr, paused) || !paused;
+ render |= scr->force_render;
+ *force = scr->force_render;
+ scr->force_render = false;
+ return render;
}
void camu_screen_wake(struct camu_screen *scr)
diff --git a/src/screen/screen.h b/src/screen/screen.h
index 80f888c..d567521 100644
--- a/src/screen/screen.h
+++ b/src/screen/screen.h
@@ -56,6 +56,7 @@ struct camu_screen {
struct nn_thread thread;
#endif
struct camu_renderer *renderer;
+ bool force_render;
s32 width;
s32 height;
u64 last_click_ts;
@@ -83,6 +84,6 @@ void camu_screen_clear(struct camu_screen *scr);
#endif
void camu_screen_set_state(struct camu_screen *scr, s32 state);
bool camu_screen_poll(struct camu_screen *scr, bool block);
-bool camu_screen_tick(struct camu_screen *scr);
+bool camu_screen_tick(struct camu_screen *scr, bool *force);
void camu_screen_wake(struct camu_screen *scr);
void camu_screen_close(struct camu_screen *scr);
diff --git a/src/sink/desktop.c b/src/sink/desktop.c
index 4a1b9ca..5529a3b 100644
--- a/src/sink/desktop.c
+++ b/src/sink/desktop.c
@@ -86,7 +86,7 @@ bool camu_desktop_init(struct camu_desktop *c, const char *name)
if (!camu_screen_create_renderer(&c->scr, c->renderer)) {
return false;
}
- c->renderer->render(c->renderer, &c->scr);
+ c->renderer->render(c->renderer, &c->scr, true);
if (!camu_mixer_init(&c->mixer, camu_audio_miniaudio_create())) {
//if (!camu_mixer_init(&c->mixer, (struct camu_audio *)&audio_plugin_null)) {
return false;
@@ -113,8 +113,9 @@ bool camu_desktop_connect(struct camu_desktop *c, u8 type, struct nn_event_loop
bool camu_desktop_tick(struct camu_desktop *c)
{
- if (!c->should_quit && camu_screen_tick(&c->scr)) {
- c->renderer->render(c->renderer, &c->scr);
+ bool force;
+ if (!c->should_quit && camu_screen_tick(&c->scr, &force)) {
+ c->renderer->render(c->renderer, &c->scr, force);
}
return !c->should_quit;
}
diff --git a/subprojects/libnaunet.wrap b/subprojects/libnaunet.wrap
index df8a1f6..833aff8 100644
--- a/subprojects/libnaunet.wrap
+++ b/subprojects/libnaunet.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/libnaunet
-revision = f5df41d650ea03de846466c66a62d0517b22f375
+revision = be4eb3831a2e5b44fb6e4c2d077e3c07edf6b776
depth = 1
diff --git a/subprojects/stela.wrap b/subprojects/stela.wrap
index a44296c..adb6090 100644
--- a/subprojects/stela.wrap
+++ b/subprojects/stela.wrap
@@ -1,4 +1,4 @@
[wrap-git]
url = https://git.akon.city/stela
-revision = 6fe15ce0d41bd55331cac006134b61c1704775c3
+revision = d8538d6616258e4920ba301edd2c86d4edc437c4
depth = 1