http skel

This commit is contained in:
Devaev Maxim 2018-09-18 02:13:42 +03:00
parent 912443eafb
commit 8039d60ad5
10 changed files with 158 additions and 57 deletions

View File

@ -1,4 +1,4 @@
LIBS = -lm -ljpeg -pthread
LIBS = -lm -ljpeg -pthread -levent
CC = gcc
CFLAGS = -c -O3 -Wall -Wextra
LDFLAGS =

View File

@ -32,13 +32,19 @@ static int _capture_release_buffer(struct device_t *dev, struct v4l2_buffer *buf
static int _capture_handle_event(struct device_t *dev);
void captured_picture_init(struct captured_picture_t *captured) {
memset(captured, 0, sizeof(struct captured_picture_t));
struct captured_picture_t *captured_picture_init() {
struct captured_picture_t *captured;
A_CALLOC(captured, 1, sizeof(*captured));
MEMSET_ZERO_PTR(captured);
A_PTHREAD_M_INIT(&captured->mutex);
return captured;
}
void captured_picture_destroy(struct captured_picture_t *captured) {
A_PTHREAD_M_DESTROY(&captured->mutex);
free(captured);
}
#ifdef DUMP_CAPTURED_JPEGS
@ -83,6 +89,9 @@ void capture_loop(struct device_t *dev, struct captured_picture_t *captured, sig
LOG_DEBUG("Allocation memory for captured (result) picture ...");
A_CALLOC(captured->picture.data, dev->run->max_picture_size, sizeof(*captured->picture.data));
captured->width = dev->run->width;
captured->height = dev->run->height;
while (!*global_stop) {
SEP_DEBUG('-');
@ -99,6 +108,7 @@ void capture_loop(struct device_t *dev, struct captured_picture_t *captured, sig
dev->run->pictures[last_worker->ctx.index].data,
captured->picture.size * sizeof(*captured->picture.data)
);
captured->updated = true;
A_PTHREAD_M_UNLOCK(&captured->mutex);
last_worker = last_worker->order_next;
@ -418,7 +428,7 @@ static int _capture_control(struct device_t *dev, const bool enable) {
}
static int _capture_grab_buffer(struct device_t *dev, struct v4l2_buffer *buf_info) {
memset(buf_info, 0, sizeof(struct v4l2_buffer));
MEMSET_ZERO_PTR(buf_info);
buf_info->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf_info->memory = V4L2_MEMORY_MMAP;

View File

@ -55,10 +55,12 @@ struct captured_picture_t {
struct picture_t picture;
unsigned width;
unsigned height;
bool updated;
pthread_mutex_t mutex;
};
void captured_picture_init(struct captured_picture_t *captured);
struct captured_picture_t *captured_picture_init();
void captured_picture_destroy(struct captured_picture_t *captured);
void capture_loop(struct device_t *dev, struct captured_picture_t *captured, sig_atomic_t *volatile global_stop);

View File

@ -48,9 +48,17 @@ static const char *_format_to_string_null(const unsigned format);
static const char *_standard_to_string(const v4l2_std_id standard);
void device_init(struct device_t *dev, struct device_runtime_t *run) {
memset(dev, 0, sizeof(struct device_t));
memset(run, 0, sizeof(struct device_runtime_t));
struct device_t *device_init() {
struct device_t *dev;
struct device_runtime_t *run;
A_CALLOC(dev, 1, sizeof(*dev));
MEMSET_ZERO_PTR(dev);
A_CALLOC(run, 1, sizeof(*run));
MEMSET_ZERO_PTR(run);
dev->run = run;
dev->run->fd = -1;
dev->path = (char *)DEFAULT_DEVICE;
dev->width = 640;
@ -61,9 +69,12 @@ void device_init(struct device_t *dev, struct device_runtime_t *run) {
dev->jpeg_quality = 80;
dev->timeout = 1;
dev->error_timeout = 1;
return dev;
}
dev->run = run;
dev->run->fd = -1;
void device_destroy(struct device_t *dev) {
free(dev->run);
free(dev);
}
int device_parse_format(const char *const str) {

View File

@ -49,7 +49,8 @@ struct device_t {
};
void device_init(struct device_t *dev, struct device_runtime_t *run);
struct device_t *device_init();
void device_destroy(struct device_t *dev);
int device_parse_format(const char *const str);
v4l2_std_id device_parse_standard(const char *const str);

28
src/http.c Normal file
View File

@ -0,0 +1,28 @@
#include <signal.h>
#include "capture.h"
#include "tools.h"
#include "http.h"
static const char DEFAULT_HOST[] = "localhost";
struct http_server_t *http_server_init() {
struct http_server_t *server;
A_CALLOC(server, 1, sizeof(*server));
MEMSET_ZERO_PTR(server);
server->host = (char *)DEFAULT_HOST;
server->port = 8080;
return server;
}
void http_server_destroy(struct http_server_t *server) {
free(server);
}
void http_server_loop(struct http_server_t *server, struct captured_picture_t *captured, sig_atomic_t *volatile global_stop) {
// TODO: implement server here
}

16
src/http.h Normal file
View File

@ -0,0 +1,16 @@
#include <signal.h>
#include "tools.h"
#include "capture.h"
struct http_server_t {
char *host;
unsigned port;
};
struct http_server_t *http_server_init();
void http_server_destroy(struct http_server_t *server);
void http_server_loop(struct http_server_t *server, struct captured_picture_t *captured, sig_atomic_t *volatile global_stop);

View File

@ -14,34 +14,38 @@
#include "tools.h"
#include "device.h"
#include "capture.h"
#include "http.h"
static const char _short_opts[] = "hd:f:s:e:tn:q:";
static const char _short_opts[] = "d:f:a:e:tn:q:s:p:h";
static const struct option _long_opts[] = {
{"help", no_argument, NULL, 'h'},
{"device", required_argument, NULL, 'd'},
{"format", required_argument, NULL, 'f'},
{"tv-standard", required_argument, NULL, 's'},
{"every-frame", required_argument, NULL, 'e'},
{"min-frame-size", required_argument, NULL, 'z'},
{"dv-timings", no_argument, NULL, 't'},
{"buffers", required_argument, NULL, 'n'},
{"jpeg-quality", required_argument, NULL, 'q'},
{"width", required_argument, NULL, 1000},
{"height", required_argument, NULL, 1001},
{"v4l2-timeout", required_argument, NULL, 1002},
{"v4l2-error-timeout", required_argument, NULL, 1003},
{"debug", no_argument, NULL, 5000},
{"log-level", required_argument, NULL, 5001},
{NULL, 0, NULL, 0},
{"device", required_argument, NULL, 'd'},
{"format", required_argument, NULL, 'f'},
{"tv-standard", required_argument, NULL, 'a'},
{"every-frame", required_argument, NULL, 'e'},
{"min-frame-size", required_argument, NULL, 'z'},
{"dv-timings", no_argument, NULL, 't'},
{"buffers", required_argument, NULL, 'n'},
{"jpeg-quality", required_argument, NULL, 'q'},
{"width", required_argument, NULL, 1000},
{"height", required_argument, NULL, 1001},
{"device-timeout", required_argument, NULL, 1002},
{"device-error-timeout", required_argument, NULL, 1003},
{"host", required_argument, NULL, 's'},
{"port", required_argument, NULL, 'p'},
{"debug", no_argument, NULL, 5000},
{"log-level", required_argument, NULL, 5001},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
static void _help(int exit_code) {
static void _help() {
printf("No manual yet\n");
exit(exit_code);
}
static void _parse_options(int argc, char *argv[], struct device_t *dev) {
static int _parse_options(int argc, char *argv[], struct device_t *dev, struct http_server_t *server) {
# define OPT_ARG(_dest) \
{ _dest = optarg; break; }
@ -51,12 +55,12 @@ static void _parse_options(int argc, char *argv[], struct device_t *dev) {
# define OPT_UNSIGNED(_dest, _name, _min) \
{ int _tmp = strtol(optarg, NULL, 0); \
if (errno || _tmp < _min) \
{ printf("Invalid value for '%s=%u'; minimal=%u\n", _name, _tmp, _min); exit(EXIT_FAILURE); } \
{ printf("Invalid value for '%s=%u'; minimal=%u\n", _name, _tmp, _min); return -1; } \
_dest = _tmp; break; }
# define OPT_PARSE(_dest, _func, _invalid, _name) \
{ if ((_dest = _func(optarg)) == _invalid) \
{ printf("Unknown " _name ": %s\n", optarg); exit(EXIT_FAILURE); } \
{ printf("Unknown " _name ": %s\n", optarg); return -1; } \
break; }
int index;
@ -65,13 +69,12 @@ static void _parse_options(int argc, char *argv[], struct device_t *dev) {
log_level = LOG_LEVEL_INFO;
while ((ch = getopt_long(argc, argv, _short_opts, _long_opts, &index)) >= 0) {
switch (ch) {
case 0: break;
case 'd': OPT_ARG(dev->path);
# pragma GCC diagnostic ignored "-Wsign-compare"
# pragma GCC diagnostic push
case 'f': OPT_PARSE(dev->format, device_parse_format, FORMAT_UNKNOWN, "pixel format");
# pragma GCC diagnostic pop
case 's': OPT_PARSE(dev->standard, device_parse_standard, STANDARD_UNKNOWN, "TV standard");
case 'a': OPT_PARSE(dev->standard, device_parse_standard, STANDARD_UNKNOWN, "TV standard");
case 'e': OPT_UNSIGNED(dev->every_frame, "--every-frame", 1);
case 'z': OPT_UNSIGNED(dev->min_frame_size, "--min-frame-size", 0);
case 't': OPT_TRUE(dev->dv_timings);
@ -81,10 +84,14 @@ static void _parse_options(int argc, char *argv[], struct device_t *dev) {
case 1001: OPT_UNSIGNED(dev->height, "--height", 180);
case 1002: OPT_UNSIGNED(dev->timeout, "--timeout", 1);
case 1003: OPT_UNSIGNED(dev->error_timeout, "--error-timeout", 1);
case 's': server->host = optarg; break;
case 'p': OPT_UNSIGNED(server->port, "--port", 1);
case 5000: log_level = LOG_LEVEL_DEBUG; break;
case 5001: OPT_UNSIGNED(log_level, "--log-level", 0);
case 'h': _help(EXIT_SUCCESS); break;
default: _help(EXIT_FAILURE); break;
case 0: break;
case 'h': default: _help(); return -1;
}
}
@ -92,35 +99,46 @@ static void _parse_options(int argc, char *argv[], struct device_t *dev) {
# undef OPT_UNSIGNED
# undef OPT_TRUE
# undef OPT_ARG
return 0;
}
struct threads_context {
struct thread_context {
struct device_t *dev;
struct captured_picture_t *captured;
sig_atomic_t *volatile global_stop;
struct http_server_t *server;
};
static void *_capture_loop_thread(void *v_ctx) {
struct threads_context *ctx = (struct threads_context *)v_ctx;
sigset_t mask;
static volatile sig_atomic_t _global_stop = 0;
static void _block_thread_signals() {
sigset_t mask;
assert(!sigemptyset(&mask));
assert(!sigaddset(&mask, SIGINT));
assert(!sigaddset(&mask, SIGTERM));
assert(!pthread_sigmask(SIG_BLOCK, &mask, NULL));
}
capture_loop(ctx->dev, ctx->captured, (sig_atomic_t *volatile)ctx->global_stop);
static void *_capture_loop_thread(void *v_ctx) {
struct thread_context *ctx = (struct thread_context *)v_ctx;
_block_thread_signals();
capture_loop(ctx->dev, ctx->captured, (sig_atomic_t *volatile)&_global_stop);
return NULL;
}
static volatile sig_atomic_t _global_stop = 0;
static void *_server_loop_thread(void *v_ctx) {
struct thread_context *ctx = (struct thread_context *)v_ctx;
_block_thread_signals();
http_server_loop(ctx->server, ctx->captured, (sig_atomic_t *volatile)&_global_stop);
return NULL;
}
static void _signal_handler(int signum) {
LOG_INFO("===== Stopping by %s =====", strsignal(signum));
_global_stop = 1;
}
static void _init_signal_handlers() {
static void _install_signal_handlers() {
struct sigaction sig_act;
MEMSET_ZERO(sig_act);
@ -137,19 +155,33 @@ static void _init_signal_handlers() {
}
int main(int argc, char *argv[]) {
struct device_t dev;
struct device_runtime_t run;
struct captured_picture_t captured;
struct threads_context ctx = {&dev, &captured, (sig_atomic_t *volatile)&_global_stop};
pthread_t capture_loop_tid;
struct device_t *dev;
struct captured_picture_t *captured;
struct http_server_t *server;
device_init(&dev, &run);
_parse_options(argc, argv, &dev);
_init_signal_handlers();
dev = device_init();
captured = captured_picture_init();
server = http_server_init();
captured_picture_init(&captured);
A_PTHREAD_CREATE(&capture_loop_tid, _capture_loop_thread, (void *)&ctx);
A_PTHREAD_JOIN(capture_loop_tid);
captured_picture_destroy(&captured);
if (_parse_options(argc, argv, dev, server) == 0) {
_install_signal_handlers();
pthread_t capture_loop_tid;
pthread_t server_loop_tid;
struct thread_context ctx;
ctx.dev = dev;
ctx.captured = captured;
ctx.server = server;
A_PTHREAD_CREATE(&capture_loop_tid, _capture_loop_thread, (void *)&ctx);
A_PTHREAD_CREATE(&server_loop_tid, _server_loop_thread, (void *)&ctx);
A_PTHREAD_JOIN(capture_loop_tid);
A_PTHREAD_JOIN(server_loop_tid);
}
http_server_destroy(server);
captured_picture_destroy(captured);
device_destroy(dev);
return 0;
}

View File

@ -68,6 +68,7 @@ unsigned log_level;
#define A_CALLOC(_dest, _nmemb, _size) assert((_dest = calloc(_nmemb, _size)))
#define MEMSET_ZERO(_x_obj) memset(&(_x_obj), 0, sizeof(_x_obj))
#define MEMSET_ZERO_PTR(_x_ptr) memset(_x_ptr, 0, sizeof(*(_x_ptr)))
#define INLINE inline __attribute__((always_inline))

BIN
vgcore.8195 Normal file

Binary file not shown.