mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-19 08:16:31 +00:00
refactoring
This commit is contained in:
@@ -26,8 +26,8 @@
|
||||
static int _sem_wait_monotonic(sem_t *sem, long double timeout);
|
||||
|
||||
|
||||
struct rawsink_t *rawsink_init(const char *name, mode_t mode, bool rm, bool master) {
|
||||
struct rawsink_t *rawsink;
|
||||
rawsink_s *rawsink_init(const char *name, mode_t mode, bool rm, bool master) {
|
||||
rawsink_s *rawsink;
|
||||
int flags = (master ? O_RDWR | O_CREAT : O_RDWR);
|
||||
|
||||
A_CALLOC(rawsink, 1);
|
||||
@@ -66,14 +66,14 @@ struct rawsink_t *rawsink_init(const char *name, mode_t mode, bool rm, bool mast
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ftruncate(rawsink->fd, sizeof(struct rawsink_shared_t)) < 0) {
|
||||
if (ftruncate(rawsink->fd, sizeof(rawsink_shared_s)) < 0) {
|
||||
LOG_PERROR("Can't truncate RAW sink memory");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((rawsink->shared = mmap(
|
||||
NULL,
|
||||
sizeof(struct rawsink_shared_t),
|
||||
sizeof(rawsink_shared_s),
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED,
|
||||
rawsink->fd,
|
||||
@@ -98,7 +98,7 @@ struct rawsink_t *rawsink_init(const char *name, mode_t mode, bool rm, bool mast
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void rawsink_destroy(struct rawsink_t *rawsink) {
|
||||
void rawsink_destroy(rawsink_s *rawsink) {
|
||||
# define CLOSE_SEM(_role) { \
|
||||
if (rawsink->_role##_sem != SEM_FAILED) { \
|
||||
if (sem_close(rawsink->_role##_sem) < 0) { \
|
||||
@@ -118,7 +118,7 @@ void rawsink_destroy(struct rawsink_t *rawsink) {
|
||||
# undef CLOSE_SEM
|
||||
|
||||
if (rawsink->shared != MAP_FAILED) {
|
||||
if (munmap(rawsink->shared, sizeof(struct rawsink_shared_t)) < 0) {
|
||||
if (munmap(rawsink->shared, sizeof(rawsink_shared_s)) < 0) {
|
||||
LOG_PERROR("Can't unmap RAW sink memory");
|
||||
}
|
||||
}
|
||||
@@ -141,7 +141,7 @@ void rawsink_destroy(struct rawsink_t *rawsink) {
|
||||
}
|
||||
|
||||
void rawsink_put(
|
||||
struct rawsink_t *rawsink,
|
||||
rawsink_s *rawsink,
|
||||
const uint8_t *data, size_t size,
|
||||
unsigned format, unsigned width, unsigned height,
|
||||
long double grab_ts) {
|
||||
@@ -202,7 +202,7 @@ void rawsink_put(
|
||||
}
|
||||
|
||||
int rawsink_get(
|
||||
struct rawsink_t *rawsink,
|
||||
rawsink_s *rawsink,
|
||||
char *data, size_t *size,
|
||||
unsigned *format, unsigned *width, unsigned *height,
|
||||
long double *grab_ts,
|
||||
|
||||
@@ -44,22 +44,22 @@
|
||||
#define RAWSINK_MAX_DATA ((size_t)(CFG_RAWSINK_MAX_DATA))
|
||||
|
||||
|
||||
struct rawsink_shared_t {
|
||||
typedef struct {
|
||||
unsigned format;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
long double grab_ts;
|
||||
size_t size;
|
||||
uint8_t data[RAWSINK_MAX_DATA];
|
||||
};
|
||||
} rawsink_shared_s;
|
||||
|
||||
struct rawsink_t {
|
||||
typedef struct {
|
||||
char *mem_name;
|
||||
char *signal_name;
|
||||
char *lock_name;
|
||||
|
||||
int fd;
|
||||
struct rawsink_shared_t *shared;
|
||||
rawsink_shared_s *shared;
|
||||
|
||||
sem_t *signal_sem;
|
||||
sem_t *lock_sem;
|
||||
@@ -68,20 +68,20 @@ struct rawsink_t {
|
||||
bool master;
|
||||
|
||||
bool master_failed;
|
||||
};
|
||||
} rawsink_s;
|
||||
|
||||
|
||||
struct rawsink_t *rawsink_init(const char *name, mode_t mode, bool rm, bool master);
|
||||
void rawsink_destroy(struct rawsink_t *rawsink);
|
||||
rawsink_s *rawsink_init(const char *name, mode_t mode, bool rm, bool master);
|
||||
void rawsink_destroy(rawsink_s *rawsink);
|
||||
|
||||
void rawsink_put(
|
||||
struct rawsink_t *rawsink,
|
||||
rawsink_s *rawsink,
|
||||
const uint8_t *data, size_t size,
|
||||
unsigned format, unsigned witdh, unsigned height,
|
||||
long double grab_ts);
|
||||
|
||||
int rawsink_get(
|
||||
struct rawsink_t *rawsink,
|
||||
rawsink_s *rawsink,
|
||||
char *data, size_t *size,
|
||||
unsigned *format, unsigned *width, unsigned *height,
|
||||
long double *grab_ts,
|
||||
|
||||
@@ -23,21 +23,21 @@
|
||||
#include "blank.h"
|
||||
|
||||
|
||||
struct _jpeg_error_manager_t {
|
||||
typedef struct {
|
||||
struct jpeg_error_mgr mgr; // Default manager
|
||||
jmp_buf jmp;
|
||||
};
|
||||
} _jpeg_error_manager_s;
|
||||
|
||||
|
||||
static struct frame_t *_init_internal(void);
|
||||
static struct frame_t *_init_external(const char *path);
|
||||
static frame_s *_init_internal(void);
|
||||
static frame_s *_init_external(const char *path);
|
||||
|
||||
static int _jpeg_read_geometry(FILE *fp, unsigned *width, unsigned *height);
|
||||
static void _jpeg_error_handler(j_common_ptr jpeg);
|
||||
|
||||
|
||||
struct frame_t *blank_frame_init(const char *path) {
|
||||
struct frame_t *blank = NULL;
|
||||
frame_s *blank_frame_init(const char *path) {
|
||||
frame_s *blank = NULL;
|
||||
|
||||
if (path && path[0] != '\0') {
|
||||
blank = _init_external(path);
|
||||
@@ -52,8 +52,8 @@ struct frame_t *blank_frame_init(const char *path) {
|
||||
return blank;
|
||||
}
|
||||
|
||||
static struct frame_t *_init_internal(void) {
|
||||
struct frame_t *blank;
|
||||
static frame_s *_init_internal(void) {
|
||||
frame_s *blank;
|
||||
|
||||
blank = frame_init("blank_internal");
|
||||
frame_set_data(blank, BLANK_JPEG_DATA, BLANK_JPEG_DATA_SIZE);
|
||||
@@ -62,9 +62,9 @@ static struct frame_t *_init_internal(void) {
|
||||
return blank;
|
||||
}
|
||||
|
||||
static struct frame_t *_init_external(const char *path) {
|
||||
static frame_s *_init_external(const char *path) {
|
||||
FILE *fp = NULL;
|
||||
struct frame_t *blank;
|
||||
frame_s *blank;
|
||||
|
||||
blank = frame_init("blank_external");
|
||||
|
||||
@@ -116,7 +116,7 @@ static struct frame_t *_init_external(const char *path) {
|
||||
|
||||
static int _jpeg_read_geometry(FILE *fp, unsigned *width, unsigned *height) {
|
||||
struct jpeg_decompress_struct jpeg;
|
||||
struct _jpeg_error_manager_t jpeg_error;
|
||||
_jpeg_error_manager_s jpeg_error;
|
||||
|
||||
jpeg_create_decompress(&jpeg);
|
||||
|
||||
@@ -140,7 +140,7 @@ static int _jpeg_read_geometry(FILE *fp, unsigned *width, unsigned *height) {
|
||||
}
|
||||
|
||||
static void _jpeg_error_handler(j_common_ptr jpeg) {
|
||||
struct _jpeg_error_manager_t *jpeg_error = (struct _jpeg_error_manager_t *)jpeg->err;
|
||||
_jpeg_error_manager_s *jpeg_error = (_jpeg_error_manager_s *)jpeg->err;
|
||||
char msg[JMSG_LENGTH_MAX];
|
||||
|
||||
(*jpeg_error->mgr.format_message)(jpeg, msg);
|
||||
|
||||
@@ -35,4 +35,4 @@
|
||||
#include "data/blank_jpeg.h"
|
||||
|
||||
|
||||
struct frame_t *blank_frame_init(const char *path);
|
||||
frame_s *blank_frame_init(const char *path);
|
||||
|
||||
@@ -54,23 +54,23 @@ static const struct {
|
||||
};
|
||||
|
||||
|
||||
static int _device_open_check_cap(struct device_t *dev);
|
||||
static int _device_open_dv_timings(struct device_t *dev);
|
||||
static int _device_apply_dv_timings(struct device_t *dev);
|
||||
static int _device_open_format(struct device_t *dev);
|
||||
static void _device_open_hw_fps(struct device_t *dev);
|
||||
static int _device_open_io_method(struct device_t *dev);
|
||||
static int _device_open_io_method_mmap(struct device_t *dev);
|
||||
static int _device_open_io_method_userptr(struct device_t *dev);
|
||||
static int _device_open_queue_buffers(struct device_t *dev);
|
||||
static int _device_apply_resolution(struct device_t *dev, unsigned width, unsigned height);
|
||||
static int _device_open_check_cap(device_s *dev);
|
||||
static int _device_open_dv_timings(device_s *dev);
|
||||
static int _device_apply_dv_timings(device_s *dev);
|
||||
static int _device_open_format(device_s *dev);
|
||||
static void _device_open_hw_fps(device_s *dev);
|
||||
static int _device_open_io_method(device_s *dev);
|
||||
static int _device_open_io_method_mmap(device_s *dev);
|
||||
static int _device_open_io_method_userptr(device_s *dev);
|
||||
static int _device_open_queue_buffers(device_s *dev);
|
||||
static int _device_apply_resolution(device_s *dev, unsigned width, unsigned height);
|
||||
|
||||
static void _device_apply_controls(struct device_t *dev);
|
||||
static void _device_apply_controls(device_s *dev);
|
||||
static int _device_query_control(
|
||||
struct device_t *dev, struct v4l2_queryctrl *query,
|
||||
device_s *dev, struct v4l2_queryctrl *query,
|
||||
const char *name, unsigned cid, bool quiet);
|
||||
static void _device_set_control(
|
||||
struct device_t *dev, struct v4l2_queryctrl *query,
|
||||
device_s *dev, struct v4l2_queryctrl *query,
|
||||
const char *name, unsigned cid, int value, bool quiet);
|
||||
|
||||
static const char *_format_to_string_fourcc(char *buf, size_t size, unsigned format);
|
||||
@@ -83,9 +83,9 @@ static const char *_io_method_to_string_supported(enum v4l2_memory io_method);
|
||||
#define RUN(_next) dev->run->_next
|
||||
|
||||
|
||||
struct device_t *device_init(void) {
|
||||
struct device_runtime_t *run;
|
||||
struct device_t *dev;
|
||||
device_s *device_init(void) {
|
||||
device_runtime_s *run;
|
||||
device_s *dev;
|
||||
|
||||
A_CALLOC(run, 1);
|
||||
run->fd = -1;
|
||||
@@ -104,7 +104,7 @@ struct device_t *device_init(void) {
|
||||
return dev;
|
||||
}
|
||||
|
||||
void device_destroy(struct device_t *dev) {
|
||||
void device_destroy(device_s *dev) {
|
||||
free(dev->run);
|
||||
free(dev);
|
||||
}
|
||||
@@ -136,7 +136,7 @@ int device_parse_io_method(const char *str) {
|
||||
return IO_METHOD_UNKNOWN;
|
||||
}
|
||||
|
||||
int device_open(struct device_t *dev) {
|
||||
int device_open(device_s *dev) {
|
||||
if ((RUN(fd) = open(dev->path, O_RDWR|O_NONBLOCK)) < 0) {
|
||||
LOG_PERROR("Can't open device");
|
||||
goto error;
|
||||
@@ -169,7 +169,7 @@ int device_open(struct device_t *dev) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
void device_close(struct device_t *dev) {
|
||||
void device_close(device_s *dev) {
|
||||
RUN(persistent_timeout_reported) = false;
|
||||
|
||||
if (RUN(hw_buffers)) {
|
||||
@@ -208,7 +208,7 @@ void device_close(struct device_t *dev) {
|
||||
}
|
||||
}
|
||||
|
||||
int device_switch_capturing(struct device_t *dev, bool enable) {
|
||||
int device_switch_capturing(device_s *dev, bool enable) {
|
||||
if (enable != RUN(capturing)) {
|
||||
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
|
||||
|
||||
@@ -226,7 +226,7 @@ int device_switch_capturing(struct device_t *dev, bool enable) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int device_select(struct device_t *dev, bool *has_read, bool *has_write, bool *has_error) {
|
||||
int device_select(device_s *dev, bool *has_read, bool *has_write, bool *has_error) {
|
||||
struct timeval timeout;
|
||||
int retval;
|
||||
|
||||
@@ -272,7 +272,7 @@ int device_select(struct device_t *dev, bool *has_read, bool *has_write, bool *h
|
||||
return retval;
|
||||
}
|
||||
|
||||
int device_grab_buffer(struct device_t *dev) {
|
||||
int device_grab_buffer(device_s *dev) {
|
||||
struct v4l2_buffer buf_info;
|
||||
|
||||
MEMSET_ZERO(buf_info);
|
||||
@@ -332,7 +332,7 @@ int device_grab_buffer(struct device_t *dev) {
|
||||
return buf_info.index;
|
||||
}
|
||||
|
||||
int device_release_buffer(struct device_t *dev, unsigned index) {
|
||||
int device_release_buffer(device_s *dev, unsigned index) {
|
||||
# define HW(_next) RUN(hw_buffers)[index]._next
|
||||
|
||||
LOG_DEBUG("Releasing device buffer index=%u ...", index);
|
||||
@@ -350,7 +350,7 @@ int device_release_buffer(struct device_t *dev, unsigned index) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int device_consume_event(struct device_t *dev) {
|
||||
int device_consume_event(device_s *dev) {
|
||||
struct v4l2_event event;
|
||||
|
||||
LOG_DEBUG("Calling ioctl(VIDIOC_DQEVENT) ...");
|
||||
@@ -369,7 +369,7 @@ int device_consume_event(struct device_t *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _device_open_check_cap(struct device_t *dev) {
|
||||
static int _device_open_check_cap(device_s *dev) {
|
||||
struct v4l2_capability cap;
|
||||
int input = dev->input; // Needs pointer to int for ioctl()
|
||||
|
||||
@@ -409,7 +409,7 @@ static int _device_open_check_cap(struct device_t *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _device_open_dv_timings(struct device_t *dev) {
|
||||
static int _device_open_dv_timings(device_s *dev) {
|
||||
_device_apply_resolution(dev, dev->width, dev->height);
|
||||
if (dev->dv_timings) {
|
||||
LOG_DEBUG("Using DV timings");
|
||||
@@ -432,7 +432,7 @@ static int _device_open_dv_timings(struct device_t *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _device_apply_dv_timings(struct device_t *dev) {
|
||||
static int _device_apply_dv_timings(device_s *dev) {
|
||||
struct v4l2_dv_timings dv;
|
||||
|
||||
MEMSET_ZERO(dv);
|
||||
@@ -465,7 +465,7 @@ static int _device_apply_dv_timings(struct device_t *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _device_open_format(struct device_t *dev) {
|
||||
static int _device_open_format(device_s *dev) {
|
||||
struct v4l2_format fmt;
|
||||
|
||||
MEMSET_ZERO(fmt);
|
||||
@@ -517,7 +517,7 @@ static int _device_open_format(struct device_t *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _device_open_hw_fps(struct device_t *dev) {
|
||||
static void _device_open_hw_fps(device_s *dev) {
|
||||
struct v4l2_streamparm setfps;
|
||||
|
||||
RUN(hw_fps) = 0;
|
||||
@@ -572,7 +572,7 @@ static void _device_open_hw_fps(struct device_t *dev) {
|
||||
# undef SETFPS_TPF
|
||||
}
|
||||
|
||||
static int _device_open_io_method(struct device_t *dev) {
|
||||
static int _device_open_io_method(device_s *dev) {
|
||||
LOG_INFO("Using IO method: %s", _io_method_to_string_supported(dev->io_method));
|
||||
switch (dev->io_method) {
|
||||
case V4L2_MEMORY_MMAP: return _device_open_io_method_mmap(dev);
|
||||
@@ -582,7 +582,7 @@ static int _device_open_io_method(struct device_t *dev) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _device_open_io_method_mmap(struct device_t *dev) {
|
||||
static int _device_open_io_method_mmap(device_s *dev) {
|
||||
struct v4l2_requestbuffers req;
|
||||
|
||||
MEMSET_ZERO(req);
|
||||
@@ -643,7 +643,7 @@ static int _device_open_io_method_mmap(struct device_t *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _device_open_io_method_userptr(struct device_t *dev) {
|
||||
static int _device_open_io_method_userptr(device_s *dev) {
|
||||
struct v4l2_requestbuffers req;
|
||||
unsigned page_size = getpagesize();
|
||||
unsigned buf_size = align_size(RUN(raw_size), page_size);
|
||||
@@ -681,7 +681,7 @@ static int _device_open_io_method_userptr(struct device_t *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _device_open_queue_buffers(struct device_t *dev) {
|
||||
static int _device_open_queue_buffers(device_s *dev) {
|
||||
for (unsigned index = 0; index < RUN(n_buffers); ++index) {
|
||||
struct v4l2_buffer buf_info;
|
||||
|
||||
@@ -703,7 +703,7 @@ static int _device_open_queue_buffers(struct device_t *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _device_apply_resolution(struct device_t *dev, unsigned width, unsigned height) {
|
||||
static int _device_apply_resolution(device_s *dev, unsigned width, unsigned height) {
|
||||
// Тут VIDEO_MIN_* не используются из-за странностей минимального разрешения при отсутствии сигнала
|
||||
// у некоторых устройств, например Auvidea B101
|
||||
if (
|
||||
@@ -719,7 +719,7 @@ static int _device_apply_resolution(struct device_t *dev, unsigned width, unsign
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _device_apply_controls(struct device_t *dev) {
|
||||
static void _device_apply_controls(device_s *dev) {
|
||||
# define SET_CID_VALUE(_cid, _field, _value, _quiet) { \
|
||||
struct v4l2_queryctrl query; \
|
||||
if (_device_query_control(dev, &query, #_field, _cid, _quiet) == 0) { \
|
||||
@@ -775,7 +775,7 @@ static void _device_apply_controls(struct device_t *dev) {
|
||||
}
|
||||
|
||||
static int _device_query_control(
|
||||
struct device_t *dev, struct v4l2_queryctrl *query,
|
||||
device_s *dev, struct v4l2_queryctrl *query,
|
||||
const char *name, unsigned cid, bool quiet) {
|
||||
|
||||
// cppcheck-suppress redundantPointerOp
|
||||
@@ -792,7 +792,7 @@ static int _device_query_control(
|
||||
}
|
||||
|
||||
static void _device_set_control(
|
||||
struct device_t *dev, struct v4l2_queryctrl *query,
|
||||
device_s *dev, struct v4l2_queryctrl *query,
|
||||
const char *name, unsigned cid, int value, bool quiet) {
|
||||
|
||||
struct v4l2_control ctl;
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
#define IO_METHODS_STR "MMAP, USERPTR"
|
||||
|
||||
|
||||
struct hw_buffer_t {
|
||||
typedef struct {
|
||||
uint8_t *data;
|
||||
size_t used;
|
||||
size_t allocated;
|
||||
@@ -79,85 +79,85 @@ struct hw_buffer_t {
|
||||
unsigned format;
|
||||
long double grab_ts;
|
||||
|
||||
struct v4l2_buffer buf_info;
|
||||
struct v4l2_buffer buf_info;
|
||||
|
||||
pthread_mutex_t grabbed_mutex;
|
||||
bool grabbed;
|
||||
};
|
||||
} hw_buffer_s;
|
||||
|
||||
struct device_runtime_t {
|
||||
int fd;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned format;
|
||||
unsigned hw_fps;
|
||||
size_t raw_size;
|
||||
unsigned n_buffers;
|
||||
struct hw_buffer_t *hw_buffers;
|
||||
bool capturing;
|
||||
bool persistent_timeout_reported;
|
||||
};
|
||||
typedef struct {
|
||||
int fd;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned format;
|
||||
unsigned hw_fps;
|
||||
size_t raw_size;
|
||||
unsigned n_buffers;
|
||||
hw_buffer_s *hw_buffers;
|
||||
bool capturing;
|
||||
bool persistent_timeout_reported;
|
||||
} device_runtime_s;
|
||||
|
||||
enum control_mode_t {
|
||||
typedef enum {
|
||||
CTL_MODE_NONE = 0,
|
||||
CTL_MODE_VALUE,
|
||||
CTL_MODE_AUTO,
|
||||
CTL_MODE_DEFAULT,
|
||||
};
|
||||
} control_mode_e;
|
||||
|
||||
struct control_t {
|
||||
enum control_mode_t mode;
|
||||
int value;
|
||||
};
|
||||
typedef struct {
|
||||
control_mode_e mode;
|
||||
int value;
|
||||
} control_s;
|
||||
|
||||
struct controls_t {
|
||||
struct control_t brightness;
|
||||
struct control_t contrast;
|
||||
struct control_t saturation;
|
||||
struct control_t hue;
|
||||
struct control_t gamma;
|
||||
struct control_t sharpness;
|
||||
struct control_t backlight_compensation;
|
||||
struct control_t white_balance;
|
||||
struct control_t gain;
|
||||
struct control_t color_effect;
|
||||
struct control_t flip_vertical;
|
||||
struct control_t flip_horizontal;
|
||||
};
|
||||
typedef struct {
|
||||
control_s brightness;
|
||||
control_s contrast;
|
||||
control_s saturation;
|
||||
control_s hue;
|
||||
control_s gamma;
|
||||
control_s sharpness;
|
||||
control_s backlight_compensation;
|
||||
control_s white_balance;
|
||||
control_s gain;
|
||||
control_s color_effect;
|
||||
control_s flip_vertical;
|
||||
control_s flip_horizontal;
|
||||
} controls_s;
|
||||
|
||||
struct device_t {
|
||||
char *path;
|
||||
unsigned input;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned format;
|
||||
v4l2_std_id standard;
|
||||
typedef struct {
|
||||
char *path;
|
||||
unsigned input;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned format;
|
||||
v4l2_std_id standard;
|
||||
enum v4l2_memory io_method;
|
||||
bool dv_timings;
|
||||
unsigned n_buffers;
|
||||
unsigned desired_fps;
|
||||
size_t min_frame_size;
|
||||
bool persistent;
|
||||
unsigned timeout;
|
||||
bool dv_timings;
|
||||
unsigned n_buffers;
|
||||
unsigned desired_fps;
|
||||
size_t min_frame_size;
|
||||
bool persistent;
|
||||
unsigned timeout;
|
||||
|
||||
struct controls_t ctl;
|
||||
controls_s ctl;
|
||||
|
||||
struct device_runtime_t *run;
|
||||
};
|
||||
device_runtime_s *run;
|
||||
} device_s;
|
||||
|
||||
|
||||
struct device_t *device_init(void);
|
||||
void device_destroy(struct device_t *dev);
|
||||
device_s *device_init(void);
|
||||
void device_destroy(device_s *dev);
|
||||
|
||||
int device_parse_format(const char *str);
|
||||
v4l2_std_id device_parse_standard(const char *str);
|
||||
int device_parse_io_method(const char *str);
|
||||
|
||||
int device_open(struct device_t *dev);
|
||||
void device_close(struct device_t *dev);
|
||||
int device_open(device_s *dev);
|
||||
void device_close(device_s *dev);
|
||||
|
||||
int device_switch_capturing(struct device_t *dev, bool enable);
|
||||
int device_select(struct device_t *dev, bool *has_read, bool *has_write, bool *has_error);
|
||||
int device_grab_buffer(struct device_t *dev);
|
||||
int device_release_buffer(struct device_t *dev, unsigned index);
|
||||
int device_consume_event(struct device_t *dev);
|
||||
int device_switch_capturing(device_s *dev, bool enable);
|
||||
int device_select(device_s *dev, bool *has_read, bool *has_write, bool *has_error);
|
||||
int device_grab_buffer(device_s *dev);
|
||||
int device_release_buffer(device_s *dev, unsigned index);
|
||||
int device_consume_event(device_s *dev);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
static const struct {
|
||||
const char *name;
|
||||
const enum encoder_type_t type;
|
||||
const encoder_type_e type;
|
||||
} _ENCODER_TYPES[] = {
|
||||
{"CPU", ENCODER_TYPE_CPU},
|
||||
{"HW", ENCODER_TYPE_HW},
|
||||
@@ -42,9 +42,9 @@ static const struct {
|
||||
#define DR(_next) dev->run->_next
|
||||
|
||||
|
||||
struct encoder_t *encoder_init(void) {
|
||||
struct encoder_runtime_t *run;
|
||||
struct encoder_t *encoder;
|
||||
encoder_s *encoder_init(void) {
|
||||
encoder_runtime_s *run;
|
||||
encoder_s *encoder;
|
||||
|
||||
A_CALLOC(run, 1);
|
||||
run->type = ENCODER_TYPE_CPU;
|
||||
@@ -59,7 +59,7 @@ struct encoder_t *encoder_init(void) {
|
||||
return encoder;
|
||||
}
|
||||
|
||||
void encoder_destroy(struct encoder_t *encoder) {
|
||||
void encoder_destroy(encoder_s *encoder) {
|
||||
# ifdef WITH_OMX
|
||||
if (ER(omxs)) {
|
||||
for (unsigned index = 0; index < ER(n_omxs); ++index) {
|
||||
@@ -75,7 +75,7 @@ void encoder_destroy(struct encoder_t *encoder) {
|
||||
free(encoder);
|
||||
}
|
||||
|
||||
enum encoder_type_t encoder_parse_type(const char *str) {
|
||||
encoder_type_e encoder_parse_type(const char *str) {
|
||||
for (unsigned index = 0; index < ARRAY_LEN(_ENCODER_TYPES); ++index) {
|
||||
if (!strcasecmp(str, _ENCODER_TYPES[index].name)) {
|
||||
return _ENCODER_TYPES[index].type;
|
||||
@@ -84,7 +84,7 @@ enum encoder_type_t encoder_parse_type(const char *str) {
|
||||
return ENCODER_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
const char *encoder_type_to_string(enum encoder_type_t type) {
|
||||
const char *encoder_type_to_string(encoder_type_e type) {
|
||||
for (unsigned index = 0; index < ARRAY_LEN(_ENCODER_TYPES); ++index) {
|
||||
if (_ENCODER_TYPES[index].type == type) {
|
||||
return _ENCODER_TYPES[index].name;
|
||||
@@ -93,8 +93,8 @@ const char *encoder_type_to_string(enum encoder_type_t type) {
|
||||
return _ENCODER_TYPES[0].name;
|
||||
}
|
||||
|
||||
void encoder_prepare(struct encoder_t *encoder, struct device_t *dev) {
|
||||
enum encoder_type_t type = (ER(cpu_forced) ? ENCODER_TYPE_CPU : encoder->type);
|
||||
void encoder_prepare(encoder_s *encoder, device_s *dev) {
|
||||
encoder_type_e type = (ER(cpu_forced) ? ENCODER_TYPE_CPU : encoder->type);
|
||||
unsigned quality = encoder->quality;
|
||||
bool cpu_forced = false;
|
||||
|
||||
@@ -198,7 +198,7 @@ void encoder_prepare(struct encoder_t *encoder, struct device_t *dev) {
|
||||
A_MUTEX_UNLOCK(&ER(mutex));
|
||||
}
|
||||
|
||||
void encoder_get_runtime_params(struct encoder_t *encoder, enum encoder_type_t *type, unsigned *quality) {
|
||||
void encoder_get_runtime_params(encoder_s *encoder, encoder_type_e *type, unsigned *quality) {
|
||||
A_MUTEX_LOCK(&ER(mutex));
|
||||
*type = ER(type);
|
||||
*quality = ER(quality);
|
||||
@@ -207,9 +207,7 @@ void encoder_get_runtime_params(struct encoder_t *encoder, enum encoder_type_t *
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#pragma GCC diagnostic push
|
||||
int encoder_compress_buffer(
|
||||
struct encoder_t *encoder, unsigned worker_number,
|
||||
struct hw_buffer_t *hw, struct frame_t *frame) {
|
||||
int encoder_compress_buffer(encoder_s *encoder, unsigned worker_number, hw_buffer_s *hw, frame_s *frame) {
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
assert(ER(type) != ENCODER_TYPE_UNKNOWN);
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
ENCODER_TYPES_OMX_HINT \
|
||||
ENCODER_TYPES_NOOP_HINT
|
||||
|
||||
enum encoder_type_t {
|
||||
typedef enum {
|
||||
ENCODER_TYPE_UNKNOWN, // Only for encoder_parse_type() and main()
|
||||
ENCODER_TYPE_CPU,
|
||||
ENCODER_TYPE_HW,
|
||||
@@ -73,44 +73,42 @@ enum encoder_type_t {
|
||||
# ifdef WITH_RAWSINK
|
||||
ENCODER_TYPE_NOOP,
|
||||
# endif
|
||||
};
|
||||
} encoder_type_e;
|
||||
|
||||
struct encoder_runtime_t {
|
||||
enum encoder_type_t type;
|
||||
unsigned quality;
|
||||
bool cpu_forced;
|
||||
pthread_mutex_t mutex;
|
||||
typedef struct {
|
||||
encoder_type_e type;
|
||||
unsigned quality;
|
||||
bool cpu_forced;
|
||||
pthread_mutex_t mutex;
|
||||
|
||||
unsigned n_workers;
|
||||
unsigned n_workers;
|
||||
|
||||
# ifdef WITH_OMX
|
||||
unsigned n_omxs;
|
||||
struct omx_encoder_t **omxs;
|
||||
omx_encoder_s **omxs;
|
||||
# endif
|
||||
};
|
||||
} encoder_runtime_s;
|
||||
|
||||
struct encoder_t {
|
||||
enum encoder_type_t type;
|
||||
unsigned quality;
|
||||
unsigned n_workers;
|
||||
typedef struct {
|
||||
encoder_type_e type;
|
||||
unsigned quality;
|
||||
unsigned n_workers;
|
||||
# ifdef WITH_OMX
|
||||
unsigned n_glitched_resolutions;
|
||||
unsigned glitched_resolutions[2][MAX_GLITCHED_RESOLUTIONS];
|
||||
# endif
|
||||
|
||||
struct encoder_runtime_t *run;
|
||||
};
|
||||
encoder_runtime_s *run;
|
||||
} encoder_s;
|
||||
|
||||
|
||||
struct encoder_t *encoder_init(void);
|
||||
void encoder_destroy(struct encoder_t *encoder);
|
||||
encoder_s *encoder_init(void);
|
||||
void encoder_destroy(encoder_s *encoder);
|
||||
|
||||
enum encoder_type_t encoder_parse_type(const char *str);
|
||||
const char *encoder_type_to_string(enum encoder_type_t type);
|
||||
encoder_type_e encoder_parse_type(const char *str);
|
||||
const char *encoder_type_to_string(encoder_type_e type);
|
||||
|
||||
void encoder_prepare(struct encoder_t *encoder, struct device_t *dev);
|
||||
void encoder_get_runtime_params(struct encoder_t *encoder, enum encoder_type_t *type, unsigned *quality);
|
||||
void encoder_prepare(encoder_s *encoder, device_s *dev);
|
||||
void encoder_get_runtime_params(encoder_s *encoder, encoder_type_e *type, unsigned *quality);
|
||||
|
||||
int encoder_compress_buffer(
|
||||
struct encoder_t *encoder, unsigned worker_number,
|
||||
struct hw_buffer_t *hw, struct frame_t *frame);
|
||||
int encoder_compress_buffer(encoder_s *encoder, unsigned worker_number, hw_buffer_s *hw, frame_s *frame);
|
||||
|
||||
@@ -28,14 +28,14 @@
|
||||
#include "encoder.h"
|
||||
|
||||
|
||||
struct _jpeg_dest_manager_t {
|
||||
struct jpeg_destination_mgr mgr; // Default manager
|
||||
JOCTET *buffer; // Start of buffer
|
||||
struct frame_t *frame;
|
||||
};
|
||||
typedef struct {
|
||||
struct jpeg_destination_mgr mgr; // Default manager
|
||||
JOCTET *buffer; // Start of buffer
|
||||
frame_s *frame;
|
||||
} _jpeg_dest_manager_s;
|
||||
|
||||
|
||||
static void _jpeg_set_picture(j_compress_ptr jpeg, struct frame_t *frame);
|
||||
static void _jpeg_set_picture(j_compress_ptr jpeg, frame_s *frame);
|
||||
|
||||
static void _jpeg_write_scanlines_yuyv(
|
||||
struct jpeg_compress_struct *jpeg, const uint8_t *data,
|
||||
@@ -58,7 +58,7 @@ static boolean _jpeg_empty_output_buffer(j_compress_ptr jpeg);
|
||||
static void _jpeg_term_destination(j_compress_ptr jpeg);
|
||||
|
||||
|
||||
void cpu_encoder_compress_buffer(struct hw_buffer_t *hw, struct frame_t *frame, unsigned quality) {
|
||||
void cpu_encoder_compress_buffer(hw_buffer_s *hw, frame_s *frame, unsigned quality) {
|
||||
// This function based on compress_image_to_jpeg() from mjpg-streamer
|
||||
|
||||
struct jpeg_compress_struct jpeg;
|
||||
@@ -99,16 +99,16 @@ void cpu_encoder_compress_buffer(struct hw_buffer_t *hw, struct frame_t *frame,
|
||||
assert(frame->used > 0);
|
||||
}
|
||||
|
||||
static void _jpeg_set_picture(j_compress_ptr jpeg, struct frame_t *frame) {
|
||||
struct _jpeg_dest_manager_t *dest;
|
||||
static void _jpeg_set_picture(j_compress_ptr jpeg, frame_s *frame) {
|
||||
_jpeg_dest_manager_s *dest;
|
||||
|
||||
if (jpeg->dest == NULL) {
|
||||
assert((jpeg->dest = (struct jpeg_destination_mgr *)(*jpeg->mem->alloc_small)(
|
||||
(j_common_ptr) jpeg, JPOOL_PERMANENT, sizeof(struct _jpeg_dest_manager_t)
|
||||
(j_common_ptr) jpeg, JPOOL_PERMANENT, sizeof(_jpeg_dest_manager_s)
|
||||
)));
|
||||
}
|
||||
|
||||
dest = (struct _jpeg_dest_manager_t *)jpeg->dest;
|
||||
dest = (_jpeg_dest_manager_s *)jpeg->dest;
|
||||
dest->mgr.init_destination = _jpeg_init_destination;
|
||||
dest->mgr.empty_output_buffer = _jpeg_empty_output_buffer;
|
||||
dest->mgr.term_destination = _jpeg_term_destination;
|
||||
@@ -249,7 +249,7 @@ static void _jpeg_write_scanlines_rgb24(
|
||||
#define JPEG_OUTPUT_BUFFER_SIZE ((size_t)4096)
|
||||
|
||||
static void _jpeg_init_destination(j_compress_ptr jpeg) {
|
||||
struct _jpeg_dest_manager_t *dest = (struct _jpeg_dest_manager_t *)jpeg->dest;
|
||||
_jpeg_dest_manager_s *dest = (_jpeg_dest_manager_s *)jpeg->dest;
|
||||
|
||||
// Allocate the output buffer - it will be released when done with image
|
||||
assert((dest->buffer = (JOCTET *)(*jpeg->mem->alloc_small)(
|
||||
@@ -263,7 +263,7 @@ static void _jpeg_init_destination(j_compress_ptr jpeg) {
|
||||
static boolean _jpeg_empty_output_buffer(j_compress_ptr jpeg) {
|
||||
// Called whenever local jpeg buffer fills up
|
||||
|
||||
struct _jpeg_dest_manager_t *dest = (struct _jpeg_dest_manager_t *)jpeg->dest;
|
||||
_jpeg_dest_manager_s *dest = (_jpeg_dest_manager_s *)jpeg->dest;
|
||||
|
||||
frame_append_data(dest->frame, dest->buffer, JPEG_OUTPUT_BUFFER_SIZE);
|
||||
|
||||
@@ -277,7 +277,7 @@ static void _jpeg_term_destination(j_compress_ptr jpeg) {
|
||||
// Called by jpeg_finish_compress after all data has been written.
|
||||
// Usually needs to flush buffer.
|
||||
|
||||
struct _jpeg_dest_manager_t *dest = (struct _jpeg_dest_manager_t *)jpeg->dest;
|
||||
_jpeg_dest_manager_s *dest = (_jpeg_dest_manager_s *)jpeg->dest;
|
||||
size_t final = JPEG_OUTPUT_BUFFER_SIZE - dest->mgr.free_in_buffer;
|
||||
|
||||
// Write any data remaining in the buffer.
|
||||
|
||||
@@ -36,4 +36,4 @@
|
||||
#include "../../device.h"
|
||||
|
||||
|
||||
void cpu_encoder_compress_buffer(struct hw_buffer_t *hw, struct frame_t *frame, unsigned quality);
|
||||
void cpu_encoder_compress_buffer(hw_buffer_s *hw, frame_s *frame, unsigned quality);
|
||||
|
||||
@@ -28,11 +28,11 @@
|
||||
#include "encoder.h"
|
||||
|
||||
|
||||
void _copy_plus_huffman(const struct hw_buffer_t *src, struct frame_t *dest);
|
||||
void _copy_plus_huffman(const hw_buffer_s *src, frame_s *dest);
|
||||
static bool _is_huffman(const uint8_t *data);
|
||||
|
||||
|
||||
int hw_encoder_prepare(struct device_t *dev, unsigned quality) {
|
||||
int hw_encoder_prepare(device_s *dev, unsigned quality) {
|
||||
struct v4l2_jpegcompression comp;
|
||||
|
||||
MEMSET_ZERO(comp);
|
||||
@@ -49,14 +49,14 @@ int hw_encoder_prepare(struct device_t *dev, unsigned quality) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hw_encoder_compress_buffer(struct hw_buffer_t *hw, struct frame_t *frame) {
|
||||
void hw_encoder_compress_buffer(hw_buffer_s *hw, frame_s *frame) {
|
||||
if (hw->format != V4L2_PIX_FMT_MJPEG && hw->format != V4L2_PIX_FMT_JPEG) {
|
||||
assert(0 && "Unsupported input format for HW encoder");
|
||||
}
|
||||
_copy_plus_huffman(hw, frame);
|
||||
}
|
||||
|
||||
void _copy_plus_huffman(const struct hw_buffer_t *src, struct frame_t *dest) {
|
||||
void _copy_plus_huffman(const hw_buffer_s *src, frame_s *dest) {
|
||||
if (!_is_huffman(src->data)) {
|
||||
const uint8_t *src_ptr = src->data;
|
||||
const uint8_t *src_end = src->data + src->used;
|
||||
|
||||
@@ -38,5 +38,5 @@
|
||||
#include "huffman.h"
|
||||
|
||||
|
||||
int hw_encoder_prepare(struct device_t *dev, unsigned quality);
|
||||
void hw_encoder_compress_buffer(struct hw_buffer_t *hw, struct frame_t *frame);
|
||||
int hw_encoder_prepare(device_s *dev, unsigned quality);
|
||||
void hw_encoder_compress_buffer(hw_buffer_s *hw, frame_s *frame);
|
||||
|
||||
@@ -31,11 +31,11 @@ static int _i_omx = 0;
|
||||
|
||||
|
||||
static int _vcos_semwait(VCOS_SEMAPHORE_T *sem);
|
||||
static int _omx_init_component(struct omx_encoder_t *omx);
|
||||
static int _omx_init_disable_ports(struct omx_encoder_t *omx);
|
||||
static int _omx_setup_input(struct omx_encoder_t *omx, struct device_t *dev);
|
||||
static int _omx_setup_output(struct omx_encoder_t *omx, unsigned quality);
|
||||
static int _omx_encoder_clear_ports(struct omx_encoder_t *omx);
|
||||
static int _omx_init_component(omx_encoder_s *omx);
|
||||
static int _omx_init_disable_ports(omx_encoder_s *omx);
|
||||
static int _omx_setup_input(omx_encoder_s *omx, device_s *dev);
|
||||
static int _omx_setup_output(omx_encoder_s *omx, unsigned quality);
|
||||
static int _omx_encoder_clear_ports(omx_encoder_s *omx);
|
||||
|
||||
static OMX_ERRORTYPE _omx_event_handler(
|
||||
UNUSED OMX_HANDLETYPE encoder,
|
||||
@@ -51,7 +51,7 @@ static OMX_ERRORTYPE _omx_output_available_handler(
|
||||
OMX_PTR v_omx, UNUSED OMX_BUFFERHEADERTYPE *buffer);
|
||||
|
||||
|
||||
struct omx_encoder_t *omx_encoder_init(void) {
|
||||
omx_encoder_s *omx_encoder_init(void) {
|
||||
// Some theory:
|
||||
// - http://www.fourcc.org/yuv.php
|
||||
// - https://kwasi-ich.de/blog/2017/11/26/omx/
|
||||
@@ -62,7 +62,7 @@ struct omx_encoder_t *omx_encoder_init(void) {
|
||||
// - https://bitbucket.org/bensch128/omxjpegencode/src/master/jpeg_encoder.cpp
|
||||
// - http://home.nouwen.name/RaspberryPi/documentation/ilcomponents/image_encode.html
|
||||
|
||||
struct omx_encoder_t *omx;
|
||||
omx_encoder_s *omx;
|
||||
OMX_ERRORTYPE error;
|
||||
|
||||
A_CALLOC(omx, 1);
|
||||
@@ -103,7 +103,7 @@ struct omx_encoder_t *omx_encoder_init(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void omx_encoder_destroy(struct omx_encoder_t *omx) {
|
||||
void omx_encoder_destroy(omx_encoder_s *omx) {
|
||||
OMX_ERRORTYPE error;
|
||||
|
||||
LOG_INFO("Destroying OMX encoder ...");
|
||||
@@ -135,7 +135,7 @@ void omx_encoder_destroy(struct omx_encoder_t *omx) {
|
||||
free(omx);
|
||||
}
|
||||
|
||||
int omx_encoder_prepare(struct omx_encoder_t *omx, struct device_t *dev, unsigned quality) {
|
||||
int omx_encoder_prepare(omx_encoder_s *omx, device_s *dev, unsigned quality) {
|
||||
if (component_set_state(&omx->encoder, OMX_StateIdle) < 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ int omx_encoder_prepare(struct omx_encoder_t *omx, struct device_t *dev, unsigne
|
||||
return 0;
|
||||
}
|
||||
|
||||
int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct hw_buffer_t *hw, struct frame_t *frame) {
|
||||
int omx_encoder_compress_buffer(omx_encoder_s *omx, hw_buffer_s *hw, frame_s *frame) {
|
||||
# define IN(_next) omx->input_buffer->_next
|
||||
# define OUT(_next) omx->output_buffer->_next
|
||||
|
||||
@@ -259,7 +259,7 @@ static int _vcos_semwait(VCOS_SEMAPHORE_T *sem) {
|
||||
# endif
|
||||
}
|
||||
|
||||
static int _omx_init_component(struct omx_encoder_t *omx) {
|
||||
static int _omx_init_component(omx_encoder_s *omx) {
|
||||
OMX_ERRORTYPE error;
|
||||
|
||||
OMX_CALLBACKTYPE callbacks;
|
||||
@@ -277,7 +277,7 @@ static int _omx_init_component(struct omx_encoder_t *omx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _omx_init_disable_ports(struct omx_encoder_t *omx) {
|
||||
static int _omx_init_disable_ports(omx_encoder_s *omx) {
|
||||
OMX_ERRORTYPE error;
|
||||
OMX_INDEXTYPE types[] = {
|
||||
OMX_IndexParamAudioInit, OMX_IndexParamVideoInit,
|
||||
@@ -305,7 +305,7 @@ static int _omx_init_disable_ports(struct omx_encoder_t *omx) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _omx_setup_input(struct omx_encoder_t *omx, struct device_t *dev) {
|
||||
static int _omx_setup_input(omx_encoder_s *omx, device_s *dev) {
|
||||
OMX_ERRORTYPE error;
|
||||
OMX_PARAM_PORTDEFINITIONTYPE portdef;
|
||||
|
||||
@@ -364,7 +364,7 @@ static int _omx_setup_input(struct omx_encoder_t *omx, struct device_t *dev) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _omx_setup_output(struct omx_encoder_t *omx, unsigned quality) {
|
||||
static int _omx_setup_output(omx_encoder_s *omx, unsigned quality) {
|
||||
OMX_ERRORTYPE error;
|
||||
OMX_PARAM_PORTDEFINITIONTYPE portdef;
|
||||
|
||||
@@ -438,7 +438,7 @@ static int _omx_setup_output(struct omx_encoder_t *omx, unsigned quality) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _omx_encoder_clear_ports(struct omx_encoder_t *omx) {
|
||||
static int _omx_encoder_clear_ports(omx_encoder_s *omx) {
|
||||
OMX_ERRORTYPE error;
|
||||
int retval = 0;
|
||||
|
||||
@@ -475,7 +475,7 @@ static OMX_ERRORTYPE _omx_event_handler(
|
||||
|
||||
// OMX calls this handler for all the events it emits
|
||||
|
||||
struct omx_encoder_t *omx = (struct omx_encoder_t *)v_omx;
|
||||
omx_encoder_s *omx = (omx_encoder_s *)v_omx;
|
||||
|
||||
if (event == OMX_EventError) {
|
||||
LOG_ERROR_OMX((OMX_ERRORTYPE)data1, "OMX error event received");
|
||||
@@ -492,7 +492,7 @@ static OMX_ERRORTYPE _omx_input_required_handler(
|
||||
// Called by OMX when the encoder component requires
|
||||
// the input buffer to be filled with RAW image data
|
||||
|
||||
struct omx_encoder_t *omx = (struct omx_encoder_t *)v_omx;
|
||||
omx_encoder_s *omx = (omx_encoder_s *)v_omx;
|
||||
|
||||
omx->input_required = true;
|
||||
assert(vcos_semaphore_post(&omx->handler_sem) == VCOS_SUCCESS);
|
||||
@@ -506,7 +506,7 @@ static OMX_ERRORTYPE _omx_output_available_handler(
|
||||
// Called by OMX when the encoder component has filled
|
||||
// the output buffer with JPEG data
|
||||
|
||||
struct omx_encoder_t *omx = (struct omx_encoder_t *)v_omx;
|
||||
omx_encoder_s *omx = (omx_encoder_s *)v_omx;
|
||||
|
||||
omx->output_available = true;
|
||||
assert(vcos_semaphore_post(&omx->handler_sem) == VCOS_SUCCESS);
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
#define OMX_MAX_ENCODERS ((unsigned)(CFG_OMX_MAX_ENCODERS))
|
||||
|
||||
|
||||
struct omx_encoder_t {
|
||||
typedef struct {
|
||||
OMX_HANDLETYPE encoder;
|
||||
OMX_BUFFERHEADERTYPE *input_buffer;
|
||||
OMX_BUFFERHEADERTYPE *output_buffer;
|
||||
@@ -64,11 +64,11 @@ struct omx_encoder_t {
|
||||
bool i_encoder;
|
||||
bool i_input_port_enabled;
|
||||
bool i_output_port_enabled;
|
||||
};
|
||||
} omx_encoder_s;
|
||||
|
||||
|
||||
struct omx_encoder_t *omx_encoder_init(void);
|
||||
void omx_encoder_destroy(struct omx_encoder_t *omx);
|
||||
omx_encoder_s *omx_encoder_init(void);
|
||||
void omx_encoder_destroy(omx_encoder_s *omx);
|
||||
|
||||
int omx_encoder_prepare(struct omx_encoder_t *omx, struct device_t *dev, unsigned quality);
|
||||
int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct hw_buffer_t *hw, struct frame_t *frame);
|
||||
int omx_encoder_prepare(omx_encoder_s *omx, device_s *dev, unsigned quality);
|
||||
int omx_encoder_compress_buffer(omx_encoder_s *omx, hw_buffer_s *hw, frame_s *frame);
|
||||
|
||||
@@ -23,8 +23,8 @@
|
||||
#include "frame.h"
|
||||
|
||||
|
||||
struct frame_t *frame_init(const char *role) {
|
||||
struct frame_t *frame;
|
||||
frame_s *frame_init(const char *role) {
|
||||
frame_s *frame;
|
||||
|
||||
A_CALLOC(frame, 1);
|
||||
frame->role = role;
|
||||
@@ -32,14 +32,14 @@ struct frame_t *frame_init(const char *role) {
|
||||
return frame;
|
||||
}
|
||||
|
||||
void frame_destroy(struct frame_t *frame) {
|
||||
void frame_destroy(frame_s *frame) {
|
||||
if (frame->data) {
|
||||
free(frame->data);
|
||||
}
|
||||
free(frame);
|
||||
}
|
||||
|
||||
void frame_realloc_data(struct frame_t *frame, size_t size) {
|
||||
void frame_realloc_data(frame_s *frame, size_t size) {
|
||||
if (frame->allocated < size) {
|
||||
LOG_DEBUG("Increasing frame buffer '%s': %zu -> %zu (+%zu)",
|
||||
frame->role, frame->allocated, size, size - frame->allocated);
|
||||
@@ -48,13 +48,13 @@ void frame_realloc_data(struct frame_t *frame, size_t size) {
|
||||
}
|
||||
}
|
||||
|
||||
void frame_set_data(struct frame_t *frame, const uint8_t *data, size_t size) {
|
||||
void frame_set_data(frame_s *frame, const uint8_t *data, size_t size) {
|
||||
frame_realloc_data(frame, size);
|
||||
memcpy(frame->data, data, size);
|
||||
frame->used = size;
|
||||
}
|
||||
|
||||
void frame_append_data(struct frame_t *frame, const uint8_t *data, size_t size) {
|
||||
void frame_append_data(frame_s *frame, const uint8_t *data, size_t size) {
|
||||
size_t new_used = frame->used + size;
|
||||
|
||||
frame_realloc_data(frame, new_used);
|
||||
@@ -62,7 +62,7 @@ void frame_append_data(struct frame_t *frame, const uint8_t *data, size_t size)
|
||||
frame->used = new_used;
|
||||
}
|
||||
|
||||
void frame_copy(const struct frame_t *src, struct frame_t *dest) {
|
||||
void frame_copy(const frame_s *src, frame_s *dest) {
|
||||
frame_set_data(dest, src->data, src->used);
|
||||
|
||||
# define COPY(_field) dest->_field = src->_field
|
||||
@@ -80,7 +80,7 @@ void frame_copy(const struct frame_t *src, struct frame_t *dest) {
|
||||
# undef COPY
|
||||
}
|
||||
|
||||
bool frame_compare(const struct frame_t *a, const struct frame_t *b) {
|
||||
bool frame_compare(const frame_s *a, const frame_s *b) {
|
||||
return (
|
||||
a->allocated && b->allocated
|
||||
&& a->used == b->used
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
#include "../common/logging.h"
|
||||
|
||||
|
||||
struct frame_t {
|
||||
typedef struct {
|
||||
const char *role;
|
||||
uint8_t *data;
|
||||
size_t used;
|
||||
@@ -43,15 +43,15 @@ struct frame_t {
|
||||
long double grab_ts;
|
||||
long double encode_begin_ts;
|
||||
long double encode_end_ts;
|
||||
};
|
||||
} frame_s;
|
||||
|
||||
|
||||
struct frame_t *frame_init(const char *role);
|
||||
void frame_destroy(struct frame_t *frame);
|
||||
frame_s *frame_init(const char *role);
|
||||
void frame_destroy(frame_s *frame);
|
||||
|
||||
void frame_realloc_data(struct frame_t *frame, size_t size);
|
||||
void frame_set_data(struct frame_t *frame, const uint8_t *data, size_t size);
|
||||
void frame_append_data(struct frame_t *frame, const uint8_t *data, size_t size);
|
||||
void frame_realloc_data(frame_s *frame, size_t size);
|
||||
void frame_set_data(frame_s *frame, const uint8_t *data, size_t size);
|
||||
void frame_append_data(frame_s *frame, const uint8_t *data, size_t size);
|
||||
|
||||
void frame_copy(const struct frame_t *src, struct frame_t *dest);
|
||||
bool frame_compare(const struct frame_t *a, const struct frame_t *b);
|
||||
void frame_copy(const frame_s *src, frame_s *dest);
|
||||
bool frame_compare(const frame_s *a, const frame_s *b);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "gpio.h"
|
||||
|
||||
|
||||
struct gpio_t gpio = {
|
||||
gpio_s gpio = {
|
||||
.path = "/dev/gpiochip0",
|
||||
.consumer_prefix = "ustreamer",
|
||||
|
||||
@@ -46,8 +46,8 @@ struct gpio_t gpio = {
|
||||
};
|
||||
|
||||
|
||||
static void _gpio_output_init(struct gpio_output_t *output);
|
||||
static void _gpio_output_destroy(struct gpio_output_t *output);
|
||||
static void _gpio_output_init(gpio_output_s *output);
|
||||
static void _gpio_output_destroy(gpio_output_s *output);
|
||||
|
||||
|
||||
void gpio_init(void) {
|
||||
@@ -80,7 +80,7 @@ void gpio_destroy(void) {
|
||||
}
|
||||
}
|
||||
|
||||
int gpio_inner_set(struct gpio_output_t *output, bool state) {
|
||||
int gpio_inner_set(gpio_output_s *output, bool state) {
|
||||
int retval = 0;
|
||||
|
||||
assert(gpio.chip);
|
||||
@@ -98,7 +98,7 @@ int gpio_inner_set(struct gpio_output_t *output, bool state) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void _gpio_output_init(struct gpio_output_t *output) {
|
||||
static void _gpio_output_init(gpio_output_s *output) {
|
||||
assert(gpio.chip);
|
||||
assert(output->line == NULL);
|
||||
|
||||
@@ -117,7 +117,7 @@ static void _gpio_output_init(struct gpio_output_t *output) {
|
||||
}
|
||||
}
|
||||
|
||||
static void _gpio_output_destroy(struct gpio_output_t *output) {
|
||||
static void _gpio_output_destroy(gpio_output_s *output) {
|
||||
if (output->line) {
|
||||
gpiod_line_release(output->line);
|
||||
output->line = NULL;
|
||||
|
||||
@@ -35,33 +35,33 @@
|
||||
#include "../../common/threading.h"
|
||||
|
||||
|
||||
struct gpio_output_t {
|
||||
typedef struct {
|
||||
int pin;
|
||||
const char *role;
|
||||
char *consumer;
|
||||
struct gpiod_line *line;
|
||||
bool state;
|
||||
};
|
||||
} gpio_output_s;
|
||||
|
||||
struct gpio_t {
|
||||
typedef struct {
|
||||
char *path;
|
||||
char *consumer_prefix;
|
||||
|
||||
struct gpio_output_t prog_running;
|
||||
struct gpio_output_t stream_online;
|
||||
struct gpio_output_t has_http_clients;
|
||||
gpio_output_s prog_running;
|
||||
gpio_output_s stream_online;
|
||||
gpio_output_s has_http_clients;
|
||||
|
||||
pthread_mutex_t mutex;
|
||||
struct gpiod_chip *chip;
|
||||
};
|
||||
} gpio_s;
|
||||
|
||||
|
||||
extern struct gpio_t gpio;
|
||||
extern gpio_s gpio;
|
||||
|
||||
|
||||
void gpio_init(void);
|
||||
void gpio_destroy(void);
|
||||
int gpio_inner_set(struct gpio_output_t *output, bool state);
|
||||
int gpio_inner_set(gpio_output_s *output, bool state);
|
||||
|
||||
|
||||
#define SET_STATE(_output, _state) { \
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "server.h"
|
||||
|
||||
|
||||
static int _http_preprocess_request(struct evhttp_request *request, struct http_server_t *server);
|
||||
static int _http_preprocess_request(struct evhttp_request *request, server_s *server);
|
||||
|
||||
static void _http_callback_root(struct evhttp_request *request, void *v_server);
|
||||
static void _http_callback_static(struct evhttp_request *request, void *v_server);
|
||||
@@ -35,9 +35,9 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c
|
||||
static void _http_callback_stream_error(struct bufferevent *buf_event, short what, void *v_ctx);
|
||||
|
||||
static void _http_exposed_refresh(int fd, short event, void *v_server);
|
||||
static void _http_queue_send_stream(struct http_server_t *server, bool stream_updated, bool frame_updated);
|
||||
static void _http_queue_send_stream(server_s *server, bool stream_updated, bool frame_updated);
|
||||
|
||||
static bool _expose_new_frame(struct http_server_t *server);
|
||||
static bool _expose_new_frame(server_s *server);
|
||||
|
||||
static void _format_bufferevent_reason(short what, char *reason);
|
||||
|
||||
@@ -47,10 +47,10 @@ static void _format_bufferevent_reason(short what, char *reason);
|
||||
#define EX(_next) RUN(exposed->_next)
|
||||
|
||||
|
||||
struct http_server_t *http_server_init(struct stream_t *stream) {
|
||||
struct http_server_runtime_t *run;
|
||||
struct http_server_t *server;
|
||||
struct exposed_t *exposed;
|
||||
server_s *server_init(stream_s *stream) {
|
||||
server_runtime_s *run;
|
||||
server_s *server;
|
||||
exposed_s *exposed;
|
||||
|
||||
A_CALLOC(exposed, 1);
|
||||
exposed->frame = frame_init("http_exposed");
|
||||
@@ -77,7 +77,7 @@ struct http_server_t *http_server_init(struct stream_t *stream) {
|
||||
return server;
|
||||
}
|
||||
|
||||
void http_server_destroy(struct http_server_t *server) {
|
||||
void server_destroy(server_s *server) {
|
||||
if (RUN(refresh)) {
|
||||
event_del(RUN(refresh));
|
||||
event_free(RUN(refresh));
|
||||
@@ -93,8 +93,8 @@ void http_server_destroy(struct http_server_t *server) {
|
||||
libevent_global_shutdown();
|
||||
# endif
|
||||
|
||||
for (struct stream_client_t *client = RUN(stream_clients); client != NULL;) {
|
||||
struct stream_client_t *next = client->next;
|
||||
for (stream_client_s *client = RUN(stream_clients); client != NULL;) {
|
||||
stream_client_s *next = client->next;
|
||||
|
||||
free(client->key);
|
||||
free(client);
|
||||
@@ -111,7 +111,7 @@ void http_server_destroy(struct http_server_t *server) {
|
||||
free(server);
|
||||
}
|
||||
|
||||
int http_server_listen(struct http_server_t *server) {
|
||||
int server_listen(server_s *server) {
|
||||
{
|
||||
if (server->static_path[0] != '\0') {
|
||||
LOG_INFO("Enabling HTTP file server: %s", server->static_path);
|
||||
@@ -193,20 +193,20 @@ int http_server_listen(struct http_server_t *server) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void http_server_loop(struct http_server_t *server) {
|
||||
void server_loop(server_s *server) {
|
||||
LOG_INFO("Starting HTTP eventloop ...");
|
||||
event_base_dispatch(RUN(base));
|
||||
LOG_INFO("HTTP eventloop stopped");
|
||||
}
|
||||
|
||||
void http_server_loop_break(struct http_server_t *server) {
|
||||
void server_loop_break(server_s *server) {
|
||||
event_base_loopbreak(RUN(base));
|
||||
}
|
||||
|
||||
#define ADD_HEADER(_key, _value) \
|
||||
assert(!evhttp_add_header(evhttp_request_get_output_headers(request), _key, _value))
|
||||
|
||||
static int _http_preprocess_request(struct evhttp_request *request, struct http_server_t *server) {
|
||||
static int _http_preprocess_request(struct evhttp_request *request, server_s *server) {
|
||||
if (RUN(auth_token)) {
|
||||
const char *token = evhttp_find_header(evhttp_request_get_input_headers(request), "Authorization");
|
||||
|
||||
@@ -232,7 +232,7 @@ static int _http_preprocess_request(struct evhttp_request *request, struct http_
|
||||
}
|
||||
|
||||
static void _http_callback_root(struct evhttp_request *request, void *v_server) {
|
||||
struct http_server_t *server = (struct http_server_t *)v_server;
|
||||
server_s *server = (server_s *)v_server;
|
||||
struct evbuffer *buf;
|
||||
struct evkeyvalq params; // For mjpg-streamer compatibility
|
||||
const char *action; // Ditto
|
||||
@@ -258,7 +258,7 @@ static void _http_callback_root(struct evhttp_request *request, void *v_server)
|
||||
}
|
||||
|
||||
static void _http_callback_static(struct evhttp_request *request, void *v_server) {
|
||||
struct http_server_t *server = (struct http_server_t *)v_server;
|
||||
server_s *server = (server_s *)v_server;
|
||||
struct evbuffer *buf = NULL;
|
||||
struct evhttp_uri *uri = NULL;
|
||||
char *uri_path;
|
||||
@@ -331,9 +331,9 @@ static void _http_callback_static(struct evhttp_request *request, void *v_server
|
||||
}
|
||||
|
||||
static void _http_callback_state(struct evhttp_request *request, void *v_server) {
|
||||
struct http_server_t *server = (struct http_server_t *)v_server;
|
||||
server_s *server = (server_s *)v_server;
|
||||
struct evbuffer *buf;
|
||||
enum encoder_type_t encoder_type;
|
||||
encoder_type_e encoder_type;
|
||||
unsigned encoder_quality;
|
||||
|
||||
PREPROCESS_REQUEST;
|
||||
@@ -359,7 +359,7 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server)
|
||||
RUN(stream_clients_count)
|
||||
));
|
||||
|
||||
for (struct stream_client_t * client = RUN(stream_clients); client != NULL; client = client->next) {
|
||||
for (stream_client_s * client = RUN(stream_clients); client != NULL; client = client->next) {
|
||||
assert(evbuffer_add_printf(buf,
|
||||
"\"%s\": {\"fps\": %u, \"extra_headers\": %s, \"advance_headers\": %s, \"dual_final_frames\": %s}%s",
|
||||
client->id,
|
||||
@@ -379,7 +379,7 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server)
|
||||
}
|
||||
|
||||
static void _http_callback_snapshot(struct evhttp_request *request, void *v_server) {
|
||||
struct http_server_t *server = (struct http_server_t *)v_server;
|
||||
server_s *server = (server_s *)v_server;
|
||||
struct evbuffer *buf;
|
||||
char header_buf[64];
|
||||
|
||||
@@ -437,11 +437,11 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server
|
||||
// https://github.com/libevent/libevent/blob/29cc8386a2f7911eaa9336692a2c5544d8b4734f/http.c#L791
|
||||
// https://github.com/libevent/libevent/blob/29cc8386a2f7911eaa9336692a2c5544d8b4734f/http.c#L1458
|
||||
|
||||
struct http_server_t *server = (struct http_server_t *)v_server;
|
||||
server_s *server = (server_s *)v_server;
|
||||
struct evhttp_connection *conn;
|
||||
struct evkeyvalq params;
|
||||
struct bufferevent *buf_event;
|
||||
struct stream_client_t *client;
|
||||
stream_client_s *client;
|
||||
char *client_addr;
|
||||
unsigned short client_port;
|
||||
uuid_t uuid;
|
||||
@@ -469,7 +469,7 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server
|
||||
if (RUN(stream_clients) == NULL) {
|
||||
RUN(stream_clients) = client;
|
||||
} else {
|
||||
struct stream_client_t *last = RUN(stream_clients);
|
||||
stream_client_s *last = RUN(stream_clients);
|
||||
|
||||
for (; last->next != NULL; last = last->next);
|
||||
client->prev = last;
|
||||
@@ -515,8 +515,8 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c
|
||||
# define BOUNDARY "boundarydonotcross"
|
||||
# define RN "\r\n"
|
||||
|
||||
struct stream_client_t *client = (struct stream_client_t *)v_client;
|
||||
struct http_server_t *server = client->server;
|
||||
stream_client_s *client = (stream_client_s *)v_client;
|
||||
server_s *server = client->server;
|
||||
struct evbuffer *buf;
|
||||
long double now = get_now_monotonic();
|
||||
long long now_second = floor_ms(now);
|
||||
@@ -638,8 +638,8 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c
|
||||
}
|
||||
|
||||
static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UNUSED short what, void *v_client) {
|
||||
struct stream_client_t *client = (struct stream_client_t *)v_client;
|
||||
struct http_server_t *server = client->server;
|
||||
stream_client_s *client = (stream_client_s *)v_client;
|
||||
server_s *server = client->server;
|
||||
struct evhttp_connection *conn;
|
||||
char *client_addr = "???";
|
||||
unsigned short client_port = 0;
|
||||
@@ -683,14 +683,14 @@ static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UN
|
||||
free(client);
|
||||
}
|
||||
|
||||
static void _http_queue_send_stream(struct http_server_t *server, bool stream_updated, bool frame_updated) {
|
||||
static void _http_queue_send_stream(server_s *server, bool stream_updated, bool frame_updated) {
|
||||
struct evhttp_connection *conn;
|
||||
struct bufferevent *buf_event;
|
||||
long long now;
|
||||
bool has_clients = false;
|
||||
bool queued = false;
|
||||
|
||||
for (struct stream_client_t *client = RUN(stream_clients); client != NULL; client = client->next) {
|
||||
for (stream_client_s *client = RUN(stream_clients); client != NULL; client = client->next) {
|
||||
conn = evhttp_request_get_connection(client->request);
|
||||
if (conn) {
|
||||
// Фикс для бага WebKit. При включенной опции дропа одинаковых фреймов,
|
||||
@@ -739,7 +739,7 @@ static void _http_queue_send_stream(struct http_server_t *server, bool stream_up
|
||||
}
|
||||
|
||||
static void _http_exposed_refresh(UNUSED int fd, UNUSED short what, void *v_server) {
|
||||
struct http_server_t *server = (struct http_server_t *)v_server;
|
||||
server_s *server = (server_s *)v_server;
|
||||
bool stream_updated = false;
|
||||
bool frame_updated = false;
|
||||
|
||||
@@ -773,7 +773,7 @@ static void _http_exposed_refresh(UNUSED int fd, UNUSED short what, void *v_serv
|
||||
}
|
||||
}
|
||||
|
||||
static bool _expose_new_frame(struct http_server_t *server) {
|
||||
static bool _expose_new_frame(server_s *server) {
|
||||
bool updated = false;
|
||||
|
||||
A_MUTEX_LOCK(&STREAM(video->mutex));
|
||||
|
||||
@@ -72,29 +72,29 @@
|
||||
#include "static.h"
|
||||
|
||||
|
||||
struct stream_client_t {
|
||||
struct http_server_t *server;
|
||||
struct evhttp_request *request;
|
||||
typedef struct stream_client_sx {
|
||||
struct server_sx *server;
|
||||
struct evhttp_request *request;
|
||||
|
||||
char *key;
|
||||
bool extra_headers;
|
||||
bool advance_headers;
|
||||
bool dual_final_frames;
|
||||
char *key;
|
||||
bool extra_headers;
|
||||
bool advance_headers;
|
||||
bool dual_final_frames;
|
||||
|
||||
char id[37]; // ex. "1b4e28ba-2fa1-11d2-883f-0016d3cca427" + "\0"
|
||||
bool need_initial;
|
||||
bool need_first_frame;
|
||||
bool updated_prev;
|
||||
unsigned fps;
|
||||
unsigned fps_accum;
|
||||
long long fps_accum_second;
|
||||
char id[37]; // ex. "1b4e28ba-2fa1-11d2-883f-0016d3cca427" + "\0"
|
||||
bool need_initial;
|
||||
bool need_first_frame;
|
||||
bool updated_prev;
|
||||
unsigned fps;
|
||||
unsigned fps_accum;
|
||||
long long fps_accum_second;
|
||||
|
||||
struct stream_client_t *prev;
|
||||
struct stream_client_t *next;
|
||||
};
|
||||
struct stream_client_sx *prev;
|
||||
struct stream_client_sx *next;
|
||||
} stream_client_s;
|
||||
|
||||
struct exposed_t {
|
||||
struct frame_t *frame;
|
||||
typedef struct {
|
||||
frame_s *frame;
|
||||
unsigned captured_fps;
|
||||
unsigned queued_fps;
|
||||
bool online;
|
||||
@@ -106,21 +106,21 @@ struct exposed_t {
|
||||
bool notify_last_online;
|
||||
unsigned notify_last_width;
|
||||
unsigned notify_last_height;
|
||||
};
|
||||
} exposed_s;
|
||||
|
||||
struct http_server_runtime_t {
|
||||
struct event_base *base;
|
||||
struct evhttp *http;
|
||||
evutil_socket_t unix_fd;
|
||||
char *auth_token;
|
||||
struct event *refresh;
|
||||
struct stream_t *stream;
|
||||
struct exposed_t *exposed;
|
||||
struct stream_client_t *stream_clients;
|
||||
unsigned stream_clients_count;
|
||||
};
|
||||
typedef struct {
|
||||
struct event_base *base;
|
||||
struct evhttp *http;
|
||||
evutil_socket_t unix_fd;
|
||||
char *auth_token;
|
||||
struct event *refresh;
|
||||
stream_s *stream;
|
||||
exposed_s *exposed;
|
||||
stream_client_s *stream_clients;
|
||||
unsigned stream_clients_count;
|
||||
} server_runtime_s;
|
||||
|
||||
struct http_server_t {
|
||||
typedef struct server_sx {
|
||||
char *host;
|
||||
unsigned port;
|
||||
char *unix_path;
|
||||
@@ -141,13 +141,13 @@ struct http_server_t {
|
||||
|
||||
bool notify_parent;
|
||||
|
||||
struct http_server_runtime_t *run;
|
||||
};
|
||||
server_runtime_s *run;
|
||||
} server_s;
|
||||
|
||||
|
||||
struct http_server_t *http_server_init(struct stream_t *stream);
|
||||
void http_server_destroy(struct http_server_t *server);
|
||||
server_s *server_init(stream_s *stream);
|
||||
void server_destroy(server_s *server);
|
||||
|
||||
int http_server_listen(struct http_server_t *server);
|
||||
void http_server_loop(struct http_server_t *server);
|
||||
void http_server_loop_break(struct http_server_t *server);
|
||||
int server_listen(server_s *server);
|
||||
void server_loop(server_s *server);
|
||||
void server_loop_break(server_s *server);
|
||||
|
||||
@@ -50,12 +50,12 @@
|
||||
#endif
|
||||
|
||||
|
||||
struct _main_context_t {
|
||||
struct stream_t *stream;
|
||||
struct http_server_t *server;
|
||||
};
|
||||
typedef struct {
|
||||
stream_s *stream;
|
||||
server_s *server;
|
||||
} _main_context_s;
|
||||
|
||||
static struct _main_context_t *_ctx;
|
||||
static _main_context_s *_ctx;
|
||||
|
||||
static void _block_thread_signals(void) {
|
||||
sigset_t mask;
|
||||
@@ -75,14 +75,14 @@ static void *_stream_loop_thread(UNUSED void *arg) {
|
||||
static void *_server_loop_thread(UNUSED void *arg) {
|
||||
A_THREAD_RENAME("http");
|
||||
_block_thread_signals();
|
||||
http_server_loop(_ctx->server);
|
||||
server_loop(_ctx->server);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _signal_handler(int signum) {
|
||||
LOG_INFO_NOLOCK("===== Stopping by %s =====", (signum == SIGTERM ? "SIGTERM" : "SIGINT"));
|
||||
stream_loop_break(_ctx->stream);
|
||||
http_server_loop_break(_ctx->server);
|
||||
server_loop_break(_ctx->server);
|
||||
}
|
||||
|
||||
static void _install_signal_handlers(void) {
|
||||
@@ -105,11 +105,11 @@ static void _install_signal_handlers(void) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
struct options_t *options;
|
||||
struct device_t *dev;
|
||||
struct encoder_t *encoder;
|
||||
struct stream_t *stream;
|
||||
struct http_server_t *server;
|
||||
options_s *options;
|
||||
device_s *dev;
|
||||
encoder_s *encoder;
|
||||
stream_s *stream;
|
||||
server_s *server;
|
||||
int exit_code = 0;
|
||||
|
||||
LOGGING_INIT;
|
||||
@@ -119,7 +119,7 @@ int main(int argc, char *argv[]) {
|
||||
dev = device_init();
|
||||
encoder = encoder_init();
|
||||
stream = stream_init(dev, encoder);
|
||||
server = http_server_init(stream);
|
||||
server = server_init(stream);
|
||||
|
||||
if ((exit_code = options_parse(options, dev, encoder, stream, server)) == 0) {
|
||||
# ifdef WITH_GPIO
|
||||
@@ -130,13 +130,13 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
pthread_t stream_loop_tid;
|
||||
pthread_t server_loop_tid;
|
||||
struct _main_context_t ctx;
|
||||
_main_context_s ctx;
|
||||
|
||||
ctx.stream = stream;
|
||||
ctx.server = server;
|
||||
_ctx = &ctx;
|
||||
|
||||
if ((exit_code = http_server_listen(server)) == 0) {
|
||||
if ((exit_code = server_listen(server)) == 0) {
|
||||
# ifdef WITH_GPIO
|
||||
gpio_set_prog_running(true);
|
||||
# endif
|
||||
@@ -153,7 +153,7 @@ int main(int argc, char *argv[]) {
|
||||
# endif
|
||||
}
|
||||
|
||||
http_server_destroy(server);
|
||||
server_destroy(server);
|
||||
stream_destroy(stream);
|
||||
encoder_destroy(encoder);
|
||||
device_destroy(dev);
|
||||
|
||||
@@ -205,18 +205,15 @@ static const struct option _LONG_OPTS[] = {
|
||||
|
||||
static int _parse_resolution(const char *str, unsigned *width, unsigned *height, bool limited);
|
||||
#ifdef WITH_OMX
|
||||
static int _parse_glitched_resolutions(const char *str, struct encoder_t *encoder);
|
||||
static int _parse_glitched_resolutions(const char *str, encoder_s *encoder);
|
||||
#endif
|
||||
|
||||
static void _features(void);
|
||||
|
||||
static void _help(
|
||||
struct device_t *dev, struct encoder_t *encoder,
|
||||
struct stream_t *stream, struct http_server_t *server);
|
||||
static void _help(device_s *dev, encoder_s *encoder, stream_s *stream, server_s *server);
|
||||
|
||||
|
||||
struct options_t *options_init(int argc, char *argv[]) {
|
||||
struct options_t *options;
|
||||
options_s *options_init(int argc, char *argv[]) {
|
||||
options_s *options;
|
||||
|
||||
A_CALLOC(options, 1);
|
||||
options->argc = argc;
|
||||
@@ -230,7 +227,7 @@ struct options_t *options_init(int argc, char *argv[]) {
|
||||
return options;
|
||||
}
|
||||
|
||||
void options_destroy(struct options_t *options) {
|
||||
void options_destroy(options_s *options) {
|
||||
if (options->blank) {
|
||||
frame_destroy(options->blank);
|
||||
}
|
||||
@@ -242,10 +239,7 @@ void options_destroy(struct options_t *options) {
|
||||
}
|
||||
|
||||
|
||||
int options_parse(
|
||||
struct options_t *options, struct device_t *dev, struct encoder_t *encoder,
|
||||
struct stream_t *stream, struct http_server_t *server) {
|
||||
|
||||
int options_parse(options_s *options, device_s *dev, encoder_s *encoder, stream_s *stream, server_s *server) {
|
||||
# define OPT_SET(_dest, _value) { \
|
||||
_dest = _value; \
|
||||
break; \
|
||||
@@ -487,7 +481,7 @@ static int _parse_resolution(const char *str, unsigned *width, unsigned *height,
|
||||
}
|
||||
|
||||
#ifdef WITH_OMX
|
||||
static int _parse_glitched_resolutions(const char *str, struct encoder_t *encoder) {
|
||||
static int _parse_glitched_resolutions(const char *str, encoder_s *encoder) {
|
||||
char *str_copy;
|
||||
char *ptr;
|
||||
unsigned count = 0;
|
||||
@@ -574,10 +568,7 @@ static void _features(void) {
|
||||
# endif
|
||||
}
|
||||
|
||||
static void _help(
|
||||
struct device_t *dev, struct encoder_t *encoder,
|
||||
struct stream_t *stream, struct http_server_t *server) {
|
||||
|
||||
static void _help(device_s *dev, encoder_s *encoder, stream_s *stream, server_s *server) {
|
||||
printf("\nuStreamer - Lightweight and fast MJPG-HTTP streamer\n");
|
||||
printf("═══════════════════════════════════════════════════\n\n");
|
||||
printf("Version: %s; license: GPLv3\n", VERSION);
|
||||
|
||||
@@ -48,17 +48,15 @@
|
||||
#endif
|
||||
|
||||
|
||||
struct options_t {
|
||||
int argc;
|
||||
char **argv;
|
||||
char **argv_copy;
|
||||
struct frame_t *blank;
|
||||
};
|
||||
typedef struct {
|
||||
int argc;
|
||||
char **argv;
|
||||
char **argv_copy;
|
||||
frame_s *blank;
|
||||
} options_s;
|
||||
|
||||
|
||||
struct options_t *options_init(int argc, char *argv[]);
|
||||
void options_destroy(struct options_t *options);
|
||||
options_s *options_init(int argc, char *argv[]);
|
||||
void options_destroy(options_s *options);
|
||||
|
||||
int options_parse(
|
||||
struct options_t *options, struct device_t *dev, struct encoder_t *encoder,
|
||||
struct stream_t *stream, struct http_server_t *server);
|
||||
int options_parse(options_s *options, device_s *dev, encoder_s *encoder, stream_s *stream, server_s *server);
|
||||
|
||||
@@ -23,70 +23,70 @@
|
||||
#include "stream.h"
|
||||
|
||||
|
||||
struct _worker_t {
|
||||
pthread_t tid;
|
||||
unsigned number;
|
||||
atomic_bool *proc_stop;
|
||||
atomic_bool *workers_stop;
|
||||
typedef struct _worker_sx {
|
||||
pthread_t tid;
|
||||
unsigned number;
|
||||
atomic_bool *proc_stop;
|
||||
atomic_bool *workers_stop;
|
||||
|
||||
long double last_comp_time;
|
||||
char *frame_role;
|
||||
struct frame_t *frame;
|
||||
long double last_comp_time;
|
||||
char *frame_role;
|
||||
frame_s *frame;
|
||||
|
||||
pthread_mutex_t has_job_mutex;
|
||||
unsigned buf_index;
|
||||
atomic_bool has_job;
|
||||
bool job_timely;
|
||||
bool job_failed;
|
||||
long double job_start_ts;
|
||||
pthread_cond_t has_job_cond;
|
||||
pthread_mutex_t has_job_mutex;
|
||||
unsigned buf_index;
|
||||
atomic_bool has_job;
|
||||
bool job_timely;
|
||||
bool job_failed;
|
||||
long double job_start_ts;
|
||||
pthread_cond_t has_job_cond;
|
||||
|
||||
pthread_mutex_t *free_workers_mutex;
|
||||
unsigned *free_workers;
|
||||
pthread_cond_t *free_workers_cond;
|
||||
pthread_mutex_t *free_workers_mutex;
|
||||
unsigned *free_workers;
|
||||
pthread_cond_t *free_workers_cond;
|
||||
|
||||
struct _worker_t *order_prev;
|
||||
struct _worker_t *order_next;
|
||||
struct _worker_sx *order_prev;
|
||||
struct _worker_sx *order_next;
|
||||
|
||||
struct stream_t *stream;
|
||||
};
|
||||
stream_s *stream;
|
||||
} _worker_s;
|
||||
|
||||
struct _workers_pool_t {
|
||||
unsigned n_workers;
|
||||
struct _worker_t *workers;
|
||||
struct _worker_t *oldest_wr;
|
||||
struct _worker_t *latest_wr;
|
||||
typedef struct {
|
||||
unsigned n_workers;
|
||||
_worker_s *workers;
|
||||
_worker_s *oldest_wr;
|
||||
_worker_s *latest_wr;
|
||||
|
||||
long double approx_comp_time;
|
||||
long double approx_comp_time;
|
||||
|
||||
pthread_mutex_t free_workers_mutex;
|
||||
unsigned free_workers;
|
||||
pthread_cond_t free_workers_cond;
|
||||
pthread_mutex_t free_workers_mutex;
|
||||
unsigned free_workers;
|
||||
pthread_cond_t free_workers_cond;
|
||||
|
||||
atomic_bool workers_stop;
|
||||
atomic_bool workers_stop;
|
||||
|
||||
long double desired_frames_interval;
|
||||
};
|
||||
long double desired_frames_interval;
|
||||
} _pool_s;
|
||||
|
||||
|
||||
static struct _workers_pool_t *_stream_init_loop(struct stream_t *stream);
|
||||
static struct _workers_pool_t *_stream_init_one(struct stream_t *stream);
|
||||
static void _stream_expose_frame(struct stream_t *stream, struct frame_t *frame, unsigned captured_fps);
|
||||
static _pool_s *_stream_init_loop(stream_s *stream);
|
||||
static _pool_s *_stream_init_one(stream_s *stream);
|
||||
static void _stream_expose_frame(stream_s *stream, frame_s *frame, unsigned captured_fps);
|
||||
|
||||
static struct _workers_pool_t *_workers_pool_init(struct stream_t *stream);
|
||||
static void _workers_pool_destroy(struct _workers_pool_t *pool);
|
||||
static _pool_s *_workers_pool_init(stream_s *stream);
|
||||
static void _workers_pool_destroy(_pool_s *pool);
|
||||
|
||||
static void *_worker_thread(void *v_worker);
|
||||
|
||||
static struct _worker_t *_workers_pool_wait(struct _workers_pool_t *pool);
|
||||
static void _workers_pool_assign(struct _workers_pool_t *pool, struct _worker_t *ready_wr, unsigned buf_index);
|
||||
static long double _workers_pool_get_fluency_delay(struct _workers_pool_t *pool, struct _worker_t *ready_wr);
|
||||
static _worker_s *_workers_pool_wait(_pool_s *pool);
|
||||
static void _workers_pool_assign(_pool_s *pool, _worker_s *ready_wr, unsigned buf_index);
|
||||
static long double _workers_pool_get_fluency_delay(_pool_s *pool, _worker_s *ready_wr);
|
||||
|
||||
|
||||
struct stream_t *stream_init(struct device_t *dev, struct encoder_t *encoder) {
|
||||
struct process_t *proc;
|
||||
struct video_t *video;
|
||||
struct stream_t *stream;
|
||||
stream_s *stream_init(device_s *dev, encoder_s *encoder) {
|
||||
process_s *proc;
|
||||
video_s *video;
|
||||
stream_s *stream;
|
||||
|
||||
A_CALLOC(proc, 1);
|
||||
atomic_init(&proc->stop, false);
|
||||
@@ -111,7 +111,7 @@ struct stream_t *stream_init(struct device_t *dev, struct encoder_t *encoder) {
|
||||
return stream;
|
||||
}
|
||||
|
||||
void stream_destroy(struct stream_t *stream) {
|
||||
void stream_destroy(stream_s *stream) {
|
||||
A_MUTEX_DESTROY(&stream->video->mutex);
|
||||
frame_destroy(stream->video->frame);
|
||||
free(stream->video);
|
||||
@@ -119,15 +119,15 @@ void stream_destroy(struct stream_t *stream) {
|
||||
free(stream);
|
||||
}
|
||||
|
||||
void stream_loop(struct stream_t *stream) {
|
||||
void stream_loop(stream_s *stream) {
|
||||
# define DEV(_next) stream->dev->_next
|
||||
struct _workers_pool_t *pool;
|
||||
_pool_s *pool;
|
||||
|
||||
LOG_INFO("Using V4L2 device: %s", DEV(path));
|
||||
LOG_INFO("Using desired FPS: %u", DEV(desired_fps));
|
||||
|
||||
# ifdef WITH_RAWSINK
|
||||
struct rawsink_t *rawsink = NULL;
|
||||
rawsink_s *rawsink = NULL;
|
||||
if (stream->rawsink_name[0] != '\0') {
|
||||
rawsink = rawsink_init(stream->rawsink_name, stream->rawsink_mode, stream->rawsink_rm, true);
|
||||
}
|
||||
@@ -143,7 +143,7 @@ void stream_loop(struct stream_t *stream) {
|
||||
LOG_INFO("Capturing ...");
|
||||
|
||||
while (!atomic_load(&stream->proc->stop)) {
|
||||
struct _worker_t *ready_wr;
|
||||
_worker_s *ready_wr;
|
||||
|
||||
SEP_DEBUG('-');
|
||||
LOG_DEBUG("Waiting for worker ...");
|
||||
@@ -272,16 +272,16 @@ void stream_loop(struct stream_t *stream) {
|
||||
# undef DEV
|
||||
}
|
||||
|
||||
void stream_loop_break(struct stream_t *stream) {
|
||||
void stream_loop_break(stream_s *stream) {
|
||||
atomic_store(&stream->proc->stop, true);
|
||||
}
|
||||
|
||||
void stream_switch_slowdown(struct stream_t *stream, bool slowdown) {
|
||||
void stream_switch_slowdown(stream_s *stream, bool slowdown) {
|
||||
atomic_store(&stream->proc->slowdown, slowdown);
|
||||
}
|
||||
|
||||
static struct _workers_pool_t *_stream_init_loop(struct stream_t *stream) {
|
||||
struct _workers_pool_t *pool = NULL;
|
||||
static _pool_s *_stream_init_loop(stream_s *stream) {
|
||||
_pool_s *pool = NULL;
|
||||
int access_error = 0;
|
||||
|
||||
LOG_DEBUG("%s: stream->proc->stop=%d", __FUNCTION__, atomic_load(&stream->proc->stop));
|
||||
@@ -313,7 +313,7 @@ static struct _workers_pool_t *_stream_init_loop(struct stream_t *stream) {
|
||||
return pool;
|
||||
}
|
||||
|
||||
static struct _workers_pool_t *_stream_init_one(struct stream_t *stream) {
|
||||
static _pool_s *_stream_init_one(stream_s *stream) {
|
||||
if (device_open(stream->dev) < 0) {
|
||||
goto error;
|
||||
}
|
||||
@@ -329,10 +329,10 @@ static struct _workers_pool_t *_stream_init_one(struct stream_t *stream) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void _stream_expose_frame(struct stream_t *stream, struct frame_t *frame, unsigned captured_fps) {
|
||||
static void _stream_expose_frame(stream_s *stream, frame_s *frame, unsigned captured_fps) {
|
||||
# define VID(_next) stream->video->_next
|
||||
|
||||
struct frame_t *new = NULL;
|
||||
frame_s *new = NULL;
|
||||
|
||||
A_MUTEX_LOCK(&VID(mutex));
|
||||
|
||||
@@ -382,11 +382,11 @@ static void _stream_expose_frame(struct stream_t *stream, struct frame_t *frame,
|
||||
# undef VID
|
||||
}
|
||||
|
||||
static struct _workers_pool_t *_workers_pool_init(struct stream_t *stream) {
|
||||
static _pool_s *_workers_pool_init(stream_s *stream) {
|
||||
# define DEV(_next) stream->dev->_next
|
||||
# define RUN(_next) stream->dev->run->_next
|
||||
|
||||
struct _workers_pool_t *pool;
|
||||
_pool_s *pool;
|
||||
|
||||
LOG_INFO("Creating pool with %u workers ...", stream->encoder->run->n_workers);
|
||||
|
||||
@@ -437,7 +437,7 @@ static struct _workers_pool_t *_workers_pool_init(struct stream_t *stream) {
|
||||
return pool;
|
||||
}
|
||||
|
||||
static void _workers_pool_destroy(struct _workers_pool_t *pool) {
|
||||
static void _workers_pool_destroy(_pool_s *pool) {
|
||||
LOG_INFO("Destroying workers pool ...");
|
||||
|
||||
atomic_store(&pool->workers_stop, true);
|
||||
@@ -467,7 +467,7 @@ static void _workers_pool_destroy(struct _workers_pool_t *pool) {
|
||||
}
|
||||
|
||||
static void *_worker_thread(void *v_worker) {
|
||||
struct _worker_t *wr = (struct _worker_t *)v_worker;
|
||||
_worker_s *wr = (_worker_s *)v_worker;
|
||||
|
||||
A_THREAD_RENAME("worker-%u", wr->number);
|
||||
LOG_DEBUG("Hello! I am a worker #%u ^_^", wr->number);
|
||||
@@ -520,8 +520,8 @@ static void *_worker_thread(void *v_worker) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct _worker_t *_workers_pool_wait(struct _workers_pool_t *pool) {
|
||||
struct _worker_t *ready_wr = NULL;
|
||||
static _worker_s *_workers_pool_wait(_pool_s *pool) {
|
||||
_worker_s *ready_wr = NULL;
|
||||
|
||||
A_MUTEX_LOCK(&pool->free_workers_mutex);
|
||||
A_COND_WAIT_TRUE(pool->free_workers, &pool->free_workers_cond, &pool->free_workers_mutex);
|
||||
@@ -549,7 +549,7 @@ static struct _worker_t *_workers_pool_wait(struct _workers_pool_t *pool) {
|
||||
return ready_wr;
|
||||
}
|
||||
|
||||
static void _workers_pool_assign(struct _workers_pool_t *pool, struct _worker_t *ready_wr, unsigned buf_index) {
|
||||
static void _workers_pool_assign(_pool_s *pool, _worker_s *ready_wr, unsigned buf_index) {
|
||||
if (pool->oldest_wr == NULL) {
|
||||
pool->oldest_wr = ready_wr;
|
||||
pool->latest_wr = pool->oldest_wr;
|
||||
@@ -579,7 +579,7 @@ static void _workers_pool_assign(struct _workers_pool_t *pool, struct _worker_t
|
||||
LOG_DEBUG("Assigned new frame in buffer %u to worker %u", buf_index, ready_wr->number);
|
||||
}
|
||||
|
||||
static long double _workers_pool_get_fluency_delay(struct _workers_pool_t *pool, struct _worker_t *ready_wr) {
|
||||
static long double _workers_pool_get_fluency_delay(_pool_s *pool, _worker_s *ready_wr) {
|
||||
long double approx_comp_time;
|
||||
long double min_delay;
|
||||
|
||||
|
||||
@@ -48,21 +48,21 @@
|
||||
#endif
|
||||
|
||||
|
||||
struct process_t {
|
||||
typedef struct {
|
||||
atomic_bool stop;
|
||||
atomic_bool slowdown;
|
||||
};
|
||||
} process_s;
|
||||
|
||||
struct video_t {
|
||||
struct frame_t *frame;
|
||||
bool online;
|
||||
unsigned captured_fps;
|
||||
atomic_bool updated;
|
||||
long double last_as_blank_ts;
|
||||
pthread_mutex_t mutex;
|
||||
};
|
||||
typedef struct {
|
||||
frame_s *frame;
|
||||
bool online;
|
||||
unsigned captured_fps;
|
||||
atomic_bool updated;
|
||||
long double last_as_blank_ts;
|
||||
pthread_mutex_t mutex;
|
||||
} video_s;
|
||||
|
||||
struct stream_t {
|
||||
typedef struct {
|
||||
int last_as_blank;
|
||||
unsigned error_delay;
|
||||
# ifdef WITH_RAWSINK
|
||||
@@ -71,18 +71,18 @@ struct stream_t {
|
||||
bool rawsink_rm;
|
||||
# endif
|
||||
|
||||
struct device_t *dev;
|
||||
struct encoder_t *encoder;
|
||||
struct frame_t *blank;
|
||||
device_s *dev;
|
||||
encoder_s *encoder;
|
||||
frame_s *blank;
|
||||
|
||||
struct process_t *proc;
|
||||
struct video_t *video;
|
||||
};
|
||||
process_s *proc;
|
||||
video_s *video;
|
||||
} stream_s;
|
||||
|
||||
|
||||
struct stream_t *stream_init(struct device_t *dev, struct encoder_t *encoder);
|
||||
void stream_destroy(struct stream_t *stream);
|
||||
stream_s *stream_init(device_s *dev, encoder_s *encoder);
|
||||
void stream_destroy(stream_s *stream);
|
||||
|
||||
void stream_loop(struct stream_t *stream);
|
||||
void stream_loop_break(struct stream_t *stream);
|
||||
void stream_switch_slowdown(struct stream_t *stream, bool slowdown);
|
||||
void stream_loop(stream_s *stream);
|
||||
void stream_loop_break(stream_s *stream);
|
||||
void stream_switch_slowdown(stream_s *stream, bool slowdown);
|
||||
|
||||
Reference in New Issue
Block a user