mirror of
https://github.com/outbackdingo/UltraGrid.git
synced 2026-03-20 11:40:08 +00:00
Added import capture module (currently video only)
This commit is contained in:
@@ -83,8 +83,9 @@ OBJS = @OBJS@ \
|
||||
src/video.o \
|
||||
src/video_codec.o \
|
||||
src/video_capture.o \
|
||||
src/video_capture/null.o \
|
||||
src/video_capture/aggregate.o \
|
||||
src/video_capture/import.o \
|
||||
src/video_capture/null.o \
|
||||
src/video_compress.o \
|
||||
src/video_compress/none.o \
|
||||
src/video_decompress.o \
|
||||
|
||||
11
src/main.c
11
src/main.c
@@ -110,6 +110,7 @@
|
||||
#define OPT_CUDA_DEVICE (('C' << 8) | 'D')
|
||||
#define OPT_MCAST_IF (('M' << 8) | 'I')
|
||||
#define OPT_EXPORT (('E' << 8) | 'X')
|
||||
#define OPT_IMPORT (('I' << 8) | 'M')
|
||||
|
||||
#ifdef HAVE_MACOSX
|
||||
#define INITIAL_VIDEO_RECV_BUFFER_SIZE 5944320
|
||||
@@ -229,7 +230,9 @@ static void usage(void)
|
||||
"[-m <mtu>] [-c] [-i] [-6]\n");
|
||||
printf(" [-m <video_mode>] [-p <postprocess>] "
|
||||
"[-f <fec_options>] [-p <port>]\n");
|
||||
printf(" [--mcast-if <iface>] [--export] address(es)\n\n");
|
||||
printf(" [--mcast-if <iface>]\n");
|
||||
printf(" [--export[=<d>]|--import <d>]\n");
|
||||
printf(" address(es)\n\n");
|
||||
printf
|
||||
("\t-d <display_device> \tselect display device, use '-d help'\n");
|
||||
printf("\t \tto get list of supported devices\n");
|
||||
@@ -288,6 +291,7 @@ static void usage(void)
|
||||
printf("\n");
|
||||
printf("\t--export[=<directory>] \texport captured (and compressed) data\n");
|
||||
printf("\n");
|
||||
printf("\t--import <directory> \timport previous session from directory\n");
|
||||
printf("\n");
|
||||
printf("\taddress(es) \tdestination address\n");
|
||||
printf("\n");
|
||||
@@ -1010,6 +1014,7 @@ int main(int argc, char *argv[])
|
||||
{"cuda-device", required_argument, 0, OPT_CUDA_DEVICE},
|
||||
{"mcast-if", required_argument, 0, OPT_MCAST_IF},
|
||||
{"export", optional_argument, 0, OPT_EXPORT},
|
||||
{"import", required_argument, 0, OPT_IMPORT},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
int option_index = 0;
|
||||
@@ -1174,6 +1179,10 @@ int main(int argc, char *argv[])
|
||||
should_export = true;
|
||||
export_opts = optarg;
|
||||
break;
|
||||
case OPT_IMPORT:
|
||||
uv->requested_capture = "import";
|
||||
capture_cfg = optarg;
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return EXIT_FAIL_USAGE;
|
||||
|
||||
@@ -59,6 +59,7 @@
|
||||
#include "video_capture/decklink.h"
|
||||
#include "video_capture/deltacast.h"
|
||||
#include "video_capture/dvs.h"
|
||||
#include "video_capture/import.h"
|
||||
#include "video_capture/linsys.h"
|
||||
#include "video_capture/null.h"
|
||||
#include "video_capture/quicktime.h"
|
||||
@@ -115,6 +116,16 @@ struct vidcap_device_api vidcap_device_table[] = {
|
||||
MK_STATIC(vidcap_aggregate_grab),
|
||||
NULL
|
||||
},
|
||||
{
|
||||
0,
|
||||
NULL,
|
||||
MK_STATIC(vidcap_import_probe),
|
||||
MK_STATIC(vidcap_import_init),
|
||||
MK_STATIC(vidcap_import_finish),
|
||||
MK_STATIC(vidcap_import_done),
|
||||
MK_STATIC(vidcap_import_grab),
|
||||
NULL
|
||||
},
|
||||
#if defined HAVE_SCREEN_CAP || defined BUILD_LIBRARIES
|
||||
{
|
||||
/* The screen capture card */
|
||||
|
||||
421
src/video_capture/import.c
Normal file
421
src/video_capture/import.c
Normal file
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
* FILE: import.c
|
||||
* AUTHORS: Martin Benes <martinbenesh@gmail.com>
|
||||
* Lukas Hejtmanek <xhejtman@ics.muni.cz>
|
||||
* Petr Holub <hopet@ics.muni.cz>
|
||||
* Milos Liska <xliska@fi.muni.cz>
|
||||
* Jiri Matela <matela@ics.muni.cz>
|
||||
* Dalibor Matura <255899@mail.muni.cz>
|
||||
* Ian Wesley-Smith <iwsmith@cct.lsu.edu>
|
||||
*
|
||||
* Copyright (c) 2005-2010 CESNET z.s.p.o.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, is permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
*
|
||||
* This product includes software developed by CESNET z.s.p.o.
|
||||
*
|
||||
* 4. Neither the name of the CESNET nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#include "config_unix.h"
|
||||
#include "config_win32.h"
|
||||
#endif // HAVE_CONFIG_H
|
||||
|
||||
#include "debug.h"
|
||||
#include "host.h"
|
||||
#include "video_codec.h"
|
||||
#include "video_capture.h"
|
||||
|
||||
#include "tv.h"
|
||||
|
||||
#include "video_export.h"
|
||||
#include "video_capture/import.h"
|
||||
//#include "audio/audio.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <glob.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define BUFFER_LEN_MAX 40
|
||||
|
||||
#define VIDCAP_IMPORT_ID 0x76FA7F6D
|
||||
|
||||
struct processed_entry;
|
||||
|
||||
struct processed_entry {
|
||||
char *data;
|
||||
int data_len;
|
||||
struct processed_entry *next;
|
||||
};
|
||||
|
||||
struct vidcap_import_state {
|
||||
struct video_frame *frame;
|
||||
struct tile *tile;
|
||||
char *directory;
|
||||
|
||||
pthread_mutex_t lock;
|
||||
pthread_cond_t reader_cv;
|
||||
volatile bool reader_waiting;
|
||||
pthread_cond_t boss_cv;
|
||||
volatile bool boss_waiting;
|
||||
struct processed_entry * volatile head, * volatile tail;
|
||||
volatile int queue_len;
|
||||
|
||||
volatile bool finish_thread;
|
||||
volatile bool reader_finished;
|
||||
|
||||
pthread_t thread_id;
|
||||
|
||||
struct timeval prev_time;
|
||||
int count;
|
||||
};
|
||||
|
||||
static void * reading_thread(void *args);
|
||||
|
||||
struct vidcap_type *
|
||||
vidcap_import_probe(void)
|
||||
{
|
||||
struct vidcap_type* vt;
|
||||
|
||||
vt = (struct vidcap_type *) malloc(sizeof(struct vidcap_type));
|
||||
if (vt != NULL) {
|
||||
vt->id = VIDCAP_IMPORT_ID;
|
||||
vt->name = "import";
|
||||
vt->description = "Video importer (not to be called directly)";
|
||||
}
|
||||
return vt;
|
||||
}
|
||||
|
||||
void *
|
||||
vidcap_import_init(char *directory, unsigned int flags)
|
||||
{
|
||||
UNUSED(flags);
|
||||
struct vidcap_import_state *s;
|
||||
|
||||
printf("vidcap_import_init\n");
|
||||
|
||||
s = (struct vidcap_import_state *) calloc(1, sizeof(struct vidcap_import_state));
|
||||
s->head = s->tail = NULL;
|
||||
s->queue_len = 0;
|
||||
|
||||
s->boss_waiting = false;
|
||||
s->reader_waiting = false;
|
||||
|
||||
s->finish_thread = false;
|
||||
s->reader_finished = false;
|
||||
|
||||
pthread_mutex_init(&s->lock, NULL);
|
||||
pthread_cond_init(&s->reader_cv, NULL);
|
||||
pthread_cond_init(&s->boss_cv, NULL);
|
||||
|
||||
char *info_filename = malloc(strlen(directory) + sizeof("/video.info") + 1);
|
||||
assert(info_filename != NULL);
|
||||
strcpy(info_filename, directory);
|
||||
strcat(info_filename, "/video.info");
|
||||
|
||||
FILE *info = fopen(info_filename, "r");
|
||||
free(info_filename);
|
||||
if(info == NULL) {
|
||||
perror("[import] Failed to open index file.");
|
||||
goto free_state;
|
||||
}
|
||||
|
||||
s->frame = vf_alloc(1);
|
||||
s->tile = vf_get_tile(s->frame, 0);
|
||||
char line[512];
|
||||
uint32_t items_found = 0;
|
||||
while(!feof(info)) {
|
||||
if(fgets(line, sizeof(line), info) == NULL) {
|
||||
// empty line
|
||||
continue;
|
||||
}
|
||||
if(strncmp(line, "version ", strlen("version ")) == 0) {
|
||||
long int version = strtol(line + strlen("version "), (char **) NULL, 10);
|
||||
if(version == LONG_MIN || version == LONG_MAX) {
|
||||
fprintf(stderr, "[import] cannot read version line.\n");
|
||||
goto close_file;
|
||||
}
|
||||
if(version != VIDEO_EXPORT_SUMMARY_VERSION) {
|
||||
fprintf(stderr, "[import] Invalid version %ld.\n", version);
|
||||
goto close_file;
|
||||
}
|
||||
items_found |= 1<<0;
|
||||
} else if(strncmp(line, "width ", strlen("width ")) == 0) {
|
||||
long int width = strtol(line + strlen("width "), (char **) NULL, 10);
|
||||
if(width == LONG_MIN || width == LONG_MAX) {
|
||||
fprintf(stderr, "[import] cannot read video width.\n");
|
||||
goto close_file;
|
||||
}
|
||||
s->tile->width = width;
|
||||
items_found |= 1<<1;
|
||||
} else if(strncmp(line, "height ", strlen("height ")) == 0) {
|
||||
long int height = strtol(line + strlen("height "), (char **) NULL, 10);
|
||||
if(height == LONG_MIN || height == LONG_MAX) {
|
||||
fprintf(stderr, "[import] cannot read video height.\n");
|
||||
goto close_file;
|
||||
}
|
||||
s->tile->height = height;
|
||||
items_found |= 1<<2;
|
||||
} else if(strncmp(line, "fourcc ", strlen("fourcc ")) == 0) {
|
||||
char *ptr = line + strlen("fourcc ");
|
||||
if(strlen(ptr) != 5) { // including '\n'
|
||||
fprintf(stderr, "[import] cannot read video FourCC tag.\n");
|
||||
goto close_file;
|
||||
}
|
||||
uint32_t fourcc;
|
||||
memcpy((void *) &fourcc, ptr, sizeof(fourcc));
|
||||
s->frame->color_spec = get_codec_from_fcc(fourcc);
|
||||
if(s->frame->color_spec == (codec_t) -1) {
|
||||
fprintf(stderr, "[import] Requested codec not known.\n");
|
||||
goto close_file;
|
||||
}
|
||||
items_found |= 1<<3;
|
||||
} else if(strncmp(line, "fps ", strlen("fps ")) == 0) {
|
||||
char *ptr = line + strlen("fps ");
|
||||
s->frame->fps = strtod(ptr, NULL);
|
||||
if(s->frame->fps == HUGE_VAL || s->frame->fps <= 0) {
|
||||
fprintf(stderr, "[import] Invalid FPS.\n");
|
||||
goto close_file;
|
||||
}
|
||||
items_found |= 1<<4;
|
||||
} else if(strncmp(line, "interlacing ", strlen("interlacing ")) == 0) {
|
||||
char *ptr = line + strlen("interlacing ");
|
||||
s->frame->interlacing = atoi(ptr);
|
||||
if(s->frame->interlacing > 4) {
|
||||
fprintf(stderr, "[import] Invalid interlacing.\n");
|
||||
goto close_file;
|
||||
}
|
||||
items_found |= 1<<5;
|
||||
} else if(strncmp(line, "count ", strlen("count ")) == 0) {
|
||||
char *ptr = line + strlen("count ");
|
||||
s->count = atoi(ptr);
|
||||
items_found |= 1<<6;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(info);
|
||||
|
||||
if(items_found != (1 << 7) - 1) {
|
||||
fprintf(stderr, "[import] Failed while reading config file - some items missing.\n");
|
||||
goto free_frame;
|
||||
}
|
||||
|
||||
if(pthread_create(&s->thread_id, NULL, reading_thread, (void *) s) != 0) {
|
||||
fprintf(stderr, "Unable to create thread.\n");
|
||||
goto free_frame;
|
||||
}
|
||||
|
||||
s->directory = strdup(directory);
|
||||
|
||||
gettimeofday(&s->prev_time, NULL);
|
||||
|
||||
return s;
|
||||
|
||||
close_file:
|
||||
fclose(info);
|
||||
free_frame:
|
||||
vf_free(s->frame);
|
||||
free_state:
|
||||
free(s);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
vidcap_import_finish(void *state)
|
||||
{
|
||||
struct vidcap_import_state *s = (struct vidcap_import_state *) state;
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
{
|
||||
s->finish_thread = true;
|
||||
if(s->reader_waiting)
|
||||
pthread_cond_signal(&s->reader_cv);
|
||||
}
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
pthread_join(s->thread_id, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
vidcap_import_done(void *state)
|
||||
{
|
||||
struct vidcap_import_state *s = (struct vidcap_import_state *) state;
|
||||
assert(s != NULL);
|
||||
|
||||
struct processed_entry *current = s->head;
|
||||
while(current != NULL) {
|
||||
free(current->data);
|
||||
struct processed_entry *tmp = current;
|
||||
current = current->next;
|
||||
free(tmp);
|
||||
}
|
||||
free(s->tile->data);
|
||||
vf_free(s->frame);
|
||||
|
||||
pthread_mutex_destroy(&s->lock);
|
||||
pthread_cond_destroy(&s->reader_cv);
|
||||
pthread_cond_destroy(&s->boss_cv);
|
||||
free(s->directory);
|
||||
free(s);
|
||||
}
|
||||
|
||||
static void * reading_thread(void *args)
|
||||
{
|
||||
struct vidcap_import_state *s = (struct vidcap_import_state *) args;
|
||||
int index = 0;
|
||||
char name[512];
|
||||
|
||||
while(index < s->count && !s->finish_thread) {
|
||||
struct processed_entry *new_entry = NULL;
|
||||
pthread_mutex_lock(&s->lock);
|
||||
{
|
||||
while(s->queue_len >= BUFFER_LEN_MAX - 1 && !s->finish_thread) {
|
||||
s->reader_waiting = true;
|
||||
pthread_cond_wait(&s->reader_cv, &s->lock);
|
||||
s->reader_waiting = false;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
snprintf(name, sizeof(name), "%s/%08d.%s", s->directory, index,
|
||||
get_codec_file_extension(s->frame->color_spec));
|
||||
|
||||
struct stat sb;
|
||||
if (stat(name, &sb)) {
|
||||
perror("stat");
|
||||
goto next;
|
||||
}
|
||||
FILE *file = fopen(name, "rb");
|
||||
if(!file) {
|
||||
perror("fopen");
|
||||
goto next;
|
||||
}
|
||||
new_entry = malloc(sizeof(struct processed_entry));
|
||||
assert(new_entry != NULL);
|
||||
new_entry->data_len = sb.st_size;
|
||||
new_entry->data = malloc(new_entry->data_len);
|
||||
new_entry->next = NULL;
|
||||
assert(new_entry->data != NULL);
|
||||
|
||||
size_t res = fread(new_entry->data, new_entry->data_len, 1, file);
|
||||
if(res != 1) {
|
||||
perror("fread");
|
||||
goto next;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
{
|
||||
if(s->head) {
|
||||
s->tail->next = new_entry;
|
||||
s->tail = new_entry;
|
||||
} else {
|
||||
s->head = s->tail = new_entry;
|
||||
}
|
||||
s->queue_len += 1;
|
||||
|
||||
if(s->boss_waiting)
|
||||
pthread_cond_signal(&s->boss_cv);
|
||||
}
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
next:
|
||||
index++;
|
||||
}
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
{
|
||||
s->reader_finished = true;
|
||||
|
||||
if(s->boss_waiting)
|
||||
pthread_cond_signal(&s->boss_cv);
|
||||
}
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct video_frame *
|
||||
vidcap_import_grab(void *state, struct audio_frame **audio)
|
||||
{
|
||||
struct vidcap_import_state *s = (struct vidcap_import_state *) state;
|
||||
struct timeval cur_time;
|
||||
|
||||
struct processed_entry *current = NULL;
|
||||
|
||||
// free old data
|
||||
free(s->tile->data);
|
||||
s->tile->data = NULL;
|
||||
|
||||
pthread_mutex_lock(&s->lock);
|
||||
{
|
||||
while(s->queue_len == 0 && !s->reader_finished) {
|
||||
s->boss_waiting = true;
|
||||
pthread_cond_wait(&s->boss_cv, &s->lock);
|
||||
s->boss_waiting = false;
|
||||
}
|
||||
|
||||
if(s->queue_len == 0 && s->reader_finished) {
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
current = s->head;
|
||||
s->head = s->head->next;
|
||||
s->queue_len -= 1;
|
||||
|
||||
if(s->reader_waiting)
|
||||
pthread_cond_signal(&s->reader_cv);
|
||||
}
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
s->tile->data_len = current->data_len;
|
||||
s->tile->data = current->data;
|
||||
free(current);
|
||||
|
||||
gettimeofday(&cur_time, NULL);
|
||||
while(tv_diff_usec(cur_time, s->prev_time) < 1000000.0 / s->frame->fps)
|
||||
gettimeofday(&cur_time, NULL);
|
||||
tv_add_usec(&s->prev_time, 1000000.0 / s->frame->fps);
|
||||
|
||||
*audio = NULL;
|
||||
|
||||
return s->frame;
|
||||
}
|
||||
|
||||
52
src/video_capture/import.h
Normal file
52
src/video_capture/import.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* FILE: import.h
|
||||
* AUTHORS: Martin Benes <martinbenesh@gmail.com>
|
||||
* Lukas Hejtmanek <xhejtman@ics.muni.cz>
|
||||
* Petr Holub <hopet@ics.muni.cz>
|
||||
* Milos Liska <xliska@fi.muni.cz>
|
||||
* Jiri Matela <matela@ics.muni.cz>
|
||||
* Dalibor Matura <255899@mail.muni.cz>
|
||||
* Ian Wesley-Smith <iwsmith@cct.lsu.edu>
|
||||
*
|
||||
* Copyright (c) 2005-2010 CESNET z.s.p.o.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, is permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
*
|
||||
* This product includes software developed by CESNET z.s.p.o.
|
||||
*
|
||||
* 4. Neither the name of the CESNET nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
|
||||
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
|
||||
* EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
|
||||
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
struct vidcap_type *vidcap_import_probe(void);
|
||||
void *vidcap_import_init(char *fmt, unsigned int flags);
|
||||
void vidcap_import_finish(void *state);
|
||||
void vidcap_import_done(void *state);
|
||||
struct video_frame *vidcap_import_grab(void *state, struct audio_frame **audio);
|
||||
Reference in New Issue
Block a user