From 8e6c374acf10229195746b3c553a07d15017ea69 Mon Sep 17 00:00:00 2001 From: Maxim Devaev Date: Fri, 29 Mar 2024 15:36:43 +0200 Subject: [PATCH] refactoring --- src/libs/drm/drm.c | 56 +++++++++++++++++++++++++++------ src/libs/drm/drm.h | 9 ++++-- src/ustreamer/options.c | 8 ++++- src/ustreamer/options.h | 6 ++++ src/ustreamer/stream.c | 69 ++++++++++++----------------------------- src/ustreamer/stream.h | 8 +---- src/v4p/main.c | 30 ++++-------------- 7 files changed, 94 insertions(+), 92 deletions(-) diff --git a/src/libs/drm/drm.c b/src/libs/drm/drm.c index 124b009e..3c6594a5 100644 --- a/src/libs/drm/drm.c +++ b/src/libs/drm/drm.c @@ -72,6 +72,7 @@ us_drm_s *us_drm_init(void) { run->fd = -1; run->status_fd = -1; run->dpms_state = -1; + run->opened = -1; run->has_vsync = true; run->exposing_dma_fd = -1; run->ft = us_frametext_init(); @@ -82,6 +83,7 @@ us_drm_s *us_drm_init(void) { drm->path = "/dev/dri/by-path/platform-gpu-card"; drm->port = "HDMI-A-2"; // OUT2 on PiKVM V4 Plus drm->timeout = 5; + drm->blank_after = 5; drm->run = run; return drm; } @@ -97,6 +99,8 @@ int us_drm_open(us_drm_s *drm, const us_capture_s *cap) { assert(run->fd < 0); + _LOG_INFO("Using passthrough: %s[%s]", drm->path, drm->port); + switch (_drm_check_status(drm)) { case 0: break; case US_ERROR_NO_DEVICE: goto unplugged; @@ -164,22 +168,24 @@ int us_drm_open(us_drm_s *drm, const us_capture_s *cap) { goto error; } - run->opened_for_stub = (stub > 0); + _LOG_INFO("Opened for %s ...", (stub > 0 ? "STUB" : "DMA")); run->exposing_dma_fd = -1; - run->unplugged_once = 0; - _LOG_INFO("Opened for %s ...", (run->opened_for_stub ? "STUB" : "DMA")); - return stub; + run->blank_at_ts = 0; + run->opened = stub; + run->once = 0; + return run->opened; error: us_drm_close(drm); - return -1; + return run->opened; // -1 after us_drm_close() unplugged: - US_ONCE_FOR(run->unplugged_once, __LINE__, { + US_ONCE_FOR(run->once, __LINE__, { _LOG_ERROR("Display is not plugged"); }); us_drm_close(drm); - return US_ERROR_NO_DEVICE; + run->opened = US_ERROR_NO_DEVICE; + return run->opened; } void us_drm_close(us_drm_s *drm) { @@ -233,6 +239,7 @@ void us_drm_close(us_drm_s *drm) { run->crtc_id = 0; run->dpms_state = -1; + run->opened = -1; run->has_vsync = true; run->stub_n_buf = 0; @@ -241,6 +248,34 @@ void us_drm_close(us_drm_s *drm) { } } +int us_drm_ensure_no_signal(us_drm_s *drm) { + us_drm_runtime_s *const run = drm->run; + + assert(run->fd >= 0); + assert(run->opened > 0); + + const ldf now_ts = us_get_now_monotonic(); + if (run->blank_at_ts == 0) { + run->blank_at_ts = now_ts + drm->blank_after; + } + const ldf saved_ts = run->blank_at_ts; // us_drm*() rewrites it to 0 + + int retval; + if (now_ts <= run->blank_at_ts) { + retval = us_drm_wait_for_vsync(drm); + if (retval == 0) { + retval = us_drm_expose_stub(drm, US_DRM_STUB_NO_SIGNAL, NULL); + } + } else { + US_ONCE_FOR(run->once, __LINE__, { + _LOG_INFO("Turning off the display by timeout ..."); + }); + retval = us_drm_dpms_power_off(drm); + } + run->blank_at_ts = saved_ts; + return retval; +} + int us_drm_dpms_power_off(us_drm_s *drm) { assert(drm->run->fd >= 0); switch (_drm_check_status(drm)) { @@ -259,6 +294,7 @@ int us_drm_wait_for_vsync(us_drm_s *drm) { us_drm_runtime_s *const run = drm->run; assert(run->fd >= 0); + run->blank_at_ts = 0; switch (_drm_check_status(drm)) { case 0: break; @@ -313,7 +349,8 @@ int us_drm_expose_stub(us_drm_s *drm, us_drm_stub_e stub, const us_capture_s *ca us_drm_runtime_s *const run = drm->run; assert(run->fd >= 0); - assert(run->opened_for_stub); + assert(run->opened > 0); + run->blank_at_ts = 0; switch (_drm_check_status(drm)) { case 0: break; @@ -377,7 +414,8 @@ int us_drm_expose_dma(us_drm_s *drm, const us_capture_hwbuf_s *hw) { us_drm_buffer_s *const buf = &run->bufs[hw->buf.index]; assert(run->fd >= 0); - assert(!run->opened_for_stub); + assert(run->opened == 0); + run->blank_at_ts = 0; switch (_drm_check_status(drm)) { case 0: break; diff --git a/src/libs/drm/drm.h b/src/libs/drm/drm.h index a45c1d79..91bb8878 100644 --- a/src/libs/drm/drm.h +++ b/src/libs/drm/drm.h @@ -63,11 +63,14 @@ typedef struct { uint n_bufs; drmModeCrtc *saved_crtc; int dpms_state; - bool opened_for_stub; + int opened; + bool has_vsync; int exposing_dma_fd; uint stub_n_buf; - int unplugged_once; + ldf blank_at_ts; + + int once; us_frametext_s *ft; } us_drm_runtime_s; @@ -75,6 +78,7 @@ typedef struct { char *path; char *port; uint timeout; + uint blank_after; us_drm_runtime_s *run; } us_drm_s; @@ -90,3 +94,4 @@ int us_drm_dpms_power_off(us_drm_s *drm); int us_drm_wait_for_vsync(us_drm_s *drm); int us_drm_expose_stub(us_drm_s *drm, us_drm_stub_e stub, const us_capture_s *cap); int us_drm_expose_dma(us_drm_s *drm, const us_capture_hwbuf_s *hw); +int us_drm_ensure_no_signal(us_drm_s *drm); diff --git a/src/ustreamer/options.c b/src/ustreamer/options.c index a9f25e99..143d4579 100644 --- a/src/ustreamer/options.c +++ b/src/ustreamer/options.c @@ -270,6 +270,9 @@ void us_options_destroy(us_options_s *options) { US_DELETE(options->jpeg_sink, us_memsink_destroy); US_DELETE(options->raw_sink, us_memsink_destroy); US_DELETE(options->h264_sink, us_memsink_destroy); +# ifdef WITH_V4P + US_DELETE(options->drm, us_drm_destroy); +# endif for (unsigned index = 0; index < options->argc; ++index) { free(options->argv_copy[index]); @@ -463,7 +466,10 @@ int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, u case _O_H264_M2M_DEVICE: OPT_SET(stream->h264_m2m_path, optarg); # ifdef WITH_V4P - case _O_V4P: OPT_SET(stream->v4p, true); + case _O_V4P: + options->drm = us_drm_init(); + stream->drm = options->drm; + break; # endif # ifdef WITH_GPIO diff --git a/src/ustreamer/options.h b/src/ustreamer/options.h index aa76eb4f..611c4141 100644 --- a/src/ustreamer/options.h +++ b/src/ustreamer/options.h @@ -40,6 +40,9 @@ #include "../libs/memsink.h" #include "../libs/options.h" #include "../libs/capture.h" +#ifdef WITH_V4P +# include "../libs/drm/drm.h" +#endif #include "encoder.h" #include "stream.h" @@ -56,6 +59,9 @@ typedef struct { us_memsink_s *jpeg_sink; us_memsink_s *raw_sink; us_memsink_s *h264_sink; +# ifdef WITH_V4P + us_drm_s *drm; +# endif } us_options_s; diff --git a/src/ustreamer/stream.c b/src/ustreamer/stream.c index 57274c7d..d18087ad 100644 --- a/src/ustreamer/stream.c +++ b/src/ustreamer/stream.c @@ -138,14 +138,6 @@ void us_stream_loop(us_stream_s *stream) { run->h264 = us_h264_stream_init(stream->h264_sink, stream->h264_m2m_path, stream->h264_bitrate, stream->h264_gop); } -# ifdef WITH_V4P - if (stream->v4p) { - run->drm = us_drm_init(); - run->drm_opened = -1; - US_LOG_INFO("Using passthrough: %s[%s]", run->drm->path, run->drm->port); - } -# endif - while (!_stream_init_loop(stream)) { atomic_bool threads_stop; atomic_init(&threads_stop, false); @@ -177,7 +169,7 @@ void us_stream_loop(us_stream_s *stream) { CREATE_WORKER((run->h264 != NULL), h264_ctx, _h264_thread, cap->run->n_bufs); CREATE_WORKER((stream->raw_sink != NULL), raw_ctx, _raw_thread, 2); # ifdef WITH_V4P - CREATE_WORKER((run->drm != NULL), drm_ctx, _drm_thread, cap->run->n_bufs); // cppcheck-suppress assertWithSideEffect + CREATE_WORKER((stream->drm != NULL), drm_ctx, _drm_thread, cap->run->n_bufs); // cppcheck-suppress assertWithSideEffect # endif # undef CREATE_WORKER @@ -267,9 +259,6 @@ void us_stream_loop(us_stream_s *stream) { } } -# ifdef WITH_V4P - US_DELETE(run->drm, us_drm_destroy); -# endif US_DELETE(run->h264, us_h264_stream_destroy); } @@ -453,11 +442,10 @@ static void *_raw_thread(void *v_ctx) { static void *_drm_thread(void *v_ctx) { US_THREAD_SETTLE("str_drm"); _worker_context_s *ctx = v_ctx; - us_stream_runtime_s *run = ctx->stream->run; + us_stream_s *stream = ctx->stream; // Close previously opened DRM for a stub - us_drm_close(run->drm); - run->drm_opened = -1; + us_drm_close(stream->drm); us_capture_hwbuf_s *prev_hw = NULL; while (!atomic_load(ctx->stop)) { @@ -472,10 +460,10 @@ static void *_drm_thread(void *v_ctx) { } \ } - CHECK(run->drm_opened = us_drm_open(run->drm, ctx->stream->cap)); + CHECK(us_drm_open(stream->drm, ctx->stream->cap)); while (!atomic_load(ctx->stop)) { - CHECK(us_drm_wait_for_vsync(run->drm)); + CHECK(us_drm_wait_for_vsync(stream->drm)); US_DELETE(prev_hw, us_capture_hwbuf_decref); us_capture_hwbuf_s *hw = _get_latest_hw(ctx->queue); @@ -483,21 +471,20 @@ static void *_drm_thread(void *v_ctx) { continue; } - if (run->drm_opened == 0) { - CHECK(us_drm_expose_dma(run->drm, hw)); + if (stream->drm->run->opened == 0) { + CHECK(us_drm_expose_dma(stream->drm, hw)); prev_hw = hw; continue; } - CHECK(us_drm_expose_stub(run->drm, run->drm_opened, ctx->stream->cap)); + CHECK(us_drm_expose_stub(stream->drm, stream->drm->run->opened, ctx->stream->cap)); us_capture_hwbuf_decref(hw); SLOWDOWN; } close: - us_drm_close(run->drm); - run->drm_opened = -1; + us_drm_close(stream->drm); US_DELETE(prev_hw, us_capture_hwbuf_decref); SLOWDOWN; @@ -536,7 +523,7 @@ static bool _stream_has_any_clients_cached(us_stream_s *stream) { || (run->h264 != NULL && atomic_load(&run->h264->sink->has_clients)) || (stream->raw_sink != NULL && atomic_load(&stream->raw_sink->has_clients)) # ifdef WITH_V4P - || (run->drm != NULL) + || (stream->drm != NULL) # endif ); } @@ -568,7 +555,7 @@ static int _stream_init_loop(us_stream_s *stream) { stream->enc->type == US_ENCODER_TYPE_M2M_VIDEO || stream->enc->type == US_ENCODER_TYPE_M2M_IMAGE || run->h264 != NULL - || run->drm != NULL + || stream->drm != NULL ); switch (us_capture_open(stream->cap)) { case 0: break; @@ -618,37 +605,21 @@ static int _stream_init_loop(us_stream_s *stream) { #ifdef WITH_V4P static void _stream_drm_ensure_no_signal(us_stream_s *stream) { - us_stream_runtime_s *const run = stream->run; - - if (run->drm == NULL) { + if (stream->drm == NULL) { return; } - -# define CHECK(x_arg) if ((x_arg) < 0) { goto close; } - if (run->drm_opened <= 0) { - us_drm_close(run->drm); - run->drm_blank_at_ts = 0; - CHECK(run->drm_opened = us_drm_open(run->drm, NULL)); + if (stream->drm->run->opened <= 0) { + us_drm_close(stream->drm); + if (us_drm_open(stream->drm, NULL) < 0) { + goto close; + } } - - ldf now_ts = us_get_now_monotonic(); - if (run->drm_blank_at_ts == 0) { - run->drm_blank_at_ts = now_ts + 5; - } - - if (now_ts <= run->drm_blank_at_ts) { - CHECK(us_drm_wait_for_vsync(run->drm)); - CHECK(us_drm_expose_stub(run->drm, US_DRM_STUB_NO_SIGNAL, NULL)); - } else { - // US_ONCE({ US_LOG_INFO("DRM: Turning off the display by timeout ..."); }); - CHECK(us_drm_dpms_power_off(run->drm)); + if (us_drm_ensure_no_signal(stream->drm) < 0) { + goto close; } return; -# undef CHECK - close: - us_drm_close(run->drm); - run->drm_opened = -1; + us_drm_close(stream->drm); } #endif diff --git a/src/ustreamer/stream.h b/src/ustreamer/stream.h index e51fde19..4aa2ed1e 100644 --- a/src/ustreamer/stream.h +++ b/src/ustreamer/stream.h @@ -43,12 +43,6 @@ typedef struct { us_h264_stream_s *h264; -# ifdef WITH_V4P - us_drm_s *drm; - int drm_opened; - ldf drm_blank_at_ts; -# endif - us_ring_s *http_jpeg_ring; atomic_bool http_has_clients; atomic_uint http_snapshot_requested; @@ -78,7 +72,7 @@ typedef struct { char *h264_m2m_path; # ifdef WITH_V4P - bool v4p; + us_drm_s *drm; # endif us_stream_runtime_s *run; diff --git a/src/v4p/main.c b/src/v4p/main.c index 24294781..79b498bd 100644 --- a/src/v4p/main.c +++ b/src/v4p/main.c @@ -174,18 +174,14 @@ static void _main_loop(void) { cap->dma_required = true; int once = 0; - ldf blank_at_ts = 0; - int drm_opened = -1; while (!atomic_load(&_g_stop)) { # define CHECK(x_arg) if ((x_arg) < 0) { goto close; } - if (drm_opened <= 0) { - blank_at_ts = 0; - CHECK(drm_opened = us_drm_open(drm, NULL)); + if (drm->run->opened <= 0) { + CHECK(us_drm_open(drm, NULL)); } if (atomic_load(&_g_ustreamer_online)) { - blank_at_ts = 0; US_ONCE({ US_LOG_INFO("DRM: Online stream is active, pausing the service ..."); }); CHECK(us_drm_wait_for_vsync(drm)); CHECK(us_drm_expose_stub(drm, US_DRM_STUB_BUSY, NULL)); @@ -194,25 +190,14 @@ static void _main_loop(void) { } if (us_capture_open(cap) < 0) { - ldf now_ts = us_get_now_monotonic(); - if (blank_at_ts == 0) { - blank_at_ts = now_ts + 5; - } - if (now_ts <= blank_at_ts) { - CHECK(us_drm_wait_for_vsync(drm)); - CHECK(us_drm_expose_stub(drm, US_DRM_STUB_NO_SIGNAL, NULL)); - } else { - US_ONCE({ US_LOG_INFO("DRM: Turning off the display by timeout ..."); }); - CHECK(us_drm_dpms_power_off(drm)); - } + CHECK(us_drm_ensure_no_signal(drm)); _slowdown(); continue; } once = 0; - blank_at_ts = 0; us_drm_close(drm); - CHECK(drm_opened = us_drm_open(drm, cap)); + CHECK(us_drm_open(drm, cap)); us_capture_hwbuf_s *prev_hw = NULL; while (!atomic_load(&_g_stop)) { @@ -234,23 +219,20 @@ static void _main_loop(void) { default: goto close; // Any error } - if (drm_opened == 0) { + if (drm->run->opened == 0) { CHECK(us_drm_expose_dma(drm, hw)); prev_hw = hw; continue; } - CHECK(us_drm_expose_stub(drm, drm_opened, cap)); + CHECK(us_drm_expose_stub(drm, drm->run->opened, cap)); CHECK(us_capture_hwbuf_release(cap, hw)); _slowdown(); } close: us_drm_close(drm); - drm_opened = -1; - us_capture_close(cap); - _slowdown(); # undef CHECK