diff --git a/src/video_capture/screen_avf.c b/src/video_capture/screen_avf.c index ffd9459cc..f81ad2303 100644 --- a/src/video_capture/screen_avf.c +++ b/src/video_capture/screen_avf.c @@ -79,12 +79,51 @@ vidcap_screen_avf_probe(struct device_info **available_cards, int *count, } } +/// @returns whether the config string contains device spec (d=/uid=/name=) +static bool +contains_dev_spec(const char *fmt) +{ + char *cpy = strdup(fmt); + char *tmp = cpy; + char *saveptr = nullptr; + char *item = nullptr; + while ((item = strtok_r(tmp, ":", &saveptr)) != nullptr) { + tmp = nullptr; + char *delim = strchr(item, '='); + if (!delim) { + continue; + } + *delim = '\0'; + if (strstr(item, "device") == item || + strstr(item, "uid") == item || + strstr(item, "name") == item) { + return true; + } + } + return false; +} + static int vidcap_screen_avf_init(struct vidcap_params *params, void **state) { - if (avfoundation_usage(vidcap_params_get_fmt(params), true)) { + const char *fmt = vidcap_params_get_fmt(params); + + if (avfoundation_usage(fmt, true)) { return VIDCAP_INIT_NOERR; // help shown } + + if (contains_dev_spec(fmt)) { + return vidcap_avfoundation_info.init(params, state); + } + + // add "d=100" to initialize first screen cap av foundation device + const size_t orig_len = strlen(fmt); + const size_t new_len = orig_len + 50; + char *new_fmt = malloc(new_len); + (void) snprintf(new_fmt, new_len, "%s%sd=%u", fmt, + orig_len == 0 ? "" : ":", AVF_SCR_CAP_OFF); + vidcap_params_replace_fmt(params, new_fmt); + free(new_fmt); return vidcap_avfoundation_info.init(params, state); } diff --git a/src/video_capture_params.cpp b/src/video_capture_params.cpp index ebaf96e61..65faa8a0f 100644 --- a/src/video_capture_params.cpp +++ b/src/video_capture_params.cpp @@ -5,7 +5,7 @@ * @ingroup vidcap */ /* - * Copyright (c) 2013-2025 CESNET, zájmové sdružení právnických osob + * Copyright (c) 2013-2026 CESNET, zájmové sdružení právnických osob * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -280,6 +280,13 @@ struct vidcap_params *vidcap_params_copy(const struct vidcap_params *params) return ret; } +void +vidcap_params_replace_fmt(struct vidcap_params *params, const char *new_fmt) +{ + free(params->fmt); + params->fmt = strdup(new_fmt); +} + /** * Frees all members of the given structure as well as its members. * diff --git a/src/video_capture_params.h b/src/video_capture_params.h index 71f07c1d0..05b90b9df 100644 --- a/src/video_capture_params.h +++ b/src/video_capture_params.h @@ -10,7 +10,7 @@ * individual devices' parameters (namely per-device capture filter). */ /** - * Copyright (c) 2013-2025 CESNET, zájmové sdružení právnických osob + * Copyright (c) 2013-2026 CESNET, zájmové sdružení právnických osob * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -81,6 +81,8 @@ void vidcap_params_add_capture_filter(struct vidcap_params *par const char *vidcap_params_get_capture_filter(const struct vidcap_params *params); void vidcap_params_set_flags(struct vidcap_params *params, unsigned int flags); void vidcap_params_add_flags(struct vidcap_params *params, unsigned int flags); +void vidcap_params_replace_fmt(struct vidcap_params *params, + const char *new_fmt); /// @} #ifdef __cplusplus