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.
This commit is contained in:
Martin Pulec
2022-10-04 16:04:37 +02:00
parent e1dcefc9d2
commit 00801fa3d4
26 changed files with 45 additions and 44 deletions

View File

@@ -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_init(struct module * /* parent */, const char *fmt, unsigned int flags);
__declspec(dllimport) void display_aja_done(void *state); __declspec(dllimport) void display_aja_done(void *state);
__declspec(dllimport) struct video_frame *display_aja_getf(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) 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, __declspec(dllimport) int display_aja_reconfigure_audio(void *state, int quant_samples, int channels,
int sample_rate); int sample_rate);

View File

@@ -357,16 +357,17 @@ struct video_frame *display_get_frame(struct display *d)
* @param d display to be putted frame to * @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. * @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. * 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 0 if displayed succesfully (or discarded if flag=PUTF_DISCARD)
* @retval 1 if not displayed when flag=PUTF_NONBLOCK and it would block * @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); assert(d->magic == DISPLAY_MAGIC);
if (!frame) { if (!frame) {
return d->funcs->putf(d->state, frame, flag); return d->funcs->putf(d->state, frame, timeout_ns);
} }
if (d->postprocess) { if (d->postprocess) {
@@ -383,11 +384,11 @@ int display_put_frame(struct display *d, struct video_frame *frame, int flag)
return 1; 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; 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) { if (ret != 0 || !d->funcs->generic_fps_indicator_prefix) {
return ret; return ret;
} }

View File

@@ -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 *); typedef bool (*display_needs_mainloop_t)(void *);
#define DISPLAY_DOESNT_NEED_MAINLOOP ((display_needs_mainloop_t) 0x00) #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 (*run) (void *state); ///< may be NULL
void (*done) (void *state); void (*done) (void *state);
struct video_frame *(*getf) (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 (*reconfigure_video)(void *state, struct video_desc desc);
int (*ctl_property)(void *state, int property, void *val, size_t *len); 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 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); void display_done(struct display *d);
struct video_frame *display_get_frame(struct display *d); struct video_frame *display_get_frame(struct display *d);
/** @brief putf flags */ /** @ancor putf_flags
enum display_put_frame_flags { * { */
PUTF_BLOCKING = 0, ///< Block until frame can be displayed. #define PUTF_DISCARD (-1LL)
PUTF_NONBLOCK = 1, ///< Do not block. #define PUTF_NONBLOCK 0LL
PUTF_DISCARD = 2, #define PUTF_BLOCKING LLONG_MAX
}; /// }
// documented at definition // 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); int display_reconfigure(struct display *d, struct video_desc desc, enum video_mode mode);
/** @brief Get/set property (similar to ioctl) /** @brief Get/set property (similar to ioctl)
* @retval TRUE if succeeds * @retval TRUE if succeeds

View File

@@ -211,7 +211,7 @@ static struct video_frame *display_aggregate_getf(void *state)
return s->frame; 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; unsigned int i;
struct display_aggregate_state *s = (struct display_aggregate_state *)state; struct display_aggregate_state *s = (struct display_aggregate_state *)state;

View File

@@ -201,7 +201,7 @@ public:
AJAStatus SetUpVideo(); AJAStatus SetUpVideo();
AJAStatus SetUpAudio(); AJAStatus SetUpAudio();
void RouteOutputSignal(); void RouteOutputSignal();
int Putf(struct video_frame *frame, int nonblock); int Putf(struct video_frame *frame, long long nonblock);
static NTV2FrameRate getFrameRate(double fps); static NTV2FrameRate getFrameRate(double fps);
void print_stats(); 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) { if (frame == nullptr) {
return 1; return 1;
} }
@@ -1012,7 +1012,7 @@ LINK_SPEC struct video_frame *display_aja_getf(void *state)
return vf_alloc_desc_data(s->desc); 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<struct aja::display *>(state); auto s = static_cast<struct aja::display *>(state);

View File

@@ -336,7 +336,7 @@ static struct video_frame *display_blend_getf(void *state)
return vf_alloc_desc_data(s->desc); 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<struct state_blend_common> s = ((struct state_blend *)state)->common; shared_ptr<struct state_blend_common> s = ((struct state_blend *)state)->common;

View File

@@ -889,7 +889,7 @@ display_bluefish444_getf(void *state)
return frame; 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); UNUSED(nonblock);
display_bluefish444_state *s = display_bluefish444_state *s =

View File

@@ -703,7 +703,7 @@ static struct video_frame *display_conference_getf(void *state)
return vf_alloc_desc_data(s->desc); 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_conference *>(state)->common; auto s = static_cast<state_conference *>(state)->common;

View File

@@ -106,7 +106,7 @@ using namespace std;
using rang::fg; using rang::fg;
using rang::style; 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 { namespace {
class PlaybackDelegate : public IDeckLinkVideoOutputCallback // , public IDeckLinkAudioOutputCallback class PlaybackDelegate : public IDeckLinkVideoOutputCallback // , public IDeckLinkAudioOutputCallback
@@ -116,7 +116,7 @@ private:
uint64_t frames_flushed = 0; uint64_t frames_flushed = 0;
uint64_t frames_late = 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: public:
virtual ~PlaybackDelegate() = default; virtual ~PlaybackDelegate() = default;
// IUnknown needs only a dummy implementation // IUnknown needs only a dummy implementation
@@ -576,7 +576,7 @@ static void update_timecode(DeckLinkTimecode *tc, double fps)
tc->SetBCD(bcd); 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; struct state_decklink *s = (struct state_decklink *)state;

View File

@@ -123,7 +123,7 @@ display_deltacast_getf(void *state)
return s->frame; 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 state_deltacast *s = (struct state_deltacast *)state;
struct timeval tv; struct timeval tv;

View File

@@ -154,7 +154,7 @@ static void dump_buf(unsigned char *buf, size_t len, int block_size) {
printf("\n"); 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) { if (flags == PUTF_DISCARD || frame == nullptr) {
return 0; return 0;

View File

@@ -112,7 +112,7 @@ static struct video_frame *display_dump_getf(void *state)
return s->f; 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; struct dump_display_state *s = state;
if (frame == NULL || flags == PUTF_DISCARD) { if (frame == NULL || flags == PUTF_DISCARD) {

View File

@@ -493,7 +493,7 @@ display_dvs_getf(void *state)
return s->frame; 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; struct state_hdsp *s = (struct state_hdsp *)state;

View File

@@ -396,7 +396,7 @@ static constexpr array gl_supp_codecs = {
/* Prototyping */ /* Prototyping */
static bool display_gl_init_opengl(struct state_gl *s); 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 bool display_gl_process_key(struct state_gl *s, long long int key);
static int display_gl_reconfigure(void *state, struct video_desc desc); 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; 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; struct state_gl *s = (struct state_gl *) state;

View File

@@ -228,7 +228,7 @@ static struct video_frame *display_multiplier_getf(void *state)
return vf_alloc_desc_data(s->desc); 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<struct state_multiplier_common> s = ((struct state_multiplier *)state)->common; shared_ptr<struct state_multiplier_common> s = ((struct state_multiplier *)state)->common;

View File

@@ -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 * 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; struct display_ndi *s = (struct display_ndi *) state;

View File

@@ -97,7 +97,7 @@ static struct video_frame *display_null_getf(void *state)
return NULL; 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; struct state_null *s = (struct state_null *)state;
assert(s->magic == MAGIC_NULL); assert(s->magic == MAGIC_NULL);

View File

@@ -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_xrgl *>(state); struct state_xrgl *s = static_cast<state_xrgl *>(state);
std::unique_lock<std::mutex> lk(s->lock); std::unique_lock<std::mutex> lk(s->lock);

View File

@@ -273,7 +273,7 @@ static struct video_frame * display_panogl_getf(void *state) {
return vf_alloc_desc_data(s->current_desc); 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; PROFILE_FUNC;
struct state_vr *s = static_cast<state_vr *>(state); struct state_vr *s = static_cast<state_vr *>(state);

View File

@@ -184,7 +184,7 @@ static struct audio_frame * display_pipe_get_audio(struct state_pipe *s)
return out; 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; struct state_pipe *s = (struct state_pipe *) state;

View File

@@ -497,7 +497,7 @@ static struct video_frame *display_rpi4_getf(void *state) {
return new_frame; 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<rpi4_display_state *>(state); auto *s = static_cast<rpi4_display_state *>(state);

View File

@@ -330,7 +330,7 @@ static struct video_frame *display_sage_getf(void *state)
return s->frame; 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; int tmp;
struct state_sage *s = (struct state_sage *)state; struct state_sage *s = (struct state_sage *)state;

View File

@@ -142,7 +142,7 @@ struct state_sdl {
static void loadSplashscreen(struct state_sdl *s); static void loadSplashscreen(struct state_sdl *s);
static void show_help(void); 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(void *state, struct video_desc desc);
static int display_sdl_reconfigure_real(void *state, struct video_desc desc); static int display_sdl_reconfigure_real(void *state, struct video_desc desc);

View File

@@ -98,7 +98,7 @@ using namespace std::chrono;
static void show_help(void); static void show_help(void);
static void display_sdl2_new_message(struct module *); 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(void *state, struct video_desc desc);
static int display_sdl2_reconfigure_real(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); 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; struct state_sdl2 *s = (struct state_sdl2 *)state;

View File

@@ -244,7 +244,7 @@ static struct video_frame *display_unix_sock_getf(void *state)
return vf_alloc_desc_data(s->desc); 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_unix_sock *>(state); auto s = static_cast<state_unix_sock *>(state);
auto f = unique_frame(frame); auto f = unique_frame(frame);

View File

@@ -220,7 +220,7 @@ static struct video_frame *display_v4l2_getf(void *state)
return s->f; 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); UNUSED(nonblock);
struct display_v4l2_state *s = state; struct display_v4l2_state *s = state;