Added control to capture filters

This commit is contained in:
Martin Pulec
2013-08-14 14:58:59 +02:00
parent 569c8b7dd3
commit c3ead7852f
15 changed files with 245 additions and 77 deletions

View File

@@ -53,6 +53,7 @@
#endif /* HAVE_CONFIG_H */
#include "capture_filter.h"
#include "module.h"
#include "utils/list.h"
#include "video.h"
@@ -65,6 +66,7 @@ static struct capture_filter_info *capture_filters[] = {
};
struct capture_filter {
struct module mod;
struct simple_linked_list *filters;
};
@@ -73,7 +75,41 @@ struct capture_filter_instance {
void *state;
};
int capture_filter_init(const char *cfg, struct capture_filter **state)
static bool create_filter(struct capture_filter *s, char *cfg)
{
unsigned int i;
char *options = NULL;
char *filter_name = cfg;
if(strchr(filter_name, ':')) {
options = strchr(filter_name, ':') + 1;
*strchr(filter_name, ':') = '\0';
}
for(i = 0; i < sizeof(capture_filters) / sizeof(struct capture_filter_info *); ++i) {
if(strcasecmp(capture_filters[i]->name, filter_name) == 0) {
struct capture_filter_instance *instance =
malloc(sizeof(struct capture_filter_instance));
instance->index = i;
int ret = capture_filters[i]->init(&s->mod, options, &instance->state);
if(ret < 0) {
fprintf(stderr, "Unable to initialize capture filter: %s\n",
filter_name);
}
if(ret != 0) {
return ret;
}
simple_linked_list_append(s->filters, instance);
break;
}
}
if(i == sizeof(capture_filters) / sizeof(struct capture_filter_info *)) {
fprintf(stderr, "Unable to find capture filter: %s\n",
filter_name);
return false;
}
return true;
}
int capture_filter_init(struct module *parent, const char *cfg, struct capture_filter **state)
{
struct capture_filter *s = calloc(1, sizeof(struct capture_filter));
char *item, *save_ptr;
@@ -83,6 +119,10 @@ int capture_filter_init(const char *cfg, struct capture_filter **state)
s->filters = simple_linked_list_init();
module_init_default(&s->mod);
s->mod.cls = MODULE_CLASS_FILTER;
module_register(&s->mod, parent);
if(cfg) {
if(strcasecmp(cfg, "help") == 0) {
printf("Available capture filters:\n");
@@ -95,36 +135,10 @@ int capture_filter_init(const char *cfg, struct capture_filter **state)
filter_list_str = tmp = strdup(cfg);
while((item = strtok_r(filter_list_str, ",", &save_ptr))) {
unsigned int i;
char filter_name[128];
char *options = NULL;
strncpy(filter_name, item, sizeof(filter_name));
if(strchr(filter_name, ':')) {
options = strchr(filter_name, ':') + 1;
*strchr(filter_name, ':') = '\0';
}
for(i = 0; i < sizeof(capture_filters) / sizeof(struct capture_filter_info *); ++i) {
if(strcasecmp(capture_filters[i]->name, filter_name) == 0) {
struct capture_filter_instance *instance =
malloc(sizeof(struct capture_filter_instance));
instance->index = i;
int ret = capture_filters[i]->init(options, &instance->state);
if(ret < 0) {
fprintf(stderr, "Unable to initialize capture filter: %s\n",
filter_name);
}
if(ret != 0) {
return ret;
}
simple_linked_list_append(s->filters, instance);
break;
}
}
if(i == sizeof(capture_filters) / sizeof(struct capture_filter_info *)) {
fprintf(stderr, "Unable to find capture filter: %s\n",
filter_name);
if (!create_filter(s, filter_name))
return -1;
}
filter_list_str = NULL;
}
}
@@ -148,12 +162,46 @@ void capture_filter_destroy(struct capture_filter *state)
simple_linked_list_destroy(s->filters);
module_done(&s->mod);
free(state);
}
static void process_message(struct capture_filter *s, struct msg_universal *msg)
{
if (strncmp("delete ", msg->text, strlen("delete ")) == 0) {
int index = atoi(msg->text + strlen("delete "));
struct capture_filter_instance *inst =
simple_linked_list_remove_index(s->filters, index);
if (!inst) {
fprintf(stderr, "Unable to remove capture filter index %d.\n",
index);
} else {
printf("Capture filter #%d removed successfully.\n", index);
}
capture_filters[inst->index]->done(inst->state);
} else {
char *fmt = strdup(msg->text);
if (!create_filter(s, fmt)) {
fprintf(stderr, "Cannot create capture filter: %s.\n",
msg->text);
} else {
printf("Capture filter \"%s\" created successfully.\n",
msg->text);
}
free(fmt);
}
}
struct video_frame *capture_filter(struct capture_filter *state, struct video_frame *frame) {
struct capture_filter *s = state;
struct message *msg;
while ((msg = check_message(&s->mod))) {
process_message(s, (struct msg_universal *) msg);
free_message(msg);
}
for(void *it = simple_linked_list_it_init(s->filters);
it != NULL;
) {

View File

@@ -53,20 +53,23 @@
extern "C" {
#endif
struct module;
struct capture_filter_info {
const char *name;
int (*init)(const char *cfg, void **state);
int (*init)(struct module *parent, const char *cfg, void **state);
void (*done)(void *state);
struct video_frame *(*filter)(void *state, struct video_frame *);
};
struct capture_filter;
struct module;
struct video_frame;
/**
* @see display_init
*/
int capture_filter_init(const char *cfg, struct capture_filter **state);
int capture_filter_init(struct module *parent, const char *cfg, struct capture_filter **state);
void capture_filter_destroy(struct capture_filter *state);
struct video_frame *capture_filter(struct capture_filter *state, struct video_frame *frame);
@@ -75,3 +78,4 @@ struct video_frame *capture_filter(struct capture_filter *state, struct video_fr
#endif
#endif /* CAPTURE_FILTER_H_ */

View File

@@ -53,69 +53,88 @@
#endif /* HAVE_CONFIG_H */
#include "capture_filter.h"
#include "messaging.h"
#include "module.h"
#include "video.h"
#include "video_codec.h"
static int init(const char *cfg, void **state);
static int init(struct module *parent, const char *cfg, void **state);
static void done(void *state);
static struct video_frame *filter(void *state, struct video_frame *in);
struct state_blank {
struct module mod;
int x,y, width, height;
bool outline;
};
static int init(const char *cfg, void **state)
static bool parse(struct state_blank *s, char *cfg)
{
int vals[4];
unsigned int counter = 0;
char *cfg_mutable = NULL, *tmp = NULL;
char *item, *save_ptr;
bool outline = false;
if(cfg) {
if(strcasecmp(cfg, "help") == 0) {
printf("Blanks specified rectangular area:\n\n");
printf("blank usage:\n");
printf("\tblank:x:y:widht:height[:outline]\n");
printf("\t(all values in pixels)\n");
return 1;
}
cfg_mutable = tmp = strdup(cfg);
while ((item = strtok_r(cfg_mutable, ":", &save_ptr))) {
vals[counter] = atoi(item);
char *item, *save_ptr;
while ((item = strtok_r(cfg, ":", &save_ptr))) {
vals[counter] = atoi(item);
cfg_mutable = NULL;
counter += 1;
if (counter == sizeof(vals) / sizeof(int))
break;
}
while ((item = strtok_r(cfg_mutable, ":", &save_ptr))) {
if (strcmp(item, "outline") == 0) {
outline = true;
} else {
fprintf(stderr, "[Blank] Unknown config value: %s\n",
item);
return -1;
}
cfg = NULL;
counter += 1;
if (counter == sizeof(vals) / sizeof(int))
break;
}
while ((item = strtok_r(cfg, ":", &save_ptr))) {
if (strcmp(item, "outline") == 0) {
outline = true;
} else {
fprintf(stderr, "[Blank] Unknown config value: %s\n",
item);
return false;
}
}
if(counter != sizeof(vals) / sizeof(int)) {
fprintf(stderr, "[Blank] Few config values.\n");
return -1;
return false;
}
struct state_blank *s = calloc(1, sizeof(struct state_blank));
assert(s);
s->x = vals[0];
s->y = vals[1];
s->width = vals[2];
s->height = vals[3];
s->outline = outline;
free(tmp);
return true;
}
static int init(struct module *parent, const char *cfg, void **state)
{
if (cfg && strcasecmp(cfg, "help") == 0) {
printf("Blanks specified rectangular area:\n\n");
printf("blank usage:\n");
printf("\tblank:x:y:widht:height[:outline]\n");
printf("\t(all values in pixels)\n");
return 1;
}
struct state_blank *s = calloc(1, sizeof(struct state_blank));
assert(s);
if (cfg) {
char *tmp = strdup(cfg);
bool ret = parse(s, tmp);
free(tmp);
if (!ret) {
free(s);
return -1;
}
}
module_init_default(&s->mod);
s->mod.cls = MODULE_CLASS_DATA;
module_register(&s->mod, parent);
*state = s;
return 0;
@@ -123,9 +142,16 @@ static int init(const char *cfg, void **state)
static void done(void *state)
{
struct state_blank *s = state;
module_done(&s->mod);
free(state);
}
static void process_message(struct state_blank *s, struct msg_universal *msg)
{
parse(s, msg->text);
}
/**
* @note v210 etc. will be green
*/
@@ -134,6 +160,12 @@ static struct video_frame *filter(void *state, struct video_frame *in)
struct state_blank *s = state;
codec_t codec = in->color_spec;
struct message *msg;
while ((msg = check_message(&s->mod))) {
process_message(s, (struct msg_universal *) msg);
free_message(msg);
}
for(int y = s->y; y < s->y + s->height; ++y) {
if(y >= (int) in->tiles[0].height) {
break;

View File

@@ -54,12 +54,16 @@
#include "capture_filter.h"
#include "debug.h"
#include "video.h"
#include "video_codec.h"
#define MAX_TILES 16
static int init(const char *cfg, void **state);
struct module;
static int init(struct module *parent, const char *cfg, void **state);
static void done(void *state);
static struct video_frame *filter(void *state, struct video_frame *in);
@@ -77,8 +81,10 @@ static void usage() {
printf("Example: every:2 - every second frame will be dropped\n");
}
static int init(const char *cfg, void **state)
static int init(struct module *parent, const char *cfg, void **state)
{
UNUSED(parent);
int n;
int denom = 1;;
if(cfg) {

View File

@@ -261,9 +261,11 @@ static int process_msg(struct control_state *s, fd_t client_fd, char *message)
{
int ret = 0;
struct response *resp = NULL;
char path[1024] = { '\0' };
char path[1024];
char buf[1024];
memset(path, 0, sizeof(path));
if(prefix_matches(message, "port ")) {
message = suffix(message, "port ");
snprintf(path, 1024, "%s[%d]", module_class_name(MODULE_CLASS_PORT), atoi(message));
@@ -358,9 +360,18 @@ static int process_msg(struct control_state *s, fd_t client_fd, char *message)
} else if(strcasecmp(message, "bye") == 0) {
ret = CONTROL_CLOSE_HANDLE;
resp = new_response(RESPONSE_OK, NULL);
} else {
snprintf(buf, sizeof(buf), "(unrecognized control sequence: %s)", message);
resp = new_response(RESPONSE_BAD_REQUEST, strdup(buf));
} else { // assume message in format "path message"
struct msg_universal *msg = (struct msg_universal *)
new_message(sizeof(struct msg_universal));
if (strchr(message, ' ')) {
memcpy(path, message, strchr(message, ' ') - message);
strncpy(msg->text, strchr(message, ' ') + 1, sizeof(path) - 1);
} else {
strncpy(path, message, sizeof(path) - 1); // empty message ??
}
resp = send_message(s->root_module, path, (struct message *) msg);
}
if(!resp) {

View File

@@ -43,14 +43,16 @@ extern struct vidcap_type *(*vidcap_get_device_details_extrn)(int i);
extern void (*display_free_devices_extrn)(void);
extern vidcap_id_t (*vidcap_get_null_device_id_extrn)();
extern display_id_t (*display_get_null_device_id_extrn)();
extern int (*vidcap_init_extrn)(vidcap_id_t id, const struct vidcap_params *, struct vidcap **);
extern int (*vidcap_init_extrn)(struct module *parent, vidcap_id_t id,
const struct vidcap_params *, struct vidcap **);
extern int (*display_init_extrn)(display_id_t id, char *fmt, unsigned int flags, struct display **);
extern int (*vidcap_get_device_count_extrn)(void);
extern int (*display_get_device_count_extrn)(void);
extern int (*vidcap_init_devices_extrn)(void);
extern int (*display_init_devices_extrn)(void);
int initialize_video_capture(const char *requested_capture,
int initialize_video_capture(struct module *parent,
const char *requested_capture,
const struct vidcap_params *params,
struct vidcap **state)
{
@@ -82,7 +84,7 @@ int initialize_video_capture(const char *requested_capture,
pthread_mutex_unlock(vidcap_lock);
rm_release_shared_lock("VIDCAP_LOCK");
return vidcap_init_extrn(id, params, state);
return vidcap_init_extrn(parent, id, params, state);
}
int initialize_video_display(const char *requested_display,

View File

@@ -94,10 +94,11 @@ extern bool verbose;
// for aggregate.c
struct vidcap;
struct display;
struct module;
int initialize_video_display(const char *requested_display,
char *fmt, unsigned int flags,
struct display **);
int initialize_video_capture(const char *requested_capture,
int initialize_video_capture(struct module *parent, const char *requested_capture,
const struct vidcap_params *params,
struct vidcap **);

View File

@@ -1342,7 +1342,8 @@ int main(int argc, char *argv[])
printf("Display initialized-%s\n", uv->requested_display);
ret = initialize_video_capture(vidcap_params[0].driver, &vidcap_params[0], &uv->capture_device);
ret = initialize_video_capture(&root_mod, vidcap_params[0].driver,
&vidcap_params[0], &uv->capture_device);
if (ret < 0) {
printf("Unable to open capture device: %s\n",
vidcap_params[0].driver);

View File

@@ -91,6 +91,11 @@ struct msg_stats {
int value;
};
struct msg_universal {
struct message m;
char text[8192];
};
struct response *new_response(int status, char *optional_message);
typedef struct response *(*msg_callback_t)(struct module *mod, struct message *msg);

View File

@@ -129,6 +129,8 @@ const char *module_class_name_pairs[] = {
[MODULE_CLASS_TX] = "transmit",
[MODULE_CLASS_AUDIO] = "audio",
[MODULE_CLASS_CONTROL] = "control",
[MODULE_CLASS_CAPTURE] = "capture",
[MODULE_CLASS_FILTER] = "filter",
};
const char *module_class_name(enum module_class cls)

View File

@@ -72,6 +72,8 @@ enum module_class {
MODULE_CLASS_TX,
MODULE_CLASS_AUDIO,
MODULE_CLASS_CONTROL,
MODULE_CLASS_CAPTURE,
MODULE_CLASS_FILTER,
};
struct module;

View File

@@ -88,16 +88,21 @@ void *simple_linked_list_it_next(void **it)
int simple_linked_list_remove(struct simple_linked_list *l, void *item)
{
struct node **child_ptr = &l->head;
struct node *parent = NULL;
bool found = false;
while(*child_ptr) {
if((*child_ptr)->val == item) {
struct node *tmp = *child_ptr;
*child_ptr = (*child_ptr)->next;
if (l->tail == *child_ptr) {
l->tail = parent;
}
free(tmp);
found = true;
break;
}
parent = *child_ptr;
child_ptr = &(*child_ptr)->next;
}
@@ -109,3 +114,32 @@ int simple_linked_list_remove(struct simple_linked_list *l, void *item)
}
}
void *simple_linked_list_remove_index(struct simple_linked_list *l, int index)
{
struct node **child_ptr = &l->head;
struct node *parent = NULL;
for (int i = 0; i < index; ++i) {
if (*child_ptr) {
parent = *child_ptr;
child_ptr = &(*child_ptr)->next;
} else {
return NULL;
}
}
if (!*child_ptr)
return NULL;
struct node *tmp = *child_ptr;
void *ret = (*child_ptr)->val;
*child_ptr = (*child_ptr)->next;
if (l->tail == *child_ptr) {
l->tail = parent;
}
free(tmp);
l->size -= 1;
return ret;
}

View File

@@ -29,6 +29,12 @@ void *simple_linked_list_it_next(void **it);
*/
int simple_linked_list_remove(struct simple_linked_list *, void *);
/**
* @retval pointer pointer to removed value
* @retval NULL if not found
*/
void *simple_linked_list_remove_index(struct simple_linked_list *, int index);
#ifdef __cplusplus
}
#endif

View File

@@ -60,6 +60,7 @@
#include "capture_filter.h"
#include "debug.h"
#include "lib_common.h"
#include "module.h"
#include "video.h"
#include "video_capture.h"
#include "video_capture/DirectShowGrabber.h"
@@ -89,7 +90,7 @@ void (*vidcap_free_devices_extrn)() = vidcap_free_devices;
void (*vidcap_done_extrn)(struct vidcap *) = vidcap_done;
vidcap_id_t (*vidcap_get_null_device_id_extrn)(void) = vidcap_get_null_device_id;
struct vidcap_type *(*vidcap_get_device_details_extrn)(int index) = vidcap_get_device_details;
int (*vidcap_init_extrn)(vidcap_id_t id, const struct vidcap_params *, struct vidcap **) = vidcap_init;
int (*vidcap_init_extrn)(struct module *mod, vidcap_id_t id, const struct vidcap_params *, struct vidcap **) = vidcap_init;
struct video_frame *(*vidcap_grab_extrn)(struct vidcap *state, struct audio_frame **audio) = vidcap_grab;
int (*vidcap_get_device_count_extrn)(void) = vidcap_get_device_count;
int (*vidcap_init_devices_extrn)(void) = vidcap_init_devices;
@@ -102,6 +103,7 @@ int vidcap_init_noerr;
/// @brief This struct represents video capture state.
struct vidcap {
struct module mod;
void *state; ///< state of the created video capture driver
int index; ///< index to @ref vidcap_device_table
uint32_t magic; ///< For debugging. Conatins @ref VIDCAP_MAGIC
@@ -445,7 +447,8 @@ vidcap_id_t vidcap_get_null_device_id(void)
* @retval <0 if initialization failed
* @retval >0 if initialization was successful but no state was returned (eg. only having shown help).
*/
int vidcap_init(vidcap_id_t id, const struct vidcap_params *param, struct vidcap **state)
int vidcap_init(struct module *parent, vidcap_id_t id, const struct vidcap_params *param,
struct vidcap **state)
{
unsigned int i;
@@ -467,14 +470,22 @@ int vidcap_init(vidcap_id_t id, const struct vidcap_params *param, struct vidcap
free(d);
return 1;
}
int ret = capture_filter_init(param->requested_capture_filter, &d->capture_filter);
module_init_default(&d->mod);
d->mod.cls = MODULE_CLASS_CAPTURE;
module_register(&d->mod, parent);
int ret = capture_filter_init(&d->mod, param->requested_capture_filter,
&d->capture_filter);
if(ret != 0) {
fprintf(stderr, "Unable to initialize capture filter: %s.\n",
param->requested_capture_filter);
module_done(&d->mod);
return ret;
}
*state = d;
return 0;
}
}
@@ -489,6 +500,7 @@ void vidcap_done(struct vidcap *state)
assert(state->magic == VIDCAP_MAGIC);
vidcap_device_table[state->index].func_done(state->state);
capture_filter_destroy(state->capture_filter);
module_done(&state->mod);
free(state);
}

View File

@@ -130,9 +130,11 @@ int vidcap_get_device_count(void);
struct vidcap_type *vidcap_get_device_details(int index);
vidcap_id_t vidcap_get_null_device_id(void);
struct module;
struct vidcap;
int vidcap_init(vidcap_id_t id, const struct vidcap_params *param, struct vidcap **);
int vidcap_init(struct module *parent, vidcap_id_t id,
const struct vidcap_params *param, struct vidcap **);
void vidcap_done(struct vidcap *state);
struct video_frame *vidcap_grab(struct vidcap *state, struct audio_frame **audio);