displays: changed api for mainloop

- removed `needs_mainloop` attribute and deduce if mainloop is needed
  from the presence of _run callback (the information is now redundant
  only displays needing/running mainloop should announce _run callback)

- run the custom mainloop (currently only Syphon!) only when display
  doesn't run its mainloop. This allows running Syphon and GL/SDL
  display because it connects to the display mainloop.
This commit is contained in:
Martin Pulec
2023-03-27 13:47:36 +02:00
parent dd0c38b01d
commit a3daa89ef6
31 changed files with 20 additions and 82 deletions

View File

@@ -89,7 +89,6 @@ static const struct video_display_info display_aja_info = {
display_aja_get_property,
display_aja_put_audio_frame,
display_aja_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -827,6 +827,11 @@ void print_video_codecs(void) {
cout << "\nLegend:\n" << " I - interframe codec\n";
}
/**
* Registers mainloop that will be run if display-owned mainloop isn't run.
* Currently this is only used by Syphon, that either connects to display event
* loop and if there isn't any, it runs its own.
*/
bool register_mainloop(mainloop_t m, void *u)
{
if (mainloop) {

View File

@@ -102,6 +102,7 @@ extern unsigned int cuda_devices_count;
#define MODE_RECEIVER (1U<<1U)
typedef void (*mainloop_t)(void *);
/// mainloop to be run if display mainloop isn't run
extern mainloop_t mainloop;
extern void *mainloop_udata;

View File

@@ -1658,17 +1658,7 @@ int main(int argc, char *argv[])
control_start(control);
kc.start();
if(mainloop) {
if (display_needs_mainloop(uv.display_device)) {
throw string("Cannot run display when "
"another mainloop registered!\n");
}
display_run_new_thread(uv.display_device);
mainloop(mainloop_udata);
display_join(uv.display_device);
} else {
display_run_this_thread(uv.display_device);
}
display_run_mainloop(uv.display_device);
} catch (ug_no_error const &e) {
exit_uv(0);

View File

@@ -195,13 +195,7 @@ void display_done(struct display *d)
bool display_needs_mainloop(struct display *d)
{
assert(d->magic == DISPLAY_MAGIC);
if (d->funcs->needs_mainloop == DISPLAY_NEEDS_MAINLOOP) {
return true;
}
if (d->funcs->needs_mainloop == DISPLAY_DOESNT_NEED_MAINLOOP) {
return false;
}
return d->funcs->needs_mainloop(d->state);
return d->funcs->run != NULL;
}
#define CHECK(cmd) do { \
@@ -225,29 +219,25 @@ static void *display_run_helper(void *args)
/**
* @brief Display mainloop function.
*
* This function runs the display in the thread it is called from
* and blocks until the display stops.
* It is intended for GUI displays (GL/SDL), which run main event loop and need
* to be run from main thread of the program (macOS).
*
* It is mainly intended for GUI displays (GL/SDL), which usually need
* to be run from main thread of the * program (OS X).
*
* The function blocks while the display runs.
* The display can be terminated by passing a poisoned pill (frame == NULL)
* using the display_put_frame() call.
*
* @param d display to be run
*/
void display_run_this_thread(struct display *d)
void display_run_mainloop(struct display *d)
{
assert(d->magic == DISPLAY_MAGIC);
if (d->funcs->run) {
d->funcs->run(d->state);
} else if (mainloop) {
mainloop(mainloop_udata);
}
}
/**
* @brief Display mainloop function.
*
* This function runs the display in a new thread and does not block.
*
* It should not be used for GUI displays (GL/SDL), which usually need

View File

@@ -59,7 +59,7 @@
* Thread #1 (main thread)
* @code{.c}
* d = ininitalize_video_display(...);
* display_run_this_thread(d);
* display_run_mainloop(d);
* display_done(d);
*
* Thread #2
@@ -142,18 +142,14 @@ enum display_prop_vid_mode {
};
/// @}
#define VIDEO_DISPLAY_ABI_VERSION 17
typedef bool (*display_needs_mainloop_t)(void *);
#define DISPLAY_DOESNT_NEED_MAINLOOP ((display_needs_mainloop_t) 0x00)
#define DISPLAY_NEEDS_MAINLOOP ((display_needs_mainloop_t) 0x01)
#define VIDEO_DISPLAY_ABI_VERSION 18
#define DISPLAY_NO_GENERIC_FPS_INDICATOR ((const char *) 0x00)
struct video_display_info {
device_probe_func probe;
void *(*init) (struct module *parent, const char *fmt, unsigned int flags);
void (*run) (void *state); ///< may be NULL
void (*run) (void *state); ///< callback to display main event loop; may be NULL
void (*done) (void *state);
struct video_frame *(*getf) (void *state);
/// @param timeout_ns display is supposed immplement the PUTF_* macros, numerical timeout is seldom used (but double-framerate postprocess can use that)
@@ -163,7 +159,6 @@ struct video_display_info {
void (*put_audio_frame) (void *state, const struct audio_frame *frame); ///< may be NULL
int (*reconfigure_audio) (void *state, int quant_samples, int channels, ///< may be NULL
int sample_rate);
display_needs_mainloop_t needs_mainloop;
const char *generic_fps_indicator_prefix; ///< NO_GENERIC_FPS_INDICATOR or pointer to preferred module name
};
@@ -179,7 +174,7 @@ int initialize_video_display(struct module *parent,
/* not_null */ const char *requested_display, /* not_null */ const char *fmt,
unsigned int flags, const char *postprocess, /* not_null */ struct display **out);
bool display_needs_mainloop(struct display *d);
void display_run_this_thread(struct display *d);
void display_run_mainloop(struct display *d);
void display_run_new_thread(struct display *d);
void display_join(struct display *d);
void display_done(struct display *d);

View File

@@ -390,7 +390,6 @@ static const struct video_display_info display_aggregate_info = {
display_aggregate_get_property,
display_aggregate_put_audio_frame,
display_aggregate_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -1105,7 +1105,6 @@ static const struct video_display_info display_aja_info = {
display_aja_get_property,
display_aja_put_audio_frame,
display_aja_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -424,7 +424,6 @@ static const struct video_display_info display_blend_info = {
display_blend_get_property,
display_blend_put_audio_frame,
display_blend_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -1035,7 +1035,6 @@ static const struct video_display_info display_bluefish444_info = {
display_bluefish444_get_property,
display_bluefish444_put_audio_frame,
display_bluefish444_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -314,7 +314,6 @@ static const void *display_caca_info_get() {
display_caca_get_property,
NULL,
NULL,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};
const char *display = getenv("DISPLAY");

View File

@@ -635,7 +635,7 @@ static void display_conference_run(void *state)
std::thread worker = std::thread(display_conference_worker, s);
display_run_this_thread(s->real_display.get());
display_run_mainloop(s->real_display.get());
worker.join();
}
@@ -731,12 +731,6 @@ static int display_conference_putf(void *state, struct video_frame *frame, long
return 0;
}
static auto display_conference_needs_mainloop(void *state)
{
auto s = static_cast<struct state_conference *>(state)->common;
return display_needs_mainloop(s->real_display.get());
}
static void display_conference_probe(struct device_info **available_cards, int *count, void (**deleter)(void *)) {
UNUSED(deleter);
*available_cards = nullptr;
@@ -754,7 +748,6 @@ static const struct video_display_info display_conference_info = {
display_conference_get_property,
display_conference_put_audio_frame,
display_conference_reconfigure_audio,
display_conference_needs_mainloop,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -2029,7 +2029,6 @@ static const struct video_display_info display_decklink_info = {
display_decklink_get_property,
display_decklink_put_audio_frame,
display_decklink_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
MOD_NAME,
};

View File

@@ -559,7 +559,6 @@ static const struct video_display_info display_deltacast_info = {
display_deltacast_get_property,
display_deltacast_put_audio_frame,
display_deltacast_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -291,7 +291,6 @@ static const struct video_display_info display_dummy_info = {
display_dummy_get_property,
NULL, // _put_audio_frame
NULL, // _reconfigure_audio
DISPLAY_DOESNT_NEED_MAINLOOP,
MOD_NAME,
};

View File

@@ -189,7 +189,6 @@ static const struct video_display_info display_dump_info = {
display_dump_get_property,
NULL, // _put_audio_frame
NULL, // _reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
MOD_NAME,
};

View File

@@ -985,7 +985,6 @@ static const struct video_display_info display_dvs_info = {
display_dvs_get_property,
display_dvs_put_audio_frame,
display_dvs_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -1944,7 +1944,6 @@ static const struct video_display_info display_gl_info = {
display_gl_get_property,
display_gl_put_audio_frame,
display_gl_reconfigure_audio,
DISPLAY_NEEDS_MAINLOOP, // many GLFW functions must be called from main thread (notably glfwPollEvents())
MOD_NAME,
};

View File

@@ -208,7 +208,7 @@ static void display_multiplier_run(void *state)
s->worker_thread = thread(display_multiplier_worker, state);
display_run_this_thread(s->displays[0].get());
display_run_mainloop(s->displays[0].get());
s->worker_thread.join();
for (size_t i = 1; i < s->displays.size(); i++) {
@@ -300,12 +300,6 @@ static int display_multiplier_reconfigure_audio(void *state, int quant_samples,
return display_reconfigure_audio(s->common->displays.at(0).get(), quant_samples, channels, sample_rate);
}
static auto display_multiplier_needs_mainloop(void *state)
{
auto s = static_cast<struct state_multiplier *>(state)->common;
return !s->displays.empty() && display_needs_mainloop(s->displays[0].get());
}
static void display_multiplier_probe(struct device_info **available_cards, int *count, void (**deleter)(void *)) {
UNUSED(deleter);
*available_cards = nullptr;
@@ -323,7 +317,6 @@ static const struct video_display_info display_multiplier_info = {
display_multiplier_get_property,
display_multiplier_put_audio_frame,
display_multiplier_reconfigure_audio,
display_multiplier_needs_mainloop,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -454,7 +454,6 @@ static const struct video_display_info display_ndi_info = {
display_ndi_get_property,
display_ndi_put_audio_frame,
display_ndi_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
MOD_NAME,
};

View File

@@ -148,7 +148,6 @@ static const struct video_display_info display_null_info = {
display_null_get_property,
display_null_put_audio_frame,
display_null_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -1160,7 +1160,6 @@ static const struct video_display_info openxr_gl_info = {
display_xrgl_get_property,
NULL,
NULL,
DISPLAY_NEEDS_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -377,7 +377,6 @@ static const struct video_display_info display_panogl_info = {
display_panogl_get_property,
NULL,
NULL,
DISPLAY_NEEDS_MAINLOOP,
MOD_NAME,
};

View File

@@ -299,7 +299,6 @@ static const struct video_display_info display_pipe_info = {
display_pipe_get_property,
display_pipe_put_audio_frame,
display_pipe_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -658,7 +658,6 @@ static const struct video_display_info display_rpi4_info = {
display_rpi4_get_property,
display_rpi4_put_audio_frame,
display_rpi4_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
"[RPi display] ",
};

View File

@@ -571,7 +571,6 @@ static const struct video_display_info display_sage_info = {
display_sage_get_property,
display_sage_put_audio_frame,
display_sage_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -785,11 +785,6 @@ static const struct video_display_info display_sdl_info = {
display_sdl_get_property,
display_sdl_put_audio_frame,
display_sdl_reconfigure_audio,
#ifdef __APPLE__
DISPLAY_NEEDS_MAINLOOP,
#else
DISPLAY_DOESNT_NEED_MAINLOOP,
#endif
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -809,7 +809,6 @@ static const struct video_display_info display_sdl2_info = {
display_sdl2_get_property,
NULL,
NULL,
DISPLAY_NEEDS_MAINLOOP,
MOD_NAME,
};

View File

@@ -355,7 +355,6 @@ static const struct video_display_info display_unix_sock_info = {
display_unix_sock_get_property,
display_unix_sock_put_audio_frame,
display_unix_sock_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
MOD_NAME,
};
@@ -370,7 +369,6 @@ static const struct video_display_info display_preview_info = {
display_unix_sock_get_property,
display_unix_sock_put_audio_frame,
display_unix_sock_reconfigure_audio,
DISPLAY_DOESNT_NEED_MAINLOOP,
"[unix sock preview] ",
};

View File

@@ -334,7 +334,6 @@ static const struct video_display_info display_v4l2_info = {
display_v4l2_get_property,
NULL,
NULL,
DISPLAY_DOESNT_NEED_MAINLOOP,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};

View File

@@ -1001,8 +1001,7 @@ const video_display_info display_vulkan_info = {
display_vulkan_get_property,
display_vulkan_put_audio_frame,
display_vulkan_reconfigure_audio,
DISPLAY_NEEDS_MAINLOOP,
nullptr,
DISPLAY_NO_GENERIC_FPS_INDICATOR,
};
} // namespace