mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-20 00:36:30 +00:00
Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
160a0e8d29 | ||
|
|
9dddd0075e | ||
|
|
0e0e3939b2 | ||
|
|
9c8d87412e | ||
|
|
3666d92819 | ||
|
|
9388d4dd22 | ||
|
|
6cf4924e05 | ||
|
|
713e3751b4 |
@@ -1,7 +1,7 @@
|
||||
[bumpversion]
|
||||
commit = True
|
||||
tag = True
|
||||
current_version = 0.41
|
||||
current_version = 0.43
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)(\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?)?
|
||||
serialize =
|
||||
{major}.{minor}
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -5,4 +5,5 @@
|
||||
/ustreamer-*.pkg.tar.xz
|
||||
/vgcore.*
|
||||
/ustreamer
|
||||
/*.sock
|
||||
*.o
|
||||
|
||||
2
Makefile
2
Makefile
@@ -59,5 +59,5 @@ push:
|
||||
|
||||
clean-all: clean
|
||||
clean:
|
||||
rm -f src/*.o src/{jpeg,omx}/*.o vgcore.* $(PROG)
|
||||
rm -f src/*.o src/{jpeg,omx}/*.o vgcore.* *.sock $(PROG)
|
||||
rm -rf pkg src/$(PROG)-* src/v*.tar.gz v*.tar.gz $(PROG)-*.pkg.tar.xz
|
||||
|
||||
2
PKGBUILD
2
PKGBUILD
@@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
pkgname=ustreamer
|
||||
pkgver=0.41
|
||||
pkgver=0.43
|
||||
pkgrel=1
|
||||
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
|
||||
url="https://github.com/pi-kvm/ustreamer"
|
||||
|
||||
@@ -10,9 +10,10 @@
|
||||
|----------|---------------|-------------------|
|
||||
| Multithreaded JPEG encoding |  Yes |  No |
|
||||
| [OpenMAX IL](https://www.khronos.org/openmaxil) hardware acceleration<br>on Raspberry Pi |  Yes |  No |
|
||||
| Behavior when the device<br>is disconnected while streaming |  Shows a black screen<br>with ```NO SIGNAL``` on it<br>until reconnected |  Stops the broadcast<sup>1</sup> |
|
||||
| Behavior when the device<br>is disconnected while streaming |  Shows a black screen<br>with ```NO SIGNAL``` on it<br>until reconnected |  Stops the broadcast <sup>1</sup> |
|
||||
| [DV-timings](https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/dv-timings.html) support -<br>the ability to change resolution<br>on the fly by source signal |  Yes |  Partially yes <sup>1</sup> |
|
||||
| Option to skip frames when streaming<br>static images by HTTP to save traffic |  Yes <sup>2</sup> |  No |
|
||||
| Streaming via UNIX domain socket |  Yes |  No |
|
||||
| Debug logs without recompiling,<br>performance statistics log,<br>access to HTTP broadcast parameters |  Yes |  No |
|
||||
| Supported input devices |  YUYV, UYVY,<br>RGB565, ~~MJPG~~ <sup>3</sup> |  YUYV, UYVY,<br>RGB565, MJPG |
|
||||
| Access to webcam controls (focus, servos)<br>and settings such as brightness via HTTP |  No |  Yes |
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
| Поведение при физическом отключении устройства<br>от сервера во время работы |  Транслирует черный экран<br>с надписью ```NO SIGNAL```,<br>пока устройство не будет подключено снова |  Прерывает трансляцию <sup>1</sup> |
|
||||
| Поддержка [DV-таймингов](https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/dv-timings.html) - возможности изменения <br>параметров разрешения трансляции на лету<br>по сигналу источника (устройства видеозахвата) |  Есть |  Условно есть <sup>1</sup> |
|
||||
| Возможность пропуска фреймов при передаче<br>статического изображения по HTTP<br>для экономии трафика |  Есть <sup>2</sup> |  Нет |
|
||||
| Стрим через UNIX domain socket |  Есть |  Нет |
|
||||
| Дебаг-логи без перекомпиляции,<br>логгирование статистики производительности,<br>возможность получения параметров<br>трансляции по HTTP |  Есть |  Нет |
|
||||
| Поддерживаемые входные форматы устройств |  YUYV, UYVY,<br>RGB565, ~~MJPG~~ <sup>3</sup> |  YUYV, UYVY,<br>RGB565, MJPG |
|
||||
| Поддержка контролов веб-камер (фокус,<br> движение сервами) и всяких настроек,<br> типа яркости, через HTTP |  Нет |  Есть |
|
||||
|
||||
@@ -21,4 +21,4 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#define VERSION "0.41"
|
||||
#define VERSION "0.43"
|
||||
|
||||
61
src/http.c
61
src/http.c
@@ -23,8 +23,14 @@
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <event2/thread.h>
|
||||
#include <event2/http.h>
|
||||
@@ -105,6 +111,9 @@ void http_server_destroy(struct http_server_t *server) {
|
||||
}
|
||||
|
||||
evhttp_free(server->run->http);
|
||||
if (server->run->unix_fd) {
|
||||
close(server->run->unix_fd);
|
||||
}
|
||||
event_base_free(server->run->base);
|
||||
libevent_global_shutdown();
|
||||
|
||||
@@ -128,15 +137,57 @@ int http_server_listen(struct http_server_t *server) {
|
||||
|
||||
server->run->drop_same_frames_blank = max_u(server->drop_same_frames, server->run->drop_same_frames_blank);
|
||||
|
||||
LOG_DEBUG("Binding HTTP to [%s]:%d ...", server->host, server->port);
|
||||
evhttp_set_timeout(server->run->http, server->timeout);
|
||||
|
||||
if (evhttp_bind_socket(server->run->http, server->host, server->port) < 0) {
|
||||
LOG_PERROR("Can't listen HTTP on [%s]:%d", server->host, server->port)
|
||||
return -1;
|
||||
if (server->unix_path) {
|
||||
struct sockaddr_un unix_addr;
|
||||
int unix_fd_flags;
|
||||
|
||||
LOG_DEBUG("Binding HTTP to UNIX socket '%s' ...", server->unix_path);
|
||||
|
||||
assert((server->run->unix_fd = socket(AF_UNIX, SOCK_STREAM, 0)));
|
||||
assert((unix_fd_flags = fcntl(server->run->unix_fd, F_GETFL)) >= 0);
|
||||
unix_fd_flags |= O_NONBLOCK;
|
||||
assert(fcntl(server->run->unix_fd, F_SETFL, unix_fd_flags) >= 0);
|
||||
|
||||
strncpy(unix_addr.sun_path, server->unix_path, 107);
|
||||
unix_addr.sun_path[107] = '\0';
|
||||
unix_addr.sun_family = AF_UNIX;
|
||||
|
||||
if (server->unix_rm && unlink(server->unix_path) < 0) {
|
||||
if (errno != ENOENT) {
|
||||
LOG_PERROR("Can't remove old UNIX socket '%s'", server->unix_path);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (bind(server->run->unix_fd, (struct sockaddr *)&unix_addr, sizeof(struct sockaddr_un)) < 0) {
|
||||
LOG_PERROR("Can't bind HTTP to UNIX socket '%s'", server->unix_path);
|
||||
return -1;
|
||||
}
|
||||
if (server->unix_mode && chmod(server->unix_path, server->unix_mode) < 0) {
|
||||
LOG_PERROR("Can't set permissions %o to UNIX socket '%s'", server->unix_mode, server->unix_path);
|
||||
return -1;
|
||||
}
|
||||
if (listen(server->run->unix_fd, 128) < 0) {
|
||||
LOG_PERROR("Can't listen UNIX socket '%s'", server->unix_path);
|
||||
return -1;
|
||||
}
|
||||
if (evhttp_accept_socket(server->run->http, server->run->unix_fd) < 0) {
|
||||
LOG_PERROR("Can't evhttp_accept_socket() UNIX socket '%s'", server->unix_path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_INFO("Listening HTTP on UNIX socket '%s'", server->unix_path);
|
||||
|
||||
} else {
|
||||
LOG_DEBUG("Binding HTTP to [%s]:%d ...", server->host, server->port);
|
||||
if (evhttp_bind_socket(server->run->http, server->host, server->port) < 0) {
|
||||
LOG_PERROR("Can't bind HTTP on [%s]:%d", server->host, server->port)
|
||||
return -1;
|
||||
}
|
||||
LOG_INFO("Listening HTTP on [%s]:%d", server->host, server->port);
|
||||
}
|
||||
|
||||
LOG_INFO("Listening HTTP on [%s]:%d", server->host, server->port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,11 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <event2/http.h>
|
||||
#include <event2/util.h>
|
||||
|
||||
#include "tools.h"
|
||||
#include "stream.h"
|
||||
@@ -65,6 +68,7 @@ struct exposed_t {
|
||||
struct http_server_runtime_t {
|
||||
struct event_base *base;
|
||||
struct evhttp *http;
|
||||
evutil_socket_t unix_fd;
|
||||
struct event *refresh;
|
||||
struct stream_t *stream;
|
||||
struct exposed_t *exposed;
|
||||
@@ -76,6 +80,9 @@ struct http_server_runtime_t {
|
||||
struct http_server_t {
|
||||
char *host;
|
||||
unsigned port;
|
||||
char *unix_path;
|
||||
bool unix_rm;
|
||||
mode_t unix_mode;
|
||||
unsigned drop_same_frames;
|
||||
unsigned fake_width;
|
||||
unsigned fake_height;
|
||||
|
||||
36
src/main.c
36
src/main.c
@@ -40,7 +40,7 @@
|
||||
#include "http.h"
|
||||
|
||||
|
||||
static const char _short_opts[] = "d:i:x:y:f:a:z:tn:w:q:c:s:p:r:h";
|
||||
static const char _short_opts[] = "d:i:x:y:f:a:z:tn:w:q:c:s:p:u:ro:e:h";
|
||||
static const struct option _long_opts[] = {
|
||||
{"device", required_argument, NULL, 'd'},
|
||||
{"input", required_argument, NULL, 'i'},
|
||||
@@ -61,7 +61,10 @@ static const struct option _long_opts[] = {
|
||||
|
||||
{"host", required_argument, NULL, 's'},
|
||||
{"port", required_argument, NULL, 'p'},
|
||||
{"drop-same-frames", required_argument, NULL, 'r'},
|
||||
{"unix", required_argument, NULL, 'u'},
|
||||
{"unix-rm", no_argument, NULL, 'r'},
|
||||
{"unix-mode", required_argument, NULL, 'o'},
|
||||
{"drop-same-frames", required_argument, NULL, 'e'},
|
||||
{"fake-width", required_argument, NULL, 2001},
|
||||
{"fake-height", required_argument, NULL, 2002},
|
||||
{"server-timeout", required_argument, NULL, 2003},
|
||||
@@ -112,7 +115,7 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s
|
||||
printf(" Default: %d (number of CPU cores + 1)\n\n", dev->n_buffers);
|
||||
printf(" -w|--workers <N> -- The number of compressing threads. Default: %d (== --buffers).\n\n", dev->n_workers);
|
||||
printf(" -q|--quality <N> -- Set quality of JPEG encoding from 1 to 100 (best). Default: %d.\n\n", encoder->quality);
|
||||
printf(" --encoder <type> -- Use specified encoder. It may affects to workers number.\n");
|
||||
printf(" -c|--encoder <type> -- Use specified encoder. It may affects to workers number.\n");
|
||||
printf(" -- Available: %s; default: CPU.\n\n", ENCODER_TYPES_STR);
|
||||
printf(" --device-timeout <seconds> -- Timeout for device querying. Default: %d\n\n", dev->timeout);
|
||||
printf(" --device-persistent -- Don't re-initialize device on timeout. Default: disabled.\n\n");
|
||||
@@ -120,9 +123,12 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s
|
||||
printf(" after a timeout. Default: %d\n\n", dev->error_delay);
|
||||
printf("HTTP server options:\n");
|
||||
printf("--------------------\n");
|
||||
printf(" --host <address> -- Listen on Hostname or IP. Default: %s\n\n", server->host);
|
||||
printf(" --port <N> -- Bind to this TCP port. Default: %d\n\n", server->port);
|
||||
printf(" --drop-same-frames <N> -- Don't send same frames to clients, but no more than specified number.\n");
|
||||
printf(" -s|--host <address> -- Listen on Hostname or IP. Default: %s\n\n", server->host);
|
||||
printf(" -p|--port <N> -- Bind to this TCP port. Default: %d\n\n", server->port);
|
||||
printf(" -u|--unix <path> -- Bind to UNIX domain socket. Default: disabled\n\n");
|
||||
printf(" -r|--unix-rm -- Try to remove old UNIX socket file before binding. Default: disabled\n\n");
|
||||
printf(" -o|--unix-mode <mode> -- Set UNIX socket file permissions (like 777). Default: disabled\n\n");
|
||||
printf(" -e|--drop-same-frames <N> -- Don't send same frames to clients, but no more than specified number.\n");
|
||||
printf(" It can significantly reduce the outgoing traffic, but will increase\n");
|
||||
printf(" the CPU loading. Don't use this option with analog signal sources\n");
|
||||
printf(" or webcams, it's useless. Default: disabled.\n\n");
|
||||
@@ -146,9 +152,9 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e
|
||||
{ _dest = _value; break; }
|
||||
|
||||
# define OPT_UNSIGNED(_dest, _name, _min, _max) \
|
||||
{ errno = 0; int _tmp = strtol(optarg, NULL, 0); \
|
||||
if (errno || _tmp < _min || _tmp > _max) \
|
||||
{ printf("Invalid value for '%s=%u'; min=%u; max=%u\n", _name, _tmp, _min, _max); return -1; } \
|
||||
{ errno = 0; char *_end = NULL; int _tmp = strtol(optarg, &_end, 0); \
|
||||
if (errno || *_end || _tmp < _min || _tmp > _max) \
|
||||
{ printf("Invalid value for '%s=%s'; min=%u; max=%u\n", _name, optarg, _min, _max); return -1; } \
|
||||
_dest = _tmp; break; }
|
||||
|
||||
# define OPT_PARSE(_dest, _func, _invalid, _name) \
|
||||
@@ -156,6 +162,12 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e
|
||||
{ printf("Unknown " _name ": %s\n", optarg); return -1; } \
|
||||
break; }
|
||||
|
||||
# define OPT_CHMOD(_dest, _name) \
|
||||
{ errno = 0; char *_end = NULL; int _tmp = strtol(optarg, &_end, 8); \
|
||||
if (errno || *_end) \
|
||||
{ printf("Invalid value for '%s=%s'\n", _name, optarg); return -1; } \
|
||||
_dest = _tmp; break; }
|
||||
|
||||
int index;
|
||||
int ch;
|
||||
|
||||
@@ -184,7 +196,10 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e
|
||||
|
||||
case 's': OPT_SET(server->host, optarg);
|
||||
case 'p': OPT_UNSIGNED(server->port, "--port", 1, 65535);
|
||||
case 'r': OPT_UNSIGNED(server->drop_same_frames, "--drop-same-frames", 0, 30);
|
||||
case 'u': OPT_SET(server->unix_path, optarg);
|
||||
case 'r': OPT_SET(server->unix_rm, true);
|
||||
case 'o': OPT_CHMOD(server->unix_mode, "--unix-mode");
|
||||
case 'e': OPT_UNSIGNED(server->drop_same_frames, "--drop-same-frames", 0, 30);
|
||||
case 2001: OPT_UNSIGNED(server->fake_width, "--fake-width", 0, 1920);
|
||||
case 2002: OPT_UNSIGNED(server->fake_height, "--fake-height", 0, 1200);
|
||||
case 2003: OPT_UNSIGNED(server->timeout, "--server-timeout", 1, 60);
|
||||
@@ -200,6 +215,7 @@ static int _parse_options(int argc, char *argv[], struct device_t *dev, struct e
|
||||
}
|
||||
}
|
||||
|
||||
# undef OPT_CHMOD
|
||||
# undef OPT_PARSE
|
||||
# undef OPT_UNSIGNED
|
||||
# undef OPT_SET
|
||||
|
||||
Reference in New Issue
Block a user