mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-03-15 12:03:41 +00:00
enabled slowdown logic for sinks
This commit is contained in:
@@ -106,6 +106,9 @@ Path to JPEG file that will be shown when the device is disconnected during the
|
|||||||
.BR \-K\ \fIsec ", " \-\-last\-as\-blank\ \fIsec
|
.BR \-K\ \fIsec ", " \-\-last\-as\-blank\ \fIsec
|
||||||
Show the last frame received from the camera after it was disconnected, but no more than specified time (or endlessly if 0 is specified). If the device has not yet been online, display 'NO SIGNAL' or the image specified by option \-\-blank. Default: disabled.
|
Show the last frame received from the camera after it was disconnected, but no more than specified time (or endlessly if 0 is specified). If the device has not yet been online, display 'NO SIGNAL' or the image specified by option \-\-blank. Default: disabled.
|
||||||
.TP
|
.TP
|
||||||
|
.BR \-l ", " \-\-slowdown
|
||||||
|
Slowdown capturing to 1 FPS or less when no stream or sink clients are connected. Useful to reduce CPU consumption. Default: disabled.
|
||||||
|
.TP
|
||||||
.BR \-\-device\-timeout\ \fIsec
|
.BR \-\-device\-timeout\ \fIsec
|
||||||
Timeout for device querying. Default: 1.
|
Timeout for device querying. Default: 1.
|
||||||
.TP
|
.TP
|
||||||
@@ -182,9 +185,6 @@ Path to dir with static files instead of embedded root index page. Symlinks are
|
|||||||
.BR \-e\ \fIN ", " \-\-drop\-same\-frames\ \fIN
|
.BR \-e\ \fIN ", " \-\-drop\-same\-frames\ \fIN
|
||||||
Don't send identical frames to clients, but no more than specified number. It can significantly reduce the outgoing traffic, but will increase the CPU loading. Don't use this option with analog signal sources or webcams, it's useless. Default: disabled.
|
Don't send identical frames to clients, but no more than specified number. It can significantly reduce the outgoing traffic, but will increase the CPU loading. Don't use this option with analog signal sources or webcams, it's useless. Default: disabled.
|
||||||
.TP
|
.TP
|
||||||
.BR \-l ", " \-\-slowdown
|
|
||||||
Slowdown capturing to 1 FPS or less when no stream clients are connected. Useful to reduce CPU consumption. Default: disabled.
|
|
||||||
.TP
|
|
||||||
.BR \-R\ \fIWxH ", " \-\-fake\-resolution\ \fIWxH
|
.BR \-R\ \fIWxH ", " \-\-fake\-resolution\ \fIWxH
|
||||||
Override image resolution for the /state. Default: disabled.
|
Override image resolution for the /state. Default: disabled.
|
||||||
.TP
|
.TP
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ int memsink_server_put(memsink_s *sink, const frame_s *frame) {
|
|||||||
COPY(grab_ts);
|
COPY(grab_ts);
|
||||||
COPY(encode_begin_ts);
|
COPY(encode_begin_ts);
|
||||||
COPY(encode_end_ts);
|
COPY(encode_end_ts);
|
||||||
|
sink->has_clients = (sink->mem->last_consumed_ts + 10 > get_now_monotonic());
|
||||||
memcpy(sink->mem->data, frame->data, frame->used);
|
memcpy(sink->mem->data, frame->data, frame->used);
|
||||||
# undef COPY
|
# undef COPY
|
||||||
|
|
||||||
@@ -159,6 +160,7 @@ int memsink_client_get(memsink_s *sink, frame_s *frame) { // cppcheck-suppress u
|
|||||||
COPY(grab_ts);
|
COPY(grab_ts);
|
||||||
COPY(encode_begin_ts);
|
COPY(encode_begin_ts);
|
||||||
COPY(encode_end_ts);
|
COPY(encode_end_ts);
|
||||||
|
sink->mem->last_consumed_ts = get_now_monotonic();
|
||||||
frame_set_data(frame, sink->mem->data, sink->mem->used);
|
frame_set_data(frame, sink->mem->data, sink->mem->used);
|
||||||
# undef COPY
|
# undef COPY
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -56,6 +56,7 @@ typedef struct {
|
|||||||
long double grab_ts;
|
long double grab_ts;
|
||||||
long double encode_begin_ts;
|
long double encode_begin_ts;
|
||||||
long double encode_end_ts;
|
long double encode_end_ts;
|
||||||
|
long double last_consumed_ts;
|
||||||
uint8_t data[MEMSINK_MAX_DATA];
|
uint8_t data[MEMSINK_MAX_DATA];
|
||||||
} memsink_shared_s;
|
} memsink_shared_s;
|
||||||
|
|
||||||
@@ -69,6 +70,7 @@ typedef struct {
|
|||||||
int fd;
|
int fd;
|
||||||
memsink_shared_s *mem;
|
memsink_shared_s *mem;
|
||||||
uint64_t last_id;
|
uint64_t last_id;
|
||||||
|
bool has_clients; // Only for server
|
||||||
} memsink_s;
|
} memsink_s;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -139,10 +139,6 @@ int server_listen(server_s *server) {
|
|||||||
assert(!event_add(RUN(refresh), &refresh_interval));
|
assert(!event_add(RUN(refresh), &refresh_interval));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (server->slowdown) {
|
|
||||||
stream_switch_slowdown(RUN(stream), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
evhttp_set_timeout(RUN(http), server->timeout);
|
evhttp_set_timeout(RUN(http), server->timeout);
|
||||||
|
|
||||||
if (server->user[0] != '\0') {
|
if (server->user[0] != '\0') {
|
||||||
@@ -476,10 +472,7 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server
|
|||||||
RUN(stream_clients_count) += 1;
|
RUN(stream_clients_count) += 1;
|
||||||
|
|
||||||
if (RUN(stream_clients_count) == 1) {
|
if (RUN(stream_clients_count) == 1) {
|
||||||
if (server->slowdown) {
|
atomic_store(&VID(has_clients), true);
|
||||||
stream_switch_slowdown(RUN(stream), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef WITH_GPIO
|
# ifdef WITH_GPIO
|
||||||
gpio_set_has_http_clients(true);
|
gpio_set_has_http_clients(true);
|
||||||
# endif
|
# endif
|
||||||
@@ -650,10 +643,7 @@ static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UN
|
|||||||
RUN(stream_clients_count) -= 1;
|
RUN(stream_clients_count) -= 1;
|
||||||
|
|
||||||
if (RUN(stream_clients_count) == 0) {
|
if (RUN(stream_clients_count) == 0) {
|
||||||
if (client->server->slowdown) {
|
atomic_store(&VID(has_clients), false);
|
||||||
stream_switch_slowdown(RUN(stream), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
# ifdef WITH_GPIO
|
# ifdef WITH_GPIO
|
||||||
gpio_set_has_http_clients(false);
|
gpio_set_has_http_clients(false);
|
||||||
# endif
|
# endif
|
||||||
|
|||||||
@@ -135,7 +135,6 @@ typedef struct server_sx {
|
|||||||
char *allow_origin;
|
char *allow_origin;
|
||||||
|
|
||||||
unsigned drop_same_frames;
|
unsigned drop_same_frames;
|
||||||
bool slowdown;
|
|
||||||
unsigned fake_width;
|
unsigned fake_width;
|
||||||
unsigned fake_height;
|
unsigned fake_height;
|
||||||
|
|
||||||
|
|||||||
@@ -41,16 +41,16 @@ enum _OPT_VALUES {
|
|||||||
# ifdef WITH_OMX
|
# ifdef WITH_OMX
|
||||||
_O_GLITCHED_RESOLUTIONS = 'g',
|
_O_GLITCHED_RESOLUTIONS = 'g',
|
||||||
# endif
|
# endif
|
||||||
|
_O_BLANK = 'k',
|
||||||
|
_O_LAST_AS_BLANK = 'K',
|
||||||
|
_O_SLOWDOWN = 'l',
|
||||||
|
|
||||||
_O_HOST = 's',
|
_O_HOST = 's',
|
||||||
_O_PORT = 'p',
|
_O_PORT = 'p',
|
||||||
_O_UNIX = 'U',
|
_O_UNIX = 'U',
|
||||||
_O_UNIX_RM = 'D',
|
_O_UNIX_RM = 'D',
|
||||||
_O_UNIX_MODE = 'M',
|
_O_UNIX_MODE = 'M',
|
||||||
_O_BLANK = 'k',
|
|
||||||
_O_LAST_AS_BLANK = 'K',
|
|
||||||
_O_DROP_SAME_FRAMES = 'e',
|
_O_DROP_SAME_FRAMES = 'e',
|
||||||
_O_SLOWDOWN = 'l',
|
|
||||||
_O_FAKE_RESOLUTION = 'R',
|
_O_FAKE_RESOLUTION = 'R',
|
||||||
|
|
||||||
_O_HELP = 'h',
|
_O_HELP = 'h',
|
||||||
@@ -141,6 +141,7 @@ static const struct option _LONG_OPTS[] = {
|
|||||||
# endif
|
# endif
|
||||||
{"blank", required_argument, NULL, _O_BLANK},
|
{"blank", required_argument, NULL, _O_BLANK},
|
||||||
{"last-as-blank", required_argument, NULL, _O_LAST_AS_BLANK},
|
{"last-as-blank", required_argument, NULL, _O_LAST_AS_BLANK},
|
||||||
|
{"slowdown", no_argument, NULL, _O_SLOWDOWN},
|
||||||
{"device-timeout", required_argument, NULL, _O_DEVICE_TIMEOUT},
|
{"device-timeout", required_argument, NULL, _O_DEVICE_TIMEOUT},
|
||||||
{"device-error-delay", required_argument, NULL, _O_DEVICE_ERROR_DELAY},
|
{"device-error-delay", required_argument, NULL, _O_DEVICE_ERROR_DELAY},
|
||||||
|
|
||||||
@@ -167,7 +168,6 @@ static const struct option _LONG_OPTS[] = {
|
|||||||
{"passwd", required_argument, NULL, _O_PASSWD},
|
{"passwd", required_argument, NULL, _O_PASSWD},
|
||||||
{"static", required_argument, NULL, _O_STATIC},
|
{"static", required_argument, NULL, _O_STATIC},
|
||||||
{"drop-same-frames", required_argument, NULL, _O_DROP_SAME_FRAMES},
|
{"drop-same-frames", required_argument, NULL, _O_DROP_SAME_FRAMES},
|
||||||
{"slowdown", no_argument, NULL, _O_SLOWDOWN},
|
|
||||||
{"allow-origin", required_argument, NULL, _O_ALLOW_ORIGIN},
|
{"allow-origin", required_argument, NULL, _O_ALLOW_ORIGIN},
|
||||||
{"fake-resolution", required_argument, NULL, _O_FAKE_RESOLUTION},
|
{"fake-resolution", required_argument, NULL, _O_FAKE_RESOLUTION},
|
||||||
{"tcp-nodelay", no_argument, NULL, _O_TCP_NODELAY},
|
{"tcp-nodelay", no_argument, NULL, _O_TCP_NODELAY},
|
||||||
@@ -382,6 +382,7 @@ int options_parse(options_s *options, device_s *dev, encoder_s *enc, stream_s *s
|
|||||||
# endif
|
# endif
|
||||||
case _O_BLANK: OPT_SET(blank_path, optarg);
|
case _O_BLANK: OPT_SET(blank_path, optarg);
|
||||||
case _O_LAST_AS_BLANK: OPT_NUMBER("--last-as-blank", stream->last_as_blank, 0, 86400, 0);
|
case _O_LAST_AS_BLANK: OPT_NUMBER("--last-as-blank", stream->last_as_blank, 0, 86400, 0);
|
||||||
|
case _O_SLOWDOWN: OPT_SET(stream->slowdown, true);
|
||||||
case _O_DEVICE_TIMEOUT: OPT_NUMBER("--device-timeout", dev->timeout, 1, 60, 0);
|
case _O_DEVICE_TIMEOUT: OPT_NUMBER("--device-timeout", dev->timeout, 1, 60, 0);
|
||||||
case _O_DEVICE_ERROR_DELAY: OPT_NUMBER("--device-error-delay", stream->error_delay, 1, 60, 0);
|
case _O_DEVICE_ERROR_DELAY: OPT_NUMBER("--device-error-delay", stream->error_delay, 1, 60, 0);
|
||||||
|
|
||||||
@@ -421,7 +422,6 @@ int options_parse(options_s *options, device_s *dev, encoder_s *enc, stream_s *s
|
|||||||
case _O_PASSWD: OPT_SET(server->passwd, optarg);
|
case _O_PASSWD: OPT_SET(server->passwd, optarg);
|
||||||
case _O_STATIC: OPT_SET(server->static_path, optarg);
|
case _O_STATIC: OPT_SET(server->static_path, optarg);
|
||||||
case _O_DROP_SAME_FRAMES: OPT_NUMBER("--drop-same-frames", server->drop_same_frames, 0, VIDEO_MAX_FPS, 0);
|
case _O_DROP_SAME_FRAMES: OPT_NUMBER("--drop-same-frames", server->drop_same_frames, 0, VIDEO_MAX_FPS, 0);
|
||||||
case _O_SLOWDOWN: OPT_SET(server->slowdown, true);
|
|
||||||
case _O_FAKE_RESOLUTION: OPT_RESOLUTION("--fake-resolution", server->fake_width, server->fake_height, false);
|
case _O_FAKE_RESOLUTION: OPT_RESOLUTION("--fake-resolution", server->fake_width, server->fake_height, false);
|
||||||
case _O_ALLOW_ORIGIN: OPT_SET(server->allow_origin, optarg);
|
case _O_ALLOW_ORIGIN: OPT_SET(server->allow_origin, optarg);
|
||||||
case _O_TCP_NODELAY: OPT_SET(server->tcp_nodelay, true);
|
case _O_TCP_NODELAY: OPT_SET(server->tcp_nodelay, true);
|
||||||
@@ -617,6 +617,8 @@ static void _help(FILE *fp, device_s *dev, encoder_s *enc, stream_s *stream, ser
|
|||||||
SAY(" but no more than specified time (or endlessly if 0 is specified).");
|
SAY(" but no more than specified time (or endlessly if 0 is specified).");
|
||||||
SAY(" If the device has not yet been online, display 'NO SIGNAL' or the image");
|
SAY(" If the device has not yet been online, display 'NO SIGNAL' or the image");
|
||||||
SAY(" specified by option --blank. Default: disabled.\n");
|
SAY(" specified by option --blank. Default: disabled.\n");
|
||||||
|
SAY(" -l|--slowdown ─────────────────────── Slowdown capturing to 1 FPS or less when no stream or sink clients");
|
||||||
|
SAY(" are connected. Useful to reduce CPU consumption. Default: disabled.\n");
|
||||||
SAY(" --device-timeout <sec> ────────────── Timeout for device querying. Default: %u.\n", dev->timeout);
|
SAY(" --device-timeout <sec> ────────────── Timeout for device querying. Default: %u.\n", dev->timeout);
|
||||||
SAY(" --device-error-delay <sec> ────────── Delay before trying to connect to the device again");
|
SAY(" --device-error-delay <sec> ────────── Delay before trying to connect to the device again");
|
||||||
SAY(" after an error (timeout for example). Default: %u.\n", stream->error_delay);
|
SAY(" after an error (timeout for example). Default: %u.\n", stream->error_delay);
|
||||||
@@ -651,8 +653,6 @@ static void _help(FILE *fp, device_s *dev, encoder_s *enc, stream_s *stream, ser
|
|||||||
SAY(" It can significantly reduce the outgoing traffic, but will increase");
|
SAY(" It can significantly reduce the outgoing traffic, but will increase");
|
||||||
SAY(" the CPU loading. Don't use this option with analog signal sources");
|
SAY(" the CPU loading. Don't use this option with analog signal sources");
|
||||||
SAY(" or webcams, it's useless. Default: disabled.\n");
|
SAY(" or webcams, it's useless. Default: disabled.\n");
|
||||||
SAY(" -l|--slowdown ────────────── Slowdown capturing to 1 FPS or less when no stream clients are connected.");
|
|
||||||
SAY(" Useful to reduce CPU consumption. Default: disabled.\n");
|
|
||||||
SAY(" -R|--fake-resolution <WxH> ─ Override image resolution for the /state. Default: disabled.\n");
|
SAY(" -R|--fake-resolution <WxH> ─ Override image resolution for the /state. Default: disabled.\n");
|
||||||
SAY(" --tcp-nodelay ────────────── Set TCP_NODELAY flag to the client /stream socket. Ignored for --unix.");
|
SAY(" --tcp-nodelay ────────────── Set TCP_NODELAY flag to the client /stream socket. Ignored for --unix.");
|
||||||
SAY(" Default: disabled.\n");
|
SAY(" Default: disabled.\n");
|
||||||
|
|||||||
@@ -41,13 +41,13 @@ stream_s *stream_init(device_s *dev, encoder_s *enc) {
|
|||||||
stream_runtime_s *run;
|
stream_runtime_s *run;
|
||||||
A_CALLOC(run, 1);
|
A_CALLOC(run, 1);
|
||||||
atomic_init(&run->stop, false);
|
atomic_init(&run->stop, false);
|
||||||
atomic_init(&run->slowdown, false);
|
|
||||||
|
|
||||||
video_s *video;
|
video_s *video;
|
||||||
A_CALLOC(video, 1);
|
A_CALLOC(video, 1);
|
||||||
video->frame = frame_init("stream_video");
|
video->frame = frame_init("stream_video");
|
||||||
atomic_init(&video->updated, false);
|
atomic_init(&video->updated, false);
|
||||||
A_MUTEX_INIT(&video->mutex);
|
A_MUTEX_INIT(&video->mutex);
|
||||||
|
atomic_init(&video->has_clients, false);
|
||||||
run->video = video;
|
run->video = video;
|
||||||
|
|
||||||
stream_s *stream;
|
stream_s *stream;
|
||||||
@@ -122,7 +122,14 @@ void stream_loop(stream_s *stream) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (atomic_load(&RUN(slowdown))) {
|
if (
|
||||||
|
stream->slowdown
|
||||||
|
&& !atomic_load(&RUN(video->has_clients))
|
||||||
|
&& (stream->sink == NULL || !stream->sink->has_clients)
|
||||||
|
# ifdef WITH_OMX
|
||||||
|
&& (stream->h264 == NULL || /*stream->h264->sink == NULL ||*/ !stream->h264->sink->has_clients)
|
||||||
|
# endif
|
||||||
|
) {
|
||||||
usleep(1000000);
|
usleep(1000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,10 +233,6 @@ void stream_loop_break(stream_s *stream) {
|
|||||||
atomic_store(&RUN(stop), true);
|
atomic_store(&RUN(stop), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stream_switch_slowdown(stream_s *stream, bool slowdown) {
|
|
||||||
atomic_store(&RUN(slowdown), slowdown);
|
|
||||||
}
|
|
||||||
|
|
||||||
static workers_pool_s *_stream_init_loop(stream_s *stream) {
|
static workers_pool_s *_stream_init_loop(stream_s *stream) {
|
||||||
|
|
||||||
workers_pool_s *pool = NULL;
|
workers_pool_s *pool = NULL;
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ typedef struct {
|
|||||||
unsigned captured_fps;
|
unsigned captured_fps;
|
||||||
atomic_bool updated;
|
atomic_bool updated;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
|
||||||
|
atomic_bool has_clients; // For slowdown
|
||||||
} video_s;
|
} video_s;
|
||||||
|
|
||||||
#ifdef WITH_OMX
|
#ifdef WITH_OMX
|
||||||
@@ -76,17 +78,16 @@ typedef struct {
|
|||||||
# endif
|
# endif
|
||||||
|
|
||||||
atomic_bool stop;
|
atomic_bool stop;
|
||||||
atomic_bool slowdown;
|
|
||||||
} stream_runtime_s;
|
} stream_runtime_s;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
device_s *dev;
|
device_s *dev;
|
||||||
encoder_s *enc;
|
encoder_s *enc;
|
||||||
|
|
||||||
int last_as_blank;
|
|
||||||
unsigned error_delay;
|
|
||||||
|
|
||||||
frame_s *blank;
|
frame_s *blank;
|
||||||
|
int last_as_blank;
|
||||||
|
bool slowdown;
|
||||||
|
unsigned error_delay;
|
||||||
|
|
||||||
memsink_s *sink;
|
memsink_s *sink;
|
||||||
|
|
||||||
@@ -105,4 +106,3 @@ void stream_destroy(stream_s *stream);
|
|||||||
|
|
||||||
void stream_loop(stream_s *stream);
|
void stream_loop(stream_s *stream);
|
||||||
void stream_loop_break(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