mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-27 20:26:31 +00:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
37216250b8 | ||
|
|
dc82894038 | ||
|
|
f3a350148e | ||
|
|
5e49f50e22 | ||
|
|
91ff97f721 | ||
|
|
daaa488dd6 |
@@ -1,7 +1,7 @@
|
|||||||
[bumpversion]
|
[bumpversion]
|
||||||
commit = True
|
commit = True
|
||||||
tag = True
|
tag = True
|
||||||
current_version = 3.18
|
current_version = 3.21
|
||||||
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}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Manpage for ustreamer-dump.
|
.\" Manpage for ustreamer-dump.
|
||||||
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
||||||
.TH USTREAMER-DUMP 1 "version 3.18" "January 2021"
|
.TH USTREAMER-DUMP 1 "version 3.21" "January 2021"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ustreamer-dump \- Dump uStreamer's memory sink to file
|
ustreamer-dump \- Dump uStreamer's memory sink to file
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
.\" Manpage for ustreamer.
|
.\" Manpage for ustreamer.
|
||||||
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
||||||
.TH USTREAMER 1 "version 3.18" "November 2020"
|
.TH USTREAMER 1 "version 3.21" "November 2020"
|
||||||
|
|
||||||
.SH NAME
|
.SH NAME
|
||||||
ustreamer \- stream MJPG video from any V4L2 device to the network
|
ustreamer \- stream MJPG video from any V4L2 device to the network
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
|
|
||||||
pkgname=ustreamer
|
pkgname=ustreamer
|
||||||
pkgver=3.18
|
pkgver=3.21
|
||||||
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:=3.18
|
PKG_VERSION:=3.21
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from distutils.core import setup
|
|||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
setup(
|
setup(
|
||||||
name="ustreamer",
|
name="ustreamer",
|
||||||
version="3.18",
|
version="3.21",
|
||||||
description="uStreamer tools",
|
description="uStreamer tools",
|
||||||
author="Maxim Devaev",
|
author="Maxim Devaev",
|
||||||
author_email="mdevaev@gmail.com",
|
author_email="mdevaev@gmail.com",
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ typedef struct {
|
|||||||
memsink_shared_s *mem;
|
memsink_shared_s *mem;
|
||||||
|
|
||||||
tmp_frame_s *tmp_frame;
|
tmp_frame_s *tmp_frame;
|
||||||
PyObject *dict_frame; // PyDict
|
|
||||||
} MemsinkObject;
|
} MemsinkObject;
|
||||||
|
|
||||||
|
|
||||||
@@ -59,10 +58,6 @@ typedef struct {
|
|||||||
|
|
||||||
|
|
||||||
static void MemsinkObject_destroy_internals(MemsinkObject *self) {
|
static void MemsinkObject_destroy_internals(MemsinkObject *self) {
|
||||||
if (self->dict_frame != NULL) {
|
|
||||||
Py_DECREF(self->dict_frame);
|
|
||||||
self->dict_frame = NULL;
|
|
||||||
}
|
|
||||||
if (self->mem != NULL) {
|
if (self->mem != NULL) {
|
||||||
munmap(self->mem, sizeof(memsink_shared_s));
|
munmap(self->mem, sizeof(memsink_shared_s));
|
||||||
self->mem = NULL;
|
self->mem = NULL;
|
||||||
@@ -130,10 +125,6 @@ static int MemsinkObject_init(MemsinkObject *self, PyObject *args, PyObject *kwa
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((self->dict_frame = PyDict_New()) == NULL) {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@@ -274,14 +265,17 @@ static PyObject *MemsinkObject_wait_frame(MemsinkObject *self, PyObject *Py_UNUS
|
|||||||
return PyErr_SetFromErrno(PyExc_OSError);
|
return PyErr_SetFromErrno(PyExc_OSError);
|
||||||
}
|
}
|
||||||
|
|
||||||
PyDict_Clear(self->dict_frame);
|
PyObject *dict_frame = PyDict_New();
|
||||||
|
if (dict_frame == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
# define SET_VALUE(_key, _maker) { \
|
# define SET_VALUE(_key, _maker) { \
|
||||||
PyObject *_tmp = _maker; \
|
PyObject *_tmp = _maker; \
|
||||||
if (_tmp == NULL) { \
|
if (_tmp == NULL) { \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
if (PyDict_SetItemString(self->dict_frame, _key, _tmp) < 0) { \
|
if (PyDict_SetItemString(dict_frame, _key, _tmp) < 0) { \
|
||||||
Py_DECREF(_tmp); \
|
Py_DECREF(_tmp); \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
@@ -303,8 +297,7 @@ static PyObject *MemsinkObject_wait_frame(MemsinkObject *self, PyObject *Py_UNUS
|
|||||||
# undef SET_NUMBER
|
# undef SET_NUMBER
|
||||||
# undef SET_VALUE
|
# undef SET_VALUE
|
||||||
|
|
||||||
Py_INCREF(self->dict_frame);
|
return dict_frame;
|
||||||
return self->dict_frame;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject *MemsinkObject_is_opened(MemsinkObject *self, PyObject *Py_UNUSED(ignored)) {
|
static PyObject *MemsinkObject_is_opened(MemsinkObject *self, PyObject *Py_UNUSED(ignored)) {
|
||||||
|
|||||||
@@ -23,5 +23,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef VERSION
|
#ifndef VERSION
|
||||||
# define VERSION "3.18"
|
# define VERSION "3.21"
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -39,6 +39,8 @@ static void _http_queue_send_stream(server_s *server, bool stream_updated, bool
|
|||||||
|
|
||||||
static bool _expose_new_frame(server_s *server);
|
static bool _expose_new_frame(server_s *server);
|
||||||
|
|
||||||
|
static char *_http_get_client_hostport(struct evhttp_request *request);
|
||||||
|
|
||||||
|
|
||||||
#define RUN(_next) server->run->_next
|
#define RUN(_next) server->run->_next
|
||||||
#define STREAM(_next) RUN(stream->_next)
|
#define STREAM(_next) RUN(stream->_next)
|
||||||
@@ -94,6 +96,7 @@ void server_destroy(server_s *server) {
|
|||||||
for (stream_client_s *client = RUN(stream_clients); client != NULL;) {
|
for (stream_client_s *client = RUN(stream_clients); client != NULL;) {
|
||||||
stream_client_s *next = client->next;
|
stream_client_s *next = client->next;
|
||||||
free(client->key);
|
free(client->key);
|
||||||
|
free(client->hostport);
|
||||||
free(client);
|
free(client);
|
||||||
client = next;
|
client = next;
|
||||||
}
|
}
|
||||||
@@ -473,6 +476,7 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server
|
|||||||
# undef PARSE_PARAM
|
# undef PARSE_PARAM
|
||||||
evhttp_clear_headers(¶ms);
|
evhttp_clear_headers(¶ms);
|
||||||
|
|
||||||
|
client->hostport = _http_get_client_hostport(request);
|
||||||
client->id = get_now_id();
|
client->id = get_now_id();
|
||||||
|
|
||||||
if (RUN(stream_clients) == NULL) {
|
if (RUN(stream_clients) == NULL) {
|
||||||
@@ -493,23 +497,18 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
char *client_addr;
|
LOG_INFO("HTTP: Registered client: %s, id=%" PRIx64 "; clients now: %u",
|
||||||
unsigned short client_port;
|
client->hostport, client->id, RUN(stream_clients_count));
|
||||||
evhttp_connection_get_peer(conn, &client_addr, &client_port);
|
|
||||||
|
|
||||||
LOG_INFO("HTTP: Registered client: [%s]:%u, id=%" PRIx64 "; clients now: %u",
|
|
||||||
client_addr, client_port, client->id, RUN(stream_clients_count));
|
|
||||||
|
|
||||||
|
|
||||||
struct bufferevent *buf_event = evhttp_connection_get_bufferevent(conn);
|
struct bufferevent *buf_event = evhttp_connection_get_bufferevent(conn);
|
||||||
if (server->tcp_nodelay && !RUN(unix_fd)) {
|
if (server->tcp_nodelay && !RUN(unix_fd)) {
|
||||||
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);
|
LOG_DEBUG("HTTP: Setting up TCP_NODELAY to the client %s ...", client->hostport);
|
||||||
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 [%s]:%u", client_addr, client_port);
|
LOG_PERROR("HTTP: Can't set TCP_NODELAY to the client %s", client->hostport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bufferevent_setcb(buf_event, NULL, NULL, _http_callback_stream_error, (void *)client);
|
bufferevent_setcb(buf_event, NULL, NULL, _http_callback_stream_error, (void *)client);
|
||||||
@@ -668,17 +667,10 @@ static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UN
|
|||||||
# endif
|
# endif
|
||||||
}
|
}
|
||||||
|
|
||||||
char *client_addr = "???";
|
LOG_INFO("HTTP: Disconnected client: %s, id=%" PRIx64 ", %s; clients now: %u",
|
||||||
unsigned short client_port = 0;
|
client->hostport, client->id, reason, RUN(stream_clients_count));
|
||||||
|
|
||||||
struct evhttp_connection *conn = evhttp_request_get_connection(client->request);
|
struct evhttp_connection *conn = evhttp_request_get_connection(client->request);
|
||||||
if (conn) {
|
|
||||||
evhttp_connection_get_peer(conn, &client_addr, &client_port);
|
|
||||||
}
|
|
||||||
|
|
||||||
LOG_INFO("HTTP: Disconnected client: [%s]:%u, id=%" PRIx64 ", %s; clients now: %u",
|
|
||||||
client_addr, client_port, client->id, reason, RUN(stream_clients_count));
|
|
||||||
|
|
||||||
if (conn) {
|
if (conn) {
|
||||||
evhttp_connection_free(conn);
|
evhttp_connection_free(conn);
|
||||||
}
|
}
|
||||||
@@ -692,6 +684,7 @@ static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UN
|
|||||||
client->next->prev = client->prev;
|
client->next->prev = client->prev;
|
||||||
}
|
}
|
||||||
free(client->key);
|
free(client->key);
|
||||||
|
free(client->hostport);
|
||||||
free(client);
|
free(client);
|
||||||
|
|
||||||
free(reason);
|
free(reason);
|
||||||
@@ -834,3 +827,40 @@ static bool _expose_new_frame(server_s *server) {
|
|||||||
#undef VID
|
#undef VID
|
||||||
#undef STREAM
|
#undef STREAM
|
||||||
#undef RUN
|
#undef RUN
|
||||||
|
|
||||||
|
static char *_http_get_client_hostport(struct evhttp_request *request) {
|
||||||
|
char *addr = NULL;
|
||||||
|
unsigned short port = 0;
|
||||||
|
struct evhttp_connection *conn = evhttp_request_get_connection(request);
|
||||||
|
if (conn) {
|
||||||
|
char *peer;
|
||||||
|
evhttp_connection_get_peer(conn, &peer, &port);
|
||||||
|
assert(addr = strdup(peer));
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *xff = evhttp_find_header(evhttp_request_get_input_headers(request), "X-Forwarded-For");
|
||||||
|
if (xff) {
|
||||||
|
if (addr) {
|
||||||
|
free(addr);
|
||||||
|
}
|
||||||
|
assert(addr = strndup(xff, 1024));
|
||||||
|
for (unsigned index = 0; addr[index]; ++index) {
|
||||||
|
if (addr[index] == ',') {
|
||||||
|
addr[index] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addr == NULL) {
|
||||||
|
assert(addr = strdup("???"));
|
||||||
|
}
|
||||||
|
|
||||||
|
char *hostport;
|
||||||
|
size_t hostport_len = strlen(addr) + 64;
|
||||||
|
A_CALLOC(hostport, hostport_len);
|
||||||
|
|
||||||
|
snprintf(hostport, hostport_len, "[%s]:%u", addr, port);
|
||||||
|
free(addr);
|
||||||
|
return hostport;
|
||||||
|
}
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ typedef struct stream_client_sx {
|
|||||||
bool dual_final_frames;
|
bool dual_final_frames;
|
||||||
bool zero_data;
|
bool zero_data;
|
||||||
|
|
||||||
|
char *hostport;
|
||||||
uint64_t id;
|
uint64_t id;
|
||||||
bool need_initial;
|
bool need_initial;
|
||||||
bool need_first_frame;
|
bool need_first_frame;
|
||||||
|
|||||||
Reference in New Issue
Block a user