From 00801fa3d4af98645e2c93b7ca0aee2829b991df Mon Sep 17 00:00:00 2001 From: Martin Pulec Date: Tue, 4 Oct 2022 16:04:37 +0200 Subject: [PATCH] video display: updated putf api - use timeout Replace blocking/nonblock/discard flags with numerical timeout for fine-grainer control of latency. The original flags are kept as convenience macros so the API changes is only small as long as non-block (default) or blocking is used. --- src/aja_win32_stub.cpp | 2 +- src/video_display.c | 11 ++++++----- src/video_display.h | 18 +++++++++--------- src/video_display/aggregate.c | 2 +- src/video_display/aja.cpp | 6 +++--- src/video_display/blend.cpp | 2 +- src/video_display/bluefish444.cpp | 2 +- src/video_display/conference.cpp | 2 +- src/video_display/decklink.cpp | 6 +++--- src/video_display/deltacast.cpp | 2 +- src/video_display/dummy.cpp | 2 +- src/video_display/dump.c | 2 +- src/video_display/dvs.c | 2 +- src/video_display/gl.cpp | 4 ++-- src/video_display/multiplier.cpp | 2 +- src/video_display/ndi.c | 2 +- src/video_display/null.c | 2 +- src/video_display/openxr_gl.cpp | 2 +- src/video_display/pano_gl.cpp | 2 +- src/video_display/pipe.cpp | 2 +- src/video_display/rpi4_out.cpp | 2 +- src/video_display/sage.cpp | 2 +- src/video_display/sdl.cpp | 2 +- src/video_display/sdl2.cpp | 4 ++-- src/video_display/unix_sock.cpp | 2 +- src/video_display/v4l2.c | 2 +- 26 files changed, 45 insertions(+), 44 deletions(-) diff --git a/src/aja_win32_stub.cpp b/src/aja_win32_stub.cpp index 50e69454e..7099212fd 100644 --- a/src/aja_win32_stub.cpp +++ b/src/aja_win32_stub.cpp @@ -75,7 +75,7 @@ __declspec(dllimport) int display_aja_reconfigure(void *state, struct video_desc __declspec(dllimport) void *display_aja_init(struct module * /* parent */, const char *fmt, unsigned int flags); __declspec(dllimport) void display_aja_done(void *state); __declspec(dllimport) struct video_frame *display_aja_getf(void *state); -__declspec(dllimport) int display_aja_putf(void *state, struct video_frame *frame, int nonblock); +__declspec(dllimport) int display_aja_putf(void *state, struct video_frame *frame, long long nonblock); __declspec(dllimport) void display_aja_put_audio_frame(void *state, const struct audio_frame *frame); __declspec(dllimport) int display_aja_reconfigure_audio(void *state, int quant_samples, int channels, int sample_rate); diff --git a/src/video_display.c b/src/video_display.c index 91562d4e0..139534647 100644 --- a/src/video_display.c +++ b/src/video_display.c @@ -357,16 +357,17 @@ struct video_frame *display_get_frame(struct display *d) * @param d display to be putted frame to * @param frame frame that has been obtained from display_get_frame() and has not yet been put. * Should not be NULL unless we want to quit display mainloop. - * @param flags specifies blocking behavior (@ref display_put_frame_flags) + * @param timeout_ns specifies timeout that should be waited (@sa putf_flags). + * displays may ignore the value and act like PUTF_NONBLOCK if blocking is not requested. * @retval 0 if displayed succesfully (or discarded if flag=PUTF_DISCARD) * @retval 1 if not displayed when flag=PUTF_NONBLOCK and it would block */ -int display_put_frame(struct display *d, struct video_frame *frame, int flag) +int display_put_frame(struct display *d, struct video_frame *frame, long long timeout_ns) { assert(d->magic == DISPLAY_MAGIC); if (!frame) { - return d->funcs->putf(d->state, frame, flag); + return d->funcs->putf(d->state, frame, timeout_ns); } if (d->postprocess) { @@ -383,11 +384,11 @@ int display_put_frame(struct display *d, struct video_frame *frame, int flag) return 1; } - display_ret = d->funcs->putf(d->state, display_frame, flag); + display_ret = d->funcs->putf(d->state, display_frame, timeout_ns); } return display_ret; } - int ret = d->funcs->putf(d->state, frame, flag); + int ret = d->funcs->putf(d->state, frame, timeout_ns); if (ret != 0 || !d->funcs->generic_fps_indicator_prefix) { return ret; } diff --git a/src/video_display.h b/src/video_display.h index 9e324fc2e..cfbea4c72 100644 --- a/src/video_display.h +++ b/src/video_display.h @@ -141,7 +141,7 @@ enum display_prop_vid_mode { }; /// @} -#define VIDEO_DISPLAY_ABI_VERSION 15 +#define VIDEO_DISPLAY_ABI_VERSION 16 typedef bool (*display_needs_mainloop_t)(void *); #define DISPLAY_DOESNT_NEED_MAINLOOP ((display_needs_mainloop_t) 0x00) @@ -155,7 +155,7 @@ struct video_display_info { void (*run) (void *state); ///< may be NULL void (*done) (void *state); struct video_frame *(*getf) (void *state); - int (*putf) (void *state, struct video_frame *frame, int nonblock); ///< @copydoc display_put_frame + int (*putf) (void *state, struct video_frame *frame, long long timeout_ns); ///< @copydoc display_put_frame int (*reconfigure_video)(void *state, struct video_desc desc); int (*ctl_property)(void *state, int property, void *val, size_t *len); void (*put_audio_frame) (void *state, const struct audio_frame *frame); ///< may be NULL @@ -185,15 +185,15 @@ void display_join(struct display *d); void display_done(struct display *d); struct video_frame *display_get_frame(struct display *d); -/** @brief putf flags */ -enum display_put_frame_flags { - PUTF_BLOCKING = 0, ///< Block until frame can be displayed. - PUTF_NONBLOCK = 1, ///< Do not block. - PUTF_DISCARD = 2, -}; +/** @ancor putf_flags + * { */ +#define PUTF_DISCARD (-1LL) +#define PUTF_NONBLOCK 0LL +#define PUTF_BLOCKING LLONG_MAX +/// } // documented at definition -int display_put_frame(struct display *d, struct video_frame *frame, int flag); +int display_put_frame(struct display *d, struct video_frame *frame, long long timeout_ns); int display_reconfigure(struct display *d, struct video_desc desc, enum video_mode mode); /** @brief Get/set property (similar to ioctl) * @retval TRUE if succeeds diff --git a/src/video_display/aggregate.c b/src/video_display/aggregate.c index 76ac2b0d5..6846048d6 100644 --- a/src/video_display/aggregate.c +++ b/src/video_display/aggregate.c @@ -211,7 +211,7 @@ static struct video_frame *display_aggregate_getf(void *state) return s->frame; } -static int display_aggregate_putf(void *state, struct video_frame *frame, int nonblock) +static int display_aggregate_putf(void *state, struct video_frame *frame, long long nonblock) { unsigned int i; struct display_aggregate_state *s = (struct display_aggregate_state *)state; diff --git a/src/video_display/aja.cpp b/src/video_display/aja.cpp index a6ff33968..ef2cc8398 100644 --- a/src/video_display/aja.cpp +++ b/src/video_display/aja.cpp @@ -201,7 +201,7 @@ public: AJAStatus SetUpVideo(); AJAStatus SetUpAudio(); void RouteOutputSignal(); - int Putf(struct video_frame *frame, int nonblock); + int Putf(struct video_frame *frame, long long nonblock); static NTV2FrameRate getFrameRate(double fps); void print_stats(); @@ -686,7 +686,7 @@ void display::process_frames() } } -int display::Putf(struct video_frame *frame, int flags) { +int display::Putf(struct video_frame *frame, long long flags) { if (frame == nullptr) { return 1; } @@ -1012,7 +1012,7 @@ LINK_SPEC struct video_frame *display_aja_getf(void *state) return vf_alloc_desc_data(s->desc); } -LINK_SPEC int display_aja_putf(void *state, struct video_frame *frame, int nonblock) +LINK_SPEC int display_aja_putf(void *state, struct video_frame *frame, long long nonblock) { auto s = static_cast(state); diff --git a/src/video_display/blend.cpp b/src/video_display/blend.cpp index 1c2c4380a..8c9c35be5 100644 --- a/src/video_display/blend.cpp +++ b/src/video_display/blend.cpp @@ -336,7 +336,7 @@ static struct video_frame *display_blend_getf(void *state) return vf_alloc_desc_data(s->desc); } -static int display_blend_putf(void *state, struct video_frame *frame, int flags) +static int display_blend_putf(void *state, struct video_frame *frame, long long flags) { shared_ptr s = ((struct state_blend *)state)->common; diff --git a/src/video_display/bluefish444.cpp b/src/video_display/bluefish444.cpp index 17660cc7c..cd30bd647 100644 --- a/src/video_display/bluefish444.cpp +++ b/src/video_display/bluefish444.cpp @@ -889,7 +889,7 @@ display_bluefish444_getf(void *state) return frame; } -static int display_bluefish444_putf(void *state, struct video_frame *frame, int nonblock) +static int display_bluefish444_putf(void *state, struct video_frame *frame, long long nonblock) { UNUSED(nonblock); display_bluefish444_state *s = diff --git a/src/video_display/conference.cpp b/src/video_display/conference.cpp index 4d6a29192..b6d49aad1 100644 --- a/src/video_display/conference.cpp +++ b/src/video_display/conference.cpp @@ -703,7 +703,7 @@ static struct video_frame *display_conference_getf(void *state) return vf_alloc_desc_data(s->desc); } -static int display_conference_putf(void *state, struct video_frame *frame, int flags) +static int display_conference_putf(void *state, struct video_frame *frame, long long flags) { auto s = static_cast(state)->common; diff --git a/src/video_display/decklink.cpp b/src/video_display/decklink.cpp index 965e6ab10..a4609cf72 100644 --- a/src/video_display/decklink.cpp +++ b/src/video_display/decklink.cpp @@ -106,7 +106,7 @@ using namespace std; using rang::fg; using rang::style; -static int display_decklink_putf(void *state, struct video_frame *frame, int nonblock); +static int display_decklink_putf(void *state, struct video_frame *frame, long long nonblock); namespace { class PlaybackDelegate : public IDeckLinkVideoOutputCallback // , public IDeckLinkAudioOutputCallback @@ -116,7 +116,7 @@ private: uint64_t frames_flushed = 0; uint64_t frames_late = 0; - friend int ::display_decklink_putf(void *state, struct video_frame *frame, int nonblock); + friend int ::display_decklink_putf(void *state, struct video_frame *frame, long long nonblock); public: virtual ~PlaybackDelegate() = default; // IUnknown needs only a dummy implementation @@ -576,7 +576,7 @@ static void update_timecode(DeckLinkTimecode *tc, double fps) tc->SetBCD(bcd); } -static int display_decklink_putf(void *state, struct video_frame *frame, int flag) +static int display_decklink_putf(void *state, struct video_frame *frame, long long flag) { struct state_decklink *s = (struct state_decklink *)state; diff --git a/src/video_display/deltacast.cpp b/src/video_display/deltacast.cpp index db264934f..5121d745d 100644 --- a/src/video_display/deltacast.cpp +++ b/src/video_display/deltacast.cpp @@ -123,7 +123,7 @@ display_deltacast_getf(void *state) return s->frame; } -static int display_deltacast_putf(void *state, struct video_frame *frame, int nonblock) +static int display_deltacast_putf(void *state, struct video_frame *frame, long long nonblock) { struct state_deltacast *s = (struct state_deltacast *)state; struct timeval tv; diff --git a/src/video_display/dummy.cpp b/src/video_display/dummy.cpp index 07acc2949..dd3f28b6d 100644 --- a/src/video_display/dummy.cpp +++ b/src/video_display/dummy.cpp @@ -154,7 +154,7 @@ static void dump_buf(unsigned char *buf, size_t len, int block_size) { printf("\n"); } -static int display_dummy_putf(void *state, struct video_frame *frame, int flags) +static int display_dummy_putf(void *state, struct video_frame *frame, long long flags) { if (flags == PUTF_DISCARD || frame == nullptr) { return 0; diff --git a/src/video_display/dump.c b/src/video_display/dump.c index 55af88eff..efeb04368 100644 --- a/src/video_display/dump.c +++ b/src/video_display/dump.c @@ -112,7 +112,7 @@ static struct video_frame *display_dump_getf(void *state) return s->f; } -static int display_dump_putf(void *state, struct video_frame *frame, int flags) +static int display_dump_putf(void *state, struct video_frame *frame, long long flags) { struct dump_display_state *s = state; if (frame == NULL || flags == PUTF_DISCARD) { diff --git a/src/video_display/dvs.c b/src/video_display/dvs.c index 26314fe8d..43ee5219c 100644 --- a/src/video_display/dvs.c +++ b/src/video_display/dvs.c @@ -493,7 +493,7 @@ display_dvs_getf(void *state) return s->frame; } -static int display_dvs_putf(void *state, struct video_frame *frame, int flags) +static int display_dvs_putf(void *state, struct video_frame *frame, long long flags) { struct state_hdsp *s = (struct state_hdsp *)state; diff --git a/src/video_display/gl.cpp b/src/video_display/gl.cpp index 94b99c0a9..9cbca09b1 100644 --- a/src/video_display/gl.cpp +++ b/src/video_display/gl.cpp @@ -396,7 +396,7 @@ static constexpr array gl_supp_codecs = { /* Prototyping */ static bool display_gl_init_opengl(struct state_gl *s); -static int display_gl_putf(void *state, struct video_frame *frame, int nonblock); +static int display_gl_putf(void *state, struct video_frame *frame, long long timeout); static bool display_gl_process_key(struct state_gl *s, long long int key); static int display_gl_reconfigure(void *state, struct video_desc desc); @@ -1808,7 +1808,7 @@ static struct video_frame * display_gl_getf(void *state) return buffer; } -static int display_gl_putf(void *state, struct video_frame *frame, int nonblock) +static int display_gl_putf(void *state, struct video_frame *frame, long long nonblock) { struct state_gl *s = (struct state_gl *) state; diff --git a/src/video_display/multiplier.cpp b/src/video_display/multiplier.cpp index 31980ce59..ec2684666 100644 --- a/src/video_display/multiplier.cpp +++ b/src/video_display/multiplier.cpp @@ -228,7 +228,7 @@ static struct video_frame *display_multiplier_getf(void *state) return vf_alloc_desc_data(s->desc); } -static int display_multiplier_putf(void *state, struct video_frame *frame, int flags) +static int display_multiplier_putf(void *state, struct video_frame *frame, long long flags) { shared_ptr s = ((struct state_multiplier *)state)->common; diff --git a/src/video_display/ndi.c b/src/video_display/ndi.c index a31980a41..556a27e4c 100644 --- a/src/video_display/ndi.c +++ b/src/video_display/ndi.c @@ -318,7 +318,7 @@ static void ndi_disp_convert_Y416_to_PA16(const struct video_frame *f, char *out /** * flag = PUTF_NONBLOCK is not implemented */ -static int display_ndi_putf(void *state, struct video_frame *frame, int flag) +static int display_ndi_putf(void *state, struct video_frame *frame, long long flag) { struct display_ndi *s = (struct display_ndi *) state; diff --git a/src/video_display/null.c b/src/video_display/null.c index 7485e5601..430cb7505 100644 --- a/src/video_display/null.c +++ b/src/video_display/null.c @@ -97,7 +97,7 @@ static struct video_frame *display_null_getf(void *state) return NULL; } -static int display_null_putf(void *state, struct video_frame *frame, int nonblock) +static int display_null_putf(void *state, struct video_frame *frame, long long nonblock) { struct state_null *s = (struct state_null *)state; assert(s->magic == MAGIC_NULL); diff --git a/src/video_display/openxr_gl.cpp b/src/video_display/openxr_gl.cpp index 3f34f85d0..b1bab0ee9 100644 --- a/src/video_display/openxr_gl.cpp +++ b/src/video_display/openxr_gl.cpp @@ -1020,7 +1020,7 @@ static struct video_frame * display_xrgl_getf(void *state) { } } -static int display_xrgl_putf(void *state, struct video_frame *frame, int nonblock) { +static int display_xrgl_putf(void *state, struct video_frame *frame, long long nonblock) { struct state_xrgl *s = static_cast(state); std::unique_lock lk(s->lock); diff --git a/src/video_display/pano_gl.cpp b/src/video_display/pano_gl.cpp index 8c77c7785..fe267a873 100644 --- a/src/video_display/pano_gl.cpp +++ b/src/video_display/pano_gl.cpp @@ -273,7 +273,7 @@ static struct video_frame * display_panogl_getf(void *state) { return vf_alloc_desc_data(s->current_desc); } -static int display_panogl_putf(void *state, struct video_frame *frame, int nonblock) { +static int display_panogl_putf(void *state, struct video_frame *frame, long long nonblock) { PROFILE_FUNC; struct state_vr *s = static_cast(state); diff --git a/src/video_display/pipe.cpp b/src/video_display/pipe.cpp index 12e5ab61f..edc9c4b9e 100644 --- a/src/video_display/pipe.cpp +++ b/src/video_display/pipe.cpp @@ -184,7 +184,7 @@ static struct audio_frame * display_pipe_get_audio(struct state_pipe *s) return out; } -static int display_pipe_putf(void *state, struct video_frame *frame, int flags) +static int display_pipe_putf(void *state, struct video_frame *frame, long long flags) { struct state_pipe *s = (struct state_pipe *) state; diff --git a/src/video_display/rpi4_out.cpp b/src/video_display/rpi4_out.cpp index af06fba49..4c8b68528 100644 --- a/src/video_display/rpi4_out.cpp +++ b/src/video_display/rpi4_out.cpp @@ -497,7 +497,7 @@ static struct video_frame *display_rpi4_getf(void *state) { return new_frame; } -static int display_rpi4_putf(void *state, struct video_frame *frame, int flags) +static int display_rpi4_putf(void *state, struct video_frame *frame, long long flags) { auto *s = static_cast(state); diff --git a/src/video_display/sage.cpp b/src/video_display/sage.cpp index 8831a7477..52fe719b1 100644 --- a/src/video_display/sage.cpp +++ b/src/video_display/sage.cpp @@ -330,7 +330,7 @@ static struct video_frame *display_sage_getf(void *state) return s->frame; } -static int display_sage_putf(void *state, struct video_frame *frame, int nonblock) +static int display_sage_putf(void *state, struct video_frame *frame, long long nonblock) { int tmp; struct state_sage *s = (struct state_sage *)state; diff --git a/src/video_display/sdl.cpp b/src/video_display/sdl.cpp index 5352d0a0e..e4bd68c55 100644 --- a/src/video_display/sdl.cpp +++ b/src/video_display/sdl.cpp @@ -142,7 +142,7 @@ struct state_sdl { static void loadSplashscreen(struct state_sdl *s); static void show_help(void); -static int display_sdl_putf(void *state, struct video_frame *frame, int nonblock); +static int display_sdl_putf(void *state, struct video_frame *frame, long long nonblock); static int display_sdl_reconfigure(void *state, struct video_desc desc); static int display_sdl_reconfigure_real(void *state, struct video_desc desc); diff --git a/src/video_display/sdl2.cpp b/src/video_display/sdl2.cpp index b7f3848dd..2f24f6e10 100644 --- a/src/video_display/sdl2.cpp +++ b/src/video_display/sdl2.cpp @@ -98,7 +98,7 @@ using namespace std::chrono; static void show_help(void); static void display_sdl2_new_message(struct module *); -static int display_sdl2_putf(void *state, struct video_frame *frame, int nonblock); +static int display_sdl2_putf(void *state, struct video_frame *frame, long long nonblock); static int display_sdl2_reconfigure(void *state, struct video_desc desc); static int display_sdl2_reconfigure_real(void *state, struct video_desc desc); @@ -701,7 +701,7 @@ static struct video_frame *display_sdl2_getf(void *state) return vf_alloc_desc_data(s->current_desc); } -static int display_sdl2_putf(void *state, struct video_frame *frame, int nonblock) +static int display_sdl2_putf(void *state, struct video_frame *frame, long long nonblock) { struct state_sdl2 *s = (struct state_sdl2 *)state; diff --git a/src/video_display/unix_sock.cpp b/src/video_display/unix_sock.cpp index 48550efcd..fc93a3596 100644 --- a/src/video_display/unix_sock.cpp +++ b/src/video_display/unix_sock.cpp @@ -244,7 +244,7 @@ static struct video_frame *display_unix_sock_getf(void *state) return vf_alloc_desc_data(s->desc); } -static int display_unix_sock_putf(void *state, struct video_frame *frame, int flags) +static int display_unix_sock_putf(void *state, struct video_frame *frame, long long flags) { auto s = static_cast(state); auto f = unique_frame(frame); diff --git a/src/video_display/v4l2.c b/src/video_display/v4l2.c index 5c80ce959..7788ad756 100644 --- a/src/video_display/v4l2.c +++ b/src/video_display/v4l2.c @@ -220,7 +220,7 @@ static struct video_frame *display_v4l2_getf(void *state) return s->f; } -static int display_v4l2_putf(void *state, struct video_frame *frame, int nonblock) +static int display_v4l2_putf(void *state, struct video_frame *frame, long long nonblock) { UNUSED(nonblock); struct display_v4l2_state *s = state;