From 24b58a516e6bacfdf59aac422411c2f1fcf4ffb2 Mon Sep 17 00:00:00 2001 From: Andrew Opalach Date: Wed, 1 Jan 2025 16:04:59 -0500 Subject: Optimizations based on video loop performance - Support nn_packet_stream direct mode - Hook up FFmpeg hardware accelerated decoding - Refactor VCR - Reduce locking when returning packets to a packet pool Signed-off-by: Andrew Opalach --- src/render/queue_libplacebo.c | 2 +- src/render/renderer.h | 7 ++++ src/render/renderer_libplacebo.c | 84 +++++++++++++++++++++++++++++----------- src/render/renderer_libplacebo.h | 3 ++ 4 files changed, 72 insertions(+), 24 deletions(-) (limited to 'src/render') diff --git a/src/render/queue_libplacebo.c b/src/render/queue_libplacebo.c index dfaa190..861dd5e 100644 --- a/src/render/queue_libplacebo.c +++ b/src/render/queue_libplacebo.c @@ -270,7 +270,7 @@ static void discard_av_frame(const struct pl_source_frame *src) { AVFrame *frame = src->frame_data; av_frame_free(&frame); - al_log_debug("frame_queue_libplacebo", "Dropped frame with PTS %.3f.", src->pts); + al_log_warn("frame_queue_libplacebo", "Dropped frame with PTS %.3f.", src->pts); } static void queue_lp_push_av_frame(struct camu_frame_queue *queue, AVFrame *frame, f64 pts) diff --git a/src/render/renderer.h b/src/render/renderer.h index 7afd8de..a9780e5 100644 --- a/src/render/renderer.h +++ b/src/render/renderer.h @@ -8,6 +8,9 @@ #if defined STELA_API_OPENGL #define CAMU_RENDERER_OPENGL +#ifdef STELA_USE_EGL +#include +#endif #elif defined STELA_API_VULKAN #define CAMU_RENDERER_VULKAN #endif @@ -22,6 +25,10 @@ struct camu_renderer { VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *), const char *const *(*vk_get_extensions)(u32 *), #elif defined CAMU_RENDERER_OPENGL +#ifdef STELA_USE_EGL + EGLDisplay display, + EGLContext context, +#endif void (*get_gl_proc_address(char const *procname))(void), bool (*gl_load_loader)(void *), bool (*gl_make_current)(void *), diff --git a/src/render/renderer_libplacebo.c b/src/render/renderer_libplacebo.c index c528da5..ad7e7fc 100644 --- a/src/render/renderer_libplacebo.c +++ b/src/render/renderer_libplacebo.c @@ -6,7 +6,6 @@ #endif #include "../screen/screen.h" -#include "../libsink/common.h" #include "../util/color_palette.h" #include "renderer_libplacebo.h" @@ -17,14 +16,20 @@ static f32 clear_color[4] = { 0.0f, 0.0f, 0.0f, 1.f }; static void renderer_lp_resize(struct camu_renderer *renderer, s32 *width, s32 *height) { struct camu_renderer_lp *lr = (struct camu_renderer_lp *)renderer; - if (lr->swapchain) pl_swapchain_resize(lr->swapchain, width, height); + if (lr->swapchain) { + if (lr->have_frame) { + pl_swapchain_submit_frame(lr->swapchain); + lr->have_frame = false; + } + pl_swapchain_resize(lr->swapchain, width, height); + } } static void log_callback(void *userdata, enum pl_log_level level, const char *message) { (void)userdata; (void)level; - al_log_debug("render_libplacebo", message); + al_log_info("render_libplacebo", message); } static bool renderer_lp_create_renderer(struct camu_renderer *renderer, s32 *width, s32 *height, @@ -33,6 +38,10 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, s32 *wid VkResult (*vk_create_surface)(void *, VkInstance, VkSurfaceKHR *), const char *const *(*vk_get_extensions)(u32 *), #elif defined CAMU_RENDERER_OPENGL +#ifdef STELA_USE_EGL + EGLDisplay display, + EGLContext context, +#endif void (*get_gl_proc_address(char const *procname))(void), bool (*gl_load_loader)(void *), bool (*gl_make_current)(void *), @@ -105,6 +114,10 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, s32 *wid .release_current = gl_release_current, .get_proc_addr = get_gl_proc_address, .get_proc_addr_ex = NULL, +#ifdef STELA_USE_EGL + .egl_display = display, + .egl_context = context, +#endif .priv = priv, )); if (!lr->gl) { @@ -127,6 +140,8 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, s32 *wid lr->renderer = pl_renderer_create(lr->logger, lr->gpu); + lr->have_frame = false; + pl_swapchain_resize(lr->swapchain, width, height); al_memset(&lr->params, 0, sizeof(struct pl_render_params)); @@ -136,8 +151,6 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, s32 *wid //lr->params = pl_render_high_quality_params; lr->params.deband_params = NULL; - // Don't let the cache treat different images of the same size as the same frame. - lr->params.skip_caching_single_frame = true; // Clear manually so we can draw multiple images per frame. lr->params.border = PL_CLEAR_SKIP; // Prioritize a more consistent image. @@ -164,6 +177,8 @@ static bool renderer_lp_create_renderer(struct camu_renderer *renderer, s32 *wid lr->ass = ass_library_init(); + lr->last_render_tick = nn_get_tick(); + return true; err: lr->r.free((struct camu_renderer **)&lr); @@ -200,33 +215,44 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree } #endif - struct pl_swapchain_frame frame; - struct pl_frame target; + if (!lr->have_frame) { + struct pl_swapchain_frame frame; + pl_swapchain_start_frame(lr->swapchain, &frame); + pl_frame_from_swapchain(&lr->target, &frame); + pl_frame_clear_rgba(lr->gpu, &lr->target, clear_color); + lr->have_frame = true; + } + + struct pl_frame *target = &lr->target; struct pl_frame_mix mix; - pl_swapchain_start_frame(lr->swapchain, &frame); - pl_frame_from_swapchain(&target, &frame); - pl_frame_clear_rgba(lr->gpu, &target, clear_color); + bool do_gpu_finish = false; struct camu_screen_video *video; while (scr->videos.size > 0) { bool any_eof = false; al_array_foreach_ptr(scr->videos, i, video) { - if (camu_video_buffer_read(video->buf, &mix)) { - // QUEUE_MORE doesn't return a frame obviously but don't treat it like an EOF. + bool weighted; + if (camu_video_buffer_read(video->buf, &mix, &weighted)) { + // If mix.frames is NULL, read() returned QUEUE_MORE. if (mix.frames) { - target.crop = mix.frames[0]->crop; - target.crop.x1 *= video->view.zoom / video->view.stretch; - target.crop.y1 *= video->view.zoom * video->view.stretch; - target.crop.x0 += video->view.x_offset; - target.crop.y0 += video->view.y_offset; - target.crop.x1 += video->view.x_offset; - target.crop.y1 += video->view.y_offset; - target.rotation = video->view.rotation; + // weighted is only set when read() returns QUEUE_OK. + do_gpu_finish |= weighted; + // Terrible hack. Let's us distinguish single frames with the same dimensions. + // Tied to a libplacebo patch to consider info_priv in the hash. + lr->params.info_priv = video->buf; + target->crop = mix.frames[0]->crop; + target->crop.x1 *= video->view.zoom / video->view.stretch; + target->crop.y1 *= video->view.zoom * video->view.stretch; + target->crop.x0 += video->view.x_offset; + target->crop.y0 += video->view.y_offset; + target->crop.x1 += video->view.x_offset; + target->crop.y1 += video->view.y_offset; + target->rotation = video->view.rotation; //lr->params.color_adjustment = pl_color_adjustment( // .saturation = 0.0 //); - pl_render_image_mix(lr->renderer, &mix, &target, &lr->params); + pl_render_image_mix(lr->renderer, &mix, target, &lr->params); } } else { any_eof = true; @@ -243,13 +269,25 @@ static void renderer_lp_render(struct camu_renderer *renderer, struct camu_scree } } - pl_swapchain_submit_frame(lr->swapchain); - if (scr->videos.size == 0 && !force) { return; } + pl_swapchain_submit_frame(lr->swapchain); pl_swapchain_swap_buffers(lr->swapchain); + lr->have_frame = false; + + if (do_gpu_finish) { + // Block until render completes. + pl_gpu_finish(lr->gpu); + } + + f64 tick = nn_get_tick(); + f64 frame_time = tick - lr->last_render_tick; + if (frame_time > 0.020) { + al_log_info("render_libplacebo", "FRAME_TIME: %fs", frame_time); + } + lr->last_render_tick = tick; } void renderer_lp_free(struct camu_renderer **renderer) diff --git a/src/render/renderer_libplacebo.h b/src/render/renderer_libplacebo.h index eff7a34..38407bb 100644 --- a/src/render/renderer_libplacebo.h +++ b/src/render/renderer_libplacebo.h @@ -26,7 +26,10 @@ struct camu_renderer_lp { pl_gpu gpu; pl_log logger; pl_swapchain swapchain; + struct pl_frame target; + bool have_frame; pl_renderer renderer; + f64 last_render_tick; struct pl_render_params params; ASS_Library *ass; }; -- cgit v1.2.3-101-g0448