mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-03-01 13:16:32 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6cdaceb561 | ||
|
|
08aacdc9af | ||
|
|
3db57cfa42 | ||
|
|
d8a774e358 | ||
|
|
869d12759c |
@@ -1,7 +1,7 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
current_version = 0.52
|
current_version = 0.53
|
||||||
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}
|
||||||
|
|||||||
2
PKGBUILD
2
PKGBUILD
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
pkgname=ustreamer
|
pkgname=ustreamer
|
||||||
pkgver=0.52
|
pkgver=0.53
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
|
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
|
||||||
url="https://github.com/pi-kvm/ustreamer"
|
url="https://github.com/pi-kvm/ustreamer"
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
| Multithreaded JPEG encoding |  Yes |  No |
|
| Multithreaded JPEG encoding |  Yes |  No |
|
||||||
| [OpenMAX IL](https://www.khronos.org/openmaxil) hardware acceleration<br>on Raspberry Pi |  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> |
|
| [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>2</sup> |
|
||||||
| Option to skip frames when streaming<br>static images by HTTP to save traffic |  Yes <sup>2</sup> |  No |
|
| 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 |
|
| Streaming via UNIX domain socket |  Yes |  No |
|
||||||
| Debug logs without recompiling,<br>performance statistics log,<br>access to HTTP broadcast parameters |  Yes |  No |
|
| Debug logs without recompiling,<br>performance statistics log,<br>access to HTTP broadcast parameters |  Yes |  No |
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
| Многопоточное кодирование JPEG |  Есть |  Нет |
|
| Многопоточное кодирование JPEG |  Есть |  Нет |
|
||||||
| Аппаратное кодирование с помощью [OpenMAX IL](https://www.khronos.org/openmaxil) на Raspberry Pi |  Есть |  Нет |
|
| Аппаратное кодирование с помощью [OpenMAX IL](https://www.khronos.org/openmaxil) на Raspberry Pi |  Есть |  Нет |
|
||||||
| Поведение при физическом отключении устройства<br>от сервера во время работы |  Транслирует черный экран<br>с надписью ```NO SIGNAL```,<br>пока устройство не будет подключено снова |  Прерывает трансляцию <sup>1</sup> |
|
| Поведение при физическом отключении устройства<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> |
|
| Поддержка [DV-таймингов](https://linuxtv.org/downloads/v4l-dvb-apis/uapi/v4l/dv-timings.html) - возможности изменения <br>параметров разрешения трансляции на лету<br>по сигналу источника (устройства видеозахвата) |  Есть |  Условно есть <sup>2</sup> |
|
||||||
| Возможность пропуска фреймов при передаче<br>статического изображения по HTTP<br>для экономии трафика |  Есть <sup>2</sup> |  Нет |
|
| Возможность пропуска фреймов при передаче<br>статического изображения по HTTP<br>для экономии трафика |  Есть <sup>2</sup> |  Нет |
|
||||||
| Стрим через UNIX domain socket |  Есть |  Нет |
|
| Стрим через UNIX domain socket |  Есть |  Нет |
|
||||||
| Дебаг-логи без перекомпиляции,<br>логгирование статистики производительности,<br>возможность получения параметров<br>трансляции по HTTP |  Есть |  Нет |
|
| Дебаг-логи без перекомпиляции,<br>логгирование статистики производительности,<br>возможность получения параметров<br>трансляции по HTTP |  Есть |  Нет |
|
||||||
|
|||||||
@@ -22,4 +22,4 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define VERSION "0.52"
|
#define VERSION "0.53"
|
||||||
|
|||||||
@@ -136,8 +136,15 @@ enum encoder_type_t encoder_parse_type(const char *str) {
|
|||||||
return ENCODER_TYPE_UNKNOWN;
|
return ENCODER_TYPE_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-parameter"
|
const char *encoder_type_to_string(enum encoder_type_t type) {
|
||||||
#pragma GCC diagnostic push
|
for (unsigned index = 0; index < ARRAY_LEN(_ENCODER_TYPES); ++index) {
|
||||||
|
if (_ENCODER_TYPES[index].type == type) {
|
||||||
|
return _ENCODER_TYPES[index].name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return _ENCODER_TYPES[0].name;
|
||||||
|
}
|
||||||
|
|
||||||
void encoder_prepare_live(struct encoder_t *encoder, struct device_t *dev) {
|
void encoder_prepare_live(struct encoder_t *encoder, struct device_t *dev) {
|
||||||
assert(encoder->run->type != ENCODER_TYPE_UNKNOWN);
|
assert(encoder->run->type != ENCODER_TYPE_UNKNOWN);
|
||||||
|
|
||||||
@@ -160,9 +167,9 @@ void encoder_prepare_live(struct encoder_t *encoder, struct device_t *dev) {
|
|||||||
A_PTHREAD_M_LOCK(&encoder->run->mutex);
|
A_PTHREAD_M_LOCK(&encoder->run->mutex);
|
||||||
encoder->run->quality = 0;
|
encoder->run->quality = 0;
|
||||||
A_PTHREAD_M_UNLOCK(&encoder->run->mutex);
|
A_PTHREAD_M_UNLOCK(&encoder->run->mutex);
|
||||||
|
LOG_INFO("Using JPEG quality: HW default");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
# ifdef OMX_ENCODER
|
# ifdef OMX_ENCODER
|
||||||
else if (encoder->run->type == ENCODER_TYPE_OMX) {
|
else if (encoder->run->type == ENCODER_TYPE_OMX) {
|
||||||
for (unsigned index = 0; index < encoder->run->n_omxs; ++index) {
|
for (unsigned index = 0; index < encoder->run->n_omxs; ++index) {
|
||||||
@@ -176,14 +183,11 @@ void encoder_prepare_live(struct encoder_t *encoder, struct device_t *dev) {
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
# pragma GCC diagnostic ignored "-Wunused-label"
|
|
||||||
# pragma GCC diagnostic push
|
|
||||||
use_fallback:
|
use_fallback:
|
||||||
A_PTHREAD_M_LOCK(&encoder->run->mutex);
|
A_PTHREAD_M_LOCK(&encoder->run->mutex);
|
||||||
encoder->run->type = ENCODER_TYPE_CPU;
|
encoder->run->type = ENCODER_TYPE_CPU;
|
||||||
encoder->run->quality = encoder->quality;
|
encoder->run->quality = encoder->quality;
|
||||||
A_PTHREAD_M_UNLOCK(&encoder->run->mutex);
|
A_PTHREAD_M_UNLOCK(&encoder->run->mutex);
|
||||||
# pragma GCC diagnostic pop
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wunused-label"
|
#pragma GCC diagnostic ignored "-Wunused-label"
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ struct encoder_t *encoder_init();
|
|||||||
void encoder_destroy(struct encoder_t *encoder);
|
void encoder_destroy(struct encoder_t *encoder);
|
||||||
|
|
||||||
enum encoder_type_t encoder_parse_type(const char *str);
|
enum encoder_type_t encoder_parse_type(const char *str);
|
||||||
|
const char *encoder_type_to_string(enum encoder_type_t type);
|
||||||
|
|
||||||
void encoder_prepare(struct encoder_t *encoder, struct device_t *dev);
|
void encoder_prepare(struct encoder_t *encoder, struct device_t *dev);
|
||||||
void encoder_prepare_live(struct encoder_t *encoder, struct device_t *dev);
|
void encoder_prepare_live(struct encoder_t *encoder, struct device_t *dev);
|
||||||
|
|||||||
22
src/http.c
22
src/http.c
@@ -257,22 +257,28 @@ static void _http_callback_root(struct evhttp_request *request, UNUSED void *arg
|
|||||||
static void _http_callback_state(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;
|
struct http_server_t *server = (struct http_server_t *)v_server;
|
||||||
struct evbuffer *buf;
|
struct evbuffer *buf;
|
||||||
|
enum encoder_type_t encoder_run_type;
|
||||||
|
unsigned encoder_run_quality;
|
||||||
|
|
||||||
PROCESS_HEAD_REQUEST;
|
PROCESS_HEAD_REQUEST;
|
||||||
|
|
||||||
A_PTHREAD_M_LOCK(&server->run->stream->encoder->run->mutex);
|
# define ENCODER(_next) server->run->stream->encoder->_next
|
||||||
enum encoder_type_t encoder_run_type = server->run->stream->encoder->run->type;
|
|
||||||
unsigned encoder_run_quality = server->run->stream->encoder->run->quality;
|
A_PTHREAD_M_LOCK(&ENCODER(run->mutex));
|
||||||
A_PTHREAD_M_UNLOCK(&server->run->stream->encoder->run->mutex);
|
encoder_run_type = ENCODER(run->type);
|
||||||
|
encoder_run_quality = ENCODER(run->quality);
|
||||||
|
A_PTHREAD_M_UNLOCK(&ENCODER(run->mutex));
|
||||||
|
|
||||||
assert((buf = evbuffer_new()));
|
assert((buf = evbuffer_new()));
|
||||||
|
|
||||||
assert(evbuffer_add_printf(buf,
|
assert(evbuffer_add_printf(buf,
|
||||||
"{\"ok\": true, \"result\": {"
|
"{\"ok\": true, \"result\": {"
|
||||||
" \"encoder\": {\"fallback\": %s, \"quality\": %u},"
|
" \"encoder\": {\"type\": \"%s\", \"fallback\": %s, \"quality\": %u},"
|
||||||
" \"source\": {\"resolution\": {\"width\": %u, \"height\": %u},"
|
" \"source\": {\"resolution\": {\"width\": %u, \"height\": %u},"
|
||||||
" \"online\": %s, \"desired_fps\": %u, \"captured_fps\": %u},"
|
" \"online\": %s, \"desired_fps\": %u, \"captured_fps\": %u},"
|
||||||
" \"stream\": {\"queued_fps\": %u, \"clients\": %u, \"clients_stat\": {",
|
" \"stream\": {\"queued_fps\": %u, \"clients\": %u, \"clients_stat\": {",
|
||||||
bool_to_string(server->run->stream->encoder->type != encoder_run_type),
|
encoder_type_to_string(encoder_run_type),
|
||||||
|
bool_to_string(ENCODER(type) != encoder_run_type),
|
||||||
encoder_run_quality,
|
encoder_run_quality,
|
||||||
(server->fake_width ? server->fake_width : server->run->exposed->width),
|
(server->fake_width ? server->fake_width : server->run->exposed->width),
|
||||||
(server->fake_height ? server->fake_height : server->run->exposed->height),
|
(server->fake_height ? server->fake_height : server->run->exposed->height),
|
||||||
@@ -282,6 +288,9 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server)
|
|||||||
server->run->exposed->queued_fps,
|
server->run->exposed->queued_fps,
|
||||||
server->run->stream_clients_count
|
server->run->stream_clients_count
|
||||||
));
|
));
|
||||||
|
|
||||||
|
# undef ENCODER
|
||||||
|
|
||||||
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) {
|
||||||
assert(evbuffer_add_printf(buf,
|
assert(evbuffer_add_printf(buf,
|
||||||
"\"%s\": {\"fps\": %u, \"extra_headers\": %s, \"advance_headers\": %s, \"dual_final_frames\": %s}%s",
|
"\"%s\": {\"fps\": %u, \"extra_headers\": %s, \"advance_headers\": %s, \"dual_final_frames\": %s}%s",
|
||||||
@@ -293,6 +302,7 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server)
|
|||||||
(client->next ? ", " : "")
|
(client->next ? ", " : "")
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(evbuffer_add_printf(buf, "}}}}"));
|
assert(evbuffer_add_printf(buf, "}}}}"));
|
||||||
|
|
||||||
ADD_HEADER("Content-Type", "application/json");
|
ADD_HEADER("Content-Type", "application/json");
|
||||||
|
|||||||
27
ustreamer.ebuild
Normal file
27
ustreamer.ebuild
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# Copyright 2019 Gentoo Authors
|
||||||
|
# Distributed under the terms of the GNU General Public License v2
|
||||||
|
|
||||||
|
EAPI=7
|
||||||
|
|
||||||
|
inherit git-r3
|
||||||
|
|
||||||
|
DESCRIPTION="µStreamer - Lightweight and fast MJPG-HTTP streamer"
|
||||||
|
HOMEPAGE="https://github.com/pi-kvm/ustreamer"
|
||||||
|
EGIT_REPO_URI="https://github.com/pi-kvm/ustreamer.git"
|
||||||
|
|
||||||
|
LICENSE="GPL-3"
|
||||||
|
SLOT="0"
|
||||||
|
KEYWORDS="~amd64"
|
||||||
|
IUSE=""
|
||||||
|
|
||||||
|
DEPEND="
|
||||||
|
>=dev-libs/libevent-2.1.8
|
||||||
|
>=media-libs/libjpeg-turbo-1.5.3
|
||||||
|
>=sys-apps/util-linux-2.33
|
||||||
|
"
|
||||||
|
RDEPEND="${DEPEND}"
|
||||||
|
BDEPEND=""
|
||||||
|
|
||||||
|
src_install() {
|
||||||
|
dobin ustreamer
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user