UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
host.cpp
Go to the documentation of this file.
1
8/*
9 * Copyright (c) 2013-2024 CESNET
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, is permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 *
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 *
23 * 3. Neither the name of CESNET nor the names of its contributors may be
24 * used to endorse or promote products derived from this software without
25 * specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
28 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
29 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
30 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
31 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
32 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
33 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
34 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
37 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
38 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41#ifdef HAVE_CONFIG_H
42#include "config.h"
43#endif
44
45#include "host.h"
46
47#ifdef _WIN32
48#include <io.h>
49#else
50#include <execinfo.h>
51#include <fcntl.h>
52#endif // !defined _WIN32
53
54#ifdef __gnu_linux__
55#include <features.h> // for __GLIBC__, __GLIBC_MINOR__
56#include <sys/mman.h> // for memfd_create, MFD_CLOEXEC
57#endif
58
59#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 27
60#include <sys/syscall.h>
61#endif
62
63#include <algorithm> // for max
64#include <array>
65#include <cassert> // for assert
66#include <cerrno> // for errno
67#include <cmath> // for abs
68#include <csignal> // for signal, SIGALRM, SIG_DFL, raise
69#include <cstdint> // for uint32_t
70#include <cstdio> // for printf, puts, perror, _IONBF
71#include <cstdlib> // for abort, getenv, free, abs, EXI...
72#include <cstring> // for strlen, strcmp, NULL, strchr
73#include <getopt.h> // for getopt, optarg, opterr
74#include <iterator> // for size
75#include <map> // for map, _Rb_tree_iterator, opera...
76#include <mutex> // for mutex, unique_lock
77#include <string_view> // for operator<<, operator==, strin...
78#include <sys/types.h> // for ssize_t
79#include <tuple> // for tuple, get, make_tuple
80#include <unistd.h> // for STDERR_FILENO
81#include <vector> // for vector
82
83#include "audio/audio_capture.h"
84#include "audio/audio_filter.h"
86#include "audio/codec.h"
87#include "audio/types.h" // for audio_desc
88#include "audio/utils.h"
89#include "capture_filter.h"
91#include "compat/strings.h" // strdupa
92#include "config_unix.h" // for fd_t
93#include "cuda_wrapper.h" // for cudaDeviceReset
94#include "debug.h"
95#include "keyboard_control.h"
96#include "lib_common.h"
97#include "module.h"
98#include "types.h" // for device_info, device_option
99#include "utils/color_out.h"
100#include "utils/fs.h" // for MAX_PATH_SIZE
101#include "utils/misc.h" // ug_strerror
102#include "utils/random.h"
103#include "utils/string.h"
105#include "utils/text.h"
106#include "utils/thread.h"
107#include "utils/windows.h"
108#include "video_capture.h"
109#include "video_codec.h" // for get_codec_name, get_codec_nam...
110#include "video_compress.h"
111#include "video_display.h"
112
113#include <iomanip>
114#include <iostream>
115#include <list>
116#include <fstream>
117#include <string>
118#include <thread>
119#include <utility>
120
121#if defined HAVE_X || defined BUILD_LIBRARIES
122#include <dlfcn.h>
123#endif
124#if defined HAVE_X
125#include <X11/Xlib.h>
128#define X11_LIB_NAME "libX11.so.6"
129#endif
130
131#ifdef HAVE_FEC_INIT
132#define restrict __restrict // not a C++ keyword
133extern "C" {
134#include <fec.h>
135}
136#endif
137
138#ifdef __linux__
139#include <mcheck.h>
140#endif
141
142#define MOD_NAME "[host] "
143
144using std::array;
145using std::cout;
146using std::endl;
147using std::get;
148using std::ifstream;
149using std::left;
150using std::list;
151using std::make_tuple;
152using std::max;
153using std::mutex;
154using std::pair;
155using std::setw;
156using std::string;
157using std::thread;
158using std::to_string;
159using std::tuple;
160using std::unordered_map;
161using std::unique_lock;
162
163unsigned int audio_capture_channels = 0;
164unsigned int audio_capture_bps = 0;
166
167unsigned int cuda_devices[MAX_CUDA_DEVICES] = { 0 };
168unsigned int cuda_devices_count = 1;
170
171uint32_t RTT = 0; /* this is computed by handle_rr in rtp_callback */
172
174char **uv_argv;
175
176char *export_dir = NULL;
177
178volatile int audio_offset;
179volatile int video_offset;
180
183
184std::unordered_map<std::string, std::string> commandline_params;
185
188
189#if defined HAVE_CUDA && defined _WIN32
190// required for NVCC+MSVC compiled objs if /nodefaultlib is used
191extern "C" int _fltused = 0;
192#endif
193
194struct init_data {
195 bool com_initialized = false;
196 list <void *> opened_libs;
197};
198
199static void print_param_doc(void);
200static bool validate_param(const char *param);
201
202static bool unexpected_exit_called = true; // check for unexpected exit()
204{
205 if (init) {
206#if defined BUILD_LIBRARIES
207 for (auto a : init->opened_libs) {
208 dlclose(a);
209 }
210#endif
211 com_uninitialize(&init->com_initialized);
212 }
213 delete init;
214
215#ifdef __linux__
216 muntrace();
217#endif
218
219#ifdef _WIN32
220 WSACleanup();
221#endif
222
223#if defined CUDA_DEVICE_RESET
224 // to allow "cuda-memcheck --leak-check full"
226#endif
227
229}
230
231ADD_TO_PARAM("stdout-buf",
232 "* stdout-buf={no|line|full}\n"
233 " Buffering for stdout\n");
234ADD_TO_PARAM("stderr-buf",
235 "* stderr-buf={no|line|full}\n"
236 " Buffering for stderr\n");
237static bool set_output_buffering() {
238 const unordered_map<const char *, pair<FILE *, int>> outs = { // pair<output, default mode>
239#ifdef _WIN32
240 { "stdout-buf", pair{stdout, _IONBF} },
241#else
242 { "stdout-buf", pair{stdout, _IOLBF} },
243#endif
244 { "stderr-buf", pair{stderr, _IONBF} }
245 };
246 for (const auto& outp : outs) {
247 int mode = outp.second.second; // default
248
250 mode = _IONBF;
251 log_msg(LOG_LEVEL_WARNING, "Running inside debugger - disabling output buffering.\n");
252 }
253
254 if (get_commandline_param(outp.first)) {
255 const unordered_map<string, int> buf_map {
256 { "no", _IONBF }, { "line", _IOLBF }, { "full", _IOFBF }
257 };
258
259 if (string("help") == get_commandline_param(outp.first)) {
260 printf("Available values for buffering are \"no\", \"line\" and \"full\"\n");
261 return false;
262 }
263 auto it = buf_map.find(get_commandline_param(outp.first));
264 if (it == buf_map.end()) {
265 log_msg(LOG_LEVEL_ERROR, "Wrong buffer type: %s\n", get_commandline_param(outp.first));
266 return false;
267 }
268 mode = it->second;
269 }
270 if (setvbuf(outp.second.first, NULL, mode, BUFSIZ) != 0) {
271 log_msg(LOG_LEVEL_WARNING, "setvbuf: %s\n", ug_strerror(errno));
272 }
273 }
274 return true;
275}
276
277#ifdef HAVE_X
283static int x11_error_handler(Display *d, XErrorEvent *e) {
284 //char msg[1024] = "";
285 //XGetErrorText(d, e->error_code, msg, sizeof msg - 1);
286 UNUSED(d);
287 log_msg(LOG_LEVEL_ERROR, "X11 error - code: %d, serial: %d, error: %d, request: %d, minor: %d\n",
288 e->error_code, e->serial, e->error_code, e->request_code, e->minor_code);
289 fprintf(stderr, "Backtrace:\n");
290 array<void *, 256> addresses{};
291 int num_symbols = backtrace(addresses.data(), addresses.size());
292 backtrace_symbols_fd(addresses.data(), num_symbols, 2);
293 return 0;
294}
295#endif
296
300static void load_libgcc()
301{
302#ifndef _WIN32
303 array<void *, 1> addresses{};
304 backtrace(addresses.data(), addresses.size());
305#endif
306}
307
313int set_audio_capture_format(const char *optarg)
314{
315 struct audio_desc desc = {};
316 if (int ret = parse_audio_format(optarg, &desc)) {
317 return ret;
318 }
319
323
324 return 0;
325}
326
327int set_pixfmt_conv_policy(const char *optarg) {
328 if (strcmp(optarg, "help") == 0) {
329 char desc[] =
330 TBOLD("--conv-policy") " specifies the order in which various pixfmt properties are to be evaluated "
331 "if some pixel format needs conversion to another suitable pixel format.";
332 color_printf("%s\n\n", wrap_paragraph(desc));
333 color_printf("\t" TBOLD("c") " - color space\n");
334 color_printf("\t" TBOLD("d") " - bit depth\n");
335 color_printf("\t" TBOLD("s") " - subsampling\n");
336 color_printf("\nDefault: \"" TBOLD("dsc") "\" - first is respected bit-depth, then subsampling and finally color space\n\n"
337 "Permute the above letters to change the default order, eg. \"" TBOLD("cds") "\" to attempt to keep colorspace.\n");
338 return 1;
339 }
340 if (strlen(optarg) != strlen(pixfmt_conv_pref)) {
341 log_msg(LOG_LEVEL_ERROR, "Wrong pixfmt conversion policy length (exactly 3 letters need to be used)!\n");
342 return -1;
343 }
344 if (strchr(optarg, 'd') == NULL || strchr(optarg, 's') == NULL || strchr(optarg, 'c') == NULL) {
345 log_msg(LOG_LEVEL_ERROR, "Wrong pixfmt conversion policy - use exactly the set 'dsc'!\n");
346 return -1;
347 }
348 memcpy(pixfmt_conv_pref, optarg, strlen(pixfmt_conv_pref));
349 return 0;
350}
351
357static bool parse_opts_set_logging(int argc, char *argv[])
358{
359 char *log_opt = nullptr;
360 static struct option getopt_options[] = {
361 {"param", required_argument, nullptr, 'O'},
362 {"verbose", optional_argument, nullptr, 'V'},
363 { nullptr, 0, nullptr, 0 }
364 };
365 const char *const optstring = "+O:V";
366 int saved_opterr = opterr;
367 opterr = 0; // options are further handled in main.cpp. skip unknown
368
369 int logging_lvl = 0;
370 bool logger_skip_repeats = true;
371
372 log_timestamp_mode logger_show_timestamps = LOG_TIMESTAMP_AUTO;
373
374 while (optind < argc) {
375 const int ch =
376 getopt_long(argc, argv, optstring, getopt_options, nullptr);
377 switch (ch) {
378 case 'V':
379 if (optarg != nullptr) {
380 log_opt = optarg;
381 } else {
382 logging_lvl += 1;
383 }
384 break;
385 case 'O':
386 if (!parse_params(optarg, true)) {
387 return false;
388 }
389 break;
390 case -1: // skip a non-option (or an argument to an option that
391 // is not recognized by this getopt)
392 optind += 1;
393 break;
394 case '?': // other option that will be handled in main
395 break;
396 default:
397 abort(); // shouldn't reach here
398 }
399 }
400 optind = 0;
401 opterr = saved_opterr;
402 if (logging_lvl == 0) {
403 logging_lvl = getenv("ULTRAGRID_VERBOSE") != nullptr && strlen(getenv("ULTRAGRID_VERBOSE")) > 0 ? LOG_LEVEL_VERBOSE : log_level;
404 } else {
405 logging_lvl += LOG_LEVEL_INFO;
406 }
407 if (log_opt != nullptr && !parse_log_cfg(log_opt, &logging_lvl, &logger_skip_repeats, &logger_show_timestamps)) {
408 return false;
409 }
410 log_level = logging_lvl;
411 get_log_output().set_skip_repeats(logger_skip_repeats);
412 get_log_output().set_timestamp_mode(logger_show_timestamps);
413 return true;
414}
415
416bool
417tok_in_argv(char **argv, const char *tok)
418{
419 while (*argv != nullptr) {
420 if (strstr(*argv, tok) != nullptr) {
421 return true;
422 }
423 argv++;
424 }
425 return false;
426}
427
428static void echeck_unexpected_exit(void ) {
430 return;
431 }
432 fprintf(stderr, "exit() called unexpectedly! Maybe by some library?\n");
433}
434
435struct init_data *common_preinit(int argc, char *argv[])
436{
437 uv_argc = argc;
438 uv_argv = argv;
439
440 if (!parse_opts_set_logging(argc, argv)) {
441 return nullptr;
442 }
443
444 if (!set_output_buffering()) {
445 LOG(LOG_LEVEL_WARNING) << "Cannot set console output buffering!\n";
446 return nullptr;
447 }
448 std::clog.rdbuf(std::cout.rdbuf()); // use stdout for logs by default
450
451#ifdef HAVE_X
452 void *handle = dlopen(X11_LIB_NAME, RTLD_NOW);
453
454 if (handle) {
455 Status (*XInitThreadsProc)();
456 XInitThreadsProc = (Status (*)()) dlsym(handle, "XInitThreads");
457 if (XInitThreadsProc) {
458 Status s = XInitThreadsProc();
459 if (s != True) {
460 log_msg(LOG_LEVEL_WARNING, "XInitThreads failed.\n");
461 }
462 } else {
463 log_msg(LOG_LEVEL_WARNING, "Unable to load symbol XInitThreads: %s\n", dlerror());
464 }
465
466 typedef int (*XSetErrorHandler_t(int (*handler)(Display *, XErrorEvent *)))();
467 XSetErrorHandler_t *XSetErrorHandlerProc;
468 XSetErrorHandlerProc = (XSetErrorHandler_t *) dlsym(handle, "XSetErrorHandler");
469 if (XSetErrorHandlerProc) {
470 XSetErrorHandlerProc(x11_error_handler);
471 } else {
472 log_msg(LOG_LEVEL_WARNING, "Unable to load symbol XSetErrorHandler: %s\n", dlerror());
473 }
474
475 dlclose(handle);
476 } else {
477 log_msg(LOG_LEVEL_WARNING, "Unable open " X11_LIB_NAME " library: %s\n", dlerror());
478 }
479#endif
480
481 struct init_data init{};
482#ifdef _WIN32
483 WSADATA wsaData;
484 int err = WSAStartup(MAKEWORD(2, 2), &wsaData);
485 if(err != 0) {
486 fprintf(stderr, "WSAStartup failed with error %d.", err);
487 return nullptr;
488 }
489 if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
490 fprintf(stderr, "Counld not found usable version of Winsock.\n");
491 WSACleanup();
492 return nullptr;
493 }
494
495 SetConsoleOutputCP(CP_UTF8); // see also https://stackoverflow.com/questions/1660492/utf-8-output-on-windows-console
496
497 // Initialize COM on main thread - otherwise Portaudio would initialize it as COINIT_APARTMENTTHREADED but MULTITHREADED
498 // is perhaps better variant (Portaudio would accept that).
499 const bool init_com = !tok_in_argv(argv, "screen:unregister_elevated");
500 if (init_com) {
501 com_initialize(&init.com_initialized, nullptr);
502 }
503
504 // warn in W10 "legacy" terminal emulators
505 if (getenv("TERM") == nullptr &&
506 _isatty(fileno(stdout)) &&
507 get_windows_build() < BUILD_WINDOWS_11_OR_LATER &&
508 (win_has_ancestor_process("powershell.exe") ||
509 win_has_ancestor_process("cmd.exe")) &&
510 !win_has_ancestor_process("WindowsTerminal.exe")) {
511 MSG(WARNING, "Running inside PS/cmd terminal is not recommended "
512 "because scrolling the output freezes the process, "
513 "consider using Windows Terminal instead!\n");
514 Sleep(1000);
515 }
516#endif
517
518 if (strstr(argv[0], "run_tests") == nullptr) {
519 open_all("ultragrid_*.so", init.opened_libs); // load modules
520 }
521
522 ug_rand_init();
523
524#ifdef __linux__
525 mtrace();
526#endif
527
528 load_libgcc();
529
530#ifdef HAVE_FEC_INIT
531 fec_init();
532#endif
533
535
536 return new init_data{ std::move(init) };
537}
538
540 state_root() noexcept {
542 LOG(LOG_LEVEL_FATAL) << "FATAL: Cannot create pipe!\n";
543 abort();
544 }
546 }
548 unique_lock<mutex> lk(lock);
549 should_exit_callbacks.clear();
550 lk.unlock();
551 broadcast_should_exit(true); // here just exit the should exit thr
552 should_exit_thread.join();
553 for (int i = 0; i < 2; ++i) {
555 }
556 }
557 static void deleter(struct module *m) {
558 delete (state_root*) m->priv_data;
559 }
560
562 set_thread_name(__func__);
563 char q = 0;
564 bool should_exit_thread_notified = false;
565 while (q != QUIT_WATCHER_FLAG) {
566 while (PLATFORM_PIPE_READ(s->should_exit_pipe[0], &q,
567 1) != 1) {
568 perror("PLATFORM_PIPE_READ");
569 }
570 if (!should_exit_thread_notified) {
571 unique_lock<mutex> lk(s->lock);
572 for (auto const &c : s->should_exit_callbacks) {
573 get<0>(c)(get<1>(c));
574 }
575 should_exit_thread_notified = true;
576 }
577 }
578 }
579 void broadcast_should_exit(bool quit_watcher = false)
580 {
581 const char q = quit_watcher ? QUIT_WATCHER_FLAG : 0;
582 while (PLATFORM_PIPE_WRITE(should_exit_pipe[1], &q, 1) != 1) {
583 perror("PLATFORM_PIPE_WRITE");
584 }
585 }
586
587 volatile int exit_status = EXIT_SUCCESS;
588private:
589 static constexpr char QUIT_WATCHER_FLAG = 1;
590 mutex lock;
593 list<tuple<void (*)(void *), void *>> should_exit_callbacks;
594 friend void register_should_exit_callback(struct module *mod,
595 void (*callback)(void *),
596 void *udata);
598 void (*callback)(void *),
599 void *udata);
600};
601
602static state_root * volatile state_root_static;
603
610void init_root_module(struct module *root_mod) {
611 module_init_default(root_mod);
612 root_mod->cls = MODULE_CLASS_ROOT;
613 root_mod->new_message = nullptr; // note that the root mod messages
614 // processes also the reflector
615 root_mod->deleter = state_root::deleter;
617 root_mod->priv_data = state_root_static;
618}
619
625void exit_uv(int status) {
626 if (!state_root_static) {
627 log_msg(LOG_LEVEL_WARNING, "%s called witout state registered.\n", __func__);
628 }
631}
632
633int get_exit_status(struct module *root_mod) {
634 assert(root_mod->cls == MODULE_CLASS_ROOT);
635 return static_cast<state_root *>(root_mod->priv_data)->exit_status;
636}
637
638using module_info_map = std::map<std::string, const void *>;
639
640static void print_device(std::string purpose, std::string const & mod, const device_info& device){
641 cout << "[capability][device] {"
642 "\"purpose\":" << std::quoted(purpose) << ", "
643 "\"module\":" << std::quoted(mod) << ", "
644 "\"device\":" << std::quoted(device.dev) << ", "
645 "\"name\":" << std::quoted(device.name) << ", "
646 "\"extra\": {" << device.extra << "}, "
647 "\"repeatable\":\"" << device.repeatable << "\", "
648 "\"modes\": [";
649
650 for(unsigned int j = 0; j < std::size(device.modes); j++) {
651 if (device.modes[j].id[0] == '\0') { // last item
652 break;
653 }
654 if (j > 0) {
655 printf(", ");
656 }
657 std::cout << "{\"name\":" << std::quoted(device.modes[j].name) << ", "
658 "\"opts\":" << device.modes[j].id << "}";
659 }
660 std::cout << "]";
661
662 std::cout << ", \"options\": [";
663 for(unsigned int j = 0; j < std::size(device.options); j++) {
664 if (device.options[j].key[0] == '\0') { // last item
665 break;
666 }
667 if (j > 0) {
668 printf(", ");
669 }
670 cout << "{"
671 "\"display_name\":" << std::quoted(device.options[j].display_name) << ", "
672 "\"display_desc\":" << std::quoted(device.options[j].display_desc) << ", "
673 "\"key\":" << std::quoted(device.options[j].key) << ", "
674 "\"opt_str\":" << std::quoted(device.options[j].opt_str) << ", "
675 "\"is_boolean\":\"" << (device.options[j].is_boolean ? "t" : "f") << "\"}";
676 }
677 std::cout << "]";
678
679 std::cout << "}\n";
680}
681
682template<typename T>
683static void probe_device(std::string_view cap_str, std::string const & name, const void *mod){
684 auto vdi = static_cast<T>(mod);
685 int count = 0;
686 struct device_info *devices = nullptr;
687 void (*deleter)(void *) = nullptr;
688 vdi->probe(&devices, &count, &deleter);
689 for (int i = 0; i < count; ++i) {
690 print_device(std::string(cap_str), name, devices[i]);
691 }
692 deleter ? deleter(devices) : free(devices);
693}
694
695static void probe_compress(std::string const & name, const void *mod) noexcept {
696 auto vci = static_cast<const struct video_compress_info *>(mod);
697
698 if(vci->get_module_info){
699 auto module_info = vci->get_module_info();
700 cout << "[capability][video_compress] {"
701 "\"name\":" << std::quoted(name) << ", "
702 "\"options\": [";
703
704 int i = 0;
705 for(const auto& opt : module_info.opts){
706 if(i++ > 0)
707 cout << ", ";
708
709 cout << "{"
710 "\"display_name\":" << std::quoted(opt.display_name) << ", "
711 "\"display_desc\":" << std::quoted(opt.display_desc) << ", "
712 "\"placeholder_text\":" << std::quoted(opt.placeholder_text) << ", "
713 "\"key\":" << std::quoted(opt.key) << ", "
714 "\"opt_str\":" << std::quoted(opt.opt_str) << ", "
715 "\"is_boolean\":\"" << (opt.is_boolean ? "t" : "f") << "\"}";
716 }
717
718 cout << "], "
719 "\"codecs\": [";
720
721 int j = 0;
722 for(const auto& c : module_info.codecs){
723 if(j++ > 0)
724 cout << ", ";
725
726 cout << "{\"name\":" << std::quoted(c.name) << ", "
727 "\"priority\": " << c.priority << ", "
728 "\"encoders\":[";
729
730 int z = 0;
731 for(const auto& e : c.encoders){
732 if(z++ > 0)
733 cout << ", ";
734
735 cout << "{\"name\":" << std::quoted(e.name) << ", "
736 "\"opt_str\":" << std::quoted(e.opt_str) << "}";
737 }
738 cout << "]}";
739 }
740
741 cout << "]}" << std::endl;
742
743 }
744}
745
746const static struct {
747 std::string_view desc;
748 std::string_view cap_str;
751 void (*probe_print)(std::string name, const void *);
752} mod_classes[] = {
753 {"Compressions", "compress",
755 [](std::string name, const void *m) { probe_compress(name, m); }},
756 {"Capture filters", "capture_filter",
758 nullptr},
759 {"Capturers", "capture",
761 [](std::string name, const void *m){ probe_device<const video_capture_info *>("capture", name, m); }},
762 {"Displays", "display",
764 [](std::string name, const void *m){ probe_device<const video_display_info *>("video_disp", name, m); }},
765 {"Audio capturers", "audio_cap",
767 [](std::string name, const void *m){ probe_device<const audio_capture_info *>("audio_cap", name, m); }},
768 {"Audio filters", "audio_filter",
770 nullptr},
771 {"Audio compress", "audio_compress",
773 nullptr},
774 {"Audio playback", "audio_play",
776 [](std::string name, const void *m){ probe_device<const audio_playback_info *>("audio_play", name, m); }},
778
779
780static void probe_all(std::map<enum library_class, module_info_map>& class_mod_map)
781{
782 for(const auto& mod_class : mod_classes){
783 for(const auto& mod : class_mod_map[mod_class.cls]){
784 if(!mod_class.probe_print)
785 continue;
786 mod_class.probe_print(mod.first, mod.second);
787 }
788 }
789}
790
791static void print_modules(std::map<enum library_class, module_info_map>& class_mod_map)
792{
793 for(const auto& mod_class : mod_classes){
794 std::cout << "[cap] " << mod_class.desc << ":\n";
795 for(const auto& mod : class_mod_map[mod_class.cls]){
796 cout << "[cap][" << mod_class.cap_str <<"] " << mod.first << "\n";
797 }
798 }
799}
800
801void print_capabilities(const char *cfg)
802{
803 std::string_view conf(cfg);
804
805 std::cout << "[capability][start] version 4" << endl;
806
807 std::map<enum library_class, module_info_map> class_mod_map;
808 for(const auto& mod_class: mod_classes){
809 class_mod_map.emplace(mod_class.cls,
810 get_libraries_for_class(mod_class.cls, mod_class.abi_ver));
811 }
813 for(const auto& codec : codecs){
814 class_mod_map[LIBRARY_CLASS_AUDIO_COMPRESS].emplace(get<0>(codec).name, nullptr);
815 }
816
817 if(conf == "noprobe"){
818 print_modules(class_mod_map);
819 } else if(conf.empty()){
820 print_modules(class_mod_map);
821 probe_all(class_mod_map);
822 } else {
823 auto class_sv = tokenize(conf, ':');
824 auto mod_sv = tokenize(conf, ':');
825
827 void (*probe_print)(std::string name, const void *) = nullptr;
828 for(const auto& i : mod_classes){
829 if(i.cap_str == class_sv){
830 cls = i.cls;
831 probe_print = i.probe_print;
832 }
833 }
834
836 log_msg(LOG_LEVEL_FATAL, "Unknown library class\n");
837 return;
838 }
839
840 auto& modmap = class_mod_map[cls];
841
842 auto modinfo = modmap.find(std::string(mod_sv));
843 if(modinfo == modmap.end()){
844 log_msg(LOG_LEVEL_FATAL, "Module not found\n");
845 return;
846 }
847
848 if(probe_print)
849 probe_print(std::string(mod_sv), modinfo->second);
850
851 }
852
853 cout << "[capability][end]" << endl;
854}
855
857{
858 return
859#ifdef GIT_BRANCH
860 GIT_BRANCH " "
861#endif
862#ifdef GIT_REV
863 "rev " GIT_REV " "
864#endif
865 "built " __DATE__ " " __TIME__;
866}
867
869{
870 bool is_release = true;
871#ifdef GIT_BRANCH
872 if (strstr(GIT_BRANCH, "release") == nullptr &&
873 strstr(GIT_BRANCH, "tags/v") == nullptr) {
874 is_release = false;
875 }
876#endif
877 col() << SBOLD(S256_FG(T_PEACH_FUZZ, PACKAGE_STRING <<
878 (is_release ? "" : "+"))) <<
879 " (" << get_version_details() << ")\n";
880}
881
883{
884 const char *config_flags = CONFIG_FLAGS;
885 if (strlen(config_flags) == 0) {
886 config_flags = "(none)";
887 }
888 printf("configuration flags: %s", config_flags);
889 printf("\n\n");
890 printf(PACKAGE_NAME " was compiled with following features:\n");
891 printf(AUTOCONF_RESULT);
892}
893
894const char *get_commandline_param(const char *key)
895{
896 auto it = commandline_params.find(key);
897 if (it != commandline_params.end()) {
898 return it->second.c_str();
899 } else {
900 return NULL;
901 }
902}
903
904void set_commandline_param(const char *key, const char *val)
905{
907}
908
910{
911 return audio_offset > 0 ? audio_offset : -video_offset;
912}
913
914void set_audio_delay(int audio_delay)
915{
916 log_msg(LOG_LEVEL_NOTICE, "Setting A/V delay: %d\n", audio_delay);
917 audio_offset = max(audio_delay, 0);
918 video_offset = audio_delay < 0 ? abs(audio_delay) : 0;
919}
920
921static struct {
922 const char *param;
923 const char *doc;
924} params[100];
925
930void register_param(const char *param, const char *doc)
931{
932 assert(param != NULL && doc != NULL);
933 for (unsigned int i = 0; i < sizeof params / sizeof params[0]; ++i) {
934 if (params[i].param == NULL) {
935 params[i].param = param;
936 params[i].doc = doc;
937 return;
938 }
939 if (strcmp(params[i].param, param) == 0) {
940 if (strcmp(params[i].doc, doc) != 0) {
941 log_msg(LOG_LEVEL_WARNING, "Param \"%s\" as it is already registered but with different documentation.\n", param);
942 }
943 return;
944 }
945 }
946 log_msg(LOG_LEVEL_WARNING, "Cannot register param \"%s\", maxmimum number of parameters reached.\n", param);
947}
948
949bool validate_param(const char *param)
950{
951 for (unsigned int i = 0; i < sizeof params / sizeof params[0]; ++i) {
952 if (params[i].param == NULL) {
953 return false;
954 }
955 if (strcmp(params[i].param, param) == 0) {
956 return true;
957 }
958 }
959 return false;
960}
961
962
976bool parse_params(const char *optarg, bool preinit)
977{
978 if (!preinit && strcmp(optarg, "help") == 0) {
979 puts("Use of params below is experimental and should be used with a caution and a knowledge of consequences and affected functionality!\n");
980 puts("Params can be one or more (separated by comma) of following:");
982 return false;
983 }
984 char *tmp = strdupa(optarg);
985 char *item = nullptr;
986 char *save_ptr = nullptr;
987 while ((item = strtok_r(tmp, ",", &save_ptr)) != nullptr) {
988 tmp = nullptr;
989 char *key_cstr = item;
990 const char *val_cstr = "";
991 if (char *delim = strchr(item, '=')) {
992 val_cstr = delim + 1;
993 *delim = '\0';
994 }
995 if (!validate_param(key_cstr)) {
996 if (preinit) {
997 continue;
998 }
999 LOG(LOG_LEVEL_ERROR) << "Unknown parameter: " << key_cstr << "\n";
1000 LOG(LOG_LEVEL_INFO) << "Type '" << uv_argv[0] << " --param help' for list.\n";
1001 if (get_commandline_param("allow-unknown-params") ==
1002 nullptr) {
1003 return false;
1004 }
1005 }
1006 commandline_params[key_cstr] = val_cstr;
1007 }
1008 return true;
1009}
1010
1011bool
1012parse_bitrate(char *optarg, long long int *bitrate)
1013{
1014 unordered_map<string, long long int> bitrate_spec_map = {
1015 {"auto", RATE_AUTO },
1016 { "dynamic", RATE_DYNAMIC },
1017 { "unlimited", RATE_UNLIMITED},
1018 };
1019
1020 if (auto it = bitrate_spec_map.find(optarg);
1021 it != bitrate_spec_map.end()) {
1022 *bitrate = it->second;
1023 return true;
1024 }
1025 if (strcmp(optarg, "help") == 0) {
1026 constexpr char const *NUMERIC_PATTERN = "{1-9}{0-9}*[kMG][!][E]";
1027 col()
1028 << "Usage:\n"
1029 << "\tuv " << TERM_BOLD "-l [auto | dynamic | unlimited | "
1030 << NUMERIC_PATTERN << "]\n" TERM_RESET
1031 << "where\n"
1032 "\t"
1033 << TBOLD("auto")
1034 << " - spread packets across frame time\n"
1035 "\t"
1036 << TBOLD("dynamic")
1037 << " - similar to \"auto\" but more relaxed - occasional "
1038 "huge frame can spread 1.5x frame time (default)\n"
1039 "\t"
1040 << TBOLD("unlimited")
1041 << " - send packets at a wire speed (in bursts)\n"
1042 "\t"
1043 << SBOLD(NUMERIC_PATTERN)
1044 << " - send packets at most at specified bitrate\n\n"
1045 << TBOLD("Notes: ")
1046 << "Use an exclamation mark to indicate intentionally very "
1047 "low bitrate. 'E' to use the value as a fixed bitrate, "
1048 "not cap /i. e. even the frames that may be sent at "
1049 "lower bitrate are sent at the nominal bitrate)\n"
1050 << "\n";
1051 return true;
1052 }
1053 bool force = false;
1054 bool fixed = false;
1055 for (int i = 0; i < 2; ++i) {
1056 if (optarg[strlen(optarg) - 1] == '!' ||
1057 optarg[strlen(optarg) - 1] == 'E') {
1058 if (optarg[strlen(optarg) - 1] == '!') {
1059 force = true;
1060 optarg[strlen(optarg) - 1] = '\0';
1061 }
1062 if (optarg[strlen(optarg) - 1] == 'E') {
1063 fixed = true;
1064 optarg[strlen(optarg) - 1] = '\0';
1065 }
1066 }
1067 }
1068 *bitrate = unit_evaluate(optarg, nullptr);
1069 if (*bitrate <= 0) {
1070 log_msg(LOG_LEVEL_ERROR, "Invalid bitrate %s!\n", optarg);
1071 return false;
1072 }
1073 constexpr long long mb5 =
1074 5ll * 1000 *
1075 1000; // it'll take 6.4 sec to send 4 MB frame at 5 Mbps
1076 constexpr long long gb100 =
1077 100ll * 1000 * 1000 *
1078 1000; // traffic shaping to eg. 40 Gbps may make sense
1079 if ((*bitrate < mb5 || *bitrate > gb100) && !force) {
1081 "Bitrate %lld bps seems to be too %s, use \"-l %s!\" "
1082 "to force if this is not a mistake.\n",
1083 *bitrate, *bitrate < mb5 ? "low" : "high", optarg);
1084 return false;
1085 }
1086 if (fixed) {
1087 *bitrate |= RATE_FLAG_FIXED_RATE;
1088 }
1089 return true;
1090}
1091
1093{
1094 for (unsigned int i = 0; i < sizeof params / sizeof params[0]; ++i) {
1095 if (params[i].doc != NULL) {
1096 puts(params[i].doc);
1097 } else {
1098 break;
1099 }
1100 }
1101}
1102
1104 cout << "codec RGB/YCbCr depth description\n";
1105 for (codec_t c = VIDEO_CODEC_FIRST; c != VIDEO_CODEC_COUNT; c = static_cast<codec_t>(static_cast<int>(c) + 1)) {
1106 if (is_codec_opaque(c)) {
1107 continue;
1108 }
1109
1110 char tag = codec_is_a_rgb(c) ? 'R' : 'Y';
1111 col() << " " << left << setw(12) << SBOLD(get_codec_name(c)) << setw(0) << " " << tag << " " << setw(2) << get_bits_per_component(c) << setw(0) << " " << get_codec_name_long(c) << "\n";
1112 }
1113}
1114
1116 for (codec_t c = VIDEO_CODEC_FIRST; c != VIDEO_CODEC_COUNT; c = static_cast<codec_t>(static_cast<int>(c) + 1)) {
1117 if (!is_codec_opaque(c)) {
1118 continue;
1119 }
1120
1121 char tag = is_codec_interframe(c) ? 'I' : '.';
1122 col() << " " << left << setw(12) << SBOLD(get_codec_name(c)) << setw(0) << " " << tag << " " << " " << get_codec_name_long(c) << "\n";
1123 }
1124 cout << "\nLegend:\n" << " I - interframe codec\n";
1125}
1126
1133{
1134 if (mainloop) {
1135 return false;
1136 }
1137
1138 mainloop = m;
1139 mainloop_udata = u;
1140
1141 return true;
1142}
1143
1144void register_should_exit_callback(struct module *mod, void (*callback)(void *), void *udata)
1145{
1146 auto *s = (state_root *) get_root_module(mod)->priv_data;
1147 unique_lock<mutex> lk(s->lock);
1148 s->should_exit_callbacks.emplace_back(callback, udata);
1149}
1150
1157void
1159 void *udata)
1160{
1161 auto *s = (state_root *) get_root_module(mod)->priv_data;
1162 unique_lock<mutex> lk(s->lock);
1163 for (auto it = s->should_exit_callbacks.begin();
1164 it != s->should_exit_callbacks.end(); ++it) {
1165 if (get<0>(*it) == callback && get<1>(*it) == udata) {
1166 s->should_exit_callbacks.erase(it);
1167 return;
1168 }
1169 }
1170 abort();
1171}
1172
1173ADD_TO_PARAM("errors-fatal", "* errors-fatal\n"
1174 " Treats some errors as fatal and exit even though " PACKAGE_NAME " could continue otherwise.\n"
1175 " This allows less severe errors to be catched (which should not occur under normal circumstances).\n"
1176 " An environment variable ULTRAGRID_ERRORS_FATAL with the same effect can also be used.\n");
1185 if (get_commandline_param("errors-fatal") || getenv("ULTRAGRID_ERRORS_FATAL")) {
1186 exit_uv(status);
1187 }
1188}
1189
1191#ifdef __linux__
1192 ifstream ppid_f("/proc/" + to_string(getppid()) + "/comm", ifstream::in);
1193 if (ppid_f.is_open()) {
1194 string comm;
1195 ppid_f >> comm;
1196 if (comm == "gdb") {
1197 return true;
1198 }
1199 }
1200#endif
1201 return false;
1202}
1203
1204static void
1206{
1207#ifdef _WIN32
1208 print_stacktrace_win();
1209#else
1210 // print to a temporary file to avoid interleaving from multiple
1211 // threads
1212#if __GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 27)
1213 int fd = memfd_create("ultragrid_backtrace", MFD_CLOEXEC);
1214#else
1215 char path[MAX_PATH_SIZE];
1216#ifdef __APPLE__
1217 const unsigned long tid = pthread_mach_thread_np(pthread_self());
1218#else
1219 const unsigned long tid = syscall(__NR_gettid);
1220#endif
1221 snprintf(path, sizeof path, "%s/ug-%lu", get_temp_dir(), tid);
1222 int fd = open(path, O_CLOEXEC | O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
1223 unlink(path);
1224#endif
1225 if (fd == -1) {
1226 fd = STDERR_FILENO;
1227 }
1228 char backtrace_msg[] = "Backtrace:\n";
1229 write_all(fd, sizeof backtrace_msg, backtrace_msg);
1230 array<void *, 256> addresses{};
1231 const int num_symbols = backtrace(addresses.data(), addresses.size());
1232 backtrace_symbols_fd(addresses.data(), num_symbols, fd);
1233 if (fd == STDERR_FILENO) {
1234 return;
1235 }
1236
1237 lseek(fd, 0, SEEK_SET);
1238 char buf[STR_LEN];
1239 ssize_t rbytes = 0;
1240 while ((rbytes = read(fd, buf, sizeof buf)) > 0) {
1241 ssize_t written = 0;
1242 ssize_t wbytes = 0;
1243 while (written < rbytes &&
1244 (wbytes = write(STDERR_FILENO, buf + written,
1245 rbytes - written)) > 0) {
1246 written += wbytes;
1247 }
1248 }
1249 close(fd);
1250#endif // defined _WIN32
1251}
1252
1254{
1256
1257 char buf[1024];
1258 char *ptr = buf;
1259 char *ptr_end = buf + sizeof buf;
1260 strappend(&ptr, ptr_end, "\n" PACKAGE_NAME " has crashed");
1261
1262 append_sig_desc(&ptr, ptr_end, sig);
1263
1264 strappend(&ptr, ptr_end, ".\n\nPlease send a bug report to address " PACKAGE_BUGREPORT ".\n");
1265 strappend(&ptr, ptr_end, "You may find some tips how to report bugs in file doc/REPORTING_BUGS.md distributed with " PACKAGE_NAME "\n");
1266 strappend(&ptr, ptr_end, "(or available online at https://github.com/CESNET/UltraGrid/blob/master/doc/REPORTING-BUGS.md).\n");
1267
1268 write_all(STDERR_FILENO, ptr - buf, buf);
1269
1271
1272 signal(sig, SIG_DFL);
1273 raise(sig);
1274}
1275
1277{
1278 UNUSED(sig);
1279#ifndef _WIN32
1280 assert(sig == SIGALRM);
1281 char msg[] = "Hang detected - you may continue waiting or kill UltraGrid. Please report if UltraGrid doesn't exit after reasonable amount of time.\n";
1282 write_all(STDERR_FILENO, sizeof msg - 1, msg);
1283 signal(SIGALRM, SIG_DFL);
1284#endif // ! defined _WIN32
1285}
1286
1287// some common parameters used within multiple modules
1288ADD_TO_PARAM("allow-unknown-params", "* allow-unknown-params\n"
1289 " Do not exit on unknown parameter.\n");
1290ADD_TO_PARAM("audio-buffer-len", "* audio-buffer-len=<ms>\n"
1291 " Sets length of software audio playback buffer (in ms, ALSA/Coreaudio/Portaudio/WASAPI)\n");
1292ADD_TO_PARAM("audio-cap-frames", "* audio-cap-frames=<f>\n"
1293 " Sets number of audio frames captured at once (CoreAudio)\n");
1294ADD_TO_PARAM("audio-disable-adaptive-buffer", "* audio-disable-adaptive-buffer\n"
1295 " Disables audio adaptive playback buffer (CoreAudio/JACK)\n");
1296ADD_TO_PARAM("color", "* color=CT\n"
1297 " [experimental] Color space to use, C - colorimetry: 0 - undefined, 1 - BT.709, 2 - BT.2020/2100, 3 - P3; T - transfer fn: 0 - undefined, 1 - 709, 2 - HLG; 3 - PQ (signalized to GLFW on mac, NDI receiver)\n");
1298ADD_TO_PARAM("low-latency-audio", "* low-latency-audio[=ultra]\n"
1299 " Try to reduce audio latency at the expense of worse reliability\n"
1300 " Add ultra for even more aggressive setting.\n");
1301ADD_TO_PARAM("window-title", "* window-title=<title>\n"
1302 " Use alternative window title (SDL/GL only)\n");
1303
#define UNUSED(x)
int void * val
struct video_desc desc
int void(** deleter)(void *))
const char * get_codec_name(codec_t codec)
This file contains definition of some common audio types.
#define AUDIO_CAPTURE_ABI_VERSION
#define AUDIO_FILTER_ABI_VERSION
#define AUDIO_PLAYBACK_ABI_VERSION
#define CAPTURE_FILTER_ABI_VERSION
static af_result_code init(struct module *parent, const char *cfg, void **state)
void set_skip_repeats(bool val)
Definition debug.h:155
void set_timestamp_mode(log_timestamp_mode val)
Definition debug.h:158
vector< tuple< audio_codec_info_t, bool, string > > get_audio_codec_list()
Definition codec.cpp:109
#define AUDIO_COMPRESS_ABI_VERSION
Definition codec.h:43
bool color_output_init()
sets internal variable color_stdout and retunrs its contents
int color_printf(const char *format,...)
#define T_PEACH_FUZZ
Definition color_out.h:65
#define TERM_BOLD
Definition color_out.h:48
#define S256_FG(col, x)
Definition color_out.h:68
#define TERM_RESET
Definition color_out.h:47
#define SBOLD(x)
Definition color_out.h:80
#define TBOLD(x)
Definition color_out.h:70
int fd_t
static ssize_t write_all(fd_t fd, const void *buf, size_t count)
static __device__ vec2 abs(const vec2 &v)
Definition cuda_dxt.cu:118
void cuda_wrapper_device_reset(void)
This file contais wrapper around CUDA functions.
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
bool parse_log_cfg(const char *conf_str, int *log_lvl, bool *logger_skip_repeats, log_timestamp_mode *show_timestamps)
Definition debug.cpp:227
#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)
Definition debug.h:313
#define LOG_LEVEL_FATAL
errors that prevent UG run
Definition debug.h:58
Log_output & get_log_output()
Definition debug.h:266
log_timestamp_mode
Definition debug.h:72
@ LOG_TIMESTAMP_AUTO
Definition debug.h:75
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
#define MAX_PATH_SIZE
Definition fs.h:48
#define VIDEO_DISPLAY_ABI_VERSION
void module_init_default(struct module *module_data)
Definition module.c:48
struct module * get_root_module(struct module *node)
Definition module.c:203
@ MODULE_CLASS_ROOT
Definition module.h:83
#define VIDEO_CAPTURE_ABI_VERSION
#define VIDEO_COMPRESS_ABI_VERSION
int count
Definition hd-rum.c:44
void handle_error(int status)
Definition host.cpp:1184
uint32_t RTT
Definition host.cpp:171
bool running_in_debugger()
Definition host.cpp:1190
static void print_modules(std::map< enum library_class, module_info_map > &class_mod_map)
Definition host.cpp:791
void set_audio_delay(int audio_delay)
Definition host.cpp:914
void crash_signal_handler(int sig)
Definition host.cpp:1253
void init_root_module(struct module *root_mod)
Definition host.cpp:610
enum library_class cls
Definition host.cpp:749
unsigned int cuda_devices_count
Definition host.cpp:168
int abi_ver
Definition host.cpp:750
void exit_uv(int status)
Definition host.cpp:625
static bool unexpected_exit_called
Definition host.cpp:202
void * mainloop_udata
Definition host.cpp:187
void print_capabilities(const char *cfg)
Definition host.cpp:801
void register_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
Definition host.cpp:1144
volatile int audio_offset
added audio delay in ms (non-negative), can be used to tune AV sync
Definition host.cpp:178
const char * doc
Definition host.cpp:923
int glfw_init_count
0->1 - call glfwInit, 1->0 call glfwTerminate; glfw{Init,Terminate} should be called from main thr,...
Definition host.cpp:182
bool cuda_devices_explicit
–cuda-device/-D specified expilcitly
Definition host.cpp:169
void print_version()
Definition host.cpp:868
void print_configuration()
Definition host.cpp:882
static const struct @18 mod_classes[]
static bool parse_opts_set_logging(int argc, char *argv[])
Definition host.cpp:357
void(* probe_print)(std::string name, const void *)
Definition host.cpp:751
static void print_device(std::string purpose, std::string const &mod, const device_info &device)
Definition host.cpp:640
unsigned int audio_capture_bps
Definition host.cpp:164
const char * get_commandline_param(const char *key)
Definition host.cpp:894
static void probe_device(std::string_view cap_str, std::string const &name, const void *mod)
Definition host.cpp:683
int get_exit_status(struct module *root_mod)
Definition host.cpp:633
int set_pixfmt_conv_policy(const char *optarg)
Definition host.cpp:327
void unregister_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
Definition host.cpp:1158
std::unordered_map< std::string, std::string > commandline_params
Definition host.cpp:184
static bool validate_param(const char *param)
Definition host.cpp:949
void register_param(const char *param, const char *doc)
Definition host.cpp:930
static void print_backtrace()
Definition host.cpp:1205
static void echeck_unexpected_exit(void)
Definition host.cpp:428
unsigned int cuda_devices[MAX_CUDA_DEVICES]
Definition host.cpp:167
bool tok_in_argv(char **argv, const char *tok)
Definition host.cpp:417
char * export_dir
Definition host.cpp:176
const char * param
Definition host.cpp:922
bool parse_params(const char *optarg, bool preinit)
Definition host.cpp:976
static state_root *volatile state_root_static
used by exit_uv() called from signal handler
Definition host.cpp:602
static void load_libgcc()
Definition host.cpp:300
std::map< std::string, const void * > module_info_map
Definition host.cpp:638
unsigned int audio_capture_sample_rate
Definition host.cpp:165
void hang_signal_handler(int sig)
Definition host.cpp:1276
static bool set_output_buffering()
Definition host.cpp:237
bool parse_bitrate(char *optarg, long long int *bitrate)
Definition host.cpp:1012
static void probe_all(std::map< enum library_class, module_info_map > &class_mod_map)
Definition host.cpp:780
char ** uv_argv
Definition host.cpp:174
volatile int video_offset
added video delay in ms (non-negative), can be used to tune AV sync
Definition host.cpp:179
std::string_view cap_str
Definition host.cpp:748
struct init_data * common_preinit(int argc, char *argv[])
Definition host.cpp:435
int uv_argc
Definition host.cpp:173
static void print_param_doc(void)
Definition host.cpp:1092
mainloop_t mainloop
mainloop to be run if display mainloop isn't run
Definition host.cpp:186
bool register_mainloop(mainloop_t m, void *u)
Definition host.cpp:1132
int get_audio_delay(void)
Definition host.cpp:909
void set_commandline_param(const char *key, const char *val)
Definition host.cpp:904
void print_video_codecs(void)
Definition host.cpp:1115
static void probe_compress(std::string const &name, const void *mod) noexcept
Definition host.cpp:695
int set_audio_capture_format(const char *optarg)
Definition host.cpp:313
std::string_view desc
Definition host.cpp:747
void print_pixel_formats(void)
Definition host.cpp:1103
unsigned int audio_capture_channels
Definition host.cpp:163
void common_cleanup(struct init_data *init)
Definition host.cpp:203
const char * get_version_details()
Definition host.cpp:856
#define RATE_AUTO
spread packets evenly across frame time (currently 3/4)
Definition host.h:123
#define MAX_CUDA_DEVICES
Definition host.h:97
#define RATE_FLAG_FIXED_RATE
use the bitrate as fixed, not capped
Definition host.h:127
void(* mainloop_t)(void *)
Definition host.h:105
char pixfmt_conv_pref[]
bitdepth, subsampling, color space
Definition video_codec.c:80
#define ADD_TO_PARAM(param, doc)
Definition host.h:203
#define RATE_UNLIMITED
Definition host.h:122
#define RATE_DYNAMIC
same as RATE_AUTO but occasional excess frame allowed
Definition host.h:124
volatile int log_level
Definition debug.cpp:65
void restore_old_tio(void)
map< string, const void * > get_libraries_for_class(enum library_class cls, int abi_version, bool include_hidden)
void open_all(const char *pattern, list< void * > &libs)
library_class
Definition lib_common.h:73
@ LIBRARY_CLASS_AUDIO_FILTER
Definition lib_common.h:85
@ LIBRARY_CLASS_VIDEO_CAPTURE
Definition lib_common.h:78
@ LIBRARY_CLASS_AUDIO_PLAYBACK
Definition lib_common.h:77
@ LIBRARY_CLASS_AUDIO_CAPTURE
Definition lib_common.h:76
@ LIBRARY_CLASS_VIDEO_DISPLAY
Definition lib_common.h:79
@ LIBRARY_CLASS_UNDEFINED
Definition lib_common.h:74
@ LIBRARY_CLASS_CAPTURE_FILTER
Definition lib_common.h:75
@ LIBRARY_CLASS_AUDIO_COMPRESS
Definition lib_common.h:80
@ LIBRARY_CLASS_VIDEO_COMPRESS
Definition lib_common.h:82
#define IF_NOT_NULL_ELSE(val, default_val)
Definition macros.h:51
@ STR_LEN
"standard" string length placeholder
Definition macros.h:134
long long unit_evaluate(const char *str, const char **endptr)
Definition misc.cpp:81
const char * ug_strerror(int errnum)
Definition misc.cpp:203
enum openssl_mode mode
int platform_pipe_init(fd_t p[2])
void platform_pipe_close(fd_t pipe)
#define PLATFORM_PIPE_READ
#define PLATFORM_PIPE_WRITE
static const char * get_temp_dir(void)
#define max(a, b)
Definition rtp.c:98
static void strappend(char **dst, size_t *dst_alloc_len, const char *src)
Definition sdp.c:366
const char * name
Definition settings.cpp:193
Option::Callback::fcn_type callback
Definition settings.cpp:251
void append_sig_desc(char **ptr, const char *ptr_end, int signum)
std::string_view tokenize(std::string_view &str, char delim, char quot)
Tokenizer for string_view.
#define strdupa(s)
Definition strings.h:77
char name[1024]
human readable name of the mode
Definition types.h:395
char id[1024]
< optional zero-terminated array of available modes
Definition types.h:392
bool repeatable
Definition types.h:386
char extra[1024]
Definition types.h:389
char name[1024]
human readable name of the device
Definition types.h:385
struct device_option options[64]
Definition types.h:398
struct device_info::mode modes[512]
char dev[1024]
Definition types.h:383
char display_name[512]
Definition types.h:369
char key[512]
Definition types.h:376
char display_desc[512]
Definition types.h:370
char opt_str[512]
Definition types.h:377
bool is_boolean
Definition types.h:379
bool com_initialized
Definition host.cpp:195
list< void * > opened_libs
Definition host.cpp:196
Definition hd-rum.c:27
enum module_class cls
Definition module.h:115
void * priv_data
Definition module.h:126
notify_t new_message
if set, notifies module that new message is in queue, receiver lock is hold during the call
Definition module.h:119
module_deleter_t deleter
Definition module.h:118
list< tuple< void(*)(void *), void * > > should_exit_callbacks
Definition host.cpp:593
void broadcast_should_exit(bool quit_watcher=false)
Definition host.cpp:579
friend void register_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
Definition host.cpp:1144
~state_root()
Definition host.cpp:547
state_root() noexcept
Definition host.cpp:540
friend void unregister_should_exit_callback(struct module *mod, void(*callback)(void *), void *udata)
Definition host.cpp:1158
fd_t should_exit_pipe[2]
Definition host.cpp:591
thread should_exit_thread
Definition host.cpp:592
volatile int exit_status
Definition host.cpp:587
static constexpr char QUIT_WATCHER_FLAG
Definition host.cpp:589
static void deleter(struct module *m)
Definition host.cpp:557
mutex lock
Definition host.cpp:590
static void should_exit_watcher(state_root *s)
Definition host.cpp:561
void set_thread_name(const char *name)
Definition thread.c:72
This file contains some common data types.
codec_t
Definition types.h:65
@ VIDEO_CODEC_FIRST
Definition types.h:68
@ VIDEO_CODEC_COUNT
count of known video codecs (including VIDEO_CODEC_NONE)
Definition types.h:108
void ug_rand_init(void)
Definition random.c:64
char * wrap_paragraph(char *text)
Definition text.c:204
int parse_audio_format(const char *str, struct audio_desc *ret)
Definition utils.cpp:655
bool is_codec_opaque(codec_t codec)
bool codec_is_a_rgb(codec_t codec)
Returns TRUE if specified pixelformat is some form of RGB (not YUV).
bool is_codec_interframe(codec_t codec)
const char * get_codec_name_long(codec_t codec)
int get_bits_per_component(codec_t codec)
const char * key
Definition cineform.cpp:125
static struct @76 codecs[]
API for video compress drivers.
bool com_initialize(bool *com_initialized, const char *err_prefix)
Definition windows.c:65
void com_uninitialize(bool *com_initialized)
Definition windows.c:94
@ BUILD_WINDOWS_11_OR_LATER
Definition windows.h:46