UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
export.c File Reference
#include <dirent.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include "export.h"
#include "audio/export.h"
#include "compat/misc.h"
#include "compat/time.h"
#include "debug.h"
#include "host.h"
#include "messaging.h"
#include "module.h"
#include "utils/color_out.h"
#include "utils/fs.h"
#include "utils/misc.h"
#include "video_export.h"
Include dependency graph for export.c:

Go to the source code of this file.

Classes

struct  exporter
 

Macros

#define HANDLE_ERROR   export_destroy(s); return NULL;
 
#define MOD_NAME   "[export] "
 
#define WANT_MKDIR
 

Functions

static bool create_dir (struct exporter *s)
 
static char * create_implicit_dir (const char *prefix)
 
static bool dir_is_empty (const char *dir)
 
static void disable_export (struct exporter *s)
 
static bool enable_export (struct exporter *s)
 
void export_audio (struct exporter *s, struct audio_frame *frame)
 
void export_destroy (struct exporter *s)
 
struct exporter * export_init (struct module *parent, const char *cfg, bool should_export)
 
void export_video (struct exporter *s, struct video_frame *frame)
 
static void new_msg (struct module *mod)
 
static bool parse_options (struct exporter *s, const char *ccfg, bool *should_export)
 
static void process_messages (struct exporter *s)
 
static void usage ()
 

Detailed Description

Author
Martin Pulec pulec.nosp@m.@ces.nosp@m.net.c.nosp@m.z

Definition in file export.c.

Macro Definition Documentation

◆ HANDLE_ERROR

#define HANDLE_ERROR   export_destroy(s); return NULL;

Definition at line 147 of file export.c.

Referenced by export_init().

◆ MOD_NAME

#define MOD_NAME   "[export] "

Definition at line 62 of file export.c.

Referenced by create_dir(), create_implicit_dir(), export_video(), and parse_options().

◆ WANT_MKDIR

#define WANT_MKDIR

Definition at line 50 of file export.c.

Function Documentation

◆ create_dir()

static bool create_dir ( struct exporter * s)
static

Definition at line 260 of file export.c.

261{
262 if (!s->dir) {
263 s->dir = create_implicit_dir(".");
264 } else {
265 int ret = mkdir(s->dir, S_IRWXU | S_IRWXG | S_IRWXO);
266 if(ret == -1) {
267 if(errno != EEXIST) {
268 perror("[Export] Directory creation failed");
269 return false;
270 }
271 if (dir_is_empty(s->dir)) {
272 log_msg(LOG_LEVEL_NOTICE, "[Export] Warning: directory %s exists but is an empty directory - using for export.\n", s->dir);
273 } else if (s->override) {
274 log_msg(LOG_LEVEL_WARNING, MOD_NAME "Warning: directory %s exists and is not an empty directory but using as requested.\n", s->dir);
275 } else {
276 MSG(ERROR,
277 "Warning: directory %s exists and is not "
278 "an empty directory! Trying to create "
279 "subdir.\n",
280 s->dir);
281 char *prefix = s->dir;
282 s->dir = create_implicit_dir(prefix);
283 free(prefix);
284 }
285 }
286 }
287
288 if (s->dir) {
289 color_printf(TERM_BOLD TERM_FG_YELLOW "Using export directory: %s\n" TERM_RESET, s->dir);
290 return true;
291 } else {
292 return false;
293 }
294}
int color_printf(const char *format,...)
#define TERM_BOLD
Definition color_out.h:48
#define TERM_FG_YELLOW
Definition color_out.h:52
#define TERM_RESET
Definition color_out.h:47
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_NOTICE
information that may be interesting
Definition debug.h:61
#define MSG(l, fmt,...)
Definition debug.h:96
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
static bool dir_is_empty(const char *dir)
Definition export.c:247
#define MOD_NAME
Definition export.c:62
static char * create_implicit_dir(const char *prefix)
Definition export.c:215
bool override
Definition export.c:67
char * dir
Definition export.c:66

References color_printf(), create_implicit_dir(), exporter::dir, dir_is_empty(), LOG_LEVEL_NOTICE, LOG_LEVEL_WARNING, log_msg(), MOD_NAME, MSG, exporter::override, TERM_BOLD, TERM_FG_YELLOW, and TERM_RESET.

Referenced by enable_export().

Here is the call graph for this function:

◆ create_implicit_dir()

static char * create_implicit_dir ( const char * prefix)
static

Tries to create directories export.<date>[-????] inside directory prefix. If succesful, returns its name.

Definition at line 215 of file export.c.

216{
217 enum {
218 MAX_EXPORTS = 9999,
219 };
220 for (int i = 1; i <= MAX_EXPORTS; i++) {
221 char name[MAX_PATH_SIZE];
222 time_t t = time(NULL);
223 struct tm tm_buf = { 0 };
224 localtime_s(&t, &tm_buf);
225 snprintf(name, sizeof name, "%s/", prefix);
226 strftime(name + strlen(name), sizeof name - strlen(name),
227 "export.%Y%m%d", &tm_buf);
228 if (i > 1) {
229 snprintf(name + strlen(name),
230 sizeof name - strlen(name), "-%d", i);
231 }
232 int ret = mkdir(name, S_IRWXU | S_IRWXG | S_IRWXO);
233 if(ret == -1) {
234 if(errno == EEXIST) { // record exists, try next directory
235 continue;
236 }
238 MOD_NAME "Directory creation failed: %s\n",
239 ug_strerror(errno));
240 return false;
241 }
242 return strdup(name);
243 }
244 return NULL;
245}
#define localtime_s
Definition time.h:51
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MAX_PATH_SIZE
Definition fs.h:48
const char * ug_strerror(int errnum)
Definition misc.cpp:203
const char * name
Definition settings.cpp:193

References localtime_s, LOG_LEVEL_ERROR, log_msg(), MAX_PATH_SIZE, MOD_NAME, name, and ug_strerror().

Referenced by create_dir().

Here is the call graph for this function:

◆ dir_is_empty()

static bool dir_is_empty ( const char * dir)
static

Definition at line 247 of file export.c.

247 {
248 DIR *d = opendir(dir);
249 if (!d) {
250 return false;
251 }
252 readdir(d); // skip . and ..
253 readdir(d);
254 bool ret = readdir(d) == NULL;
255 closedir(d);
256
257 return ret;
258}

Referenced by create_dir().

◆ disable_export()

static void disable_export ( struct exporter * s)
static

Definition at line 296 of file export.c.

296 {
299 s->audio_export = NULL;
300 s->video_export = NULL;
301 if (s->dir_auto) {
302 free(s->dir);
303 s->dir = NULL;
304 }
305 s->exporting = false;
306}
void audio_export_destroy(struct audio_export *s)
Definition export.c:182
struct video_export * video_export
Definition export.c:69
struct audio_export * audio_export
Definition export.c:70
bool dir_auto
Definition export.c:68
bool exporting
Definition export.c:71
void video_export_destroy(struct video_export *s)

References exporter::audio_export, audio_export_destroy(), exporter::dir, exporter::dir_auto, exporter::exporting, exporter::video_export, and video_export_destroy().

Referenced by export_destroy(), export_video(), and process_messages().

Here is the call graph for this function:

◆ enable_export()

static bool enable_export ( struct exporter * s)
static

Definition at line 177 of file export.c.

178{
179 if (!create_dir(s)) {
180 goto error;
181 }
182
183 if (!s->novideo) {
185 if (!s->video_export) {
186 goto error;
187 }
188 }
189
190 if (!s->noaudio) {
191 char name[MAX_PATH_SIZE];
192 snprintf(name, sizeof name, "%s/sound.wav", s->dir);
194 if (!s->audio_export) {
195 goto error;
196 }
197 }
198
199 s->exporting = true;
200
201 return true;
202
203error:
205 s->video_export = NULL;
206 return false;
207}
struct audio_export * audio_export_init(const char *filename)
Definition export.c:159
static bool create_dir(struct exporter *s)
Definition export.c:260
bool novideo
Definition export.c:73
bool noaudio
Definition export.c:72
struct video_export * video_export_init(const char *path)

References exporter::audio_export, audio_export_init(), create_dir(), exporter::dir, exporter::exporting, MAX_PATH_SIZE, name, exporter::noaudio, exporter::novideo, exporter::video_export, video_export_destroy(), and video_export_init().

Referenced by export_init(), and process_messages().

Here is the call graph for this function:

◆ export_audio()

void export_audio ( struct exporter * s,
struct audio_frame * frame )

Definition at line 341 of file export.c.

342{
343 if(!s){
344 return;
345 }
346
348
349 pthread_mutex_lock(&s->lock);
350 if (s->exporting) {
352 }
353 pthread_mutex_unlock(&s->lock);
354}
struct video_frame * frame
void audio_export(struct audio_export *s, const struct audio_frame *frame)
Definition export.c:221
static void process_messages(struct exporter *s)
Definition export.c:317
pthread_mutex_t lock
Definition export.c:74

References audio_export(), exporter::audio_export, exporter::exporting, frame, exporter::lock, and process_messages().

Referenced by audio_sender_thread().

Here is the call graph for this function:

◆ export_destroy()

void export_destroy ( struct exporter * s)

Definition at line 308 of file export.c.

308 {
310
311 pthread_mutex_destroy(&s->lock);
312 module_done(&s->mod);
313 free(s->dir);
314 free(s);
315}
static void disable_export(struct exporter *s)
Definition export.c:296
void module_done(struct module *module_data)
Definition module.c:93
struct module mod
Definition export.c:65

References exporter::dir, disable_export(), exporter::lock, exporter::mod, and module_done().

Referenced by display_dump_done(), and main().

Here is the call graph for this function:

◆ export_init()

struct exporter * export_init ( struct module * parent,
const char * cfg,
bool should_export )

Definition at line 149 of file export.c.

150{
151 struct exporter *s = calloc(1, sizeof(struct exporter));
152 pthread_mutex_init(&s->lock, NULL);
153 s->limit = -1;
154
155 if (!parse_options(s, cfg, &should_export)) {
157 }
158 if (s->dir == NULL) {
159 s->dir_auto = true;
160 }
161
162 if (should_export) {
163 if (!enable_export(s)) {
165 }
166 }
167
171 s->mod.priv_data = s;
173
174 return s;
175}
static bool enable_export(struct exporter *s)
Definition export.c:177
static bool parse_options(struct exporter *s, const char *ccfg, bool *should_export)
Definition export.c:106
#define HANDLE_ERROR
Definition export.c:147
static void new_msg(struct module *mod)
Definition export.c:85
void module_init_default(struct module *module_data)
Definition module.c:48
void module_register(struct module *module_data, struct module *parent)
Definition module.c:82
@ MODULE_CLASS_EXPORTER
Definition module.h:96
const char * parent
Definition settings.cpp:198
long long int limit
number of video frames to record, -1 == unlimited (default)
Definition export.c:76
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

References module::cls, exporter::dir, exporter::dir_auto, enable_export(), HANDLE_ERROR, exporter::limit, exporter::lock, exporter::mod, MODULE_CLASS_EXPORTER, module_init_default(), module_register(), module::new_message, new_msg(), parent, parse_options(), and module::priv_data.

Referenced by display_dump_init(), and main().

Here is the call graph for this function:

◆ export_video()

void export_video ( struct exporter * s,
struct video_frame * frame )

Definition at line 356 of file export.c.

357{
358 if(!s){
359 return;
360 }
361
363
364 pthread_mutex_lock(&s->lock);
365 if (s->exporting) {
367 }
368 if (s->limit > 0) {
369 if (--s->limit == 0) {
370 log_msg(LOG_LEVEL_NOTICE, MOD_NAME "Stopping export - limit reached.\n");
372 if (s->exit_on_limit) {
373 exit_uv(0);
374 }
375 }
376 }
377 pthread_mutex_unlock(&s->lock);
378}
void exit_uv(int status)
Definition host.cpp:625
bool exit_on_limit
Definition export.c:77
void video_export(struct video_export *s, struct video_frame *frame)

References disable_export(), exporter::exit_on_limit, exit_uv(), exporter::exporting, frame, exporter::limit, exporter::lock, LOG_LEVEL_NOTICE, log_msg(), MOD_NAME, process_messages(), exporter::video_export, and video_export().

Referenced by display_dump_putf(), and video_rxtx::sender_loop().

Here is the call graph for this function:

◆ new_msg()

static void new_msg ( struct module * mod)
static

Definition at line 85 of file export.c.

85 {
87}

References module::priv_data, and process_messages().

Referenced by export_init(), and process_msg().

Here is the call graph for this function:

◆ parse_options()

static bool parse_options ( struct exporter * s,
const char * ccfg,
bool * should_export )
static

Definition at line 106 of file export.c.

107{
108 if (ccfg == NULL) {
109 return true;
110 }
111 char buf[STR_LEN];
112 snprintf(buf, sizeof buf, "%s", ccfg);
113 char *cfg = buf;
114 char *save_ptr = NULL;
115 char *item = NULL;
116 while ((item = strtok_r(cfg, ":", &save_ptr)) != NULL) {
117 if (strstr(item, "help") == item) {
118 usage();
119 return false;
120 } else if (strstr(item, "noaudio") == item) {
121 s->noaudio = true;
122 } else if (strstr(item, "novideo") == item) {
123 s->novideo = true;
124 } else if (strstr(item, "override") == item) {
125 s->override = true;
126 } else if (strstr(item, "paused") == item) {
127 *should_export = false; // start paused
128 } else if (strstr(item, "limit=") == item) {
129 s->limit = strtoll(item + strlen("limit="), NULL, 0);
130 if (s->limit < 0) {
131 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Wrong limit: %s!\n", item + strlen("limit="));
132 return false;
133 }
134 } else if (strcmp(item, "exit_on_limit") == 0) {
135 s->exit_on_limit = true;
136 } else if (s->dir == NULL && cfg != NULL) {
137 s->dir = strdup(item);
138 } else {
139 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Wrong option: %s!\n", item);
140 return false;
141 }
142 cfg = NULL;
143 }
144 return true;
145}
static void usage()
Definition export.c:89
@ STR_LEN
"standard" string length placeholder
Definition macros.h:134
Definition hd-rum.c:27

References exporter::dir, exporter::exit_on_limit, exporter::limit, LOG_LEVEL_ERROR, log_msg(), MOD_NAME, exporter::noaudio, exporter::novideo, exporter::override, STR_LEN, and usage().

Referenced by export_init().

Here is the call graph for this function:

◆ process_messages()

static void process_messages ( struct exporter * s)
static

Definition at line 317 of file export.c.

317 {
318 struct message *m;
319 while ((m = check_message(&s->mod))) {
320 struct response *r;
321 pthread_mutex_lock(&s->lock);
322 struct msg_universal *msg = (struct msg_universal *) m;
323 if (strcmp(msg->text, "toggle") == 0) {
324 if (s->exporting) {
326 } else {
327 enable_export(s);
328 }
329 log_msg(LOG_LEVEL_NOTICE, "Exporting: %s\n", s->exporting ? "ON" : "OFF");
330 r = new_response(RESPONSE_OK, NULL);
331 } else if (strcmp(msg->text, "status") == 0) {
332 r = new_response(RESPONSE_OK, s->exporting ? "true" : "false");
333 } else {
335 }
336 pthread_mutex_unlock(&s->lock);
337 free_message(m, r);
338 }
339}
void free_message(struct message *msg, struct response *r)
struct response * new_response(int status, const char *text)
struct message * check_message(struct module *mod)
#define RESPONSE_OK
Definition messaging.h:57
#define RESPONSE_NOT_FOUND
Definition messaging.h:61
struct message m
Definition messaging.h:156

References check_message(), disable_export(), enable_export(), exporter::exporting, free_message(), exporter::lock, LOG_LEVEL_NOTICE, log_msg(), msg_universal::m, exporter::mod, new_response(), RESPONSE_NOT_FOUND, and RESPONSE_OK.

Referenced by export_audio(), export_video(), and new_msg().

Here is the call graph for this function:

◆ usage()

static void usage ( void )
static

Definition at line 89 of file export.c.

89 {
90 color_printf("Usage:\n");
92 TRED("--record") "[=<dir>[:limit=<n>[:exit_on_limit]][:noaudio]"
93 "[:novideo][:override][:paused]] ") "\n" "\t" TBOLD(TRED("-E")
94 "[<dir>[:<opts>]]") "\n\t" TBOLD("--record=help | -Ehelp") "\n");
95 color_printf("where\n");
96 color_printf(TERM_BOLD "\tlimit=<n>" TERM_RESET " - write at "
97 " most <n> video frames (with optional exit)\n");
99 " - export even if it would override "
100 "existing files in the given directory\n");
101 color_printf(TERM_BOLD "\tnoaudio | novideo" TERM_RESET " - do not export audio/video\n");
102 color_printf(TERM_BOLD "\tpaused" TERM_RESET " - use specified directory but do not export immediately (can be started with a key or through control socket)\n");
103}
#define TRED(x)
Definition color_out.h:75
#define TBOLD(x)
Definition color_out.h:70

References color_printf(), TBOLD, TERM_BOLD, TERM_RESET, and TRED.

Referenced by parse_options().

Here is the call graph for this function: