UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
Video Capture

Files

file  video_capture.h
 
file  video_capture_params.cpp
 
file  video_capture_params.h
 

Classes

struct  video_capture_info
 

Macros

#define VIDCAP_NO_GENERIC_FPS_INDICATOR   NULL
 
#define VIDEO_CAPTURE_ABI_VERSION   13
 

Functions

int initialize_video_capture (struct module *parent, struct vidcap_params *params, struct vidcap **state)
 Initializes video capture.
 
void list_video_capture_devices (bool)
 
void vidcap_done (struct vidcap *state)
 Destroys vidap state.
 
const char * vidcap_get_fps_print_prefix (struct vidcap *state)
 
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. This period, however, should not be longer than few frame times, a second at maximum.
 

vidcap_retval

Video capture init return values

#define VIDCAP_INIT_OK   0
 initialization successful
 
#define VIDCAP_INIT_NOERR   1
 state not initialized, other action performed (typically help)
 
#define VIDCAP_INIT_FAIL   (-1)
 error ocured
 
#define VIDCAP_INIT_AUDIO_NOT_SUPPORTED   (-2)
 card does not support audio
 

Detailed Description

Workflow for video capture

Normal operation is something like:

v = vidcap_init(id);
...
while (!done) {
...
f = vidcap_grab(v, &a);
...use the video frame "f"
...use the audio frame "a"
}
struct video_frame * frame
struct audio_frame ** audio
static void done(void *state)
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....
void vidcap_done(struct vidcap *state)
Destroys vidap state.

Where the "id" parameter to vidcap_init() is obtained from the probing API. The vidcap_grab() function returns a pointer to the frame, or NULL if no frame is currently available.

The vidcap_grab() may block, but not indefinitely (ideally no longer than 2x frame time) or it should observe global exit status with register_should_exit_callback() and yield control when notified.

API for video capturers

Each module should implement API from video_capture_info. Furthermore, it should register the module with REGISTER_MODULE(). E.g.:

REGISTER_MODULE(dvs, &vidcap_dvs_info, LIBRARY_CLASS_VIDEO_CAPTURE, VIDEO_CAPTURE_ABI_VERSION);
Note
The lifetime of captured frame is determined by the fact whether video_frame_callbacks::dispose is set. If so, the caller calls the callback when the frame is no longer needed. When set to NULL, the lifetime of the frame is limited to a next call to vidcap_grab().

Macro Definition Documentation

◆ VIDCAP_INIT_AUDIO_NOT_SUPPORTED

◆ VIDCAP_INIT_FAIL

◆ VIDCAP_INIT_NOERR

◆ VIDCAP_INIT_OK

◆ VIDCAP_NO_GENERIC_FPS_INDICATOR

#define VIDCAP_NO_GENERIC_FPS_INDICATOR   NULL

Definition at line 127 of file video_capture.h.

◆ VIDEO_CAPTURE_ABI_VERSION

#define VIDEO_CAPTURE_ABI_VERSION   13

Definition at line 109 of file video_capture.h.

Referenced by initialize_video_capture(), and list_video_capture_devices().

Function Documentation

◆ initialize_video_capture()

int initialize_video_capture ( struct module * parent,
struct vidcap_params * param,
struct vidcap ** state )

Initializes video capture.

Parameters
[in]parentparent module
[in]paramdriver parameters
[out]statereturned state
Return values
0if initialization was successful
<0if initialization failed
>0if initialization was successful but no state was returned (eg. only having shown help).

check appropriate cmdline parameters order (–capture-filter then -t) only if one capture device specified, allow setting -F after -t

Definition at line 96 of file video_capture.c.

99{
102 struct vidcap_params *tlast = param;
103 struct vidcap_params *tprev = param;
104 while ((vidcap_params_get_next(tlast))) {
105 tprev = tlast;
106 tlast = vidcap_params_get_next(tlast);
107 }
108 if (vidcap_params_get_driver(tlast) == NULL
109 && vidcap_params_get_capture_filter(tlast) != NULL) {
110 if (tprev != param) { // more than one -t
111 log_msg(LOG_LEVEL_ERROR, "Capture filter (--capture-filter) needs to be "
112 "specified before capture (-t)\n");
113 return -1;
114 }
115 if (vidcap_params_get_capture_filter(tprev) != NULL) { // one -t but -F specified both before and after it
116 log_msg(LOG_LEVEL_ERROR, "Multiple capture filter specification.\n");
117 return -1;
118 }
120 }
121 // similarly for audio connection
122 if (vidcap_params_get_driver(tlast) == NULL
123 && vidcap_params_get_flags(tlast) != 0) {
124 if (tprev != param) { // more than one -t
125 log_msg(LOG_LEVEL_ERROR, "Audio connection (-s) needs to be "
126 "specified before capture (-t)\n");
127 return -1;
128 }
129 if (vidcap_params_get_flags(tprev) != 0) { // one -t but -s specified both before and after it
130 log_msg(LOG_LEVEL_ERROR, "Multiple audio connection specification.\n");
131 return -1;
132 }
134 }
135
136 const struct video_capture_info *vci = (const struct video_capture_info *)
138
139 if (vci == NULL) {
140 log_msg(LOG_LEVEL_ERROR, "WARNING: Selected '%s' capture card "
141 "was not found.\n", vidcap_params_get_driver(param));
142 return -1;
143 }
144
145 struct vidcap *d =
146 (struct vidcap *)malloc(sizeof(struct vidcap));
147 d->magic = VIDCAP_MAGIC;
148 d->funcs = vci;
149
153
155 int ret = vci->init(param, &d->state);
156
157 switch (ret) {
158 case VIDCAP_INIT_OK:
159 break;
161 break;
162 case VIDCAP_INIT_FAIL:
164 "Unable to start video capture device %s\n",
166 break;
169 "Video capture driver does not support selected embedded/analog/AESEBU audio.\n");
170 break;
171 }
172 if (ret != 0) {
173 module_done(&d->mod);
174 free(d);
175 return ret;
176 }
177
179 &d->capture_filter);
180 if (ret < 0) {
181 log_msg(LOG_LEVEL_ERROR, "Unable to initialize capture filter: %s.\n",
183 }
184
185 if (ret != 0) {
186 module_done(&d->mod);
187 free(d);
188 return ret;
189 }
190
191 *state = d;
192 return 0;
193}
void ** state
int capture_filter_init(struct module *parent, const char *cfg, struct capture_filter **state)
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
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
void module_done(struct module *module_data)
Definition module.c:93
@ MODULE_CLASS_CAPTURE
Definition module.h:92
#define VIDCAP_INIT_NOERR
state not initialized, other action performed (typically help)
#define VIDCAP_INIT_OK
initialization successful
#define VIDEO_CAPTURE_ABI_VERSION
#define VIDCAP_INIT_FAIL
error ocured
#define VIDCAP_INIT_AUDIO_NOT_SUPPORTED
card does not support audio
const void * load_library(const char *name, enum library_class cls, int abi_version)
@ LIBRARY_CLASS_VIDEO_CAPTURE
Definition lib_common.h:78
const char * parent
Definition settings.cpp:198
const char * param
Definition settings.cpp:195
enum module_class cls
Definition module.h:115
This struct represents video capture state.
const struct video_capture_info * funcs
void * state
state of the created video capture driver
uint32_t magic
For debugging. Conatins VIDCAP_MAGIC.
struct module mod
struct capture_filter * capture_filter
capture_filter_state
int(* init)(struct vidcap_params *param, void **state)
#define VIDCAP_MAGIC
void vidcap_params_set_parent(struct vidcap_params *params, struct module *mod)
const char * vidcap_params_get_capture_filter(const struct vidcap_params *params)
struct vidcap_params * vidcap_params_get_next(const struct vidcap_params *curr)
const char * vidcap_params_get_driver(const struct vidcap_params *params)
void vidcap_params_set_flags(struct vidcap_params *params, unsigned int flags)
void vidcap_params_set_capture_filter(struct vidcap_params *params, const char *req_capture_filter)
unsigned int vidcap_params_get_flags(const struct vidcap_params *params)

References capture_filter, capture_filter_init(), module::cls, funcs, video_capture_info::init, LIBRARY_CLASS_VIDEO_CAPTURE, load_library(), LOG_LEVEL_ERROR, log_msg(), magic, mod, MODULE_CLASS_CAPTURE, module_done(), module_init_default(), module_register(), param, parent, state, state, VIDCAP_INIT_AUDIO_NOT_SUPPORTED, VIDCAP_INIT_FAIL, VIDCAP_INIT_NOERR, VIDCAP_INIT_OK, VIDCAP_MAGIC, vidcap_params_get_capture_filter(), vidcap_params_get_driver(), vidcap_params_get_flags(), vidcap_params_get_next(), vidcap_params_set_capture_filter(), vidcap_params_set_flags(), vidcap_params_set_parent(), and VIDEO_CAPTURE_ABI_VERSION.

Referenced by grab_worker(), main(), slave_worker(), test_video_capture(), vidcap_aggregate_init(), vidcap_screen_linux_init(), vidcap_switcher_grab(), and vidcap_switcher_init().

Here is the call graph for this function:

◆ list_video_capture_devices()

void list_video_capture_devices ( bool full)

Definition at line 82 of file video_capture.c.

83{
84 printf("Available capture devices:\n");
86}
void list_modules(enum library_class cls, int abi_version, bool full)

References LIBRARY_CLASS_VIDEO_CAPTURE, list_modules(), and VIDEO_CAPTURE_ABI_VERSION.

Referenced by parse_options_internal(), and test_video_capture().

Here is the call graph for this function:

◆ vidcap_done()

void vidcap_done ( struct vidcap * state)

Destroys vidap state.

Parameters
statestate to be destroyed (must have been successfully initialized with vidcap_init())

Definition at line 197 of file video_capture.c.

198{
199 assert(state->magic == VIDCAP_MAGIC);
200 state->funcs->done(state->state);
201 capture_filter_destroy(state->capture_filter);
202 module_done(&state->mod);
203 free(state);
204}
void capture_filter_destroy(struct capture_filter *state)

References capture_filter_destroy(), module_done(), state, and VIDCAP_MAGIC.

Referenced by grab_worker(), main(), slave_worker(), vidcap_aggregate_done(), vidcap_aggregate_init(), vidcap_screen_linux_done(), vidcap_switcher_done(), and vidcap_switcher_grab().

Here is the call graph for this function:

◆ vidcap_get_fps_print_prefix()

const char * vidcap_get_fps_print_prefix ( struct vidcap * state)
Returns
nullptr if display has own FPS indicator
otherwise the prefix (without trailing space, eg. "[GL]") to be used in a generic fps indicator

Definition at line 233 of file video_capture.c.

234{
235 assert(state->magic == VIDCAP_MAGIC);
236 if (state->funcs->generic_fps_indicator_prefix == NULL) {
237 return NULL;
238 }
239 _Thread_local static char buf[SHORT_STR];
240
241 unsigned len = snprintf(buf, sizeof buf, "%s",
242 state->funcs->generic_fps_indicator_prefix);
243 if (len > sizeof buf - 1) { // truncated
244 len = sizeof buf - 1;
245 }
246 if (len > 0 && buf[len - 1] == ' ') { // trim trailing ' '
247 buf[len - 1] = '\0';
248 }
249 return buf;
250}
int void size_t * len
@ SHORT_STR
Definition macros.h:133

References len, SHORT_STR, state, and VIDCAP_MAGIC.

Referenced by capture_thread().

◆ vidcap_grab()

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. This period, however, should not be longer than few frame times, a second at maximum.

The decision of blocking behavior is on the vidcap driver.

The returned video frame is valid only until next vidcap_grab() call.

Parameters
[in]statevidcap state
[out]audiocontains audio frame if driver is grabbing audio
Returns
video frame. If no frame was grabbed (or timeout passed) NULL is returned.

Definition at line 218 of file video_capture.c.

219{
220 assert(state->magic == VIDCAP_MAGIC);
221 struct video_frame *frame;
222 frame = state->funcs->grab(state->state, audio);
223 if (frame != NULL)
224 frame = capture_filter(state->capture_filter, frame);
225 return frame;
226}
struct video_frame * capture_filter(struct capture_filter *state, struct video_frame *frame)
Struct video_frame represents a video frame and contains video description.
Definition types.h:305

References audio, capture_filter(), frame, state, and VIDCAP_MAGIC.

Referenced by capture_thread(), grab_worker(), slave_worker(), vidcap_aggregate_grab(), vidcap_screen_linux_grab(), and vidcap_switcher_grab().

Here is the call graph for this function: