mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-27 20:26:31 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53feba1248 | ||
|
|
119821d5af | ||
|
|
4faabf27ec | ||
|
|
191f6e3c09 | ||
|
|
4e51439118 | ||
|
|
e184e187a2 | ||
|
|
592568c9aa | ||
|
|
46c5a547a9 | ||
|
|
3d097a4ffb | ||
|
|
00e32c915c | ||
|
|
d44c340dce | ||
|
|
8c18f1dffe | ||
|
|
c3c386ea5b | ||
|
|
fa09992c46 | ||
|
|
cefcd0c963 |
@@ -1,7 +1,7 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
current_version = 1.20
|
current_version = 1.22
|
||||||
parse = (?P<major>\d+)\.(?P<minor>\d+)(\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?)?
|
parse = (?P<major>\d+)\.(?P<minor>\d+)(\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?)?
|
||||||
serialize =
|
serialize =
|
||||||
{major}.{minor}
|
{major}.{minor}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
pkgname=ustreamer
|
pkgname=ustreamer
|
||||||
pkgver=1.20
|
pkgver=1.22
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
|
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
|
||||||
url="https://github.com/pikvm/ustreamer"
|
url="https://github.com/pikvm/ustreamer"
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=ustreamer
|
PKG_NAME:=ustreamer
|
||||||
PKG_VERSION:=1.20
|
PKG_VERSION:=1.22
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
||||||
|
|
||||||
|
|||||||
@@ -23,5 +23,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
# define VERSION "1.20"
|
# define VERSION "1.22"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -120,6 +120,7 @@ struct device_t *device_init(void) {
|
|||||||
dev->standard = V4L2_STD_UNKNOWN;
|
dev->standard = V4L2_STD_UNKNOWN;
|
||||||
dev->n_buffers = cores_available + 1;
|
dev->n_buffers = cores_available + 1;
|
||||||
dev->n_workers = min_u(cores_available, dev->n_buffers);
|
dev->n_workers = min_u(cores_available, dev->n_buffers);
|
||||||
|
dev->min_frame_size = 128;
|
||||||
dev->timeout = 1;
|
dev->timeout = 1;
|
||||||
dev->error_delay = 1;
|
dev->error_delay = 1;
|
||||||
dev->io_method = V4L2_MEMORY_MMAP;
|
dev->io_method = V4L2_MEMORY_MMAP;
|
||||||
@@ -736,6 +737,9 @@ static void _device_apply_controls(struct device_t *dev) {
|
|||||||
CONTROL_MANUAL_CID ( V4L2_CID_BACKLIGHT_COMPENSATION, backlight_compensation);
|
CONTROL_MANUAL_CID ( V4L2_CID_BACKLIGHT_COMPENSATION, backlight_compensation);
|
||||||
CONTROL_AUTO_CID (V4L2_CID_AUTO_WHITE_BALANCE, V4L2_CID_WHITE_BALANCE_TEMPERATURE, white_balance);
|
CONTROL_AUTO_CID (V4L2_CID_AUTO_WHITE_BALANCE, V4L2_CID_WHITE_BALANCE_TEMPERATURE, white_balance);
|
||||||
CONTROL_AUTO_CID (V4L2_CID_AUTOGAIN, V4L2_CID_GAIN, gain);
|
CONTROL_AUTO_CID (V4L2_CID_AUTOGAIN, V4L2_CID_GAIN, gain);
|
||||||
|
CONTROL_MANUAL_CID ( V4L2_CID_COLORFX, color_effect);
|
||||||
|
CONTROL_MANUAL_CID ( V4L2_CID_VFLIP, flip_vertical);
|
||||||
|
CONTROL_MANUAL_CID ( V4L2_CID_HFLIP, flip_horizontal);
|
||||||
|
|
||||||
# undef CONTROL_AUTO_CID
|
# undef CONTROL_AUTO_CID
|
||||||
# undef CONTROL_MANUAL_CID
|
# undef CONTROL_MANUAL_CID
|
||||||
|
|||||||
@@ -90,6 +90,9 @@ struct controls_t {
|
|||||||
struct control_t backlight_compensation;
|
struct control_t backlight_compensation;
|
||||||
struct control_t white_balance;
|
struct control_t white_balance;
|
||||||
struct control_t gain;
|
struct control_t gain;
|
||||||
|
struct control_t color_effect;
|
||||||
|
struct control_t flip_vertical;
|
||||||
|
struct control_t flip_horizontal;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct device_t {
|
struct device_t {
|
||||||
|
|||||||
@@ -201,16 +201,20 @@ int encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, uns
|
|||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
assert(encoder->run->type != ENCODER_TYPE_UNKNOWN);
|
assert(encoder->run->type != ENCODER_TYPE_UNKNOWN);
|
||||||
|
assert(dev->run->hw_buffers[buf_index].used > 0);
|
||||||
|
|
||||||
dev->run->pictures[buf_index]->encode_begin_ts = get_now_monotonic();
|
dev->run->pictures[buf_index]->encode_begin_ts = get_now_monotonic();
|
||||||
|
|
||||||
if (encoder->run->type == ENCODER_TYPE_CPU) {
|
if (encoder->run->type == ENCODER_TYPE_CPU) {
|
||||||
|
LOG_VERBOSE("Compressing buffer %u using CPU", buf_index);
|
||||||
cpu_encoder_compress_buffer(dev, buf_index, encoder->run->quality);
|
cpu_encoder_compress_buffer(dev, buf_index, encoder->run->quality);
|
||||||
} else if (encoder->run->type == ENCODER_TYPE_HW) {
|
} else if (encoder->run->type == ENCODER_TYPE_HW) {
|
||||||
|
LOG_VERBOSE("Compressing buffer %u using HW (just copying)", buf_index);
|
||||||
hw_encoder_compress_buffer(dev, buf_index);
|
hw_encoder_compress_buffer(dev, buf_index);
|
||||||
}
|
}
|
||||||
# ifdef WITH_OMX
|
# ifdef WITH_OMX
|
||||||
else if (encoder->run->type == ENCODER_TYPE_OMX) {
|
else if (encoder->run->type == ENCODER_TYPE_OMX) {
|
||||||
|
LOG_VERBOSE("Compressing buffer %u using OMX", buf_index);
|
||||||
if (omx_encoder_compress_buffer(encoder->run->omxs[worker_number], dev, buf_index) < 0) {
|
if (omx_encoder_compress_buffer(encoder->run->omxs[worker_number], dev, buf_index) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,11 +102,11 @@ struct omx_encoder_t *omx_encoder_init(void) {
|
|||||||
|
|
||||||
LOG_INFO("Initializing OMX encoder ...");
|
LOG_INFO("Initializing OMX encoder ...");
|
||||||
|
|
||||||
if (vcos_semaphore_create(&omx->handler_lock, "handler_lock", 0) != VCOS_SUCCESS) {
|
if (vcos_semaphore_create(&omx->handler_sem, "handler_sem", 0) != VCOS_SUCCESS) {
|
||||||
LOG_ERROR("Can't create VCOS semaphore");
|
LOG_ERROR("Can't create VCOS semaphore");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
omx->i_handler_lock = true;
|
omx->i_handler_sem = true;
|
||||||
|
|
||||||
if (_omx_init_component(omx) < 0) {
|
if (_omx_init_component(omx) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
@@ -132,8 +132,8 @@ void omx_encoder_destroy(struct omx_encoder_t *omx) {
|
|||||||
_omx_encoder_clear_ports(omx);
|
_omx_encoder_clear_ports(omx);
|
||||||
component_set_state(&omx->encoder, OMX_StateLoaded);
|
component_set_state(&omx->encoder, OMX_StateLoaded);
|
||||||
|
|
||||||
if (omx->i_handler_lock) {
|
if (omx->i_handler_sem) {
|
||||||
vcos_semaphore_delete(&omx->handler_lock);
|
vcos_semaphore_delete(&omx->handler_sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (omx->i_encoder) {
|
if (omx->i_encoder) {
|
||||||
@@ -180,6 +180,7 @@ int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct device_t *dev,
|
|||||||
# define OUT(_next) omx->output_buffer->_next
|
# define OUT(_next) omx->output_buffer->_next
|
||||||
|
|
||||||
OMX_ERRORTYPE error;
|
OMX_ERRORTYPE error;
|
||||||
|
VCOS_STATUS_T sem_status;
|
||||||
size_t slice_size = (IN(nAllocLen) < HW_BUFFER(used) ? IN(nAllocLen) : HW_BUFFER(used));
|
size_t slice_size = (IN(nAllocLen) < HW_BUFFER(used) ? IN(nAllocLen) : HW_BUFFER(used));
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
|
|
||||||
@@ -236,7 +237,13 @@ int omx_encoder_compress_buffer(struct omx_encoder_t *omx, struct device_t *dev,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vcos_semaphore_wait(&omx->handler_lock);
|
// vcos_semaphore_wait(&omx->handler_sem);
|
||||||
|
switch (sem_status = vcos_semaphore_wait_timeout(&omx->handler_sem, 3000)) {
|
||||||
|
case VCOS_SUCCESS: break;
|
||||||
|
case VCOS_EAGAIN: LOG_ERROR("Can't wait VCOS semaphore: EAGAIN (timeout)"); return -1;
|
||||||
|
case VCOS_EINVAL: LOG_ERROR("Can't wait VCOS semaphore: EINTVAL"); return -1;
|
||||||
|
default: LOG_ERROR("Can't wait VCOS semaphore: %d", sem_status); return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# undef OUT
|
# undef OUT
|
||||||
@@ -466,7 +473,7 @@ static OMX_ERRORTYPE _omx_event_handler(
|
|||||||
if (event == OMX_EventError) {
|
if (event == OMX_EventError) {
|
||||||
LOG_ERROR_OMX((OMX_ERRORTYPE)data1, "OMX error event received");
|
LOG_ERROR_OMX((OMX_ERRORTYPE)data1, "OMX error event received");
|
||||||
omx->failed = true;
|
omx->failed = true;
|
||||||
vcos_semaphore_post(&omx->handler_lock);
|
assert(vcos_semaphore_post(&omx->handler_sem) == VCOS_SUCCESS);
|
||||||
}
|
}
|
||||||
return OMX_ErrorNone;
|
return OMX_ErrorNone;
|
||||||
}
|
}
|
||||||
@@ -481,7 +488,7 @@ static OMX_ERRORTYPE _omx_input_required_handler(
|
|||||||
struct omx_encoder_t *omx = (struct omx_encoder_t *)v_omx;
|
struct omx_encoder_t *omx = (struct omx_encoder_t *)v_omx;
|
||||||
|
|
||||||
omx->input_required = true;
|
omx->input_required = true;
|
||||||
vcos_semaphore_post(&omx->handler_lock);
|
assert(vcos_semaphore_post(&omx->handler_sem) == VCOS_SUCCESS);
|
||||||
return OMX_ErrorNone;
|
return OMX_ErrorNone;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -495,6 +502,6 @@ static OMX_ERRORTYPE _omx_output_available_handler(
|
|||||||
struct omx_encoder_t *omx = (struct omx_encoder_t *)v_omx;
|
struct omx_encoder_t *omx = (struct omx_encoder_t *)v_omx;
|
||||||
|
|
||||||
omx->output_available = true;
|
omx->output_available = true;
|
||||||
vcos_semaphore_post(&omx->handler_lock);
|
assert(vcos_semaphore_post(&omx->handler_sem) == VCOS_SUCCESS);
|
||||||
return OMX_ErrorNone;
|
return OMX_ErrorNone;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,9 +42,9 @@ struct omx_encoder_t {
|
|||||||
bool input_required;
|
bool input_required;
|
||||||
bool output_available;
|
bool output_available;
|
||||||
bool failed;
|
bool failed;
|
||||||
VCOS_SEMAPHORE_T handler_lock;
|
VCOS_SEMAPHORE_T handler_sem;
|
||||||
|
|
||||||
bool i_handler_lock;
|
bool i_handler_sem;
|
||||||
bool i_encoder;
|
bool i_encoder;
|
||||||
bool i_input_port_enabled;
|
bool i_input_port_enabled;
|
||||||
bool i_output_port_enabled;
|
bool i_output_port_enabled;
|
||||||
|
|||||||
@@ -31,10 +31,12 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include <netinet/tcp.h>
|
#include <sys/types.h>
|
||||||
#include <netinet/ip.h>
|
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <netinet/tcp.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <netinet/ip.h>
|
||||||
|
|
||||||
#include <event2/event.h>
|
#include <event2/event.h>
|
||||||
#include <event2/thread.h>
|
#include <event2/thread.h>
|
||||||
@@ -233,6 +235,9 @@ int http_server_listen(struct http_server_t *server) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
LOG_INFO("Listening HTTP on UNIX socket '%s'", server->unix_path);
|
LOG_INFO("Listening HTTP on UNIX socket '%s'", server->unix_path);
|
||||||
|
if (server->tcp_nodelay) {
|
||||||
|
LOG_ERROR("TCP_NODELAY flag can't be used with UNIX socket and will be ignored");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
LOG_DEBUG("Binding HTTP to [%s]:%u ...", server->host, server->port);
|
LOG_DEBUG("Binding HTTP to [%s]:%u ...", server->host, server->port);
|
||||||
if (evhttp_bind_socket(server->run->http, server->host, server->port) < 0) {
|
if (evhttp_bind_socket(server->run->http, server->host, server->port) < 0) {
|
||||||
@@ -545,9 +550,10 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server
|
|||||||
evutil_socket_t fd;
|
evutil_socket_t fd;
|
||||||
int on = 1;
|
int on = 1;
|
||||||
|
|
||||||
|
LOG_DEBUG("HTTP: Setting up TCP_NODELAY to the client [%s]:%u ...", client_addr, client_port);
|
||||||
assert((fd = bufferevent_getfd(buf_event)) >= 0);
|
assert((fd = bufferevent_getfd(buf_event)) >= 0);
|
||||||
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)) != 0) {
|
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void *)&on, sizeof(on)) != 0) {
|
||||||
LOG_PERROR("HTTP: Can't set TCP_NODELAY to the client socket [%s]:%u", client_addr, client_port);
|
LOG_PERROR("HTTP: Can't set TCP_NODELAY to the client [%s]:%u", client_addr, client_port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bufferevent_setcb(buf_event, NULL, NULL, _http_callback_stream_error, (void *)client);
|
bufferevent_setcb(buf_event, NULL, NULL, _http_callback_stream_error, (void *)client);
|
||||||
@@ -738,6 +744,7 @@ static void _http_queue_send_stream(struct http_server_t *server, bool stream_up
|
|||||||
struct evhttp_connection *conn;
|
struct evhttp_connection *conn;
|
||||||
struct bufferevent *buf_event;
|
struct bufferevent *buf_event;
|
||||||
long long now;
|
long long now;
|
||||||
|
bool has_clients = false;
|
||||||
bool queued = false;
|
bool queued = false;
|
||||||
|
|
||||||
for (struct stream_client_t *client = server->run->stream_clients; client != NULL; client = client->next) {
|
for (struct stream_client_t *client = server->run->stream_clients; client != NULL; client = client->next) {
|
||||||
@@ -768,6 +775,8 @@ static void _http_queue_send_stream(struct http_server_t *server, bool stream_up
|
|||||||
} else if (stream_updated) { // Для dual
|
} else if (stream_updated) { // Для dual
|
||||||
client->updated_prev = false;
|
client->updated_prev = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
has_clients = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -781,6 +790,8 @@ static void _http_queue_send_stream(struct http_server_t *server, bool stream_up
|
|||||||
queued_fps_second = now;
|
queued_fps_second = now;
|
||||||
}
|
}
|
||||||
queued_fps_accum += 1;
|
queued_fps_accum += 1;
|
||||||
|
} else if (!has_clients) {
|
||||||
|
server->run->exposed->queued_fps = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -92,6 +92,9 @@ enum _OPT_VALUES {
|
|||||||
_O_BACKLIGHT_COMPENSATION,
|
_O_BACKLIGHT_COMPENSATION,
|
||||||
_O_WHITE_BALANCE,
|
_O_WHITE_BALANCE,
|
||||||
_O_GAIN,
|
_O_GAIN,
|
||||||
|
_O_COLOR_EFFECT,
|
||||||
|
_O_FLIP_VERTICAL,
|
||||||
|
_O_FLIP_HORIZONTAL,
|
||||||
|
|
||||||
_O_USER,
|
_O_USER,
|
||||||
_O_PASSWD,
|
_O_PASSWD,
|
||||||
@@ -155,6 +158,9 @@ static const struct option _LONG_OPTS[] = {
|
|||||||
{"backlight-compensation", required_argument, NULL, _O_BACKLIGHT_COMPENSATION},
|
{"backlight-compensation", required_argument, NULL, _O_BACKLIGHT_COMPENSATION},
|
||||||
{"white-balance", required_argument, NULL, _O_WHITE_BALANCE},
|
{"white-balance", required_argument, NULL, _O_WHITE_BALANCE},
|
||||||
{"gain", required_argument, NULL, _O_GAIN},
|
{"gain", required_argument, NULL, _O_GAIN},
|
||||||
|
{"color-effect", required_argument, NULL, _O_COLOR_EFFECT},
|
||||||
|
{"flip-vertical", required_argument, NULL, _O_FLIP_VERTICAL},
|
||||||
|
{"flip-horizontal", required_argument, NULL, _O_FLIP_HORIZONTAL},
|
||||||
|
|
||||||
{"host", required_argument, NULL, _O_HOST},
|
{"host", required_argument, NULL, _O_HOST},
|
||||||
{"port", required_argument, NULL, _O_PORT},
|
{"port", required_argument, NULL, _O_PORT},
|
||||||
@@ -333,7 +339,7 @@ int options_parse(struct options_t *options, struct device_t *dev, struct encode
|
|||||||
case _O_TV_STANDARD: OPT_PARSE("TV standard", dev->standard, device_parse_standard, STANDARD_UNKNOWN, STANDARDS_STR);
|
case _O_TV_STANDARD: OPT_PARSE("TV standard", dev->standard, device_parse_standard, STANDARD_UNKNOWN, STANDARDS_STR);
|
||||||
case _O_IO_METHOD: OPT_PARSE("IO method", dev->io_method, device_parse_io_method, IO_METHOD_UNKNOWN, IO_METHODS_STR);
|
case _O_IO_METHOD: OPT_PARSE("IO method", dev->io_method, device_parse_io_method, IO_METHOD_UNKNOWN, IO_METHODS_STR);
|
||||||
case _O_DESIRED_FPS: OPT_NUMBER("--desired-fps", dev->desired_fps, 0, VIDEO_MAX_FPS, 0);
|
case _O_DESIRED_FPS: OPT_NUMBER("--desired-fps", dev->desired_fps, 0, VIDEO_MAX_FPS, 0);
|
||||||
case _O_MIN_FRAME_SIZE: OPT_NUMBER("--min-frame-size", dev->min_frame_size, 0, 8192, 0);
|
case _O_MIN_FRAME_SIZE: OPT_NUMBER("--min-frame-size", dev->min_frame_size, 1, 8192, 0);
|
||||||
case _O_PERSISTENT: OPT_SET(dev->persistent, true);
|
case _O_PERSISTENT: OPT_SET(dev->persistent, true);
|
||||||
case _O_DV_TIMINGS: OPT_SET(dev->dv_timings, true);
|
case _O_DV_TIMINGS: OPT_SET(dev->dv_timings, true);
|
||||||
case _O_BUFFERS: OPT_NUMBER("--buffers", dev->n_buffers, 1, 32, 0);
|
case _O_BUFFERS: OPT_NUMBER("--buffers", dev->n_buffers, 1, 32, 0);
|
||||||
@@ -360,6 +366,9 @@ int options_parse(struct options_t *options, struct device_t *dev, struct encode
|
|||||||
OPT_CTL_DEFAULT_NOBREAK(backlight_compensation);
|
OPT_CTL_DEFAULT_NOBREAK(backlight_compensation);
|
||||||
OPT_CTL_DEFAULT_NOBREAK(white_balance);
|
OPT_CTL_DEFAULT_NOBREAK(white_balance);
|
||||||
OPT_CTL_DEFAULT_NOBREAK(gain);
|
OPT_CTL_DEFAULT_NOBREAK(gain);
|
||||||
|
OPT_CTL_DEFAULT_NOBREAK(color_effect);
|
||||||
|
OPT_CTL_DEFAULT_NOBREAK(flip_vertical);
|
||||||
|
OPT_CTL_DEFAULT_NOBREAK(flip_horizontal);
|
||||||
break;
|
break;
|
||||||
case _O_BRIGHTNESS: OPT_CTL_AUTO(brightness);
|
case _O_BRIGHTNESS: OPT_CTL_AUTO(brightness);
|
||||||
case _O_CONTRAST: OPT_CTL_MANUAL(contrast);
|
case _O_CONTRAST: OPT_CTL_MANUAL(contrast);
|
||||||
@@ -370,6 +379,9 @@ int options_parse(struct options_t *options, struct device_t *dev, struct encode
|
|||||||
case _O_BACKLIGHT_COMPENSATION: OPT_CTL_MANUAL(backlight_compensation);
|
case _O_BACKLIGHT_COMPENSATION: OPT_CTL_MANUAL(backlight_compensation);
|
||||||
case _O_WHITE_BALANCE: OPT_CTL_AUTO(white_balance);
|
case _O_WHITE_BALANCE: OPT_CTL_AUTO(white_balance);
|
||||||
case _O_GAIN: OPT_CTL_AUTO(gain);
|
case _O_GAIN: OPT_CTL_AUTO(gain);
|
||||||
|
case _O_COLOR_EFFECT: OPT_CTL_MANUAL(color_effect);
|
||||||
|
case _O_FLIP_VERTICAL: OPT_CTL_MANUAL(flip_vertical);
|
||||||
|
case _O_FLIP_HORIZONTAL: OPT_CTL_MANUAL(flip_horizontal);
|
||||||
|
|
||||||
case _O_HOST: OPT_SET(server->host, optarg);
|
case _O_HOST: OPT_SET(server->host, optarg);
|
||||||
case _O_PORT: OPT_NUMBER("--port", server->port, 1, 65535, 0);
|
case _O_PORT: OPT_NUMBER("--port", server->port, 1, 65535, 0);
|
||||||
@@ -559,7 +571,7 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s
|
|||||||
printf(" Available: %s; default: MMAP\n\n", IO_METHODS_STR);
|
printf(" Available: %s; default: MMAP\n\n", IO_METHODS_STR);
|
||||||
printf(" -f|--desired-fps <N> ──────────────── Desired FPS. Default: maximum possible.\n\n");
|
printf(" -f|--desired-fps <N> ──────────────── Desired FPS. Default: maximum possible.\n\n");
|
||||||
printf(" -z|--min-frame-size <N> ───────────── Drop frames smaller then this limit. Useful if the device\n");
|
printf(" -z|--min-frame-size <N> ───────────── Drop frames smaller then this limit. Useful if the device\n");
|
||||||
printf(" produces small-sized garbage frames. Default: disabled.\n\n");
|
printf(" produces small-sized garbage frames. Default: %zu bytes.\n\n", dev->min_frame_size);
|
||||||
printf(" -n|--persistent ───────────────────── Don't re-initialize device on timeout. Default: disabled.\n\n");
|
printf(" -n|--persistent ───────────────────── Don't re-initialize device on timeout. Default: disabled.\n\n");
|
||||||
printf(" -t|--dv-timings ───────────────────── Enable DV timings querying and events processing\n");
|
printf(" -t|--dv-timings ───────────────────── Enable DV timings querying and events processing\n");
|
||||||
printf(" to automatic resolution change. Default: disabled.\n\n");
|
printf(" to automatic resolution change. Default: disabled.\n\n");
|
||||||
@@ -600,6 +612,9 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s
|
|||||||
printf(" --backlight-compensation <N|default> ─ Set backlight compensation. Default: no change.\n\n");
|
printf(" --backlight-compensation <N|default> ─ Set backlight compensation. Default: no change.\n\n");
|
||||||
printf(" --white-balance <N|auto|default> ───── Set white balance. Default: no change.\n\n");
|
printf(" --white-balance <N|auto|default> ───── Set white balance. Default: no change.\n\n");
|
||||||
printf(" --gain <N|auto|default> ────────────── Set gain. Default: no change.\n\n");
|
printf(" --gain <N|auto|default> ────────────── Set gain. Default: no change.\n\n");
|
||||||
|
printf(" --color-effect <N|default> ─────────── Set color effect. Default: no change.\n\n");
|
||||||
|
printf(" --flip-vertical <1|0|default> ──────── Set vertical flip. Default: no change.\n\n");
|
||||||
|
printf(" --flip-horizontal <1|0|default> ────── Set horizontal flip. Default: no change.\n\n");
|
||||||
printf(" Hint: use v4l2-ctl --list-ctrls-menus to query available controls of the device.\n\n");
|
printf(" Hint: use v4l2-ctl --list-ctrls-menus to query available controls of the device.\n\n");
|
||||||
printf("HTTP server options:\n");
|
printf("HTTP server options:\n");
|
||||||
printf("════════════════════\n");
|
printf("════════════════════\n");
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ size_t picture_get_generous_size(unsigned width, unsigned height) {
|
|||||||
|
|
||||||
void picture_realloc_data(struct picture_t *picture, size_t size) {
|
void picture_realloc_data(struct picture_t *picture, size_t size) {
|
||||||
if (picture->allocated < size) {
|
if (picture->allocated < size) {
|
||||||
LOG_DEBUG("Increasing picture 0x%p buffer: %zu -> %zu (+%zu)",
|
LOG_DEBUG("Increasing picture %p buffer: %zu -> %zu (+%zu)",
|
||||||
picture, picture->allocated, size, size - picture->allocated);
|
picture, picture->allocated, size, size - picture->allocated);
|
||||||
A_REALLOC(picture->data, size);
|
A_REALLOC(picture->data, size);
|
||||||
picture->allocated = size;
|
picture->allocated = size;
|
||||||
|
|||||||
21
src/stream.c
21
src/stream.c
@@ -449,23 +449,24 @@ static void *_worker_thread(void *v_worker) {
|
|||||||
GPIO_SET_HIGH_AT(workers_busy_at, worker->number);
|
GPIO_SET_HIGH_AT(workers_busy_at, worker->number);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
if (encoder_compress_buffer(worker->encoder, worker->dev, worker->number, worker->buf_index) < 0) {
|
worker->job_failed = (bool)encoder_compress_buffer(worker->encoder, worker->dev, worker->number, worker->buf_index);
|
||||||
worker->job_failed = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (device_release_buffer(worker->dev, worker->buf_index) == 0) {
|
if (device_release_buffer(worker->dev, worker->buf_index) == 0) {
|
||||||
worker->job_start_ts = PICTURE(encode_begin_ts);
|
if (!worker->job_failed) {
|
||||||
atomic_store(&worker->has_job, false);
|
worker->job_start_ts = PICTURE(encode_begin_ts);
|
||||||
|
worker->last_comp_time = PICTURE(encode_end_ts) - worker->job_start_ts;
|
||||||
|
|
||||||
worker->last_comp_time = PICTURE(encode_end_ts) - worker->job_start_ts;
|
LOG_VERBOSE("Compressed new JPEG: size=%zu, time=%0.3Lf, worker=%u, buffer=%u",
|
||||||
|
PICTURE(used), worker->last_comp_time, worker->number, worker->buf_index);
|
||||||
LOG_VERBOSE("Compressed new JPEG: size=%zu, time=%0.3Lf, worker=%u, buffer=%u",
|
} else {
|
||||||
PICTURE(used), worker->last_comp_time, worker->number, worker->buf_index);
|
LOG_VERBOSE("Compression failed: worker=%u, buffer=%u", worker->number, worker->buf_index);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
worker->job_failed = true;
|
worker->job_failed = true;
|
||||||
atomic_store(&worker->has_job, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic_store(&worker->has_job, false);
|
||||||
|
|
||||||
# undef PICTURE
|
# undef PICTURE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,13 @@ INLINE long double get_now_monotonic(void) {
|
|||||||
time_t sec;
|
time_t sec;
|
||||||
long msec;
|
long msec;
|
||||||
|
|
||||||
|
# if defined(CLOCK_MONOTONIC_RAW)
|
||||||
get_now(CLOCK_MONOTONIC_RAW, &sec, &msec);
|
get_now(CLOCK_MONOTONIC_RAW, &sec, &msec);
|
||||||
|
# elif defined(CLOCK_MONOTONIC_FAST)
|
||||||
|
get_now(CLOCK_MONOTONIC_FAST, &sec, &msec);
|
||||||
|
# else
|
||||||
|
get_now(CLOCK_MONOTONIC, &sec, &msec);
|
||||||
|
# endif
|
||||||
return (long double)sec + ((long double)msec) / 1000;
|
return (long double)sec + ((long double)msec) / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user