UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
main.cpp File Reference
#include <array>
#include <chrono>
#include <cmath>
#include <cstdlib>
#include <execinfo.h>
#include <getopt.h>
#include <iostream>
#include <list>
#include <memory>
#include <mutex>
#include <pthread.h>
#include <stdexcept>
#include <string>
#include <string.h>
#include <thread>
#include <tuple>
#include <utility>
#include "compat/misc.h"
#include "control_socket.h"
#include "cuda_wrapper.h"
#include "debug.h"
#include "host.h"
#include "keyboard_control.h"
#include "lib_common.h"
#include "messaging.h"
#include "module.h"
#include "playback.h"
#include "rtp/rtp.h"
#include "rtsp/rtsp_utils.h"
#include "tv.h"
#include "ug_runtime_error.hpp"
#include "utils/color_out.h"
#include "utils/misc.h"
#include "utils/nat.h"
#include "utils/net.h"
#include "utils/sdp.h"
#include "utils/string_view_utils.hpp"
#include "utils/thread.h"
#include "utils/wait_obj.h"
#include "utils/udp_holepunch.h"
#include "video.h"
#include "video_capture.h"
#include "video_display.h"
#include "video_compress.h"
#include "export.h"
#include "video_rxtx.hpp"
#include "audio/audio.h"
#include "audio/audio_capture.h"
#include "audio/audio_playback.h"
#include "audio/codec.h"
#include "audio/utils.h"

Go to the source code of this file.

Classes

struct  state_uv
 
struct  ug_options
 

Macros

#define EXIT(expr)
 
#define MAX_CAPTURE_COUNT   17
 
#define MOD_NAME   "[main] "
 
#define OPT_AUDIO_CAPTURE_CHANNELS   (('a' << 8) | 'c')
 
#define OPT_AUDIO_DELAY   (('A' << 8) | 'D')
 
#define OPT_AUDIO_HOST   (('A' << 8) | 'H')
 
#define OPT_AUDIO_PROTOCOL   (('A' << 8) | 'P')
 
#define OPT_AUDIO_SCALE   (('a' << 8) | 's')
 
#define OPT_CONTROL_PORT   (('C' << 8) | 'P')
 
#define OPT_ECHO_CANCELLATION   (('E' << 8) | 'C')
 
#define OPT_MCAST_IF   (('M' << 8) | 'I')
 
#define OPT_PIX_FMTS   (('P' << 8) | 'F')
 
#define OPT_PIXFMT_CONV_POLICY   (('P' << 8) | 'C')
 
#define OPT_RTSP_SERVER   (('R' << 8) | 'S')
 
#define OPT_VIDEO_CODECS   (('V' << 8) | 'C')
 
#define OPT_VIDEO_PROTOCOL   (('V' << 8) | 'P')
 
#define OPT_WINDOW_TITLE   (('W' << 8) | 'T')
 
#define PORT_BASE   5004
 

Functions

static int adjust_params (struct ug_options *opt)
 
static void * capture_thread (void *arg)
 
template<int N>
static void copy_sv_to_c_buf (char(&dest)[N], std::string_view sv)
 
int main (int argc, char *argv[])
 
static int parse_audio_capture (struct ug_options *opt, char *optarg)
 
static bool parse_control_port (char *optarg, struct ug_options *opt)
 
static int parse_cuda_device (char *optarg)
 
static bool parse_holepunch_conf (char *conf, struct Holepunch_config *punch_c)
 
static int parse_options (int argc, char *argv[], struct ug_options *opt)
 
static int parse_options_internal (int argc, char *argv[], struct ug_options *opt)
 
static bool parse_port (char *optarg, struct ug_options *opt)
 
static bool parse_protocol (int ch, char *optarg, struct ug_options *opt)
 
static void print_fps (const char *prefix, steady_clock::time_point *t0, int *frames, double nominal_fps)
 
static void print_help_item (const string &name, const vector< string > &help)
 
static void signal_handler (int signum)
 
static void usage (const char *exec_path, bool full=false)
 

Variables

static constexpr const char * DEFAULT_AUDIO_CODEC = "PCM"
 
static constexpr const char * DEFAULT_VIDEO_COMPRESSION = "none"
 

Macro Definition Documentation

◆ EXIT

#define EXIT ( expr)
Value:
{ int rc = expr; common_cleanup(init); return rc; }
static af_result_code init(struct module *parent, const char *cfg, void **state)
void common_cleanup(struct init_data *init)
Definition host.cpp:203

Definition at line 1251 of file main.cpp.

Referenced by main().

◆ MAX_CAPTURE_COUNT

#define MAX_CAPTURE_COUNT   17

Definition at line 142 of file main.cpp.

◆ MOD_NAME

#define MOD_NAME   "[main] "

Definition at line 121 of file main.cpp.

Referenced by parse_options(), parse_port(), and parse_protocol().

◆ OPT_AUDIO_CAPTURE_CHANNELS

#define OPT_AUDIO_CAPTURE_CHANNELS   (('a' << 8) | 'c')

Definition at line 127 of file main.cpp.

Referenced by parse_options_internal().

◆ OPT_AUDIO_DELAY

#define OPT_AUDIO_DELAY   (('A' << 8) | 'D')

Definition at line 128 of file main.cpp.

Referenced by parse_options_internal().

◆ OPT_AUDIO_HOST

#define OPT_AUDIO_HOST   (('A' << 8) | 'H')

Definition at line 129 of file main.cpp.

Referenced by parse_options_internal().

◆ OPT_AUDIO_PROTOCOL

#define OPT_AUDIO_PROTOCOL   (('A' << 8) | 'P')

Definition at line 130 of file main.cpp.

Referenced by parse_options_internal(), and parse_protocol().

◆ OPT_AUDIO_SCALE

#define OPT_AUDIO_SCALE   (('a' << 8) | 's')

Definition at line 131 of file main.cpp.

Referenced by parse_options_internal().

◆ OPT_CONTROL_PORT

#define OPT_CONTROL_PORT   (('C' << 8) | 'P')

Definition at line 132 of file main.cpp.

Referenced by parse_options_internal().

◆ OPT_ECHO_CANCELLATION

#define OPT_ECHO_CANCELLATION   (('E' << 8) | 'C')

Definition at line 133 of file main.cpp.

Referenced by parse_options_internal().

◆ OPT_MCAST_IF

#define OPT_MCAST_IF   (('M' << 8) | 'I')

Definition at line 134 of file main.cpp.

Referenced by parse_options_internal().

◆ OPT_PIX_FMTS

#define OPT_PIX_FMTS   (('P' << 8) | 'F')

Definition at line 135 of file main.cpp.

Referenced by parse_options_internal().

◆ OPT_PIXFMT_CONV_POLICY

#define OPT_PIXFMT_CONV_POLICY   (('P' << 8) | 'C')

Definition at line 136 of file main.cpp.

Referenced by parse_options_internal().

◆ OPT_RTSP_SERVER

#define OPT_RTSP_SERVER   (('R' << 8) | 'S')

Definition at line 137 of file main.cpp.

Referenced by parse_options_internal().

◆ OPT_VIDEO_CODECS

#define OPT_VIDEO_CODECS   (('V' << 8) | 'C')

Definition at line 138 of file main.cpp.

Referenced by parse_options_internal().

◆ OPT_VIDEO_PROTOCOL

#define OPT_VIDEO_PROTOCOL   (('V' << 8) | 'P')

Definition at line 139 of file main.cpp.

Referenced by parse_options_internal(), and parse_protocol().

◆ OPT_WINDOW_TITLE

#define OPT_WINDOW_TITLE   (('W' << 8) | 'T')

Definition at line 140 of file main.cpp.

Referenced by parse_options_internal().

◆ PORT_BASE

#define PORT_BASE   5004

Definition at line 122 of file main.cpp.

Referenced by usage().

Function Documentation

◆ adjust_params()

static int adjust_params ( struct ug_options * opt)
static

Definition at line 1034 of file main.cpp.

1034 {
1035 unsigned int audio_rxtx_mode = 0;
1036 if (opt->is_server) {
1037 commandline_params["udp-disable-multi-socket"] = string();
1038 if (opt->requested_receiver != nullptr) {
1039 LOG(LOG_LEVEL_ERROR) << "Receiver must not be given in server mode!\n";
1040 return EXIT_FAIL_USAGE;
1041 }
1043 if (strcmp(opt->requested_display, "none") == 0 && strcmp("none", vidcap_params_get_driver(opt->vidcap_params_head)) != 0) {
1044 opt->requested_display = "dummy";
1045 }
1046 if (strcmp(opt->audio.recv_cfg, "none") == 0 && strcmp(opt->audio.send_cfg, "none") != 0) {
1047 opt->audio.recv_cfg = "dummy";
1048 }
1049 }
1050 if (opt->is_client) {
1051 commandline_params["udp-disable-multi-socket"] = string();
1052 if (opt->requested_receiver == nullptr) {
1053 LOG(LOG_LEVEL_ERROR) << "Server address required in client mode!\n";
1054 return EXIT_FAIL_USAGE;
1055 }
1056 if (strcmp("none", vidcap_params_get_driver(opt->vidcap_params_head)) == 0 && strcmp(opt->requested_display, "none") != 0) {
1057 vidcap_params_set_device(opt->vidcap_params_tail, "testcard:2:1:1:UYVY");
1058 }
1059 if (strcmp("none", opt->audio.send_cfg) == 0 && strcmp("none", opt->audio.recv_cfg) != 0) {
1060 set_audio_capture_format("sample_rate=1");
1061 opt->audio.send_cfg = "testcard:frames=1";
1062 }
1063 }
1064
1065 if (opt->requested_receiver == nullptr) {
1066 opt->requested_receiver = "localhost";
1067 }
1068
1069 if (opt->audio.host == nullptr) {
1070 opt->audio.host = opt->requested_receiver;
1071 }
1072
1073 if (!is_ipv6_supported()) {
1074 LOG(LOG_LEVEL_WARNING) << "IPv6 support missing, setting IPv4-only mode.\n";
1075 opt->common.force_ip_version = 4;
1076 }
1077
1078 // default values for different RXTX protocols
1079 if (strcasecmp(opt->video_protocol, "rtsp") == 0 || strcasecmp(opt->video_protocol, "sdp") == 0) {
1080 if (opt->requested_compression == nullptr) {
1081 if (strcasecmp(opt->video_protocol, "rtsp") == 0) {
1082 opt->requested_compression = "lavc:enc=libx264:safe";
1083 } else {
1084 opt->requested_compression = "none"; // will be set later by h264_sdp_video_rxtx::send_frame()
1085 }
1086 }
1087 } else {
1088 if (opt->requested_compression == nullptr) {
1090 }
1091 }
1092
1093 const bool tx_audio_std = strcasecmp(opt->audio.proto, "rtsp") == 0 ||
1094 strcasecmp(opt->audio.proto, "sdp") == 0;
1095 if (opt->audio.codec_cfg == nullptr) {
1096 opt->audio.codec_cfg =
1097 tx_audio_std ? "mp3" : DEFAULT_AUDIO_CODEC;
1098 }
1099
1100 if (tx_audio_std && audio_capture_channels == 0) {
1101 audio_capture_channels = 1; // needed to be known early
1102 }
1103
1104 if(opt->nat_traverse_config && strncmp(opt->nat_traverse_config, "holepunch", strlen("holepunch")) == 0){
1105#ifndef HAVE_LIBJUICE
1106 log_msg(LOG_LEVEL_ERROR, "Ultragrid was compiled without holepunch support\n");
1107 return EXIT_FAILURE;
1108#else
1109 static char punched_host[512];
1110 Holepunch_config punch_c = {};
1111
1112 if(!parse_holepunch_conf(opt->nat_traverse_config, &punch_c)){
1113 return EXIT_FAILURE;
1114 }
1115
1116 commandline_params["udp-disable-multi-socket"] = string();
1117
1118 if (strcmp("none", vidcap_params_get_driver(opt->vidcap_params_head)) == 0
1119 && strcmp("none", opt->requested_display) != 0)
1120 {
1121 vidcap_params_set_device(opt->vidcap_params_tail, "testcard:2:2:1:UYVY");
1123 }
1124
1125 if (strcmp("none", opt->audio.send_cfg) == 0
1126 && strcmp("none", opt->audio.recv_cfg) != 0)
1127 {
1128 set_audio_capture_format("sample_rate=5");
1129 opt->audio.send_cfg = "testcard:frames=1";
1130 }
1131
1132 punch_c.video_rx_port = &opt->video_rx_port;
1133 punch_c.video_tx_port = &opt->video_tx_port;
1134 punch_c.audio_rx_port = &opt->audio.recv_port;
1135 punch_c.audio_tx_port = &opt->audio.send_port;
1136
1137 punch_c.host_addr = punched_host;
1138 punch_c.host_addr_len = sizeof(punched_host);
1139
1140 auto punch_fcn = reinterpret_cast<bool(*)(Holepunch_config *)>(
1141 const_cast<void *>(
1143
1144 if(!punch_fcn){
1145 log_msg(LOG_LEVEL_ERROR, "Failed to load holepunching module\n");
1146 return EXIT_FAILURE;
1147 }
1148
1149 if(!punch_fcn(&punch_c)){
1150 log_msg(LOG_LEVEL_ERROR, "Hole punching failed.\n");
1151 return EXIT_FAILURE;
1152 }
1153
1154 log_msg(LOG_LEVEL_INFO, "[holepunch] remote: %s\n rx: %d\n tx: %d\n",
1155 punched_host, opt->video_rx_port, opt->video_tx_port);
1156 opt->requested_receiver = punched_host;
1157 opt->audio.host = punched_host;
1158#endif //HAVE_LIBJUICE
1159 }
1160
1161
1162 if (strcmp("none", opt->audio.recv_cfg) != 0) {
1163 audio_rxtx_mode |= MODE_RECEIVER;
1164 }
1165
1166 if (strcmp("none", opt->audio.send_cfg) != 0) {
1167 audio_rxtx_mode |= MODE_SENDER;
1168 }
1169
1170 if (strcmp("none", opt->requested_display) != 0) {
1172 }
1173 if (strcmp("none", vidcap_params_get_driver(opt->vidcap_params_head)) != 0) {
1175 }
1176
1177 // use dyn ports if sending only to ourselves or neither sending nor receiving
1178 const unsigned mode_both = MODE_RECEIVER | MODE_SENDER;
1179 if (is_host_loopback(opt->requested_receiver) && ((opt->video_rxtx_mode & mode_both) == mode_both || (opt->video_rxtx_mode & mode_both) == 0)
1180 && (opt->video_rx_port == -1 && opt->video_tx_port == -1)) {
1181 opt->video_rx_port = opt->video_tx_port = 0;
1182 }
1183 if (is_host_loopback(opt->requested_receiver) && ((audio_rxtx_mode & mode_both) == mode_both || (audio_rxtx_mode & mode_both) == 0)
1184 && (opt->audio.recv_port == -1 && opt->audio.send_port == -1)) {
1185 opt->audio.recv_port = opt->audio.send_port = 0;
1186 }
1187
1188 if (opt->video_rx_port == -1) {
1189 if ((opt->video_rxtx_mode & MODE_RECEIVER) == 0U) {
1190 // do not occupy recv port if we are not receiving (note that this disables communication with
1191 // our receiver, because RTCP ports are changed as well)
1192 opt->video_rx_port = 0;
1193 } else {
1194 opt->video_rx_port = opt->port_base;
1195 }
1196 }
1197
1198 if (opt->video_tx_port == -1) {
1199 if ((opt->video_rxtx_mode & MODE_SENDER) == 0U) {
1200 opt->video_tx_port = 0; // does not matter, we are receiver
1201 } else {
1202 opt->video_tx_port = opt->port_base;
1203 }
1204 }
1205
1206 if (opt->audio.recv_port == -1) {
1207 if ((audio_rxtx_mode & MODE_RECEIVER) == 0U) {
1208 // do not occupy recv port if we are not receiving (note that this disables communication with
1209 // our receiver, because RTCP ports are changed as well)
1210 opt->audio.recv_port = 0;
1211 } else {
1212 opt->audio.recv_port = opt->video_rx_port ? opt->video_rx_port + 2 : opt->port_base + 2;
1213 }
1214 }
1215
1216 if (opt->audio.send_port == -1) {
1217 if ((audio_rxtx_mode & MODE_SENDER) == 0U) {
1218 opt->audio.send_port = 0;
1219 } else {
1220 opt->audio.send_port = opt->video_tx_port ? opt->video_tx_port + 2 : opt->port_base + 2;
1221 }
1222 }
1223
1224 // If we are sure that this UltraGrid is sending to itself we can optimize some parameters
1225 // (aka "-m 9000 -l unlimited"). If ports weren't equal it is possibile that we are sending
1226 // to a reflector, thats why we require equal ports (we are a receiver as well).
1228 && (opt->video_rx_port == opt->video_tx_port || opt->video_tx_port == 0)
1229 && (opt->audio.recv_port == opt->audio.send_port || opt->audio.send_port == 0)) {
1230 opt->common.mtu = opt->common.mtu == 0 ? min(RTP_MAX_MTU, 65535)
1231 : opt->common.mtu;
1232 opt->bitrate = opt->bitrate == RATE_DEFAULT ? RATE_UNLIMITED : opt->bitrate;
1233 } else {
1234 opt->common.mtu = opt->common.mtu == 0 ? 1500 : opt->common.mtu;
1235 opt->bitrate = opt->bitrate == RATE_DEFAULT ? RATE_DYNAMIC : opt->bitrate;
1236 }
1237
1238 if((strcmp("none", opt->audio.send_cfg) != 0 || strcmp("none", opt->audio.recv_cfg) != 0) && strcmp(opt->video_protocol, "rtsp") == 0){
1239 //TODO: to implement a high level rxtx struct to manage different standards (i.e.:H264_STD, VP8_STD,...)
1240 if (strcmp(opt->audio.proto, "rtsp") != 0) {
1241 LOG(LOG_LEVEL_WARNING) << "Using RTSP for video but not for audio is not recommended. Consider adding '--audio-protocol rtsp'.\n";
1242 }
1243 }
1244 if (strcmp(opt->audio.proto, "rtsp") == 0 && strcmp(opt->video_protocol, "rtsp") != 0) {
1245 LOG(LOG_LEVEL_WARNING) << "Using RTSP for audio but not for video is not recommended and might not work.\n";
1246 }
1247
1248 return 0;
1249}
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define LOG(level)
Definition debug.h:313
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
std::unordered_map< std::string, std::string > commandline_params
Definition host.cpp:184
int set_audio_capture_format(const char *optarg)
Definition host.cpp:313
unsigned int audio_capture_channels
Definition host.cpp:163
#define RATE_DEFAULT
imaginary value, must not be passed to trasmit module
Definition host.h:126
#define MODE_SENDER
Definition host.h:102
#define RATE_UNLIMITED
Definition host.h:122
#define RATE_DYNAMIC
same as RATE_AUTO but occasional excess frame allowed
Definition host.h:124
#define MODE_RECEIVER
Definition host.h:103
#define EXIT_FAIL_USAGE
Definition host.h:61
const void * load_library(const char *name, enum library_class cls, int abi_version)
@ LIBRARY_CLASS_UNDEFINED
Definition lib_common.h:74
bool is_host_loopback(const char *hostname)
Definition net.c:174
bool is_ipv6_supported(void)
Definition net.c:402
#define IN6_BLACKHOLE_SERVER_MODE_STR
Definition net.h:52
#define min(a, b)
Definition rtp.c:99
#define RTP_MAX_MTU
Definition rtp.h:60
static constexpr const char * DEFAULT_VIDEO_COMPRESSION
Definition main.cpp:124
static constexpr const char * DEFAULT_AUDIO_CODEC
Definition main.cpp:125
static bool parse_holepunch_conf(char *conf, struct Holepunch_config *punch_c)
Definition main.cpp:423
const char * host
Definition audio.h:69
const char * proto
Definition audio.h:74
const char * recv_cfg
Definition audio.h:72
const char * send_cfg
Definition audio.h:73
int send_port
Definition audio.h:71
int recv_port
Definition audio.h:70
const char * codec_cfg
Definition audio.h:80
int mtu
Definition host.h:174
int force_ip_version
Definition host.h:176
const char * requested_display
Definition main.cpp:533
struct vidcap_params * vidcap_params_head
Definition main.cpp:515
int video_tx_port
Definition main.cpp:521
const char * video_protocol
Definition main.cpp:542
unsigned int video_rxtx_mode
Definition main.cpp:547
const char * requested_compression
Definition main.cpp:530
struct common_opts common
Definition main.cpp:510
int video_rx_port
Definition main.cpp:521
bool is_client
Definition main.cpp:537
bool is_server
Definition main.cpp:538
const char * requested_receiver
Definition main.cpp:534
struct vidcap_params * vidcap_params_tail
Definition main.cpp:516
struct audio_options audio
Definition main.cpp:512
long long int bitrate
Definition main.cpp:536
char * nat_traverse_config
Definition main.cpp:545
int port_base
Definition main.cpp:520
#define HOLEPUNCH_ABI_VERSION
struct vidcap_params * vidcap_params_allocate_next(struct vidcap_params *curr)
const char * vidcap_params_get_driver(const struct vidcap_params *params)
void vidcap_params_set_device(struct vidcap_params *params, const char *config)

References ug_options::audio, audio_capture_channels, Holepunch_config::audio_rx_port, Holepunch_config::audio_tx_port, ug_options::bitrate, audio_options::codec_cfg, commandline_params, ug_options::common, DEFAULT_AUDIO_CODEC, DEFAULT_VIDEO_COMPRESSION, EXIT_FAIL_USAGE, common_opts::force_ip_version, HOLEPUNCH_ABI_VERSION, audio_options::host, Holepunch_config::host_addr, Holepunch_config::host_addr_len, IN6_BLACKHOLE_SERVER_MODE_STR, ug_options::is_client, is_host_loopback(), is_ipv6_supported(), ug_options::is_server, LIBRARY_CLASS_UNDEFINED, load_library(), LOG, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, log_msg(), min, MODE_RECEIVER, MODE_SENDER, common_opts::mtu, ug_options::nat_traverse_config, parse_holepunch_conf(), ug_options::port_base, audio_options::proto, RATE_DEFAULT, RATE_DYNAMIC, RATE_UNLIMITED, audio_options::recv_cfg, audio_options::recv_port, ug_options::requested_compression, ug_options::requested_display, ug_options::requested_receiver, RTP_MAX_MTU, audio_options::send_cfg, audio_options::send_port, set_audio_capture_format(), vidcap_params_allocate_next(), vidcap_params_get_driver(), ug_options::vidcap_params_head, vidcap_params_set_device(), ug_options::vidcap_params_tail, ug_options::video_protocol, Holepunch_config::video_rx_port, ug_options::video_rx_port, ug_options::video_rxtx_mode, Holepunch_config::video_tx_port, and ug_options::video_tx_port.

Referenced by main().

Here is the call graph for this function:

◆ capture_thread()

static void * capture_thread ( void * arg)
static

This function captures video and possibly compresses it. It then delegates sending to another thread.

Parameters
[in]argpointer to UltraGrid (root) module

Definition at line 330 of file main.cpp.

331{
332 set_thread_name(__func__);
333
334 struct state_uv *uv = (struct state_uv *) arg;
335 assert(uv->magic == state_uv::state_magic);
336 struct wait_obj *wait_obj = wait_obj_init();
337 steady_clock::time_point t0 = steady_clock::now();
338 int frames = 0;
339 const char *print_fps_prefix =
340 vidcap_get_fps_print_prefix(uv->capture_device);
341
342 while (!uv->should_exit_capture) {
343 /* Capture and transmit video... */
344 struct audio_frame *audio = nullptr;
345 struct video_frame *tx_frame = vidcap_grab(uv->capture_device, &audio);
346
347 if (audio != nullptr) {
348 audio_sdi_send(uv->audio, audio);
350 }
351
352 if (tx_frame == nullptr) {
353 continue;
354 }
355 print_fps(print_fps_prefix, &t0, &frames, tx_frame->fps);
356 // tx_frame = vf_get_copy(tx_frame);
357 bool wait_for_cur_uncompressed_frame = false;
358 shared_ptr<video_frame> frame;
359 if (tx_frame->callbacks.dispose == nullptr) {
361 wait_for_cur_uncompressed_frame = true;
362 frame = shared_ptr<video_frame>(
363 tx_frame, [wait_obj](struct video_frame *) {
365 });
366 } else {
367 frame = shared_ptr<video_frame>(
368 tx_frame, tx_frame->callbacks.dispose);
369 }
370
371 uv->state_video_rxtx->send(
372 std::move(frame)); // std::move really important here (!)
373
374 // wait for frame frame to be processed, eg. by compress
375 // or sender (uncompressed video). Grab invalidates previous
376 // frame (if not defined dispose function).
377 if (wait_for_cur_uncompressed_frame) {
379 tx_frame->callbacks.dispose = nullptr;
380 tx_frame->callbacks.dispose_udata = nullptr;
381 }
382 }
383
385
386 return NULL;
387}
struct video_frame * frame
struct audio_frame ** audio
#define AUDIO_FRAME_DISPOSE(frame)
Definition types.h:117
void audio_sdi_send(struct state_audio *s, struct audio_frame *frame)
Definition audio.cpp:1179
struct video_frame * vidcap_grab(struct vidcap *state, struct audio_frame **audio)
Grabs video frame. This function may block for a short period if waiting for incoming frame....
const char * vidcap_get_fps_print_prefix(struct vidcap *state)
codec_t uv
Definition lavc_common.c:65
static void print_fps(const char *prefix, steady_clock::time_point *t0, int *frames, double nominal_fps)
Definition main.cpp:293
struct used to comunicate with audio capture/playback device
Definition types.h:99
static constexpr uint32_t state_magic
Definition main.cpp:171
void(* dispose)(struct video_frame *)
Definition types.h:245
Struct video_frame represents a video frame and contains video description.
Definition types.h:305
double fps
Definition types.h:308
struct video_frame_callbacks callbacks
Definition types.h:324
void set_thread_name(const char *name)
Definition thread.c:72
void wait_obj_reset(struct wait_obj *wait_obj)
Definition wait_obj.cpp:49
void wait_obj_wait(struct wait_obj *wait_obj)
Definition wait_obj.cpp:54
struct wait_obj * wait_obj_init()
Definition wait_obj.cpp:44
void wait_obj_done(struct wait_obj *wait_obj)
Definition wait_obj.cpp:64
void wait_obj_notify(struct wait_obj *wait_obj)
Definition wait_obj.cpp:59

References audio, AUDIO_FRAME_DISPOSE, audio_sdi_send(), video_frame::callbacks, video_frame_callbacks::dispose, video_frame_callbacks::dispose_udata, video_frame::fps, frame, print_fps(), set_thread_name(), state_uv::state_magic, uv, vidcap_get_fps_print_prefix(), vidcap_grab(), wait_obj_done(), wait_obj_init(), wait_obj_notify(), wait_obj_reset(), and wait_obj_wait().

Referenced by main().

Here is the call graph for this function:

◆ copy_sv_to_c_buf()

template<int N>
static void copy_sv_to_c_buf ( char(&) dest[N],
std::string_view sv )
static

Definition at line 418 of file main.cpp.

418 {
419 sv.copy(dest, N - 1);
420 dest[N - 1] = '\0';
421}
#define N
Definition tfrc.c:58

References N.

Referenced by parse_holepunch_conf().

◆ main()

int main ( int argc,
char * argv[] )

Definition at line 1253 of file main.cpp.

1254{
1255
1256 struct init_data *init = nullptr;
1257#if defined HAVE_SCHED_SETSCHEDULER && defined USE_RT
1258 struct sched_param sp;
1259#endif
1260 ug_options opt{};
1261
1262 pthread_t receiver_thread_id,
1263 capture_thread_id;
1264 bool receiver_thread_started = false,
1265 capture_thread_started = false;
1266 unsigned display_flags = 0;
1267 struct control_state *control = NULL;
1268 int ret;
1269
1271
1272 struct ug_nat_traverse *nat_traverse = nullptr;
1273
1274#ifndef _WIN32
1275 signal(SIGQUIT, crash_signal_handler);
1276#endif
1277 signal(SIGABRT, crash_signal_handler);
1278 signal(SIGFPE, crash_signal_handler);
1279 signal(SIGILL, crash_signal_handler);
1280 signal(SIGSEGV, crash_signal_handler);
1281
1282 if ((init = common_preinit(argc, argv)) == nullptr) {
1283 log_msg(LOG_LEVEL_FATAL, "common_preinit() failed!\n");
1284 EXIT(EXIT_FAILURE);
1285 }
1286
1287 struct state_uv uv{};
1288 keyboard_control kc{&uv.root_module};
1289 const bool show_help = tok_in_argv(uv_argv, "help");
1290
1291 print_version();
1292 printf("\n");
1293
1294 if (int ret = parse_options(argc, argv, &opt)) {
1295 EXIT(ret < 0 ? -ret : EXIT_SUCCESS);
1296 }
1297
1298 if (int ret = adjust_params(&opt)) {
1299 EXIT(ret);
1300 }
1301
1302 const auto ac_params = parse_audio_codec_params(opt.audio.codec_cfg);
1303 if (ac_params.codec == AC_NONE) {
1304 EXIT(EXIT_FAILURE);
1305 }
1306 if (!show_help) {
1307 col() << TBOLD("Display device : ") << opt.requested_display << "\n";
1308 col() << TBOLD("Capture device : ") << vidcap_params_get_driver(opt.vidcap_params_head) << "\n";
1309 col() << TBOLD("Audio capture : ") << opt.audio.send_cfg << "\n";
1310 col() << TBOLD("Audio playback : ") << opt.audio.recv_cfg << "\n";
1311 col() << TBOLD("MTU : ") << opt.common.mtu << " B\n";
1312 col() << TBOLD("Video compression: ") << opt.requested_compression << "\n";
1313 col() << TBOLD("Audio codec : ")
1314 << get_name_to_audio_codec(ac_params.codec) << "\n";
1315 col() << TBOLD("Network protocol : ") << video_rxtx::get_long_name(opt.video_protocol) << "\n";
1316 col() << TBOLD("Audio FEC : ") << opt.audio.fec_cfg << "\n";
1317 col() << TBOLD("Video FEC : ") << opt.requested_video_fec << "\n";
1318 col() << "\n";
1319 }
1320
1321 opt.common.parent = &uv.root_module;
1322
1323 opt.common.exporter = export_init(&uv.root_module, opt.export_opts, opt.should_export);
1324 if (!opt.common.exporter) {
1325 log_msg(LOG_LEVEL_ERROR, "Export initialization failed.\n");
1326 EXIT(EXIT_FAILURE);
1327 }
1328
1329 if (control_init(opt.control_port, opt.connection_type, &control,
1330 &uv.root_module, opt.common.force_ip_version) != 0) {
1331 LOG(LOG_LEVEL_FATAL) << "Error: Unable to initialize remote control!\n";
1333 }
1334
1335 if(!opt.nat_traverse_config
1336 || strncmp(opt.nat_traverse_config, "holepunch", strlen("holepunch")) != 0){
1337 nat_traverse = start_nat_traverse(opt.nat_traverse_config, opt.requested_receiver, opt.video_rx_port, opt.audio.recv_port);
1338 if(!nat_traverse){
1339 exit_uv(1);
1340 goto cleanup;
1341 }
1342 }
1343
1344 ret = audio_init(&uv.audio, &opt.audio, &opt.common);
1345 if (ret != 0) {
1346 exit_uv(ret < 0 ? EXIT_FAIL_AUDIO : 0);
1347 goto cleanup;
1348 }
1349
1350 display_flags |= audio_get_display_flags(uv.audio);
1351
1352 // Display initialization should be prior to modules that may use graphic card (eg. GLSL) in order
1353 // to initalize shared resource (X display) first
1354 ret =
1355 initialize_video_display(&uv.root_module, opt.requested_display, opt.display_cfg, display_flags, opt.postprocess, &uv.display_device);
1356 if (ret < 0) {
1357 printf("Unable to open display device: %s\n",
1358 opt.requested_display);
1360 goto cleanup;
1361 } else if(ret > 0) {
1362 exit_uv(EXIT_SUCCESS);
1363 goto cleanup;
1364 }
1365 log_msg(LOG_LEVEL_DEBUG, "Display initialized-%s\n", opt.requested_display);
1366
1367 ret = initialize_video_capture(&uv.root_module, opt.vidcap_params_head, &uv.capture_device);
1368 if (ret < 0) {
1369 printf("Unable to open capture device: %s\n",
1370 vidcap_params_get_driver(opt.vidcap_params_head));
1372 goto cleanup;
1373 } else if(ret > 0) {
1374 exit_uv(EXIT_SUCCESS);
1375 goto cleanup;
1376 }
1377 log_msg(LOG_LEVEL_DEBUG, "Video capture initialized-%s\n", vidcap_params_get_driver(opt.vidcap_params_head));
1378
1379 signal(SIGINT, signal_handler);
1380 signal(SIGTERM, signal_handler);
1381#ifndef _WIN32
1382 signal(SIGHUP, signal_handler);
1383 signal(SIGPIPE, signal_handler);
1384#endif
1385
1386#ifdef USE_RT
1387#ifdef HAVE_SCHED_SETSCHEDULER
1388 sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
1389 if (sched_setscheduler(0, SCHED_FIFO, &sp) != 0) {
1390 printf("WARNING: Unable to set real-time scheduling\n");
1391 }
1392#else
1393 printf("WARNING: System does not support real-time scheduling\n");
1394#endif /* HAVE_SCHED_SETSCHEDULER */
1395#endif /* USE_RT */
1396
1397 try {
1398 map<string, param_u> params;
1399
1400 // common
1401 params["compression"].str = opt.requested_compression;
1402 params["rxtx_mode"].i = opt.video_rxtx_mode;
1403
1404 // iHDTV
1405 params["capture_device"].ptr = (opt.video_rxtx_mode & MODE_SENDER) != 0U ? uv.capture_device : nullptr;
1406 params["display_device"].ptr = (opt.video_rxtx_mode & MODE_RECEIVER) != 0U ? uv.display_device : nullptr;
1407
1408 //RTP
1409 params["common"].cptr = &opt.common;
1410 params["receiver"].str = opt.requested_receiver;
1411 params["rx_port"].i = opt.video_rx_port;
1412 params["tx_port"].i = opt.video_tx_port;
1413 params["fec"].str = opt.requested_video_fec;
1414 params["bitrate"].ll = opt.bitrate;
1415 params["start_time"].ll = start_time;
1416
1417 // UltraGrid RTP
1418 params["decoder_mode"].l = (long) opt.decoder_mode;
1419 params["display_device"].ptr = uv.display_device;
1420
1421 // SAGE + RTSP
1422 params["opts"].str = opt.video_protocol_opts;
1423
1424 if (strcmp(opt.video_protocol, "rtsp") == 0) {
1426 if ((strcmp("none", opt.audio.send_cfg) != 0)) {
1427 avType = (rtsp_types_t) (avType | rtsp_type_audio); // AStream
1428 }
1429 if (strcmp("none", vidcap_params_get_driver(
1430 opt.vidcap_params_head)) != 0) {
1431 avType = (rtsp_types_t) (avType | rtsp_type_video); // VStream
1432 }
1433 if (avType == rtsp_type_none) {
1434 printf("[RTSP SERVER CHECK] no stream type... check capture devices input...\n");
1435 }
1436
1437 params["avType"].l = (long) avType;
1438 }
1439
1440 sdp_set_properties(opt.requested_receiver, opt.video_rxtx_mode & MODE_SENDER && strcasecmp(opt.video_protocol, "sdp") == 0, opt.audio.send_port != 0 && strcasecmp(opt.audio.proto, "sdp") == 0);
1441
1442 uv.state_video_rxtx = video_rxtx::create(opt.video_protocol, params);
1443 if (!uv.state_video_rxtx) {
1444 if (strcmp(opt.video_protocol, "help") != 0) {
1445 throw string("Requested RX/TX cannot be created (missing library?)");
1446 } else {
1447 throw 0;
1448 }
1449 }
1450
1451 if ((opt.video_rxtx_mode & MODE_RECEIVER) != 0U) {
1452 if (!uv.state_video_rxtx->supports_receiving()) {
1453 fprintf(stderr, "Selected RX/TX mode doesn't support receiving.\n");
1454 exit_uv(EXIT_FAILURE);
1455 goto cleanup;
1456 }
1457 // init module here so as it is capable of receiving messages
1458 if (pthread_create
1459 (&receiver_thread_id, NULL, video_rxtx::receiver_thread,
1460 (void *) uv.state_video_rxtx) != 0) {
1461 perror("Unable to create display thread!\n");
1462 exit_uv(EXIT_FAILURE);
1463 goto cleanup;
1464 } else {
1465 receiver_thread_started = true;
1466 }
1467 }
1468
1469 if ((opt.video_rxtx_mode & MODE_SENDER) != 0U) {
1470 if (pthread_create
1471 (&capture_thread_id, NULL, capture_thread,
1472 (void *) &uv) != 0) {
1473 perror("Unable to create capture thread!\n");
1474 exit_uv(EXIT_FAILURE);
1475 goto cleanup;
1476 } else {
1477 capture_thread_started = true;
1478 }
1479 }
1480
1481 struct additional_audio_data aux = {
1482 { uv.display_device, display_put_audio_frame,
1484 uv.state_video_rxtx,
1485 };
1486 audio_register_aux_data(uv.audio, aux);
1487
1488 if (opt.requested_capabilities != nullptr) {
1489 print_capabilities(opt.requested_capabilities);
1490 exit_uv(EXIT_SUCCESS);
1491 goto cleanup;
1492 }
1493
1494 audio_start(uv.audio);
1495
1496 control_start(control);
1497 kc.start();
1498
1499 display_run_mainloop(uv.display_device);
1500
1501 } catch (ug_no_error const &e) {
1502 exit_uv(0);
1503 } catch (ug_runtime_error const &e) {
1504 LOG(LOG_LEVEL_ERROR) << e.what() << "\n";
1505 exit_uv(e.get_code());
1506 } catch (runtime_error const &e) {
1507 LOG(LOG_LEVEL_ERROR) << e.what() << "\n";
1508 exit_uv(EXIT_FAILURE);
1509 } catch (exception const &e) {
1510 LOG(LOG_LEVEL_ERROR) << e.what() << "\n";
1511 exit_uv(EXIT_FAILURE);
1512 } catch (string const &str) {
1513 LOG(LOG_LEVEL_ERROR) << str << "\n";
1514 exit_uv(EXIT_FAILURE);
1515 } catch (int i) {
1516 exit_uv(i);
1517 }
1518
1519cleanup:
1520 if (strcmp("none", opt.requested_display) != 0 &&
1521 receiver_thread_started)
1522 pthread_join(receiver_thread_id, NULL);
1523
1524 if ((opt.video_rxtx_mode & MODE_SENDER) != 0U
1525 && capture_thread_started) {
1526 pthread_join(capture_thread_id, NULL);
1527 }
1528
1529 /* also wait for audio threads */
1530 audio_join(uv.audio);
1531 if (uv.state_video_rxtx)
1532 uv.state_video_rxtx->join();
1533
1534 export_destroy(opt.common.exporter);
1535
1536 signal(SIGINT, SIG_DFL);
1537 signal(SIGTERM, SIG_DFL);
1538#ifndef _WIN32
1539 signal(SIGHUP, SIG_DFL);
1540 signal(SIGALRM, hang_signal_handler);
1541#endif
1542 alarm(5); // prevent exit hangs
1543
1544 if(uv.audio)
1545 audio_done(uv.audio);
1546 delete uv.state_video_rxtx;
1547
1548 if (uv.capture_device)
1549 vidcap_done(uv.capture_device);
1550 if (uv.display_device)
1551 display_done(uv.display_device);
1552
1553 stop_nat_traverse(nat_traverse);
1554
1555 kc.stop();
1556 control_done(control);
1557
1559
1560 printf("Exit\n");
1561
1562 return get_exit_status(&uv.root_module);
1563}
@ AC_NONE
Definition types.h:52
void audio_register_aux_data(struct state_audio *s, struct additional_audio_data data)
Definition audio.cpp:1191
unsigned int audio_get_display_flags(struct state_audio *s)
Definition audio.cpp:1210
void audio_join(struct state_audio *s)
Definition audio.cpp:502
void audio_done(struct state_audio *s)
Definition audio.cpp:512
int audio_init(struct state_audio **ret, const struct audio_options *opt, const struct common_opts *common)
Definition audio.cpp:272
void audio_start(struct state_audio *s)
Definition audio.cpp:463
static void show_help()
Definition wasapi.cpp:193
int get_code() const noexcept
struct audio_codec_params parse_audio_codec_params(const char *ccfg)
Definition codec.cpp:402
const char * get_name_to_audio_codec(audio_codec_t codec)
Definition codec.cpp:450
#define TBOLD(x)
Definition color_out.h:70
int control_init(int port, int connection_type, struct control_state **state, struct module *root_module, int force_ip_version)
void control_done(struct control_state *s)
void control_start(struct control_state *s)
#define LOG_LEVEL_FATAL
errors that prevent UG run
Definition debug.h:58
void export_destroy(struct exporter *s)
Definition export.c:308
struct exporter * export_init(struct module *parent, const char *cfg, bool should_export)
Definition export.c:149
bool display_reconfigure_audio(struct display *d, int quant_samples, int channels, int sample_rate)
void display_put_audio_frame(struct display *d, const struct audio_frame *frame)
Puts audio data.
void display_run_mainloop(struct display *d)
Display mainloop function.
bool display_ctl_property(struct display *d, int property, void *val, size_t *len)
Gets property from video display.
void display_done(struct display *d)
This function performs cleanup after done.
int initialize_video_display(struct module *parent, const char *requested_display, const char *fmt, unsigned int flags, const char *postprocess, struct display **out)
Initializes video display.
int initialize_video_capture(struct module *parent, struct vidcap_params *param, struct vidcap **state)
Initializes video capture.
void vidcap_done(struct vidcap *state)
Destroys vidap state.
void crash_signal_handler(int sig)
Definition host.cpp:1253
void exit_uv(int status)
Definition host.cpp:625
void print_capabilities(const char *cfg)
Definition host.cpp:801
void print_version()
Definition host.cpp:868
int get_exit_status(struct module *root_mod)
Definition host.cpp:633
bool tok_in_argv(char **argv, const char *tok)
Definition host.cpp:417
void hang_signal_handler(int sig)
Definition host.cpp:1276
char ** uv_argv
Definition host.cpp:174
static struct @19 params[100]
struct init_data * common_preinit(int argc, char *argv[])
Definition host.cpp:435
#define EXIT_FAIL_CAPTURE
Definition host.h:64
#define EXIT_FAIL_AUDIO
Definition host.h:70
#define EXIT_FAIL_DISPLAY
Definition host.h:63
#define EXIT_FAIL_CONTROL_SOCK
Definition host.h:68
#define LOG_LEVEL_DEBUG
Definition kernels.cu:48
void stop_nat_traverse(struct ug_nat_traverse *s)
Definition nat.c:567
struct ug_nat_traverse * start_nat_traverse(const char *config, const char *remote_host, int video_rx_port, int audio_rx_port)
Definition nat.c:487
rtsp_types_t
Definition rtsp_utils.h:4
@ rtsp_type_video
Definition rtsp_utils.h:7
@ rtsp_type_none
Definition rtsp_utils.h:5
@ rtsp_type_audio
Definition rtsp_utils.h:6
static void cleanup()
Definition sdp.c:195
void sdp_set_properties(const char *receiver, bool has_sdp_video, bool has_sdp_audio)
Definition sdp.c:576
static void * capture_thread(void *arg)
Definition main.cpp:330
static int parse_options(int argc, char *argv[], struct ug_options *opt)
Definition main.cpp:1011
#define EXIT(expr)
Definition main.cpp:1251
static int adjust_params(struct ug_options *opt)
Definition main.cpp:1034
static void signal_handler(int signum)
Definition main.cpp:174
static video_rxtx * create(std::string const &name, std::map< std::string, param_u > const &)
static void * receiver_thread(void *arg)
static const char * get_long_name(std::string const &short_name)
static struct timeval start_time
Definition tv.c:57
long long time_ns_t
Definition tv.h:81
static time_ns_t get_time_in_ns()
Definition tv.h:101

References AC_NONE, adjust_params(), audio_done(), audio_get_display_flags(), audio_init(), audio_join(), audio_register_aux_data(), audio_start(), capture_thread(), cleanup(), common_cleanup(), common_preinit(), control_done(), control_init(), control_start(), crash_signal_handler(), video_rxtx::create(), display_ctl_property(), display_done(), display_put_audio_frame(), display_reconfigure_audio(), display_run_mainloop(), EXIT, EXIT_FAIL_AUDIO, EXIT_FAIL_CAPTURE, EXIT_FAIL_CONTROL_SOCK, EXIT_FAIL_DISPLAY, exit_uv(), export_destroy(), export_init(), get_exit_status(), video_rxtx::get_long_name(), get_name_to_audio_codec(), get_time_in_ns(), hang_signal_handler(), init(), initialize_video_capture(), initialize_video_display(), LOG, LOG_LEVEL_DEBUG, LOG_LEVEL_ERROR, LOG_LEVEL_FATAL, log_msg(), MODE_RECEIVER, MODE_SENDER, params, parse_audio_codec_params(), parse_options(), print_capabilities(), print_version(), video_rxtx::receiver_thread(), control_state::root_module, rtsp_type_audio, rtsp_type_none, rtsp_type_video, sdp_set_properties(), show_help(), signal_handler(), start_nat_traverse(), start_time, stop_nat_traverse(), TBOLD, tok_in_argv(), uv, uv_argv, vidcap_done(), and vidcap_params_get_driver().

Here is the call graph for this function:

◆ parse_audio_capture()

static int parse_audio_capture ( struct ug_options * opt,
char * optarg )
static

Definition at line 550 of file main.cpp.

550 {
551 if (strcmp(optarg, "help") == 0 || strcmp(optarg, "fullhelp") == 0) {
552 audio_capture_print_help(strcmp(optarg, "full") == 0);
553 return 1;
554 }
555 if (string(opt->audio.send_cfg) != ug_options().audio.send_cfg &&
557 audio_capture_get_vidcap_flags(optarg) == 0)) {
558 log_msg(LOG_LEVEL_ERROR, "Multiple audio devices given! Only "
559 "allowed for video-attached audio "
560 "connection (AESEBU/analog/embedded).\n");
561 return -EXIT_FAIL_USAGE;
562 }
563 if (audio_capture_get_vidcap_flags(optarg)) {
566 }
567 opt->audio.send_cfg = optarg;
568 return 0;
569}
unsigned int audio_capture_get_vidcap_flags(const char *const_device_name)
void audio_capture_print_help(bool full)
void vidcap_params_add_flags(struct vidcap_params *params, unsigned int flags)

References audio, ug_options::audio, audio_capture_get_vidcap_flags(), audio_capture_print_help(), EXIT_FAIL_USAGE, LOG_LEVEL_ERROR, log_msg(), audio_options::send_cfg, vidcap_params_add_flags(), and ug_options::vidcap_params_tail.

Referenced by parse_options_internal().

Here is the call graph for this function:

◆ parse_control_port()

static bool parse_control_port ( char * optarg,
struct ug_options * opt )
static

Definition at line 654 of file main.cpp.

654 {
655 if (strchr(optarg, ':')) {
656 char *save_ptr = NULL;
657 char *tok;
658 opt->control_port = atoi(strtok_r(optarg, ":", &save_ptr));
659 opt->connection_type = atoi(strtok_r(NULL, ":", &save_ptr));
660
661 if (opt->connection_type < 0 || opt->connection_type > 1){
662 usage(uv_argv[0]);
663 return false;
664 }
665 if ((tok = strtok_r(NULL, ":", &save_ptr))) {
666 usage(uv_argv[0]);
667 return false;
668 }
669 } else {
670 opt->control_port = atoi(optarg);
671 opt->connection_type = 0;
672 }
673 return true;
674}
void usage()
Definition main.cpp:28
int control_port
Definition main.cpp:526
int connection_type
Definition main.cpp:527

References ug_options::connection_type, ug_options::control_port, usage(), and uv_argv.

Referenced by parse_options_internal().

Here is the call graph for this function:

◆ parse_cuda_device()

static int parse_cuda_device ( char * optarg)
static
Return values
<0return code whose absolute value will be returned from main()
0success
1device list was printed

Definition at line 392 of file main.cpp.

392 {
393 if(strcmp("help", optarg) == 0) {
394#ifdef HAVE_CUDA
396#else
397 LOG(LOG_LEVEL_ERROR) << "CUDA support is not enabled!\n";
398 return -EXIT_FAILURE;
399#endif
400 }
401 char *item, *save_ptr = NULL;
402 unsigned int i = 0;
403 while((item = strtok_r(optarg, ",", &save_ptr))) {
404 if(i >= MAX_CUDA_DEVICES) {
405 LOG(LOG_LEVEL_ERROR) << "Maximal number of CUDA device exceeded.\n";
406 return -EXIT_FAILURE;
407 }
408 cuda_devices[i] = atoi(item);
409 optarg = NULL;
410 ++i;
411 }
414 return 0;
415}
void cuda_wrapper_print_devices_info(void)
adapted from gpujpeg_print_devices_info()
unsigned int cuda_devices_count
Definition host.cpp:168
bool cuda_devices_explicit
–cuda-device/-D specified expilcitly
Definition host.cpp:169
unsigned int cuda_devices[MAX_CUDA_DEVICES]
Definition host.cpp:167
#define MAX_CUDA_DEVICES
Definition host.h:97
Definition hd-rum.c:27

References cuda_devices, cuda_devices_count, cuda_devices_explicit, cuda_wrapper_print_devices_info(), LOG, LOG_LEVEL_ERROR, and MAX_CUDA_DEVICES.

Referenced by parse_options_internal().

Here is the call graph for this function:

◆ parse_holepunch_conf()

static bool parse_holepunch_conf ( char * conf,
struct Holepunch_config * punch_c )
static

Definition at line 423 of file main.cpp.

423 {
424 std::string_view sv = conf;
425 while(!sv.empty()){
426 auto token = tokenize(sv, ':');
427 auto key = tokenize(token, '=');
428 auto val = tokenize(token, '=');
429
430 if(key == "help"){
431 col() << "Usage:\n" <<
432 "\tuv " << TBOLD("-Nholepunch:room=<room>:(server=<host> | coord_srv=<host:port>:stun_srv=<host:port>)[:client_name=<name>][:bind_ip=<addr>] \n") <<
433 "\twhere\n"
434 "\t\t" << TBOLD("server") << " - used if both stun & coord server are on the same host on standard ports (3478, 12558)\n"
435 "\t\t" << TBOLD("room") << " - name of room to join\n"
436 "\t\t" << TBOLD("client_name") << " - name to identify as to the coord server, if not specified hostname is used\n"
437 "\t\t" << TBOLD("bind_ip") << " - local ip to bind to\n"
438 "\n";
439 return false;
440 }
441
442 if(key == "coord_srv"){
444
445 token = tokenize(sv, ':');
446 if(token.empty()){
447 log_msg(LOG_LEVEL_ERROR, "Missing hole punching coord server port.\n");
448 return false;
449 }
450
451 if(!parse_num(token, punch_c->coord_srv_port)){
452 log_msg(LOG_LEVEL_ERROR, "Failed to parse hole punching coord server port.\n");
453 return false;
454 }
455 } else if(key == "stun_srv"){
457
458 token = tokenize(sv, ':');
459 if(token.empty()){
460 log_msg(LOG_LEVEL_ERROR, "Missing hole punching stun server port.\n");
461 return false;
462 }
463
464 if(!parse_num(token, punch_c->stun_srv_port)){
465 log_msg(LOG_LEVEL_ERROR, "Failed to parse hole punching stun server port.\n");
466 return false;
467 }
468 } else if(key == "server"){
471
472 punch_c->stun_srv_port = 3478;
473 punch_c->coord_srv_port = 12558;
474 } else if(key == "room"){
475 copy_sv_to_c_buf(punch_c->room_name, val);
476 } else if(key == "client_name"){
478 } else if(key == "bind_ip"){
479 copy_sv_to_c_buf(punch_c->bind_addr, val);
480 }
481 }
482
483 if(!strlen(punch_c->stun_srv_addr)
484 || !strlen(punch_c->coord_srv_addr)
485 || !strlen(punch_c->room_name))
486 {
487 log_msg(LOG_LEVEL_ERROR, "Not all hole punch params provided.\n");
488 return false;
489 }
490
491 return true;
492}
int void * val
static void copy_sv_to_c_buf(char(&dest)[N], std::string_view sv)
Definition main.cpp:418
std::string_view tokenize(std::string_view &str, char delim, char quot)
Tokenizer for string_view.
bool parse_num(std::string_view sv, T &res, int base=10)
char client_name[512]
char coord_srv_addr[512]
char stun_srv_addr[512]
char room_name[512]
const char * key
Definition cineform.cpp:125

References Holepunch_config::bind_addr, Holepunch_config::client_name, Holepunch_config::coord_srv_addr, Holepunch_config::coord_srv_port, copy_sv_to_c_buf(), key, LOG_LEVEL_ERROR, log_msg(), parse_num(), Holepunch_config::room_name, Holepunch_config::stun_srv_addr, Holepunch_config::stun_srv_port, TBOLD, tokenize(), and val.

Referenced by adjust_params().

Here is the call graph for this function:

◆ parse_options()

static int parse_options ( int argc,
char * argv[],
struct ug_options * opt )
static

Return values
-errorerror value that should be returned from main
0success
1success (help written)

Definition at line 1011 of file main.cpp.

1012{
1013 try {
1014 return parse_options_internal(argc, argv, opt);
1015 } catch (logic_error &e) {
1016 if (!invalid_arg_is_numeric(e.what())) {
1017 throw;
1018 }
1019 if (dynamic_cast<invalid_argument *>(&e) != nullptr) {
1021 << MOD_NAME
1022 << "Non-numeric value passed to option "
1023 "expecting a number!\n";
1024 } else if (dynamic_cast<out_of_range *>(&e) != nullptr) {
1026 << MOD_NAME << "Passed value is out of bounds!\n";
1027 } else {
1028 throw;
1029 }
1030 return -1;
1031 }
1032}
bool invalid_arg_is_numeric(const char *what)
Definition misc.cpp:340
static int parse_options_internal(int argc, char *argv[], struct ug_options *opt)
Definition main.cpp:682
#define MOD_NAME
Definition main.cpp:121

References invalid_arg_is_numeric(), LOG, LOG_LEVEL_ERROR, MOD_NAME, and parse_options_internal().

Referenced by main().

Here is the call graph for this function:

◆ parse_options_internal()

static int parse_options_internal ( int argc,
char * argv[],
struct ug_options * opt )
static
Return values
-errorerror value that should be returned from main
0success
1success (help written)

Definition at line 682 of file main.cpp.

683{
684 static struct option getopt_options[] = { // sort by
685 {"audio-capture-format", required_argument, nullptr, 'a'},
686 {"capabilities", optional_argument, nullptr, 'b'},
687 {"compress", required_argument, nullptr, 'c'},
688 {"display", required_argument, nullptr, 'd'},
689 {"encryption", required_argument, nullptr, 'e'},
690 {"fec", required_argument, nullptr, 'f'},
691 {"help", no_argument, nullptr, 'h'},
692 {"audio-filter", required_argument, nullptr, 'i'},
693 {"limit-bitrate", required_argument, nullptr, 'l'},
694 {"capture", required_argument, nullptr, 't'},
695 {"mtu", required_argument, nullptr, 'm'},
696 {"postprocess", required_argument, nullptr, 'p'},
697 {"receive", required_argument, nullptr, 'r'},
698 {"send", required_argument, nullptr, 's'},
699 {"version", no_argument, nullptr, 'v'},
700 {"protocol", required_argument, nullptr, 'x'},
701 {"audio-codec", required_argument, nullptr, 'A'},
702 {"client", no_argument, nullptr, 'C'},
703 {"cuda-device", required_argument, nullptr, 'D'},
704 {"record", optional_argument, nullptr, 'E'},
705 {"capture-filter", required_argument, nullptr, 'F'},
706 {"fullhelp", no_argument, nullptr, 'H'},
707 {"playback", required_argument, nullptr, 'I'},
708 {"list-modules", no_argument, nullptr, 'L'},
709 {"mode", required_argument, nullptr, 'M'},
710 {"nat-traverse", optional_argument, nullptr, 'N'},
711 {"param", required_argument, nullptr, 'O'},
712 {"port", required_argument, nullptr, 'P'},
713 {"server", no_argument, nullptr, 'S'},
714 {"ttl", required_argument, nullptr, 'T'},
715 {"audio-channel-map", required_argument, nullptr, 'U'},
716 {"verbose", optional_argument, nullptr, 'V'},
717 {"audio-capture-channels", required_argument, 0, OPT_AUDIO_CAPTURE_CHANNELS},
718 {"audio-delay", required_argument, 0, OPT_AUDIO_DELAY},
719 {"audio-host", required_argument, 0, OPT_AUDIO_HOST},
720 {"audio-protocol", required_argument, 0, OPT_AUDIO_PROTOCOL},
721 {"control-port", required_argument, 0, OPT_CONTROL_PORT},
722 {"audio-scale", required_argument, 0, OPT_AUDIO_SCALE},
723 {"echo-cancellation", no_argument, 0, OPT_ECHO_CANCELLATION},
724 {"mcast-if", required_argument, 0, OPT_MCAST_IF},
725 {"conv-policy", required_argument, 0, OPT_PIXFMT_CONV_POLICY},
726 {"pix-fmts", no_argument, 0, OPT_PIX_FMTS},
727 {"rtsp-server", optional_argument, 0, OPT_RTSP_SERVER},
728 {"video-codecs", no_argument, 0, OPT_VIDEO_CODECS},
729 {"video-protocol", required_argument, 0, OPT_VIDEO_PROTOCOL},
730 {"window-title", required_argument, 0, OPT_WINDOW_TITLE},
731 {0, 0, 0, 0}
732 };
733 const char *optstring =
734 "46A:CD:E::F:HI:LM:N::O:P:ST:U:Va:b::c:e:f:d:hi:l:m:p:r:s:t:vx:";
735
736 int ch = 0;
737 while ((ch =
738 getopt_long(argc, argv, optstring, getopt_options,
739 NULL)) != -1) {
740 switch (ch) {
741 case 'd':
742 if (strcmp(optarg, "help") == 0 || strcmp(optarg, "fullhelp") == 0) {
743 list_video_display_devices(strcmp(optarg, "fullhelp") == 0);
744 return 1;
745 }
746 if (opt->requested_display && strcmp(opt->requested_display, "none") != 0) {
747 log_msg(LOG_LEVEL_ERROR, "Multiple displays given!\n");
748 return -EXIT_FAIL_USAGE;
749 }
750 opt->requested_display = optarg;
751 if(strchr(optarg, ':')) {
752 char *delim = strchr(optarg, ':');
753 *delim = '\0';
754 opt->display_cfg = delim + 1;
755 }
756 break;
757 case 't':
758 if (strcmp(optarg, "help") == 0 || strcmp(optarg, "fullhelp") == 0) {
759 list_video_capture_devices(strcmp(optarg, "fullhelp") == 0);
760 return 1;
761 }
764 break;
765 case 'm':
766 opt->common.mtu = atoi(optarg);
767 if (opt->common.mtu < 576 &&
768 optarg[strlen(optarg) - 1] != '!') {
770 "MTU %1$u seems to be too low, use "
771 "\"%1$u!\" to force.\n",
772 opt->common.mtu);
773 return -EXIT_FAIL_USAGE;
774 }
775 break;
776 case 'M':
778 if (opt->decoder_mode == VIDEO_UNKNOWN) {
779 return strcasecmp(optarg, "help") == 0 ? 1 : -EXIT_FAIL_USAGE;
780 }
781 break;
782 case 'p':
783 opt->postprocess = optarg;
784 break;
785 case 'v':
787 return 1;
788 case 'c':
789 opt->requested_compression = optarg;
790 break;
791 case OPT_RTSP_SERVER:
792 log_msg(LOG_LEVEL_WARNING, "Option \"--rtsp-server[=args]\" "
793 "is deprecated and will be removed in future.\n"
794 "Please use \"-x rtsp[:args]\"instead.\n");
795 opt->video_protocol = "rtsp";
796 opt->video_protocol_opts = optarg ? optarg : "";
797 break;
800 case 'x':
801 if (!parse_protocol(ch, optarg, opt)) {
802 return 1;
803 }
804 break;
805 case 'r':
806 if (strcmp(optarg, "help") == 0 || strcmp(optarg, "fullhelp") == 0) {
807 audio_playback_help(strcmp(optarg, "full") == 0);
808 return 1;
809 }
810 if (string(opt->audio.recv_cfg) != ug_options().audio.recv_cfg) {
811 log_msg(LOG_LEVEL_ERROR, "Multiple audio playback devices given!\n");
812 return -EXIT_FAIL_USAGE;
813 }
814 opt->audio.recv_cfg = optarg;
815 break;
816 case 's':
817 if (int ret = parse_audio_capture(opt, optarg)) {
818 return ret;
819 }
820 break;
821 case 'f':
822 if(strlen(optarg) > 2 && optarg[1] == ':' &&
823 (toupper(optarg[0]) == 'A' || toupper(optarg[0]) == 'V')) {
824 if(toupper(optarg[0]) == 'A') {
825 opt->audio.fec_cfg = optarg + 2;
826 } else {
827 opt->requested_video_fec = optarg + 2;
828 }
829 } else {
830 // there should be setting for both audio and video
831 // but we conservativelly expect that the user wants
832 // only vieo and let audio default until explicitly
833 // stated otehrwise
834 opt->requested_video_fec = optarg;
835 }
836 break;
837 case 'h':
838 usage(uv_argv[0], false);
839 return 1;
840 case 'P':
841 if (!parse_port(optarg, opt)) {
842 return -EXIT_FAIL_USAGE;
843 }
844 break;
845 case 'l':
846 if (!parse_bitrate(optarg, &opt->bitrate)) {
847 return -EXIT_FAILURE;
848 }
849 if (opt->bitrate == RATE_DEFAULT) {
850 return 1; // help written
851 }
852 break;
853 case '4':
854 case '6':
855 opt->common.force_ip_version = ch - '0';
856 break;
857 case 'U':
858 opt->audio.channel_map = optarg;
859 break;
860 case OPT_AUDIO_SCALE:
861 opt->audio.scale = optarg;
862 break;
864 log_msg(LOG_LEVEL_WARNING, "Parameter --audio-capture-channels is deprecated. "
865 "Use \"-a channels=<count>\" instead.\n");
866 audio_capture_channels = atoi(optarg);
867 if (audio_capture_channels < 1) {
868 log_msg(LOG_LEVEL_ERROR, "Invalid number of channels %d!\n", audio_capture_channels);
869 return -EXIT_FAIL_USAGE;
870 }
871 break;
872 case 'a':
873 if (int ret = set_audio_capture_format(optarg)) {
874 return ret < 0 ? -EXIT_FAIL_USAGE : 1;
875 }
876 break;
877 case 'i':
878 if(!opt->audio_filter_cfg.empty()){
879 opt->audio_filter_cfg += "#";
880 }
881 opt->audio_filter_cfg += optarg;
882 break;
884 opt->audio.echo_cancellation = true;
885 break;
886 case 'H':
887 usage(uv_argv[0], true);
888 return 1;
889 case 'D':
890 if (int ret = parse_cuda_device(optarg)) {
891 return ret;
892 }
893 break;
894 case OPT_MCAST_IF:
895 snprintf_ch(opt->common.mcast_if, "%s", optarg);
896 break;
897 case OPT_AUDIO_HOST:
898 opt->audio.host = optarg;
899 break;
900 case 'E':
901 opt->should_export = true;
902 opt->export_opts = optarg;
903 break;
904 case 'I':
905 opt->audio.send_cfg = "embedded";
906 {
907 char dev_string[1024];
908 int ret;
909 if ((ret = playback_set_device(dev_string, sizeof dev_string, optarg)) <= 0) {
910 return ret == 0 ? 1 : -EXIT_FAIL_USAGE;
911 }
914 }
915 break;
916 case 'A':
917 if(strcmp(optarg, "help") == 0) {
919 return 1;
920 }
921 opt->audio.codec_cfg = optarg;
922 break;
923 case 'F': {
924 std::string curr;
925 if(auto val = vidcap_params_get_capture_filter(opt->vidcap_params_tail); val != nullptr){
926 curr = val;
927 curr += ",";
928 }
929 curr += optarg;
931 break;
932 }
933 case 'e':
934 snprintf_ch(opt->common.encryption, "%s", optarg);
935 break;
936 case OPT_CONTROL_PORT:
937 if (!parse_control_port(optarg, opt)) {
938 return -EXIT_FAIL_USAGE;
939 }
940 break;
941 case 'V':
942 break; // already handled in common_preinit()
943 case OPT_WINDOW_TITLE:
944 log_msg(LOG_LEVEL_WARNING, "Deprecated option used, please use "
945 "--param window-title=<title>\n");
946 commandline_params["window-title"] = optarg;
947 break;
948 case 'b':
949 opt->requested_capabilities = optarg ? optarg : "";
950 break;
951 case OPT_AUDIO_DELAY:
952 set_audio_delay(stoi(optarg));
953 break;
954 case 'L':
955 return list_all_modules() ? 1 : -EXIT_FAILURE;
956 case 'O':
957 if (!parse_params(optarg, false)) {
958 return 1;
959 }
960 break;
961 case OPT_PIX_FMTS:
963 return 1;
965 if (int ret = set_pixfmt_conv_policy(optarg)) {
966 return ret < 0 ? -EXIT_FAIL_USAGE : 1;
967 }
968 break;
969 case OPT_VIDEO_CODECS:
971 return 1;
972 case 'N':
973 opt->nat_traverse_config = optarg == nullptr ? const_cast<char *>("") : optarg;
974 break;
975 case 'C':
976 opt->is_client = true;
977 break;
978 case 'S':
979 opt->is_server = true;
980 break;
981 case 'T':
982 opt->common.ttl = stoi(optarg);
983 break;
984 case '?':
985 default:
986 usage(uv_argv[0]);
987 return -EXIT_FAIL_USAGE;
988 }
989 }
990
991 opt->audio.filter_cfg = opt->audio_filter_cfg.data();
992
993 argc -= optind;
994 argv += optind;
995
996 if (argc > 1) {
997 log_msg(LOG_LEVEL_ERROR, "Multiple receivers given!\n");
998 usage(uv_argv[0]);
999 return -EXIT_FAIL_USAGE;
1000 }
1001
1002 if (argc > 0) {
1003 opt->requested_receiver = argv[0];
1004 }
1005
1006 return 0;
1007}
void audio_playback_help(bool full)
void list_audio_codecs(void)
Definition codec.cpp:132
void list_video_display_devices(bool full)
void list_video_capture_devices(bool full)
void set_audio_delay(int audio_delay)
Definition host.cpp:914
void print_configuration()
Definition host.cpp:882
int set_pixfmt_conv_policy(const char *optarg)
Definition host.cpp:327
bool parse_params(const char *optarg, bool preinit)
Definition host.cpp:976
bool parse_bitrate(char *optarg, long long int *bitrate)
Definition host.cpp:1012
void print_video_codecs(void)
Definition host.cpp:1115
void print_pixel_formats(void)
Definition host.cpp:1103
bool list_all_modules()
#define snprintf_ch(str,...)
shortcut for snprintf(var, sizeof var...), var must be a char array
Definition macros.h:101
int playback_set_device(char *device_string, size_t buf_len, const char *optarg)
Definition playback.c:70
#define OPT_RTSP_SERVER
Definition main.cpp:137
#define OPT_ECHO_CANCELLATION
Definition main.cpp:133
#define OPT_CONTROL_PORT
Definition main.cpp:132
static bool parse_protocol(int ch, char *optarg, struct ug_options *opt)
Definition main.cpp:602
#define OPT_MCAST_IF
Definition main.cpp:134
#define OPT_PIX_FMTS
Definition main.cpp:135
static bool parse_port(char *optarg, struct ug_options *opt)
Definition main.cpp:571
#define OPT_VIDEO_PROTOCOL
Definition main.cpp:139
#define OPT_VIDEO_CODECS
Definition main.cpp:138
#define OPT_AUDIO_PROTOCOL
Definition main.cpp:130
#define OPT_AUDIO_HOST
Definition main.cpp:129
#define OPT_PIXFMT_CONV_POLICY
Definition main.cpp:136
static int parse_audio_capture(struct ug_options *opt, char *optarg)
Definition main.cpp:550
#define OPT_AUDIO_DELAY
Definition main.cpp:128
#define OPT_AUDIO_SCALE
Definition main.cpp:131
static int parse_cuda_device(char *optarg)
Definition main.cpp:392
static bool parse_control_port(char *optarg, struct ug_options *opt)
Definition main.cpp:654
#define OPT_WINDOW_TITLE
Definition main.cpp:140
#define OPT_AUDIO_CAPTURE_CHANNELS
Definition main.cpp:127
const char * fec_cfg
Definition audio.h:76
const char * filter_cfg
Definition audio.h:81
bool echo_cancellation
Definition audio.h:79
char * channel_map
Definition audio.h:77
const char * scale
Definition audio.h:78
char encryption[STR_LEN]
Definition host.h:172
int ttl
Definition host.h:175
char mcast_if[STR_LEN]
Definition host.h:173
const char * video_protocol_opts
Definition main.cpp:543
const char * postprocess
Definition main.cpp:532
std::string audio_filter_cfg
Definition main.cpp:513
bool should_export
Definition main.cpp:523
const char * requested_video_fec
Definition main.cpp:519
char * export_opts
Definition main.cpp:524
const char * display_cfg
Definition main.cpp:518
enum video_mode decoder_mode
Definition main.cpp:529
const char * requested_capabilities
Definition main.cpp:540
@ VIDEO_UNKNOWN
unspecified video mode
Definition types.h:355
enum video_mode get_video_mode_from_str(const char *requested_mode)
Definition video.cpp:83
const char * vidcap_params_get_capture_filter(const struct vidcap_params *params)
void vidcap_params_set_capture_filter(struct vidcap_params *params, const char *req_capture_filter)

References audio, ug_options::audio, audio_capture_channels, ug_options::audio_filter_cfg, audio_playback_help(), ug_options::bitrate, audio_options::channel_map, audio_options::codec_cfg, commandline_params, ug_options::common, ug_options::decoder_mode, ug_options::display_cfg, audio_options::echo_cancellation, common_opts::encryption, EXIT_FAIL_USAGE, ug_options::export_opts, audio_options::fec_cfg, audio_options::filter_cfg, common_opts::force_ip_version, get_video_mode_from_str(), audio_options::host, ug_options::is_client, ug_options::is_server, list_all_modules(), list_audio_codecs(), list_video_capture_devices(), list_video_display_devices(), LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, log_msg(), common_opts::mcast_if, common_opts::mtu, ug_options::nat_traverse_config, OPT_AUDIO_CAPTURE_CHANNELS, OPT_AUDIO_DELAY, OPT_AUDIO_HOST, OPT_AUDIO_PROTOCOL, OPT_AUDIO_SCALE, OPT_CONTROL_PORT, OPT_ECHO_CANCELLATION, OPT_MCAST_IF, OPT_PIX_FMTS, OPT_PIXFMT_CONV_POLICY, OPT_RTSP_SERVER, OPT_VIDEO_CODECS, OPT_VIDEO_PROTOCOL, OPT_WINDOW_TITLE, parse_audio_capture(), parse_bitrate(), parse_control_port(), parse_cuda_device(), parse_params(), parse_port(), parse_protocol(), playback_set_device(), ug_options::postprocess, print_configuration(), print_pixel_formats(), print_video_codecs(), RATE_DEFAULT, audio_options::recv_cfg, ug_options::requested_capabilities, ug_options::requested_compression, ug_options::requested_display, ug_options::requested_receiver, ug_options::requested_video_fec, audio_options::scale, audio_options::send_cfg, set_audio_capture_format(), set_audio_delay(), set_pixfmt_conv_policy(), ug_options::should_export, snprintf_ch, common_opts::ttl, usage(), uv_argv, val, vidcap_params_allocate_next(), vidcap_params_get_capture_filter(), vidcap_params_set_capture_filter(), vidcap_params_set_device(), ug_options::vidcap_params_tail, ug_options::video_protocol, ug_options::video_protocol_opts, and VIDEO_UNKNOWN.

Referenced by parse_options().

Here is the call graph for this function:

◆ parse_port()

static bool parse_port ( char * optarg,
struct ug_options * opt )
static

Definition at line 571 of file main.cpp.

571 {
572 char *save_ptr = nullptr;
573 char *first_val = strtok_r(optarg, ":", &save_ptr);
574 if (first_val == nullptr || strcmp(first_val, "help") == 0) {
575 color_printf("see\n\n " TBOLD("%s --fullhelp") "\n\nfor port specification usage\n", uv_argv[0]);
576 return false;
577 }
578 if (char *tx_port_str = strtok_r(nullptr, ":", &save_ptr)) {
579 opt->video_rx_port = stoi(first_val, nullptr, 0);
580 opt->video_tx_port = stoi(tx_port_str, nullptr, 0);
581 char *tok = nullptr;
582 if ((tok = strtok_r(nullptr, ":", &save_ptr)) != nullptr) {
583 opt->audio.recv_port = stoi(tok, nullptr, 0);
584 if ((tok = strtok_r(nullptr, ":", &save_ptr)) != nullptr) {
585 opt->audio.send_port = stoi(tok, nullptr, 0);
586 } else {
587 usage(uv_argv[0]);
588 return false;
589 }
590 }
591 } else {
592 opt->port_base = stoi(first_val, nullptr, 0);
593 }
594 if (opt->audio.recv_port < -1 || opt->audio.send_port < -1 || opt->video_rx_port < -1 || opt->video_tx_port < -1 || opt->port_base < -1 ||
595 opt->audio.recv_port > UINT16_MAX || opt->audio.send_port > UINT16_MAX || opt->video_rx_port > UINT16_MAX || opt->video_tx_port > UINT16_MAX || opt->port_base > UINT16_MAX) {
596 LOG(LOG_LEVEL_ERROR) << MOD_NAME << "Invalid port value, allowed range 1-65535\n";
597 return false;
598 }
599 return true;
600}
int color_printf(const char *format,...)

References ug_options::audio, color_printf(), LOG, LOG_LEVEL_ERROR, MOD_NAME, ug_options::port_base, audio_options::recv_port, audio_options::send_port, TBOLD, usage(), uv_argv, ug_options::video_rx_port, and ug_options::video_tx_port.

Referenced by parse_options_internal().

Here is the call graph for this function:

◆ parse_protocol()

static bool parse_protocol ( int ch,
char * optarg,
struct ug_options * opt )
static

Definition at line 602 of file main.cpp.

602 {
603 bool set_audio = true;
604 bool set_video = true;
605 if (strlen(optarg) > 2 && optarg[1] == ':') {
606 set_audio = toupper(optarg[0]) == 'A';
607 set_video = toupper(optarg[0]) == 'V';
608 if (!set_audio && !set_video) {
609 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Wrong protocol setting: " << optarg << "\n";
610 return false;
611 }
612 optarg += 2;
613 }
614 char *proto = optarg;
615 const char *cfg = "";
616 if (strchr(optarg, ':')) {
617 char *delim = strchr(optarg, ':');
618 *delim = '\0';
619 cfg = delim + 1;
620 }
621 switch (ch) {
623 LOG(LOG_LEVEL_WARNING) << MOD_NAME "--audio-protocol deprecated, use '-x A:proto'\n";
624 set_video = false;
625 break;
627 LOG(LOG_LEVEL_WARNING) << MOD_NAME "--video-protocol deprecated, use '-x V:proto'\n";
628 set_audio = false;
629 break;
630 }
631 if (strcmp(optarg, "help") == 0 ||
632 strcmp(optarg, "fullhelp") == 0) {
633 col() << "Specify a transmission protocol.\nUsage:\n";
634 col() << SBOLD("\t-x proto") " - use common protocol for audio and video\n";
635 col() << SBOLD("\t-x A:proto") " - use specified audio protocol\n";
636 col() << SBOLD("\t-x V:proto") " - use specified audio protocol\n";
637 col() << "\nAudio protocol can be one of: " << TBOLD(AUDIO_PROTOCOLS) " (not all must be available)\n";
638 video_rxtx::list(strcmp(optarg, "fullhelp") == 0);
639 return false;
640 }
641 if (set_audio) {
642 opt->audio.proto = proto;
643 opt->audio.proto_cfg = cfg;
644
645 }
646 if (set_video) {
647 opt->video_protocol = proto;
648 opt->video_protocol_opts = cfg;
649
650 }
651 return true;
652}
#define AUDIO_PROTOCOLS
Definition audio.h:55
#define SBOLD(x)
Definition color_out.h:80
const char * proto_cfg
Definition audio.h:75
static void list(bool full)

References ug_options::audio, AUDIO_PROTOCOLS, video_rxtx::list(), LOG, LOG_LEVEL_ERROR, LOG_LEVEL_WARNING, MOD_NAME, OPT_AUDIO_PROTOCOL, OPT_VIDEO_PROTOCOL, audio_options::proto, audio_options::proto_cfg, SBOLD, TBOLD, ug_options::video_protocol, and ug_options::video_protocol_opts.

Referenced by parse_options_internal().

Here is the call graph for this function:

◆ print_fps()

static void print_fps ( const char * prefix,
steady_clock::time_point * t0,
int * frames,
double nominal_fps )
static

Definition at line 293 of file main.cpp.

295{
296 enum {
297 MIN_FPS_PERC_WARN = 98,
298 MIN_FPS_PERC_WARN2 = 90,
299 };
300 if (prefix == nullptr) {
301 return;
302 }
303 *frames += 1;
304 steady_clock::time_point t1 = steady_clock::now();
305 double seconds = duration_cast<duration<double>>(t1 - *t0).count();
306 if (seconds < 5.0) {
307 return;
308 }
309 const double fps = *frames / seconds;
310 const int fps_perc = (int) floor(fps / nominal_fps * 100.);
311 const char *fps_col = fps_perc >= MIN_FPS_PERC_WARN ? ""
312 : fps_perc >= MIN_FPS_PERC_WARN2
317 "%s" TERM_RESET " %d frames in %g seconds = " TERM_BOLD
318 "%s%g FPS" TERM_RESET "\n",
319 prefix, *frames, seconds, fps_col, fps);
320 *t0 = t1;
321 *frames = 0;
322}
#define T_ARCTIC_LIME
Definition color_out.h:64
#define TERM_BOLD
Definition color_out.h:48
#define TERM_FG_BRIGHT_GREEN
Definition color_out.h:56
#define T_DARKER_ORANGE
Definition color_out.h:63
#define TERM_BG_BLACK
Definition color_out.h:60
#define T256_FG_SYM(col)
Definition color_out.h:66
#define TERM_RESET
Definition color_out.h:47
int count
Definition hd-rum.c:44

References count, LOG_LEVEL_INFO, log_msg(), T256_FG_SYM, T_ARCTIC_LIME, T_DARKER_ORANGE, TERM_BG_BLACK, TERM_BOLD, TERM_FG_BRIGHT_GREEN, and TERM_RESET.

Referenced by capture_thread().

Here is the call graph for this function:

◆ print_help_item()

static void print_help_item ( const string & name,
const vector< string > & help )
static

Definition at line 197 of file main.cpp.

197 {
198 int help_lines = 0;
199
200 col() << "\t" << TBOLD(<< name <<);
201
202 for (auto const &line : help) {
203 int spaces = help_lines == 0 ? 31 - (int) name.length() : 39;
204 for (int i = 0; i < max(spaces, 0) + 1; ++i) {
205 cout << " ";
206 }
207 cout << line << "\n";
208 help_lines += 1;
209 }
210
211 if (help_lines == 0) {
212 cout << "\n";
213 }
214 cout << "\n";
215}
#define max(a, b)
Definition rtp.c:98
const char * name
Definition settings.cpp:193

References max, name, and TBOLD.

Referenced by usage().

◆ signal_handler()

static void signal_handler ( int signum)
static

Definition at line 174 of file main.cpp.

175{
176#ifdef SIGPIPE
177 if (signum == SIGPIPE) {
178 signal(SIGPIPE, SIG_IGN);
179 }
180#endif // defined SIGPIPE
182 char buf[128];
183 char *ptr = buf;
184 char *ptr_end = buf + sizeof buf;
185 strappend(&ptr, ptr_end, "Caught signal ");
186 if (signum / 10 != 0) {
187 *ptr++ = (char) ('0' + signum / 10);
188 }
189 *ptr++ = (char) ('0' + signum % 10);
190 append_sig_desc(&ptr, ptr_end - 1, signum);
191 *ptr++ = '\n';
192 write_all(STDERR_FILENO, ptr - buf, buf);
193 }
194 exit_uv(0);
195}
static ssize_t write_all(fd_t fd, const void *buf, size_t count)
#define LOG_LEVEL_VERBOSE
Definition debug.h:63
volatile int log_level
Definition debug.cpp:65
static void strappend(char **dst, size_t *dst_alloc_len, const char *src)
Definition sdp.c:366
void append_sig_desc(char **ptr, const char *ptr_end, int signum)

References append_sig_desc(), exit_uv(), log_level, LOG_LEVEL_VERBOSE, strappend(), and write_all().

Referenced by main().

Here is the call graph for this function:

◆ usage()

static void usage ( const char * exec_path,
bool full = false )
static

Definition at line 217 of file main.cpp.

218{
219 col() << "Usage: " << SBOLD(SRED((exec_path ? exec_path : "<executable_path>")) << " [options] address\n\n");
220 printf("Options:\n");
221 print_help_item("-h | -H, --fullhelp", {"show usage (basic/full)"});
222 print_help_item("-d <display_device>", {"select display device, use '-d help'",
223 "to get list of supported devices"});
224 print_help_item("-t <capture_device>", {"select capture device, use '-t help'",
225 "to get list of supported devices"});
226 print_help_item("-c <cfg>", {"video compression (see '-c help')"});
227 print_help_item("-r <playback_device>", {"audio playback device (see '-r help')"});
228 print_help_item("-s <capture_device>", {"audio capture device (see '-s help')"});
229 if (full) {
231 "-V, --verbose[=<level>]",
232 { "print verbose messages (optionally specify level [0-" +
233 to_string(LOG_LEVEL_MAX) + "])" });
234 print_help_item("--list-modules", {"prints list of modules"});
235 print_help_item("--control-port <port>[:0|1]", {"set control port (default port: " + to_string(DEFAULT_CONTROL_PORT) + ")",
236 "connection types: 0- Server (default), 1- Client"});
237 print_help_item("-x, --protocol <proto>", {"transmission protocol to use (see `-x help`)"});
238#ifdef HAVE_IPv6
239 print_help_item("-4/-6", {"force IPv4/IPv6 resolving"});
240#endif // HAVE_IPv6
241 print_help_item("--mcast-if <iface>", {"bind to specified interface for multicast"});
242 print_help_item("-m <mtu>", {"set path MTU assumption towards receiver"});
243 print_help_item("-M <video_mode>", {"received video mode (eg tiled-4K, 3D,",
244 "dual-link)"});
245 print_help_item("-N, --nat-traverse"s, {"try to deploy NAT traversal techniques"s});
246 print_help_item("-p <postprocess> | help", {"postprocess module"});
247 print_help_item("-T, --ttl <num>", {"Use specified TTL for multicast/unicast (0..255, -1 for default)"});
248 }
249 print_help_item("-f [A:|V:]<settings>", {"FEC settings (audio or video) - use",
250 "\"none\", \"mult:<nr>\",", "\"ldgm:<max_expected_loss>%\" or", "\"ldgm:<k>:<m>:<c>\"",
251 "\"rs:<k>:<n>\""});
252 if (full) {
253 print_help_item("-P <port> | <video_rx>:<video_tx>[:<audio_rx>:<audio_tx>]", { "",
254 "<port> is base port number, also 3",
255 "subsequent ports can be used for RTCP",
256 "and audio streams. Default: " + to_string(PORT_BASE) + ".",
257 "You can also specify all two or four", "ports directly."});
258 print_help_item("-l <limit_bitrate> | unlimited | auto", {"limit sending bitrate",
259 "to <limit_bitrate> (with optional k/M/G suffix)"});
260 print_help_item("--audio-host <address>", {"audio destination address",
261 "If not specified, will use same as for video"});
262 }
263 print_help_item("-a, --audio-capture-format <fmt> | help", {"format of captured audio"});
264 if (full) {
265 print_help_item("--audio-channel-map <mapping> | help", {});
266 print_help_item("--audio-filter <filter>[:<config>][#<filter>[:<config>]]...", {});
267 }
268 print_help_item("-A, --audio-codec "
269 "<codec>[:sample_rate=<sr>][:bitrate=<br>] | help",
270 { "audio codec" });
271 if (full) {
272 print_help_item("--audio-delay <delay_ms>", {"amount of time audio should be delayed to video",
273 "(may be also negative to delay video)"});
274 print_help_item("--audio-scale <factor> | <method> | help",
275 {"scales received audio"});
276 print_help_item("--echo-cancellation", {"apply acoustic echo cancellation to audio (experimental)"});
277 print_help_item("-D, --cuda-device <index> | help", {"use specified GPU"});
278 print_help_item("-e, --encryption <passphrase>", {"key material for encryption"});
279 print_help_item("-I, --playback <directory> | help", {"replays recorded audio and video"});
280 print_help_item("-E, --record[=<directory>]", {"record captured audio and video"});
281 print_help_item("-F, --capture-filter <filter> | help",
282 {"capture filter, must precede -t if more device used"});
283 print_help_item("--param <params> | help", {"additional advanced parameters, use help for list"});
284 print_help_item("--pix-fmts", {"list of pixel formats"});
285 print_help_item("--conv-policy [cds]{3} | help", {"pixel format conversion policy"});
286 print_help_item("--video-codecs", {"list of video codecs"});
287 }
288 print_help_item("address", {"destination address"});
289 printf("\n");
290}
#define SRED(x)
Definition color_out.h:85
#define DEFAULT_CONTROL_PORT
#define LOG_LEVEL_MAX
Definition debug.h:69
static void print_help_item(const string &name, const vector< string > &help)
Definition main.cpp:197
#define PORT_BASE
Definition main.cpp:122

References DEFAULT_CONTROL_PORT, LOG_LEVEL_MAX, PORT_BASE, print_help_item(), SBOLD, and SRED.

Here is the call graph for this function:

Variable Documentation

◆ DEFAULT_AUDIO_CODEC

const char* DEFAULT_AUDIO_CODEC = "PCM"
staticconstexpr

Definition at line 125 of file main.cpp.

Referenced by adjust_params().

◆ DEFAULT_VIDEO_COMPRESSION

const char* DEFAULT_VIDEO_COMPRESSION = "none"
staticconstexpr

Definition at line 124 of file main.cpp.

Referenced by adjust_params().