mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-02-19 16:26:30 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f0e070be5b | ||
|
|
aa05c470b3 | ||
|
|
13af11a3a6 | ||
|
|
41330940c6 | ||
|
|
46e630d2f6 | ||
|
|
63d87f0526 | ||
|
|
b578e9897e |
@@ -1,7 +1,7 @@
|
||||
[bumpversion]
|
||||
commit = True
|
||||
tag = True
|
||||
current_version = 5.49
|
||||
current_version = 5.51
|
||||
parse = (?P<major>\d+)\.(?P<minor>\d+)
|
||||
serialize =
|
||||
{major}.{minor}
|
||||
|
||||
@@ -151,7 +151,7 @@ Add `-e EDID=1` to set HDMI EDID before starting ustreamer. Use together with `-
|
||||
-----
|
||||
# Raspberry Pi Camera Example
|
||||
|
||||
Example usage for the Raspberry Pi v3 camera (required `libcamerify` which is located in `libcamera-tools` on Raspbian):
|
||||
Example usage for the Raspberry Pi v3 camera (required `libcamerify` which is located in `libcamera-tools` and `libcamera-v4l2` (install both) on Raspbian):
|
||||
```
|
||||
$ sudo modprobe bcm2835-v4l2
|
||||
$ libcamerify ./ustreamer --host :: --encoder=m2m-image
|
||||
|
||||
@@ -99,7 +99,9 @@ static atomic_bool _g_key_required = false;
|
||||
janus_plugin *create(void);
|
||||
|
||||
|
||||
static void *_video_rtp_thread(UNUSED void *arg) {
|
||||
static void *_video_rtp_thread(void *arg) {
|
||||
(void)arg;
|
||||
|
||||
US_THREAD_RENAME("us_video_rtp");
|
||||
atomic_store(&_g_video_rtp_tid_created, true);
|
||||
|
||||
@@ -116,7 +118,9 @@ static void *_video_rtp_thread(UNUSED void *arg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *_video_sink_thread(UNUSED void *arg) {
|
||||
static void *_video_sink_thread(void *arg) {
|
||||
(void)arg;
|
||||
|
||||
US_THREAD_RENAME("us_video_sink");
|
||||
atomic_store(&_g_video_sink_tid_created, true);
|
||||
|
||||
@@ -178,7 +182,9 @@ static void *_video_sink_thread(UNUSED void *arg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *_audio_thread(UNUSED void *arg) {
|
||||
static void *_audio_thread(void *arg) {
|
||||
(void)arg;
|
||||
|
||||
US_THREAD_RENAME("us_audio");
|
||||
atomic_store(&_g_audio_tid_created, true);
|
||||
assert(_g_config->audio_dev_name != NULL);
|
||||
@@ -344,7 +350,8 @@ static json_t *_plugin_query_session(janus_plugin_session *session) {
|
||||
return info;
|
||||
}
|
||||
|
||||
static void _set_transmit(janus_plugin_session *session, UNUSED const char *msg, bool transmit) {
|
||||
static void _set_transmit(janus_plugin_session *session, const char *msg, bool transmit) {
|
||||
(void)msg;
|
||||
_IF_DISABLED({ return; });
|
||||
_LOCK_ALL;
|
||||
bool found = false;
|
||||
@@ -503,7 +510,9 @@ static struct janus_plugin_result *_plugin_handle_message(
|
||||
# undef FREE_MSG_JSEP
|
||||
}
|
||||
|
||||
static void _plugin_incoming_rtcp(UNUSED janus_plugin_session *handle, UNUSED janus_plugin_rtcp *packet) {
|
||||
static void _plugin_incoming_rtcp(janus_plugin_session *handle, janus_plugin_rtcp *packet) {
|
||||
(void)handle;
|
||||
(void)packet;
|
||||
if (packet->video && janus_rtcp_has_pli(packet->buffer, packet->length)) {
|
||||
// US_JLOG_INFO("main", "Got video PLI");
|
||||
atomic_store(&_g_key_required, true);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Manpage for ustreamer-dump.
|
||||
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
||||
.TH USTREAMER-DUMP 1 "version 5.49" "January 2021"
|
||||
.TH USTREAMER-DUMP 1 "version 5.51" "January 2021"
|
||||
|
||||
.SH NAME
|
||||
ustreamer-dump \- Dump uStreamer's memory sink to file
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
.\" Manpage for ustreamer.
|
||||
.\" Open an issue or pull request to https://github.com/pikvm/ustreamer to correct errors or typos
|
||||
.TH USTREAMER 1 "version 5.49" "November 2020"
|
||||
.TH USTREAMER 1 "version 5.51" "November 2020"
|
||||
|
||||
.SH NAME
|
||||
ustreamer \- stream MJPEG video from any V4L2 device to the network
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
|
||||
pkgname=ustreamer
|
||||
pkgver=5.49
|
||||
pkgver=5.51
|
||||
pkgrel=1
|
||||
pkgdesc="Lightweight and fast MJPEG-HTTP streamer"
|
||||
url="https://github.com/pikvm/ustreamer"
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=ustreamer
|
||||
PKG_VERSION:=5.49
|
||||
PKG_VERSION:=5.51
|
||||
PKG_RELEASE:=1
|
||||
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ def _find_sources(suffix: str) -> list[str]:
|
||||
if __name__ == "__main__":
|
||||
setup(
|
||||
name="ustreamer",
|
||||
version="5.49",
|
||||
version="5.51",
|
||||
description="uStreamer tools",
|
||||
author="Maxim Devaev",
|
||||
author_email="mdevaev@gmail.com",
|
||||
|
||||
@@ -99,7 +99,7 @@ static int _MemsinkObject_init(_MemsinkObject *self, PyObject *args, PyObject *k
|
||||
|
||||
static PyObject *_MemsinkObject_repr(_MemsinkObject *self) {
|
||||
char repr[1024];
|
||||
snprintf(repr, 1023, "<Memsink(%s)>", self->obj);
|
||||
US_SNPRINTF(repr, 1023, "<Memsink(%s)>", self->obj);
|
||||
return Py_BuildValue("s", repr);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#pragma once
|
||||
|
||||
#define US_VERSION_MAJOR 5
|
||||
#define US_VERSION_MINOR 49
|
||||
#define US_VERSION_MINOR 51
|
||||
|
||||
#define US_MAKE_VERSION2(_major, _minor) #_major "." #_minor
|
||||
#define US_MAKE_VERSION1(_major, _minor) US_MAKE_VERSION2(_major, _minor)
|
||||
|
||||
@@ -91,7 +91,7 @@ extern pthread_mutex_t us_g_log_mutex;
|
||||
|
||||
|
||||
#define US_LOG_PRINTF_NOLOCK(x_label_color, x_label, x_msg_color, x_msg, ...) { \
|
||||
char m_tname_buf[US_MAX_THREAD_NAME] = {0}; \
|
||||
char m_tname_buf[US_THREAD_NAME_SIZE] = {0}; \
|
||||
us_thread_get_name(m_tname_buf); \
|
||||
if (us_g_log_colored) { \
|
||||
fprintf(stderr, US_COLOR_GRAY "-- " x_label_color x_label US_COLOR_GRAY \
|
||||
|
||||
@@ -41,9 +41,9 @@
|
||||
|
||||
|
||||
#ifdef PTHREAD_MAX_NAMELEN_NP
|
||||
# define US_MAX_THREAD_NAME ((size_t)(PTHREAD_MAX_NAMELEN_NP))
|
||||
# define US_THREAD_NAME_SIZE ((size_t)(PTHREAD_MAX_NAMELEN_NP))
|
||||
#else
|
||||
# define US_MAX_THREAD_NAME ((size_t)16)
|
||||
# define US_THREAD_NAME_SIZE ((size_t)16)
|
||||
#endif
|
||||
|
||||
#define US_THREAD_CREATE(x_tid, x_func, x_arg) assert(!pthread_create(&(x_tid), NULL, (x_func), (x_arg)))
|
||||
@@ -51,8 +51,8 @@
|
||||
|
||||
#ifdef WITH_PTHREAD_NP
|
||||
# define US_THREAD_RENAME(x_fmt, ...) { \
|
||||
char m_new_tname_buf[US_MAX_THREAD_NAME] = {0}; \
|
||||
assert(snprintf(m_new_tname_buf, US_MAX_THREAD_NAME, (x_fmt), ##__VA_ARGS__) > 0); \
|
||||
char m_new_tname_buf[US_THREAD_NAME_SIZE] = {0}; \
|
||||
US_SNPRINTF(m_new_tname_buf, (US_THREAD_NAME_SIZE - 1), (x_fmt), ##__VA_ARGS__); \
|
||||
us_thread_set_name(m_new_tname_buf); \
|
||||
}
|
||||
#else
|
||||
@@ -89,12 +89,12 @@ INLINE void us_thread_get_name(char *name) { // Always required for logging
|
||||
#ifdef WITH_PTHREAD_NP
|
||||
int retval = -1;
|
||||
# if defined(__linux__) || defined (__NetBSD__)
|
||||
retval = pthread_getname_np(pthread_self(), name, US_MAX_THREAD_NAME);
|
||||
retval = pthread_getname_np(pthread_self(), name, US_THREAD_NAME_SIZE - 1);
|
||||
# elif \
|
||||
(defined(__FreeBSD__) && defined(__FreeBSD_version) && __FreeBSD_version >= 1103500) \
|
||||
|| (defined(__OpenBSD__) && defined(OpenBSD) && OpenBSD >= 201905) \
|
||||
|| defined(__DragonFly__)
|
||||
pthread_get_name_np(pthread_self(), name, US_MAX_THREAD_NAME);
|
||||
pthread_get_name_np(pthread_self(), name, US_THREAD_NAME_SIZE - 1);
|
||||
if (name[0] != '\0') {
|
||||
retval = 0;
|
||||
}
|
||||
@@ -118,7 +118,7 @@ INLINE void us_thread_get_name(char *name) { // Always required for logging
|
||||
const pid_t tid = 0; // Makes cppcheck happy
|
||||
# warning gettid() not implemented
|
||||
#endif
|
||||
assert(snprintf(name, US_MAX_THREAD_NAME, "tid=%d", tid) > 0);
|
||||
US_SNPRINTF(name, (US_THREAD_NAME_SIZE - 1), "tid=%d", tid);
|
||||
|
||||
#ifdef WITH_PTHREAD_NP
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <errno.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
@@ -57,14 +56,14 @@
|
||||
#define RN "\r\n"
|
||||
|
||||
#define INLINE inline __attribute__((always_inline))
|
||||
#define UNUSED __attribute__((unused))
|
||||
|
||||
#define US_CALLOC(x_dest, x_nmemb) assert(((x_dest) = calloc((x_nmemb), sizeof(*(x_dest)))) != NULL)
|
||||
#define US_REALLOC(x_dest, x_nmemb) assert(((x_dest) = realloc((x_dest), (x_nmemb) * sizeof(*(x_dest)))) != NULL)
|
||||
#define US_DELETE(x_dest, x_free) { if (x_dest) { x_free(x_dest); } }
|
||||
#define US_MEMSET_ZERO(x_obj) memset(&(x_obj), 0, sizeof(x_obj))
|
||||
|
||||
#define US_ASPRINTF(x_dest, x_fmt, ...) assert(asprintf(&(x_dest), (x_fmt), ##__VA_ARGS__) >= 0)
|
||||
#define US_SNPRINTF(x_dest, x_size, x_fmt, ...) assert(snprintf((x_dest), (x_size), (x_fmt), ##__VA_ARGS__) > 0)
|
||||
#define US_ASPRINTF(x_dest, x_fmt, ...) assert(asprintf(&(x_dest), (x_fmt), ##__VA_ARGS__) > 0)
|
||||
|
||||
|
||||
INLINE char *us_strdup(const char *str) {
|
||||
@@ -178,15 +177,16 @@ INLINE int us_flock_timedwait_monotonic(int fd, long double timeout) {
|
||||
}
|
||||
|
||||
INLINE char *us_errno_to_string(int error) {
|
||||
locale_t locale = newlocale(LC_MESSAGES_MASK, "C", NULL);
|
||||
char *buf;
|
||||
if (locale) {
|
||||
buf = us_strdup(strerror_l(error, locale));
|
||||
freelocale(locale);
|
||||
} else {
|
||||
buf = us_strdup("!!! newlocale() error !!!");
|
||||
char buf[2048];
|
||||
const size_t max_len = sizeof(buf) - 1;
|
||||
# if (_POSIX_C_SOURCE >= 200112L) && ! _GNU_SOURCE
|
||||
if (strerror_r(error, buf, max_len) != 0) {
|
||||
US_SNPRINTF(buf, max_len, "Errno = %d", error);
|
||||
}
|
||||
return buf;
|
||||
return us_strdup(buf);
|
||||
# else
|
||||
return us_strdup(strerror_r(error, buf, max_len));
|
||||
# endif
|
||||
}
|
||||
|
||||
INLINE char *us_signum_to_string(int signum) {
|
||||
|
||||
@@ -120,7 +120,7 @@ us_workers_pool_s *us_encoder_workers_pool_init(us_encoder_s *enc, us_device_s *
|
||||
for (; _ER(n_m2ms) < n_workers; ++_ER(n_m2ms)) {
|
||||
// Начинаем с нуля и доинициализируем на следующих заходах при необходимости
|
||||
char name[32];
|
||||
snprintf(name, 32, "JPEG-%u", _ER(n_m2ms));
|
||||
US_SNPRINTF(name, 31, "JPEG-%u", _ER(n_m2ms));
|
||||
if (type == US_ENCODER_TYPE_M2M_VIDEO) {
|
||||
_ER(m2ms[_ER(n_m2ms)]) = us_m2m_mjpeg_encoder_init(name, enc->m2m_path, quality);
|
||||
} else {
|
||||
|
||||
@@ -31,7 +31,7 @@ char *us_bufferevent_format_reason(short what) {
|
||||
char *const perror_str = us_errno_to_string(EVUTIL_SOCKET_ERROR());
|
||||
bool first = true;
|
||||
|
||||
strcat(reason, perror_str);
|
||||
strncat(reason, perror_str, 1023);
|
||||
free(perror_str);
|
||||
strcat(reason, " (");
|
||||
|
||||
|
||||
@@ -502,12 +502,12 @@ static void _http_callback_snapshot(struct evhttp_request *request, void *v_serv
|
||||
char header_buf[256];
|
||||
|
||||
# define ADD_TIME_HEADER(x_key, x_value) { \
|
||||
snprintf(header_buf, 255, "%.06Lf", x_value); \
|
||||
US_SNPRINTF(header_buf, 255, "%.06Lf", x_value); \
|
||||
ADD_HEADER(x_key, header_buf); \
|
||||
}
|
||||
|
||||
# define ADD_UNSIGNED_HEADER(x_key, x_value) { \
|
||||
snprintf(header_buf, 255, "%u", x_value); \
|
||||
US_SNPRINTF(header_buf, 255, "%u", x_value); \
|
||||
ADD_HEADER(x_key, header_buf); \
|
||||
}
|
||||
|
||||
@@ -667,10 +667,12 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c
|
||||
"Cache-Control: no-store, no-cache, must-revalidate, proxy-revalidate, pre-check=0, post-check=0, max-age=0" RN
|
||||
"Pragma: no-cache" RN
|
||||
"Expires: Mon, 3 Jan 2000 12:34:56 GMT" RN
|
||||
"Set-Cookie: stream_client=%s/%" PRIx64 "; path=/; max-age=30" RN
|
||||
"Set-Cookie: stream_client%s%s=%s/%" PRIx64 "; path=/; max-age=30" RN
|
||||
"Content-Type: multipart/x-mixed-replace;boundary=" BOUNDARY RN
|
||||
RN
|
||||
"--" BOUNDARY RN,
|
||||
(server->instance_id[0] == '\0' ? "" : "_"),
|
||||
server->instance_id,
|
||||
(client->key != NULL ? client->key : "0"),
|
||||
client->id
|
||||
);
|
||||
@@ -745,7 +747,10 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c
|
||||
# undef BOUNDARY
|
||||
}
|
||||
|
||||
static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UNUSED short what, void *v_client) {
|
||||
static void _http_callback_stream_error(struct bufferevent *buf_event, short what, void *v_client) {
|
||||
(void)buf_event;
|
||||
(void)what;
|
||||
|
||||
us_stream_client_s *const client = (us_stream_client_s *)v_client;
|
||||
us_server_s *const server = client->server;
|
||||
|
||||
@@ -823,7 +828,10 @@ static void _http_queue_send_stream(us_server_s *server, bool stream_updated, bo
|
||||
}
|
||||
}
|
||||
|
||||
static void _http_request_watcher(UNUSED int fd, UNUSED short what, void *v_server) {
|
||||
static void _http_request_watcher(int fd, short what, void *v_server) {
|
||||
(void)fd;
|
||||
(void)what;
|
||||
|
||||
us_server_s *server = (us_server_s *)v_server;
|
||||
const long double now = us_get_now_monotonic();
|
||||
|
||||
@@ -837,7 +845,10 @@ static void _http_request_watcher(UNUSED int fd, UNUSED short what, void *v_serv
|
||||
}
|
||||
}
|
||||
|
||||
static void _http_refresher(UNUSED int fd, UNUSED short what, void *v_server) {
|
||||
static void _http_refresher(int fd, short what, void *v_server) {
|
||||
(void)fd;
|
||||
(void)what;
|
||||
|
||||
us_server_s *server = (us_server_s *)v_server;
|
||||
bool stream_updated = false;
|
||||
bool frame_updated = false;
|
||||
|
||||
@@ -33,7 +33,7 @@ char *us_find_static_file_path(const char *root_path, const char *request_path)
|
||||
}
|
||||
|
||||
US_CALLOC(path, strlen(root_path) + strlen(simplified_path) + 16); // + reserved for /index.html
|
||||
sprintf(path, "%s/%s", root_path, simplified_path);
|
||||
assert(sprintf(path, "%s/%s", root_path, simplified_path) > 0);
|
||||
|
||||
struct stat st;
|
||||
# define LOAD_STAT { \
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
|
||||
@@ -52,14 +52,16 @@ static void _block_thread_signals(void) {
|
||||
assert(!pthread_sigmask(SIG_BLOCK, &mask, NULL));
|
||||
}
|
||||
|
||||
static void *_stream_loop_thread(UNUSED void *arg) {
|
||||
static void *_stream_loop_thread(void *arg) {
|
||||
(void)arg;
|
||||
US_THREAD_RENAME("stream");
|
||||
_block_thread_signals();
|
||||
us_stream_loop(_g_stream);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void *_server_loop_thread(UNUSED void *arg) {
|
||||
static void *_server_loop_thread(void *arg) {
|
||||
(void)arg;
|
||||
US_THREAD_RENAME("http");
|
||||
_block_thread_signals();
|
||||
us_server_loop(_g_server);
|
||||
|
||||
Reference in New Issue
Block a user