66#define MAX_AUDIO_LEN (1024*1024)
78uniform sampler2D textureSampler;
81float CatMullRom(
float x )
92 return ( ( 12.0 - 9.0 *
B - 6.0 * C ) * ( f * f * f ) +
93 ( -18.0 + 12.0 *
B + 6.0 *C ) * ( f * f ) +
94 ( 6.0 - 2.0 *
B ) ) / 6.0;
96 else if( f >= 1.0 && f < 2.0 )
98 return ( ( -
B - 6.0 * C ) * ( f * f * f )
99 + ( 6.0 *
B + 30.0 * C ) * ( f *f ) +
100 ( - ( 12.0 *
B ) - 48.0 * C ) * f +
101 8.0 *
B + 24.0 * C)/ 6.0;
108float BSpline(
float x )
116 if( f >= 0.0 && f <= 1.0 )
118 return ( 2.0 / 3.0 ) + ( 0.5 ) * ( f* f * f ) - (f*f);
120 else if( f > 1.0 && f <= 2.0 )
122 return 1.0 / 6.0 * pow( ( 2.0 - f ), 3.0 );
126float Triangular(
float f )
141 float texelSizeX = 1.0 / fWidth;
142 float texelSizeY = 1.0 / fHeight;
143 vec4 nSum = vec4( 0.0, 0.0, 0.0, 0.0 );
144 vec4 nDenom = vec4( 0.0, 0.0, 0.0, 0.0 );
145 float a = fract( gl_TexCoord[0].x * fWidth );
146 float b = fract( gl_TexCoord[0].y * fHeight );
147 for(
int m = -1; m <=2; m++ )
149 for(
int n =-1; n<= 2; n++)
151 vec4 vecData = texture2D(textureSampler,
152 gl_TexCoord[0].xy +
vec2(texelSizeX *
float( m ),
153 texelSizeY *
float( n )));
154 float f = INTERP_ALGORITHM_PLACEHOLDER(
float( m ) - a );
155 vec4 vecCooef1 = vec4( f,f,f,f );
156 float f1 = INTERP_ALGORITHM_PLACEHOLDER( -(
float( n ) - b ) );
157 vec4 vecCoeef2 = vec4( f1, f1, f1, f1 );
158 nSum = nSum + ( vecData * vecCoeef2 * vecCooef1 );
159 nDenom = nDenom + (( vecCoeef2 * vecCooef1 ));
162 gl_FragColor = nSum / nDenom;
171 int *width,
int *height);
178 const char *rc_suffix =
"/.ug-swmix.rc";
180 if(!getenv(
"HOME")) {
184 strncpy(buf, getenv(
"HOME"),
sizeof(buf) - 1);
185 strncat(buf, rc_suffix,
sizeof(buf) - 1);
191 printf(
"SW Mix capture\n");
193 printf(
"\t-t swmix:<width>:<height>:<fps>[:<codec>[:interpolation=<i_type>[,<algo>]][:layout=<X>x<Y>]] "
194 "-t <dev1_config> -t <dev2_config>\n");
196 printf(
"\t-t swmix:file[=<file_path>] -t <dev1_config> -t <dev2_config> ...\n");
197 printf(
"\t\twhere <devn_config> is a configuration string of device as usual -\n"
198 "\t\t\tdevice config string or alias from UG config file.\n");
199 printf(
"\t\t<width> width of resulting video\n");
200 printf(
"\t\t<height> height of resulting video\n");
201 printf(
"\t\t<fps> FPS of resulting video, may be eg. 25 or 50i\n");
202 printf(
"\t\t<codec> codec of resulting video, may be one of RGBA, "
203 "RGB or UYVY (optional, default RGBA)\n");
204 printf(
"\t\t<i_type> can be one of 'bilinear' or 'bicubic' (default)\n");
205 printf(
"\t\t\t<algo> bicubic interpolation algorithm: CatMullRom, BSpline (default) or Triangular\n");
207 printf(
"\t\tIn first variant, individual inputs are arranged automatically.\n");
208 printf(
"\t\tWith the second variant, you provide overall layout and layout for \n"
209 "\t\tindividual inputs in SW mix config file (%s).\n",
get_config_name());
247 struct timeval t,
t0;
270 *available_cards = NULL;
300 m = (-1.0 + sqrt(1.0 + 4.0 * s->
devices_cnt)) / 2.0;
306 glGenTextures(2, slaves_data[i].
texture);
307 for(
int j = 0; j < 2; ++j) {
308 glBindTexture(GL_TEXTURE_2D, slaves_data[i].
texture[j]);
309 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
310 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
311 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
312 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
315 glGenFramebuffers(1, &slaves_data[i].
fbo);
321 slaves_data[i].
width = 1.0 / (int) m;
322 slaves_data[i].
height = 1.0 / n;
323 slaves_data[i].
x = (i % (int) m) * slaves_data[i].
width;
324 slaves_data[i].
y = (i / (int) m) * slaves_data[i].
height;
330 fprintf(stderr,
"Cannot find config for device \"%s\"\n",
339 slaves_data[i].
x = (double)
x /
341 slaves_data[i].
y = (double)
y /
353 for(
int i = 0; i <
count; ++i) {
354 glDeleteTextures(2, data[i].
texture);
355 glDeleteFramebuffers(1, &data[i].
fbo);
362 glBindTexture(GL_TEXTURE_2D, s->
texture[0]);
367 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
371 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
375 0, GL_BGR, GL_UNSIGNED_BYTE, NULL);
378 fprintf(stderr,
"SW mix: Unsupported color spec.\n");
383 glBindTexture(GL_TEXTURE_2D, s->
texture[1]);
385 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
387 glBindTexture(GL_TEXTURE_2D, 0);
405 s->
posX[0] = -1.0 + 2.0 *
x;
406 s->
posY[0] = -1.0 + 2.0 *
y;
410 s->
posY[1] = -1.0 + 2.0 *
y;
417 s->
posX[3] = -1.0 + 2.0 *
x;
422#define STRINGIFY(A) #A
424uniform sampler2D image;
425uniform
float imageWidth;
429 yuv.rgba = texture2D(image, gl_TexCoord[0].xy).grba;
430 if(gl_TexCoord[0].
x * imageWidth / 2.0 - floor(gl_TexCoord[0].
x * imageWidth / 2.0) > 0.5)
432 yuv.r = 1.1643 * (yuv.r - 0.0625);
435 gl_FragColor.r = yuv.r + 1.7926 * yuv.b;
436 gl_FragColor.g = yuv.r - 0.2132 * yuv.g - 0.5328 * yuv.b;
437 gl_FragColor.b = yuv.r + 2.1124 * yuv.g;
441uniform sampler2D image;
442uniform
float imageWidth;
453 coor1 = gl_TexCoord[0].xy -
vec2(1.0 / (imageWidth * 2.0), 0.0);
454 coor2 = gl_TexCoord[0].xy +
vec2(1.0 / (imageWidth * 2.0), 0.0);
455 rgba1 = texture2D(image, coor1);
456 rgba2 = texture2D(image, coor2);
457 yuv1.x = 1.0/16.0 + (rgba1.r * 0.2126 + rgba1.g * 0.7152 + rgba1.b * 0.0722) * 0.8588;
458 yuv1.y = 0.5 + (-rgba1.r * 0.1145 - rgba1.g * 0.3854 + rgba1.b * 0.5) * 0.8784;
459 yuv1.z = 0.5 + (rgba1.r * 0.5 - rgba1.g * 0.4541 - rgba1.b * 0.0458) * 0.8784;
460 yuv2.x = 1.0/16.0 + (rgba2.r * 0.2126 + rgba2.g * 0.7152 + rgba2.b * 0.0722) * 0.8588;
461 yuv2.y = 0.5 + (-rgba2.r * 0.1145 - rgba2.g * 0.3854 + rgba2.b * 0.5) * 0.8784;
462 yuv2.z = 0.5 + (rgba2.r * 0.5 - rgba2.g * 0.4541 - rgba2.b * 0.0458) * 0.8784;
463 U = mix(yuv1.y, yuv2.y, 0.5);
464 V = mix(yuv1.z, yuv2.z, 0.5);
465 gl_FragColor = vec4(U,yuv1.x, V, yuv2.x);
470 gl_TexCoord[0] = gl_MultiTexCoord0;
471 gl_Position = ftransform();
500 glBindTexture(GL_TEXTURE_2D, s->
texture[0]);
537 unsigned char *tmp = NULL, *in_gl_buffer = data;
539 tmp = in_gl_buffer = (
unsigned char *) malloc(src_height *
541 for (
int i = 0; i < src_height; ++i) {
548 if(out_codec ==
UYVY) {
549 glBindTexture(GL_TEXTURE_2D, s->
texture[1]);
551 glBindTexture(GL_TEXTURE_2D, s->
texture[0]);
553 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
554 width, src_height, format, GL_UNSIGNED_BYTE, in_gl_buffer);
557 if(out_codec ==
UYVY) {
558 glUseProgram(from_uyvy);
559 glUniform1i(glGetUniformLocation(from_uyvy,
"image"), 0);
560 glUniform1f(glGetUniformLocation(from_uyvy,
"imageWidth"),
563 glBindFramebuffer(GL_FRAMEBUFFER, s->
fbo);
564 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT,
565 GL_TEXTURE_2D, s->
texture[0], 0);
570 glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0);
571 glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0);
572 glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
573 glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0);
582 glUniform1f(glGetUniformLocation(bicubic_program,
"fWidth"),
584 glUniform1f(glGetUniformLocation(bicubic_program,
"fHeight"),
587 glBindTexture(GL_TEXTURE_2D, s->
texture[0]);
590 glTexCoord2f(0.0, 0.0); glVertex2f(s->
posX[0],
592 glTexCoord2f(1.0, 0.0); glVertex2f(s->
posX[1],
594 glTexCoord2f(1.0, 1.0); glVertex2f(s->
posX[2],
596 glTexCoord2f(0.0, 1.0); glVertex2f(s->
posX[3],
605 GLuint from_uyvy, to_uyvy;
607 gettimeofday(&t0, NULL);
610 glEnable(GL_TEXTURE_2D);
613 assert(from_uyvy != 0);
614 assert(to_uyvy != 0);
616 glUseProgram(to_uyvy);
617 glUniform1i(glGetUniformLocation(to_uyvy,
"image"), 0);
618 glUniform1f(glGetUniformLocation(to_uyvy,
"imageWidth"),
625 char *current_buffer = NULL;
628 pthread_mutex_lock(&s->
lock);
630 pthread_mutex_unlock(&s->
lock);
633 pthread_mutex_unlock(&s->
lock);
636 pthread_mutex_lock(&s->
lock);
642 pthread_mutex_unlock(&s->
lock);
670 char *audio_data = NULL;
677 fprintf(stderr,
"[swmix] Locking device #%d as an audio source.\n",
702 glBindFramebuffer(GL_FRAMEBUFFER, s->
fbo);
703 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT,
705 glClearColor(0, 0, 0, 1);
706 glClear(GL_COLOR_BUFFER_BIT);
725 GLenum format = GL_RGBA;
727 glBindFramebuffer(GL_FRAMEBUFFER, s->
fbo_uyvy);
728 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT,
731 glUseProgram(to_uyvy);
733 glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0);
734 glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0);
735 glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
736 glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0);
747 read_buf = current_buffer;
749 read_buf = tmp_buffer;
751 glReadPixels(0, 0, width,
753 format, GL_UNSIGNED_BYTE,
755 glBindFramebuffer(GL_FRAMEBUFFER, 0);
756 glBindTexture(GL_TEXTURE_2D, 0);
762 memcpy(current_buffer + i * linesize, tmp_buffer + i * linesize,
765 field = (field + 1) % 2;
773 gettimeofday(&t, NULL);
778 pthread_mutex_lock(&s->
lock);
785 current_buffer = NULL;
787 pthread_mutex_unlock(&s->
lock);
795 glDeleteProgram(from_uyvy);
796 glDeleteProgram(to_uyvy);
797 glDisable(GL_TEXTURE_2D);
811 fprintf(stderr,
"[swmix] Unable to initialize device %s (%s:%s).\n",
838 pthread_mutex_lock(&s->
lock);
847 fprintf(stderr,
"[SW Mix] Audio buffer overflow!\n");
856 pthread_mutex_unlock(&s->
lock);
866 int *width,
int *height)
872 if(!ret)
return false;
875 int x_, y_, width_, height_;
876 if(sscanf(line,
"%128s %d %d %d %d",
name, &x_, &y_, &width_, &height_) != 5)
878 if(strcasecmp(
name, slave_name) == 0) {
890 char *device_name_config)
896 if(!ret)
return false;
899 char dev_config[129];
900 int x_, y_, width_, height_;
901 if(sscanf(line,
"%128s %d %d %d %d %128s",
name, &x_, &y_, &width_, &height_, dev_config) != 6)
903 if(strcasecmp(
name, slave_name) == 0) {
904 strcpy(device_name_config, dev_config);
915 unsigned int *height,
double *
fps,
918 char *save_ptr = NULL;
926 parse_string = (
char *) alloca(strlen(
fmt) + 1);
927 strcpy(parse_string,
fmt);
930 while((
item = strtok_r(tmp,
":", &save_ptr))) {
933 if(strncasecmp(
item,
"file", strlen(
"file")) == 0) {
934 char *eq = strchr(
item,
'=');
936 *filepath = strdup(eq + 1);
943 *height = atoi(
item);
949 if(tolower(*endptr) ==
'i') {
958 fprintf(stderr,
"Unrecognized color spec string: %s\n",
item);
963 if(strncasecmp(
item,
"interpolation=", strlen(
"interpolation=")) == 0) {
964 if(strcasecmp(
item + strlen(
"interpolation="),
"bilinear") == 0) {
968 if(strchr(
item,
',')) {
969 *bicubic_algo = strdup(strchr(
item,
',') + 1);
972 }
else if (strncasecmp(
item,
"layout=", strlen(
"layout=")) == 0) {
973 const char *l =
item + strlen(
"layout=");
974 if (!strchr(l,
'x')) {
979 *grid_y = atoi(strchr(l,
'x') + 1);
980 if (*grid_x <= 0 || *grid_y <= 0) {
1004 char *config_path = NULL;
1021 fprintf(stderr,
"Params not set and config file %s not found.\n",
1030 fprintf(stderr,
"Input file is empty!\n");
1033 for(
int i = strlen(line); i > 0 && isspace(line[i - 1]); i--) line[i - 1] =
'\0';
1037 fprintf(stderr,
"Malformed input file! First line should contain config "
1038 "string same as for cmdline use (between first ':' and '#' "
1049 fprintf(stderr,
"Unsupported output codec.\n");
1073 pthread_mutex_init(&(s->
slaves[i].
lock), NULL);
1090 printf(
"vidcap_swmix_init\n");
1100 printf(
"Unable to allocate swmix capture state\n");
1111 gettimeofday(&s->
t0, NULL);
1120 pthread_mutex_init(&s->
lock, NULL);
1137 fprintf(stderr,
"[swmix] Unable to initialize OpenGL context.\n");
1142 fprintf(stderr,
"[swmix] Unsufficient OpenGL version to run SWMix.\n");
1151 while((algo_pos = strstr(bicubic,
"INTERP_ALGORITHM_PLACEHOLDER"))) {
1152 memset(algo_pos,
' ', strlen(
"INTERP_ALGORITHM_PLACEHOLDER"));
1155 printf(
"Using bicubic algorithm: %s\n", s->
bicubic_algo);
1175 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1176 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1177 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1178 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1180 0, format, GL_UNSIGNED_BYTE, NULL);
1184 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1185 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1186 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1187 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1189 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
1191 glGenFramebuffers(1, &s->
fbo);
1192 glGenFramebuffers(1, &s->
fbo_uyvy);
1198 for(
int i = 0; i < 3; ++i) {
1238 pthread_mutex_lock(&s->
lock);
1250 pthread_mutex_unlock(&s->
lock);
1286 glDeleteFramebuffers(1, &s->
fbo);
1289 glDeleteFramebuffers(1, &s->
fbo_uyvy);
1295 pthread_mutex_destroy(&s->
lock);
1317 pthread_mutex_lock(&s->
lock);
1331 pthread_mutex_unlock(&s->
lock);
1334 gettimeofday(&s->t, NULL);
1337 float fps = s->
frames / seconds;
struct video_frame * frame
struct audio_frame ** audio
int void(** deleter)(void *))
void vf_free(struct video_frame *buf)
Frees video_frame structure.
struct video_desc video_desc_from_frame(const struct video_frame *frame)
Returns struct video_desc from video frame.
int vc_get_linesize(unsigned int width, codec_t codec)
struct video_frame * vf_alloc_desc(struct video_desc desc)
Allocates video frame accordig given desc.
const char * get_codec_name(codec_t codec)
codec_t get_codec_from_name(const char *name)
This file contains definition of some common audio types.
void log_msg(int level, const char *format,...)
#define LOG_LEVEL_INFO
normal reporting
#define LOG_LEVEL_ERROR
general errors
bool init_gl_context(struct gl_context *context, int which)
initializes specified OpenGL context
void destroy_gl_context(struct gl_context *context)
void gl_context_make_current(struct gl_context *context)
GLuint glsl_compile_link(const char *vprogram, const char *fprogram)
#define GL_CONTEXT_LEGACY
#define VIDCAP_INIT_NOERR
state not initialized, other action performed (typically help)
#define VIDCAP_INIT_OK
initialization successful
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....
#define VIDCAP_NO_GENERIC_FPS_INDICATOR
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.
#define VIDEO_CAPTURE_ABI_VERSION
#define VIDCAP_INIT_FAIL
error ocured
static struct @19 params[100]
@ LIBRARY_CLASS_VIDEO_CAPTURE
#define REGISTER_MODULE(name, info, lclass, abi)
Registers module to global modules' registry.
void simple_linked_list_append(struct simple_linked_list *l, void *data)
int simple_linked_list_size(struct simple_linked_list *l)
struct simple_linked_list * simple_linked_list_init(void)
void simple_linked_list_destroy(struct simple_linked_list *l)
void * simple_linked_list_pop(struct simple_linked_list *l)
decoder_t get_best_decoder_from(codec_t in, const codec_t *out_candidates, codec_t *out)
decoder_func_t * decoder_t
struct __attribute__((packed))
struct used to comunicate with audio capture/playback device
struct video_desc saved_desc
struct video_frame * current_frame
struct audio_frame audio_frame
struct video_frame * done_frame
struct vidcap_params * device_params
struct video_frame * captured_frame
char * data
Raw tile data. Pointer must be at least 4B aligned.
unsigned int data_len
length of the data
int completed_audio_buffer_len
pthread_t master_thread_id
pthread_cond_t frame_ready_cv
struct gl_context gl_context
char * completed_audio_buffer
int audio_device_index
index of video device from which to take audio
interpolation_t interpolation
struct slave_data * slaves_data
struct simple_linked_list * free_buffer_queue
struct state_slave * slaves
char * network_audio_buffer
pthread_cond_t frame_sent_cv
struct video_frame * frame
pthread_cond_t free_buffer_queue_not_empty_cv
This struct represents video capture state.
enum interlacing_t interlacing
unsigned int width
width of every tile (!)
unsigned int height
height of every tile (!)
void(* dispose)(struct video_frame *)
Struct video_frame represents a video frame and contains video description.
enum interlacing_t interlacing
struct tile tiles[FLEXIBLE_ARRAY_MEMBER]
struct video_frame_callbacks callbacks
static bool get_slave_param_from_file(FILE *config, const char *slave_name, int *x, int *y, int *width, int *height)
static void vidcap_swmix_probe(struct device_info **available_cards, int *count, void(**deleter)(void *))
static void reconfigure_slave_rendering(struct slave_data *s, struct video_desc desc)
static void check_for_slave_format_change(struct slave_data *s)
static void load_texture(struct slave_data *s, GLuint from_uyvy)
static const char * bicubic_template
static void * slave_worker(void *arg)
static struct slave_data * init_slave_data(struct vidcap_swmix_state *s, FILE *config)
static const char * fprogram_to_uyvy
static void destroy_slave_data(struct slave_data *data, int count)
static void vidcap_swmix_done(void *state)
static const char * vprogram
static const struct video_capture_info vidcap_swmix_info
static const char * fprogram_from_uyvy
static bool get_device_config_from_file(FILE *config_file, char *slave_name, char *device_name_config) __attribute__((unused))
static void render_slave(struct slave_data *s, interpolation_t interpolation, GLuint bicubic_program)
static void * master_worker(void *arg)
static bool parse(struct vidcap_swmix_state *s, struct video_desc *desc, char *fmt, FILE **config_file, interpolation_t *interpolation, const struct vidcap_params *params)
static char * get_config_name(void)
static int vidcap_swmix_init(struct vidcap_params *params, void **state)
static void show_help(void)
static int parse_config_string(const char *fmt, unsigned int *width, unsigned int *height, double *fps, codec_t *color_spec, interpolation_t *interpolation, char **bicubic_algo, enum interlacing_t *interl, int *grid_x, int *grid_y, char **filepath)
static struct video_frame * vidcap_swmix_grab(void *state, struct audio_frame **audio)
double tv_diff(struct timeval curr_time, struct timeval prev_time)
@ PROGRESSIVE
progressive frame
@ INTERLACED_MERGED
Columngs of both fields are interlaced together.
@ RGB
RGB 8-bit (packed into 24-bit word)
@ UYVY
YCbCr 422 8-bit - Cb Y0 Cr Y1.
@ VIDEO_CODEC_NONE
dummy color spec
@ RGBA
RGBA 8-bit, big-endian.
This is an umbrella header for video functions.
struct vidcap_params * vidcap_params_get_next(const struct vidcap_params *curr)
void vidcap_params_free_struct(struct vidcap_params *buf)
struct vidcap_params * vidcap_params_copy(const struct vidcap_params *params)
const char * vidcap_params_get_name(const struct vidcap_params *params)
const char * vidcap_params_get_driver(const struct vidcap_params *params)
const char * vidcap_params_get_fmt(const struct vidcap_params *params)
void vc_deinterlace(unsigned char *src, long src_linesize, int lines)
Deinterlaces framebuffer.
bool codec_is_in_set(codec_t codec, const codec_t *set)
struct video_frame * vf_get_copy(struct video_frame *original_frame)
Makes deep copy of the video frame.
bool video_desc_eq(struct video_desc a, struct video_desc b)
Compares two video descriptions.
#define VIDEO_FRAME_DISPOSE(frame)