UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
screen_win.c
Go to the documentation of this file.
1
11/*
12 * Copyright (c) 2019-2023 CESNET, z.s.p.o.
13 * All rights reserved.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, is permitted provided that the following conditions
17 * are met:
18 *
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 *
22 * 2. Redistributions in binary form must reproduce the above copyright
23 * notice, this list of conditions and the following disclaimer in the
24 * documentation and/or other materials provided with the distribution.
25 *
26 * 3. Neither the name of CESNET nor the names of its contributors may be
27 * used to endorse or promote products derived from this software without
28 * specific prior written permission.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
31 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
32 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
33 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
34 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
35 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
36 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
37 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
39 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
40 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
41 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
42 */
43
44#ifdef HAVE_CONFIG_H
45#include "config.h"
46#include "config_unix.h"
47#include "config_win32.h"
48#endif /* HAVE_CONFIG_H */
49
50#include <shellapi.h>
51#include <stdbool.h>
52#include <stdio.h>
53#include <stdlib.h>
54
55#include "audio/types.h"
56#include "debug.h"
57#include "host.h"
58#include "lib_common.h"
59#include "utils/color_out.h"
60#include "utils/macros.h"
61#include "utils/text.h"
62#include "utils/windows.h"
63#include "video.h"
64#include "video_capture.h"
66
67#define MOD_NAME "[screen win] "
68#define FILTER_UPSTREAM_URL "https://github.com/rdp/screen-capture-recorder-to-video-windows-free/releases"
69
70extern const struct video_capture_info vidcap_dshow_info;
71static bool is_library_registered();
72static bool unregister_filter();
73
78
79static const char *const screen_cap_rec_opts[] = {
80 "capture_height",
81 "capture_width",
82 "start_x",
83 "start_y",
84 "default_max_fps",
85 "stretch_to_width",
86 "stretch_to_height",
87 "stretch_mode_high_quality_if_1",
88 "hwnd_to_track",
89 "disable_aero_for_vista_plus_if_1",
90 "track_new_x_y_coords_each_frame_if_1",
91 "capture_mouse_default_1",
92 "capture_foreground_window_if_1",
93 "dedup_if_1",
94 "millis_to_sleep_between_poll_for_dedupe_changes",
95 "capture_transparent_windows_including_mouse_in_non_aero_if_1_causes_annoying_mouse_flicker",
96 "hwnd_to_track_with_window_decoration",
97 "capture_particular_display_number_starting_at_zero"
98};
99
100static void
101show_help(bool full)
102{
103 char desc[] = "Windows " TBOLD("screen capture") " can be used to capture the whole desktop in Windows.\n\n"
104 "It uses dynamically loaded DShow filter to get the screen data. Depending on the system configuration, "
105 "it may be required to confirm the filter registration with elevated permissions. In that case the plugin "
106 "remains registered permanently (you can unregister it with \"" TBOLD(":unregister") "\" (otherwise it is "
107 "unloaded in the end. You can also download and install it from " FILTER_UPSTREAM_URL " to get latest "
108 "version.\n\n";
110 color_printf("Usage\n");
112 TBOLD(TRED("\t-t screen") "[:clear_prefs][:size=<w>x<h>][:fps=<f>][other-opts]") "\n");
113 color_printf(TBOLD("\t-t screen:[full]help") " | " TBOLD(
114 "-t screen:unregister") "\n");
115 color_printf("where:\n");
116 color_printf(TBOLD("\tunregister") " - unregister DShow filter\n");
117 color_printf(TBOLD("\tclear_prefs") " - clear screen capture preferences from registry (must be first opt)\n");
118 color_printf(TBOLD("\tother-opts") " - one of screen-capture-recorder opts (with value):");
119 for (unsigned i = 0;
120 i < sizeof screen_cap_rec_opts / sizeof screen_cap_rec_opts[0];
121 i++) {
122 color_printf(" %d) " TBOLD("%s"), i + 1, screen_cap_rec_opts[i]);
123 }
124 color_printf("\n\n");
125 if (full) {
126 color_printf("Examples:\n");
127 color_printf("\t" TBOLD("%s -t screen") " - capture with "
128 "default/registry values\n", uv_argv[0]);
129 color_printf("\t" TBOLD("%s -t screen:clear_prefs") " - erase "
130 "prefs and capture with default values\n", uv_argv[0]);
131 color_printf("\t" TBOLD("%s -t screen:clear_prefs:size=640x480")
132 " - capture VGA-sized video and dropping previous "
133 "values\n", uv_argv[0]);
134 color_printf("\t" TBOLD("%s -t screen:size_x=200:size_y=200")
135 " - capture using saved values with x/y offset 200\n\n",
136 uv_argv[0]);
137 }
138
139 color_printf(TBOLD("DShow") " filter " TBOLD("%s") " registered\n",
140 is_library_registered() ? "is" : "is not");
141}
142
143static void vidcap_screen_win_probe(struct device_info **available_cards, int *count, void (**deleter)(void *))
144{
145 *count = 1;
146 *deleter = free;
147 struct device_info *cards = calloc(1, sizeof(struct device_info));
148 // cards[0].dev can be "" since screen cap. doesn't require parameters
149 snprintf(cards[0].name, sizeof cards[0].name, "Screen capture");
150 *available_cards = cards;
151}
152
153#define SCREEN_CAP_REG_TREE "Software\\screen-capture-recorder"
154#define REG_FRIENDLY_NAME "\\HKEY_CURRENT_USER\\" SCREEN_CAP_REG_TREE
155
156static void
158{
159 HKEY hKey;
160 LONG regOpenResult = RegOpenKeyEx(
161 HKEY_CURRENT_USER, SCREEN_CAP_REG_TREE, 0, KEY_READ, &hKey);
162 if (regOpenResult != ERROR_SUCCESS) {
163 return;
164 }
165
166 log_msg(LOG_LEVEL_INFO, "\n");
167 MSG(INFO, "Using following configuration from Windows Registry:\n");
168
169 DWORD index = 0;
170 DWORD bufferSize = MAX_PATH;
171 TCHAR valueName[MAX_PATH];
172 BYTE data[MAX_PATH];
173 DWORD valueSize = MAX_PATH;
174 DWORD valueType;
175 while (RegEnumValue(hKey, index, valueName, &bufferSize, NULL,
176 &valueType, data, &valueSize) == ERROR_SUCCESS) {
177 if (valueType == REG_DWORD) {
178 MSG(INFO, "Option: %s (REG_DWORD), Value: %lu\n",
179 valueName, *(DWORD *) data);
180 } else if (valueType == REG_SZ) {
181 MSG(INFO, "Option: %s (REG_SZ), Value: %s\n", valueName,
182 (char *) data);
183 } else {
184 MSG(INFO, "Option: %s (unknown type), Data Size: %lu\n",
185 valueName, valueSize);
186 }
187
188 index++;
189 bufferSize = MAX_PATH;
190 valueSize = MAX_PATH;
191 }
192
193 RegCloseKey(hKey);
194}
195
196static bool
198{
199 const LSTATUS err =
200 RegDeleteTree(HKEY_CURRENT_USER, SCREEN_CAP_REG_TREE);
201 if (err == ERROR_SUCCESS) {
202 MSG(NOTICE,
203 "Register tree " REG_FRIENDLY_NAME " deleted succesfully.\n");
204 return true;
205 }
206 MSG(ERROR, "Cannot delete " REG_FRIENDLY_NAME " from registry: %s\n",
207 get_win32_error(err));
208 return false;
209}
210
211static LRESULT
212set_winreg_key(const char *key, int val)
213{
214 static bool printed;
215 if (!printed) {
216 MSG(NOTICE, "Options are written permanently to system registry (" REG_FRIENDLY_NAME ").\n"
217 "Use `-t screen:clear_prefs` to erase.\n");
218 printed = true;
219 }
220 HKEY hKey = NULL;
221 LRESULT res = RegCreateKeyEx(HKEY_CURRENT_USER, SCREEN_CAP_REG_TREE, 0L,
222 NULL, REG_OPTION_NON_VOLATILE,
223 KEY_ALL_ACCESS, NULL, &hKey, NULL);
224 if (res != ERROR_SUCCESS) {
225 // may already exist - try to open it
226 res = RegOpenKeyEx(HKEY_CURRENT_USER, SCREEN_CAP_REG_TREE, 0L,
227 KEY_ALL_ACCESS, &hKey);
228 if (res != ERROR_SUCCESS) {
229 return res;
230 }
231 }
232 DWORD val_dword = val;
233 return RegSetValueExA(hKey, key, 0L, REG_DWORD, (BYTE *) &val_dword, sizeof val_dword);
234}
235
236static bool
237set_key_from_str(const char *key, const char *val_c)
238{
239 char *endptr;
240 long val = strtol(val_c, &endptr, 0);
241 if (*endptr != '\0') {
242 log_msg(LOG_LEVEL_ERROR, "Wrong val: %s\n", val_c);
243 return false;
244 }
245 LRESULT res = set_winreg_key(key, val);
246 if (res == ERROR_SUCCESS) {
247 return true;
248 }
249 MSG(ERROR, "Cannot set %s=%ld: %s\n", key, val, get_win32_error(res));
250 return false;
251}
252
253static bool
254get_if_supported_key_val(char *fmt, const char **key, const char **val_c)
255{
256 if (strchr(fmt, '=') == NULL) {
257 MSG(ERROR, "No value for key %s\n", fmt);
258 return false;
259 }
260 *key = fmt;
261 *val_c = strchr(fmt, '=') + 1;
262 *strchr(fmt, '=') = '\0';
263 for (unsigned i = 0;
264 i < sizeof screen_cap_rec_opts / sizeof screen_cap_rec_opts[0];
265 i++) {
266 if (strcmp(*key, screen_cap_rec_opts[i]) == 0) {
267 return true;
268 }
269 }
270 MSG(ERROR, "Unknown parameter: %s\n", fmt);
271 return false;
272}
273
274static bool vidcap_screen_win_process_params(const char *fmt)
275{
276 if (!fmt || fmt[0] == '\0') {
277 return true;
278 }
279 char *fmt_c = strdup(fmt);
280 assert(fmt_c != NULL);
281
282 char *save_ptr;
283 char *tmp = fmt_c;
284 char *tok;
285
286 while ((tok = strtok_r(tmp, ":", &save_ptr)) != NULL) {
287 tmp = NULL;
288 const char *key;
289 const char *val_c;
290 if (IS_KEY_PREFIX(tok, "size") && strchr(tok, 'x') != NULL) {
291 char *width = strchr(tok, '=') + 1;
292 char *height = strchr(tok, 'x') + 1;
293 *strchr(tok, 'x') = '\0';
294 if (!set_key_from_str("capture_width", width) ||
295 !set_key_from_str("capture_height", height)) {
296 free(fmt_c);
297 return false;
298 }
299 continue;
300 } else if (strstr(tok, "width=") != NULL) {
301 MSG(WARNING, "Deprecated width=, use size=\n");
302 key ="capture_width";
303 val_c = tok + strlen("width=");
304 } else if (strstr(tok, "height=") != NULL) {
305 MSG(WARNING, "Deprecated height=, use size=\n");
306 key ="capture_height";
307 val_c = tok + strlen("height=");
308 } else if (strstr(tok, "fps=") != NULL) {
309 key ="default_max_fps";
310 val_c = tok + strlen("fps=");
311 } else if (!get_if_supported_key_val(tok, &key, &val_c)) {
312 free(fmt_c);
313 return false;
314 }
315 if (!set_key_from_str(key, val_c)) {
316 free(fmt_c);
317 return false;
318 }
319 }
320
321 free(fmt_c);
322 return true;
323}
324
325typedef HRESULT __stdcall (*func)();
326
327#define CHECK_NOT_NULL(cmd, err_action) do { if ((cmd) == NULL) { log_msg(LOG_LEVEL_ERROR, MOD_NAME "%s\n", #cmd); err_action; } } while(0)
328static void cleanup(struct vidcap_screen_win_state *s) {
329 assert(s != NULL);
330
331 if (s->dshow_state) {
333 }
334
335 if (s->filter_registered_here) {
337 }
338
339 free(s);
340}
341
343 void (*deleter)(void *) = NULL;
344 struct device_info *cards = NULL;
345 int count = 0;
347
348 bool ret = false;
349 for (int i = 0; i < count; ++i) {
350 if (strcmp(cards[i].name, "screen-capture-recorder") == 0) {
351 ret = true;
352 break;
353 }
354 }
356 deleter(cards);
357 return ret;
358}
359
360static int register_screen_cap_rec_library(bool is_elevated) {
361 HMODULE screen_cap_lib = LoadLibraryA("screen-capture-recorder-x64.dll");
362 if(!screen_cap_lib){
363 DWORD err_code = GetLastError();
364 MSG(ERROR, "Failed to load screen capture dll: %ld - %s\n",
365 err_code, get_win32_error(err_code));
366
367 return -1;
368 }
369 func register_filter;
370 CHECK_NOT_NULL(register_filter = (func)(void *) GetProcAddress(screen_cap_lib, "DllRegisterServer"), FreeLibrary(screen_cap_lib); return -1);
371 HRESULT res = register_filter();
372 FreeLibrary(screen_cap_lib);
373 if (SUCCEEDED(res)) {
374 return 0;
375 }
376 FreeLibrary(screen_cap_lib);
377 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Register failed: %s\n", hresult_to_str(res));
378 if (res == E_ACCESSDENIED) {
379 if (!is_elevated) {
380 log_msg(LOG_LEVEL_NOTICE, MOD_NAME "Need to register DirectShow module for screen capture, confirm if you agree.\n");
381 HINSTANCE ret = ShellExecute( NULL,
382 "runas",
383 uv_argv[0], " -t screen:register_elevated",
384 NULL, // default dir
385 SW_SHOWNORMAL
386 );
387 if ((INT_PTR) ret > 32) {
388 log_msg(LOG_LEVEL_NOTICE, MOD_NAME "Module installation successful.\n");
389 log_msg(LOG_LEVEL_NOTICE, MOD_NAME "If you want to unregister the module, run 'uv -t screen:unregister'.\n");
390 sleep(2);
391 return 1;
392 }
393 }
394 log_msg(LOG_LEVEL_WARNING, "Cannot register DLL (access denied), please allow access or install the filter from:\n"
395 " " FILTER_UPSTREAM_URL "\n");
396 } else {
397 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Register failed: %s\n", hresult_to_str(res));
398 }
399 return -1;
400}
401
402static bool
404{
405 HMODULE screen_cap_lib = NULL;
406 CHECK_NOT_NULL(screen_cap_lib =
407 LoadLibraryA("screen-capture-recorder-x64.dll"),
408 return false);
410 CHECK_NOT_NULL(unregister_filter = (func) (void *) GetProcAddress(
411 screen_cap_lib, "DllUnregisterServer"),
412 FreeLibrary(screen_cap_lib);
413 return false);
414 HRESULT res = unregister_filter();
415 if (SUCCEEDED(res)) {
416 MSG(NOTICE, "Filter unregistered successfully\n");
417 return true;
418 }
419 MSG(ERROR, "Cannot unregister filter, ret = %ld (%s)\n",
420 res, hresult_to_str(res));
421 return false;
422}
423
425 if (is_library_registered()) {
426 log_msg(LOG_LEVEL_VERBOSE, "Using already system-registered screen-capture-recorder library.\n");
427 return 0;
428 }
429
430 int rc = 0;
431 if ((rc = register_screen_cap_rec_library(false)) != 0) {
432 return rc;
433 }
434 s->filter_registered_here = true;
435 return 0;
436}
437
438static int run_child_process() {
439 char cmd[1024] = "";
440 for (int i = 0; i < uv_argc; ++i) {
441 char tmp[1024];
442 if (strstr(uv_argv[i], "screen") == uv_argv[i]) {
443 if (strlen(uv_argv[i]) >= 7) { // screen:
444 snprintf(tmp, sizeof tmp, "\"screen:child:%s\" ", uv_argv[i] + 6);
445 } else
446 snprintf(tmp, sizeof tmp, "\"screen:child\" ");
447 } else {
448 snprintf(tmp, sizeof tmp, "\"%s\" ", uv_argv[i]);
449 }
450 strncat(cmd, tmp, sizeof cmd - strlen(cmd) - 1);
451 }
452 if (strlen(cmd) == sizeof cmd - 1) {
453 return -1; // potential overflow
454 }
455 STARTUPINFO si = { 0 };
456 PROCESS_INFORMATION pi = { 0 };
457 log_msg(LOG_LEVEL_VERBOSE, MOD_NAME "Starting child process:\n%s\n", cmd);
458 const bool ret = CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL,
459 NULL, &si, &pi);
460 if (ret) {
461 WaitForSingleObject(pi.hProcess, INFINITE);
462 }
463 return ret;
464}
465
467{
468 const char *cfg = vidcap_params_get_fmt(params);
469 bool child = false; // to prevent fork bombs if error
470 if (strcmp(cfg, "help") == 0 || strcmp(cfg, "fullhelp") == 0) {
471 show_help(strcmp(cfg, "fullhelp") == 0);
472 return VIDCAP_INIT_NOERR;
473 }
474 if (strcmp(cfg, "register_elevated") == 0) {
475 int rc = register_screen_cap_rec_library(true);
476 system("pause");
477 return rc >= 0 ? VIDCAP_INIT_NOERR : VIDCAP_INIT_FAIL;
478 }
479 if (strcmp(cfg, "unregister") == 0) {
480 HINSTANCE inst = ShellExecute(NULL, "runas", uv_argv[0],
481 " -t screen:unregister_elevated",
482 NULL, // default dir
483 SW_SHOWNORMAL);
484 INT_PTR ret = (INT_PTR) inst;
485 if (ret > 32) {
486 return VIDCAP_INIT_NOERR;
487 }
488 MSG(ERROR, "Elevated subshell exec failed, res = %lld (%s)\n",
489 ret, get_win32_error(ret));
490 return VIDCAP_INIT_FAIL;
491 }
492 if (strcmp(cfg, "unregister_elevated") == 0) {
493 bool res = unregister_filter();
494 system("pause");
495 return res ? VIDCAP_INIT_NOERR : VIDCAP_INIT_FAIL;
496 }
497 if (strstr(cfg, "clear_prefs") == cfg) {
498 cfg += strlen("clear_prefs");
500 }
501 if (strstr(cfg, "child") == cfg) {
502 child = true;
503 cfg = strchr(cfg, ':') ? strchr(cfg, ':') + 1 : "";
504 }
505
507 MSG(INFO, "See \"-t screen:help\" for usage.\n");
508 return VIDCAP_INIT_FAIL;
509 }
510
511 struct vidcap_screen_win_state *s = calloc(1, sizeof *s);
512 int rc = load_screen_cap_rec_library(s);
513 if (rc != 0) {
514 cleanup(s);
515 if (rc < 0) {
516 return VIDCAP_INIT_FAIL;
517 }
518 return child ? VIDCAP_INIT_FAIL : run_child_process();
519 }
520
521 struct vidcap_params *params_dshow = vidcap_params_allocate();
522 vidcap_params_set_device(params_dshow, "dshow:device=screen-capture-recorder");
524 int ret = vidcap_dshow_info.init(params_dshow, &s->dshow_state);
525 if (ret != 0) {
526 log_msg(LOG_LEVEL_ERROR, MOD_NAME "DirectShow init failed: %d\n", ret);
527 cleanup(s);
528 return VIDCAP_INIT_FAIL;
529 }
530 vidcap_params_free_struct(params_dshow);
531
533
534 *state = s;
535 return ret;
536}
537
539{
540 cleanup(state);
541}
542
544{
545 struct vidcap_screen_win_state *s = state;
547}
548
556
558
void ** state
int void * val
struct video_desc desc
const char * fmt
struct audio_frame ** audio
int void(** deleter)(void *))
This file contains definition of some common audio types.
static void show_help()
Definition wasapi.cpp:193
int color_printf(const char *format,...)
#define TRED(x)
Definition color_out.h:75
#define TBOLD(x)
Definition color_out.h:70
#define FALSE
unsigned char BYTE
Definition crypt_aes.h:71
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
#define MSG(l, fmt,...)
Definition debug.h:96
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
#define VIDCAP_INIT_NOERR
state not initialized, other action performed (typically help)
#define VIDEO_CAPTURE_ABI_VERSION
#define VIDCAP_INIT_FAIL
error ocured
int count
Definition hd-rum.c:44
char ** uv_argv
Definition host.cpp:174
int uv_argc
Definition host.cpp:173
@ LIBRARY_CLASS_VIDEO_CAPTURE
Definition lib_common.h:78
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
Definition lib_common.h:144
#define IS_KEY_PREFIX(tok, key)
expands to true value if <k> from tok in format <k>=<v> is prefix of key
Definition macros.h:138
#define IF_NOT_NULL_ELSE(val, default_val)
Definition macros.h:51
static int run_child_process()
Definition screen_win.c:438
static struct video_frame * vidcap_screen_win_grab(void *state, struct audio_frame **audio)
Definition screen_win.c:543
const struct video_capture_info vidcap_dshow_info
static void vidcap_screen_win_probe(struct device_info **available_cards, int *count, void(**deleter)(void *))
Definition screen_win.c:143
static bool is_library_registered()
Definition screen_win.c:342
static void print_winreg_values()
Definition screen_win.c:157
HRESULT __stdcall(* func)()
Definition screen_win.c:325
static bool delete_winreg_tree()
Definition screen_win.c:197
static LRESULT set_winreg_key(const char *key, int val)
Definition screen_win.c:212
#define CHECK_NOT_NULL(cmd, err_action)
Definition screen_win.c:327
static int vidcap_screen_win_init(struct vidcap_params *params, void **state)
Definition screen_win.c:466
static void vidcap_screen_win_done(void *state)
Definition screen_win.c:538
#define FILTER_UPSTREAM_URL
Definition screen_win.c:68
static bool vidcap_screen_win_process_params(const char *fmt)
Definition screen_win.c:274
static const struct video_capture_info vidcap_screen_win_info
Definition screen_win.c:549
#define MOD_NAME
Definition screen_win.c:67
static bool get_if_supported_key_val(char *fmt, const char **key, const char **val_c)
Definition screen_win.c:254
static bool set_key_from_str(const char *key, const char *val_c)
Definition screen_win.c:237
#define SCREEN_CAP_REG_TREE
Definition screen_win.c:153
#define REG_FRIENDLY_NAME
Definition screen_win.c:154
static int register_screen_cap_rec_library(bool is_elevated)
Definition screen_win.c:360
static bool unregister_filter()
Definition screen_win.c:403
static int load_screen_cap_rec_library(struct vidcap_screen_win_state *s)
Definition screen_win.c:424
static const char *const screen_cap_rec_opts[]
Definition screen_win.c:79
static void cleanup()
Definition sdp.c:195
const char * name
Definition settings.cpp:193
struct used to comunicate with audio capture/playback device
Definition types.h:99
bool filter_registered_here
we were able to register filter as a normal user -> cleanup at end
Definition screen_win.c:75
int(* init)(struct vidcap_params *param, void **state)
device_probe_func probe
void(* done)(void *state)
struct video_frame *(* grab)(void *state, struct audio_frame **audio)
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
char * wrap_paragraph(char *text)
Definition text.c:204
This is an umbrella header for video functions.
struct module * vidcap_params_get_parent(const struct vidcap_params *params)
void vidcap_params_set_parent(struct vidcap_params *params, struct module *mod)
void vidcap_params_free_struct(struct vidcap_params *buf)
const char * vidcap_params_get_fmt(const struct vidcap_params *params)
struct vidcap_params * vidcap_params_allocate(void)
void vidcap_params_set_device(struct vidcap_params *params, const char *config)
const char * key
Definition cineform.cpp:125