Compare commits

...

23 Commits
v1.14 ... v1.17

Author SHA1 Message Date
Devaev Maxim
97403cbb75 Bump version: 1.16 → 1.17 2020-05-19 01:08:37 +03:00
Devaev Maxim
0663bb1035 fix for gcc 10 multiple definition errors 2020-05-19 01:07:55 +03:00
Devaev Maxim
06f4017a5b Bump version: 1.15 → 1.16 2020-05-12 09:42:48 +03:00
Devaev Maxim
6493a62c6c badges 2020-05-12 09:39:02 +03:00
Devaev Maxim
66c627c682 lint fixes 2020-05-12 09:37:02 +03:00
Devaev Maxim
8d6f5f7f8f .dockerignore 2020-05-12 09:36:48 +03:00
Devaev Maxim
f1cdfd4223 docker-based linters 2020-05-12 09:26:24 +03:00
Devaev Maxim
972c288df3 action fix 2020-05-12 09:08:23 +03:00
Devaev Maxim
fd1d2dec71 action fix 2020-05-12 09:05:26 +03:00
Devaev Maxim
331bd181bf action fix 2020-05-12 09:01:44 +03:00
Devaev Maxim
231ff37570 action fix 2020-05-12 08:54:01 +03:00
Devaev Maxim
cec0b203b3 action fix 2020-05-12 08:51:32 +03:00
Devaev Maxim
e5c9d699a3 action fix 2020-05-12 08:50:08 +03:00
Maxim Devaev
198fbc1756 Create ccpp.yml 2020-05-12 08:46:39 +03:00
Devaev Maxim
55aa443d68 linters 2020-05-12 08:43:12 +03:00
Devaev Maxim
44d6288416 lint fixes 2020-05-12 08:42:18 +03:00
Devaev Maxim
aeae342853 lint fixes 2020-05-12 08:19:26 +03:00
Devaev Maxim
d22034da96 lint fixes 2020-05-12 07:45:12 +03:00
Devaev Maxim
43788f812d type fixes 2020-05-12 07:27:42 +03:00
Devaev Maxim
95318e14d8 lint fixes 2020-05-12 06:44:59 +03:00
Devaev Maxim
67d6f15776 lint fix 2020-05-11 20:02:30 +03:00
Devaev Maxim
6c2353ce2c Bump version: 1.14 → 1.15 2020-05-03 06:38:11 +03:00
Devaev Maxim
fcdfb2930a refactoring 2020-05-03 06:38:02 +03:00
36 changed files with 332 additions and 78 deletions

View File

@@ -1,7 +1,7 @@
[bumpversion]
commit = True
tag = True
current_version = 1.14
current_version = 1.17
parse = (?P<major>\d+)\.(?P<minor>\d+)(\.(?P<patch>\d+)(\-(?P<release>[a-z]+))?)?
serialize =
{major}.{minor}

20
.github/workflows/dockerimage.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: CI
on:
push:
branches: [master]
pull_request:
branches: [master]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Building linters image ...
run: make linters
- name: Running linters ...
run: make tox

2
.gitignore vendored
View File

@@ -1,3 +1,5 @@
/linters/.tox/
/linters/.mypy_cache/
/pkg/arch/pkg/
/pkg/arch/src/
/pkg/arch/v*.tar.gz

View File

@@ -13,6 +13,8 @@ RPI_VC_LIBS ?= /opt/vc/lib
BUILD ?= build
LINTERS_IMAGE ?= $(PROG)-linters
# =====
_LIBS = -lm -ljpeg -pthread -levent -levent_pthreads -luuid
@@ -92,12 +94,31 @@ $(BUILD)/%.o: %.c
release:
make clean
make tox
make push
make bump
make push
make clean
tox: linters
time docker run --rm \
--volume `pwd`:/src:ro \
--volume `pwd`/linters:/src/linters:rw \
-t $(LINTERS_IMAGE) bash -c " \
cd /src \
&& tox -q -c linters/tox.ini $(if $(E),-e $(E),-p auto) \
"
linters:
docker build \
$(if $(call optbool,$(NC)),--no-cache,) \
--rm \
--tag $(LINTERS_IMAGE) \
-f linters/Dockerfile linters
bump:
bumpversion $(if $(V),$(V),minor)
@@ -107,7 +128,12 @@ push:
git push --tags
clean-all: clean
clean-all: linters clean
- docker run --rm \
--volume `pwd`:/src \
-it $(LINTERS_IMAGE) bash -c "cd src && rm -rf linters/{.tox,.mypy_cache}"
clean:
rm -rf pkg/arch/pkg pkg/arch/src pkg/arch/v*.tar.gz pkg/arch/ustreamer-*.pkg.tar.{xz,zst}
rm -rf $(PROG) $(BUILD) vgcore.* *.sock
.PHONY: linters

View File

@@ -1,4 +1,7 @@
# µStreamer
[![CI](https://github.com/pikvm/ustreamer/workflows/CI/badge.svg)](https://github.com/pikvm/ustreamer/actions?query=workflow%3ACI)
[![Discord](https://img.shields.io/discord/580094191938437144?logo=discord)](https://discord.gg/bpmXfz5)
[[Русская версия]](README.ru.md)
µStreamer is a lightweight and very quick server to broadcast [MJPG](https://en.wikipedia.org/wiki/Motion_JPEG) video from any V4L2 device to the net. All new browsers have native support of this video format, as well as most video players such as mplayer, VLC etc.

View File

@@ -1,4 +1,7 @@
# µStreamer
# µStreamer
[![CI](https://github.com/pikvm/ustreamer/workflows/CI/badge.svg)](https://github.com/pikvm/ustreamer/actions?query=workflow%3ACI)
[![Discord](https://img.shields.io/discord/580094191938437144?logo=discord)](https://discord.gg/bpmXfz5)
[[English version]](README.md)

2
linters/.dockerignore Normal file
View File

@@ -0,0 +1,2 @@
/.tox/
/.mypy_cache/

21
linters/Dockerfile Normal file
View File

@@ -0,0 +1,21 @@
FROM archlinux/base
RUN echo "Server = http://mirror.yandex.ru/archlinux/\$repo/os/\$arch" > /etc/pacman.d/mirrorlist
RUN pacman -Syu --noconfirm \
&& pacman -S --needed --noconfirm \
base \
base-devel \
vim \
git \
libjpeg \
libevent \
libutil-linux \
libbsd \
python \
python-pip \
python-tox \
cppcheck \
&& (pacman -Sc --noconfirm || true)
CMD /bin/bash

9
linters/flake8.ini Normal file
View File

@@ -0,0 +1,9 @@
[flake8]
inline-quotes = double
max-line-length = 160
ignore = W503, E227, E241, E252, Q003
# W503 line break before binary operator
# E227 missing whitespace around bitwise or shift operator
# E241 multiple spaces after
# E252 missing whitespace around parameter equals
# Q003 Change outer quotes to avoid escaping inner quotes

5
linters/mypy.ini Normal file
View File

@@ -0,0 +1,5 @@
[mypy]
python_version = 3.8
ignore_missing_imports = true
disallow_untyped_defs = true
strict_optional = true

63
linters/pylint.ini Normal file
View File

@@ -0,0 +1,63 @@
[MASTER]
ignore = .git
[DESIGN]
min-public-methods = 0
max-args = 10
[TYPECHECK]
ignored-classes=
AioQueue,
[MESSAGES CONTROL]
disable =
file-ignored,
locally-disabled,
fixme,
missing-docstring,
no-init,
no-self-use,
superfluous-parens,
abstract-class-not-used,
abstract-class-little-used,
duplicate-code,
bad-continuation,
bad-whitespace,
star-args,
broad-except,
redundant-keyword-arg,
wrong-import-order,
too-many-ancestors,
no-else-return,
len-as-condition,
[REPORTS]
msg-template = {symbol} -- {path}:{line}({obj}): {msg}
[FORMAT]
max-line-length = 160
[BASIC]
# List of builtins function names that should not be used, separated by a comma
bad-functions =
# Good variable names which should always be accepted, separated by a comma
good-names = _, __, x, y, ws, make-html-h, make-jpeg-h
# Regular expression matching correct method names
method-rgx = [a-z_][a-z0-9_]{2,50}$
# Regular expression matching correct function names
function-rgx = [a-z_][a-z0-9_]{2,50}$
# Regular expression which should only match correct module level names
const-rgx = ([a-zA-Z_][a-zA-Z0-9_]*)$
# Regular expression which should only match correct argument names
argument-rgx = [a-z_][a-z0-9_]{1,30}$
# Regular expression which should only match correct variable names
variable-rgx = [a-z_][a-z0-9_]{1,30}$
# Regular expression which should only match correct instance attribute names
attr-rgx = [a-z_][a-z0-9_]{1,30}$

48
linters/tox.ini Normal file
View File

@@ -0,0 +1,48 @@
[tox]
envlist = cppcheck, flake8, pylint, mypy, vulture
skipsdist = true
[testenv]
basepython = python3.8
changedir = /src
[testenv:cppcheck]
whitelist_externals = cppcheck
commands = cppcheck \
--force \
--std=c11 \
--error-exitcode=1 \
--quiet \
--enable=warning,unusedFunction,portability,performance,style \
--suppress=assignmentInAssert \
--suppress=variableScope \
--inline-suppr \
-DCHAR_BIT=8 \
src
[testenv:flake8]
whitelist_externals = bash
commands = bash -c 'flake8 --config=linters/flake8.ini tools/*.py'
# FIXME: pyflakes from master to support walrus
deps =
git+https://github.com/PyCQA/pyflakes@1911c20#egg=pyflakes
flake8
flake8-quotes
[testenv:pylint]
whitelist_externals = bash
commands = bash -c 'pylint --rcfile=linters/pylint.ini --output-format=colorized --reports=no tools/*.py'
deps =
pylint
[testenv:mypy]
whitelist_externals = bash
commands = bash -c 'mypy --config-file=linters/mypy.ini tools/*.py'
deps =
mypy
[testenv:vulture]
whitelist_externals = bash
commands = bash -c 'vulture tools/*.py'
deps =
vulture

View File

@@ -3,7 +3,7 @@
pkgname=ustreamer
pkgver=1.14
pkgver=1.17
pkgrel=1
pkgdesc="Lightweight and fast MJPG-HTTP streamer"
url="https://github.com/pikvm/ustreamer"

View File

@@ -6,7 +6,7 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=ustreamer
PKG_VERSION:=1.14
PKG_VERSION:=1.17
PKG_RELEASE:=1
PKG_MAINTAINER:=Maxim Devaev <mdevaev@gmail.com>

View File

@@ -23,5 +23,5 @@
#pragma once
#ifndef VERSION
# define VERSION "1.14"
# define VERSION "1.17"
#endif

View File

@@ -257,9 +257,9 @@ int device_select(struct device_t *dev, bool *has_read, bool *has_write, bool *h
*has_write = FD_ISSET(dev->run->fd, &write_fds);
*has_error = FD_ISSET(dev->run->fd, &error_fds);
} else {
has_read = false;
has_write = false;
has_error = false;
*has_read = false;
*has_write = false;
*has_error = false;
}
LOG_DEBUG("Device select() --> %d", retval);
@@ -663,6 +663,7 @@ static void _device_apply_controls(struct device_t *dev) {
}
static int _device_query_control(struct device_t *dev, struct v4l2_queryctrl *query, const char *name, unsigned cid, bool quiet) {
// cppcheck-suppress redundantPointerOp
MEMSET_ZERO(*query);
query->id = cid;
@@ -705,7 +706,7 @@ static const char *_format_to_string_fourcc(char *buf, size_t size, unsigned for
buf[1] = (format >> 8) & 0x7F;
buf[2] = (format >> 16) & 0x7F;
buf[3] = (format >> 24) & 0x7F;
if (format & (1 << 31)) {
if (format & ((unsigned)1 << 31)) {
buf[4] = '-';
buf[5] = 'B';
buf[6] = 'E';

View File

@@ -30,13 +30,13 @@
#include "picture.h"
#define VIDEO_MIN_WIDTH 160
#define VIDEO_MAX_WIDTH 10240
#define VIDEO_MIN_WIDTH ((unsigned)160)
#define VIDEO_MAX_WIDTH ((unsigned)10240)
#define VIDEO_MIN_HEIGHT 120
#define VIDEO_MAX_HEIGHT 4320
#define VIDEO_MIN_HEIGHT ((unsigned)120)
#define VIDEO_MAX_HEIGHT ((unsigned)4320)
#define VIDEO_MAX_FPS 120
#define VIDEO_MAX_FPS ((unsigned)120)
#define STANDARD_UNKNOWN V4L2_STD_UNKNOWN
#define STANDARDS_STR "PAL, NTSC, SECAM"

View File

@@ -170,6 +170,7 @@ void encoder_prepare(struct encoder_t *encoder, struct device_t *dev) {
# pragma GCC diagnostic ignored "-Wunused-label"
# pragma GCC diagnostic push
// cppcheck-suppress unusedLabel
force_cpu:
cpu_forced = true;
# pragma GCC diagnostic pop
@@ -225,6 +226,7 @@ int encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, uns
# pragma GCC diagnostic ignored "-Wunused-label"
# pragma GCC diagnostic push
// cppcheck-suppress unusedLabel
error:
LOG_INFO("Error while compressing buffer, falling back to CPU");
A_MUTEX_LOCK(&encoder->run->mutex);

View File

@@ -33,9 +33,10 @@
# define ENCODER_TYPES_OMX_HINT ", OMX"
# ifndef MAX_GLITCHED_RESOLUTIONS
# define MAX_GLITCHED_RESOLUTIONS 1024
# ifndef CFG_MAX_GLITCHED_RESOLUTIONS
# define CFG_MAX_GLITCHED_RESOLUTIONS 1024
# endif
# define MAX_GLITCHED_RESOLUTIONS ((unsigned)(CFG_MAX_GLITCHED_RESOLUTIONS))
#else
# define ENCODER_TYPES_OMX_HINT ""
#endif

View File

@@ -258,7 +258,7 @@ static void _jpeg_write_scanlines_rgb24(
}
}
#define JPEG_OUTPUT_BUFFER_SIZE 4096
#define JPEG_OUTPUT_BUFFER_SIZE ((size_t)4096)
static void _jpeg_init_destination(j_compress_ptr jpeg) {
struct _jpeg_dest_manager_t *dest = (struct _jpeg_dest_manager_t *)jpeg->dest;

View File

@@ -61,6 +61,7 @@ int component_disable_port(OMX_HANDLETYPE *component, OMX_U32 port) {
int component_get_portdef(OMX_HANDLETYPE *component, OMX_PARAM_PORTDEFINITIONTYPE *portdef, OMX_U32 port) {
OMX_ERRORTYPE error;
// cppcheck-suppress redundantPointerOp
OMX_INIT_STRUCTURE(*portdef);
portdef->nPortIndex = port;

View File

@@ -29,9 +29,10 @@
#include "../../device.h"
#ifndef OMX_MAX_ENCODERS
# define OMX_MAX_ENCODERS 3 // Raspberry Pi limitation
#ifndef CFG_OMX_MAX_ENCODERS
# define CFG_OMX_MAX_ENCODERS 3 // Raspberry Pi limitation
#endif
#define OMX_MAX_ENCODERS ((unsigned)(CFG_OMX_MAX_ENCODERS))
struct omx_encoder_t {

View File

@@ -35,9 +35,9 @@
case _value: { return #_value; }
#define CASE_ASSERT(_msg, _value) default: { \
char *_buf; A_CALLOC(_buf, 128); \
sprintf(_buf, _msg ": 0x%08x", _value); \
assert(0 && _buf); \
char *_assert_buf; A_CALLOC(_assert_buf, 128); \
sprintf(_assert_buf, _msg ": 0x%08x", _value); \
assert(0 && _assert_buf); \
}
const char *omx_error_to_string(OMX_ERRORTYPE error) {
@@ -76,6 +76,8 @@ const char *omx_state_to_string(OMX_STATETYPE state) {
CASE_TO_STRING(OMX_StateLoaded);
CASE_TO_STRING(OMX_StateIdle);
CASE_TO_STRING(OMX_StateExecuting);
// cppcheck-suppress constArgument
// cppcheck-suppress knownArgument
CASE_ASSERT("Unsupported OMX state", state);
}
}

View File

@@ -26,6 +26,7 @@
#include <wiringPi.h>
#include "tools.h"
#include "logging.h"
@@ -42,17 +43,18 @@ int gpio_pin_workers_busy_at;
gpio_pin_workers_busy_at = -1; \
}
#define GPIO_INIT_PIN(_role, _offset) { \
if (gpio_pin_##_role >= 0) { \
pinMode(gpio_pin_##_role + _offset, OUTPUT); \
digitalWrite(gpio_pin_##_role + _offset, LOW); \
if (_offset == 0) { \
LOG_INFO("GPIO: Using pin %d as %s", gpio_pin_##_role, #_role); \
} else { \
LOG_INFO("GPIO: Using pin %d+%d as %s", gpio_pin_##_role, _offset, #_role); \
} \
} \
#define GPIO_INIT_PIN(_role, _offset) _gpio_init_pin(#_role, gpio_pin_##_role, _offset)
INLINE void _gpio_init_pin(const char *role, int base, unsigned offset) {
if (base >= 0) {
pinMode(base + offset, OUTPUT);
if (offset == 0) {
LOG_INFO("GPIO: Using pin %d as %s", base, role);
} else {
LOG_INFO("GPIO: Using pin %d+%u as %s", base, offset, role);
}
}
}
#define GPIO_INIT_PINOUT { \
if ( \
@@ -74,16 +76,18 @@ int gpio_pin_workers_busy_at;
} \
}
#define GPIO_SET_STATE(_role, _offset, _state) { \
if (gpio_pin_##_role >= 0) { \
if (_offset == 0) { \
LOG_DEBUG("GPIO: Writing %d to pin %d (%s)", _state, gpio_pin_##_role, #_role); \
} else { \
LOG_DEBUG("GPIO: Writing %d to pin %d+%d (%s)", _state, gpio_pin_##_role, _offset, #_role); \
} \
digitalWrite(gpio_pin_##_role + _offset, _state); \
} \
#define GPIO_SET_STATE(_role, _offset, _state) _gpio_set_state(#_role, gpio_pin_##_role, _offset, _state)
INLINE void _gpio_set_state(const char *role, int base, unsigned offset, int state) {
if (base >= 0) {
if (offset == 0) {
LOG_DEBUG("GPIO: Writing %d to pin %d (%s)", state, base, role);
} else {
LOG_DEBUG("GPIO: Writing %d to pin %d+%u (%s)", state, base, offset, role);
}
digitalWrite(base + offset, state);
}
}
#define GPIO_SET_LOW(_role) GPIO_SET_STATE(_role, 0, LOW)
#define GPIO_SET_HIGH(_role) GPIO_SET_STATE(_role, 0, HIGH)

View File

@@ -94,7 +94,7 @@ static struct picture_t *_init_external(const char *path) {
goto error;
}
# define CHUNK_SIZE (100 * 1024)
# define CHUNK_SIZE ((size_t)(100 * 1024))
while (true) {
if (blank->used + CHUNK_SIZE >= blank->allocated) {
picture_realloc_data(blank, blank->used + CHUNK_SIZE * 2);

View File

@@ -680,9 +680,10 @@ static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UN
# define RUN(_next) client->server->run->_next
assert(RUN(stream_clients_count) > 0);
RUN(stream_clients_count) -= 1;
if (RUN(stream_clients_count) <= 0) {
if (RUN(stream_clients_count) == 0) {
if (client->server->slowdown) {
stream_switch_slowdown(RUN(stream), true);
}
@@ -721,8 +722,6 @@ static void _http_queue_send_stream(struct http_server_t *server, bool stream_up
struct bufferevent *buf_event;
long long now;
bool queued = false;
static unsigned queued_fps_accum = 0;
static long long queued_fps_second = 0;
for (struct stream_client_t *client = server->run->stream_clients; client != NULL; client = client->next) {
conn = evhttp_request_get_connection(client->request);
@@ -756,6 +755,9 @@ static void _http_queue_send_stream(struct http_server_t *server, bool stream_up
}
if (queued) {
static unsigned queued_fps_accum = 0;
static long long queued_fps_second = 0;
if ((now = floor_ms(get_now_monotonic())) != queued_fps_second) {
server->run->exposed->queued_fps = queued_fps_accum;
queued_fps_accum = 0;

34
src/logging.c Normal file
View File

@@ -0,0 +1,34 @@
/*****************************************************************************
# #
# uStreamer - Lightweight and fast MJPG-HTTP streamer. #
# #
# Copyright (C) 2018 Maxim Devaev <mdevaev@gmail.com> #
# #
# This program is free software: you can redistribute it and/or modify #
# it under the terms of the GNU General Public License as published by #
# the Free Software Foundation, either version 3 of the License, or #
# (at your option) any later version. #
# #
# This program is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# GNU General Public License for more details. #
# #
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
# #
*****************************************************************************/
#include <stdbool.h>
#include <pthread.h>
#include "logging.h"
enum log_level_t log_level;
bool log_colored;
pthread_mutex_t log_mutex;

View File

@@ -37,16 +37,19 @@
#include "threading.h"
enum {
LOG_LEVEL_INFO,
LOG_LEVEL_PERF,
LOG_LEVEL_VERBOSE,
LOG_LEVEL_DEBUG,
} log_level;
enum log_level_t {
LOG_LEVEL_INFO,
LOG_LEVEL_PERF,
LOG_LEVEL_VERBOSE,
LOG_LEVEL_DEBUG,
};
bool log_colored;
pthread_mutex_t log_mutex;
extern enum log_level_t log_level;
extern bool log_colored;
extern pthread_mutex_t log_mutex;
#define LOGGING_INIT { \

View File

@@ -240,7 +240,7 @@ int options_parse(struct options_t *options, struct device_t *dev, struct encode
# define OPT_NUMBER(_name, _dest, _min, _max, _base) { \
errno = 0; char *_end = NULL; long long _tmp = strtoll(optarg, &_end, _base); \
if (errno || *_end || _tmp < _min || _tmp > _max) { \
printf("Invalid value for '%s=%s': min=%u, max=%u\n", _name, optarg, _min, _max); \
printf("Invalid value for '%s=%s': min=%lld, max=%lld\n", _name, optarg, (long long)_min, (long long)_max); \
return -1; \
} \
_dest = _tmp; \
@@ -644,7 +644,7 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s
printf(" --log-level <N> ──── Verbosity level of messages from 0 (info) to 3 (debug).\n");
printf(" Enabling debugging messages can slow down the program.\n");
printf(" Available levels: 0 (info), 1 (performance), 2 (verbose), 3 (debug).\n");
printf(" Default: %u.\n\n", log_level);
printf(" Default: %d.\n\n", log_level);
printf(" --perf ───────────── Enable performance messages (same as --log-level=1). Default: disabled.\n\n");
printf(" --verbose ────────── Enable verbose messages and lower (same as --log-level=2). Default: disabled.\n\n");
printf(" --debug ──────────── Enable debug messages and lower (same as --log-level=3). Default: disabled.\n\n");

View File

@@ -105,13 +105,12 @@ INLINE void process_set_name_prefix(int argc, char *argv[], const char *prefix)
char *cmdline = NULL;
size_t allocated = 2048;
size_t used = 0;
size_t arg_len = 0;
A_REALLOC(cmdline, allocated);
cmdline[0] = '\0';
for (int index = 0; index < argc; ++index) {
arg_len = strlen(argv[index]);
size_t arg_len = strlen(argv[index]);
if (used + arg_len + 16 >= allocated) {
allocated += arg_len + 2048;
A_REALLOC(cmdline, allocated);

View File

@@ -51,7 +51,7 @@ struct _worker_t {
long double last_comp_time;
pthread_mutex_t has_job_mutex;
int buf_index;
unsigned buf_index;
atomic_bool has_job;
bool job_timely;
bool job_failed;
@@ -489,7 +489,7 @@ static struct _worker_t *_workers_pool_wait(struct _workers_pool_t *pool) {
A_COND_WAIT_TRUE(pool->free_workers, &pool->free_workers_cond, &pool->free_workers_mutex);
A_MUTEX_UNLOCK(&pool->free_workers_mutex);
if (pool->oldest_worker && !atomic_load(&pool->oldest_worker->has_job) && pool->oldest_worker->buf_index >= 0) {
if (pool->oldest_worker && !atomic_load(&pool->oldest_worker->has_job)) {
ready_worker = pool->oldest_worker;
ready_worker->job_timely = true;
pool->oldest_worker = pool->oldest_worker->order_next;

View File

@@ -41,9 +41,9 @@
#ifdef PTHREAD_MAX_NAMELEN_NP
# define MAX_THREAD_NAME PTHREAD_MAX_NAMELEN_NP
# define MAX_THREAD_NAME ((size_t)(PTHREAD_MAX_NAMELEN_NP))
#else
# define MAX_THREAD_NAME 16
# define MAX_THREAD_NAME ((size_t)16)
#endif
#define A_THREAD_CREATE(_tid, _func, _arg) assert(!pthread_create(_tid, NULL, _func, _arg))
@@ -51,9 +51,9 @@
#ifdef WITH_PTHREAD_NP
# define A_THREAD_RENAME(_fmt, ...) { \
char _buf[MAX_THREAD_NAME] = {0}; \
assert(snprintf(_buf, MAX_THREAD_NAME, _fmt, ##__VA_ARGS__) > 0); \
thread_set_name(_buf); \
char _new_tname_buf[MAX_THREAD_NAME] = {0}; \
assert(snprintf(_new_tname_buf, MAX_THREAD_NAME, _fmt, ##__VA_ARGS__) > 0); \
thread_set_name(_new_tname_buf); \
}
#else
# define A_THREAD_RENAME(_fmt, ...)

View File

@@ -30,9 +30,10 @@
#include "logging.h"
#ifndef XIOCTL_RETRIES
# define XIOCTL_RETRIES 4
#ifndef CFG_XIOCTL_RETRIES
# define CFG_XIOCTL_RETRIES 4
#endif
#define XIOCTL_RETRIES ((unsigned)(CFG_XIOCTL_RETRIES))
INLINE int xioctl(int fd, int request, void *arg) {
@@ -51,8 +52,9 @@ INLINE int xioctl(int fd, int request, void *arg) {
)
);
// cppcheck-suppress knownConditionTrueFalse
if (retval && retries <= 0) {
LOG_PERROR("ioctl(%d) retried %d times; giving up", request, XIOCTL_RETRIES);
LOG_PERROR("ioctl(%d) retried %u times; giving up", request, XIOCTL_RETRIES);
}
return retval;
}

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env python3
#============================================================================#
# ========================================================================== #
# #
# uStreamer - Lightweight and fast MJPG-HTTP streamer. #
# #
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
# #
#============================================================================#
# ========================================================================== #
import textwrap

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env -S python3 -B
#============================================================================#
# ========================================================================== #
# #
# uStreamer - Lightweight and fast MJPG-HTTP streamer. #
# #
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
# #
#============================================================================#
# ========================================================================== #
import sys

View File

@@ -1,5 +1,5 @@
#!/usr/bin/env -S python3 -B
#============================================================================#
# ========================================================================== #
# #
# uStreamer - Lightweight and fast MJPG-HTTP streamer. #
# #
@@ -18,7 +18,7 @@
# You should have received a copy of the GNU General Public License #
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
# #
#============================================================================#
# ========================================================================== #
import sys
@@ -26,7 +26,6 @@ import io
import struct
from typing import Tuple
from typing import List
import common
@@ -38,14 +37,15 @@ def _get_jpeg_size(data: bytes) -> Tuple[int, int]:
stream = io.BytesIO(data)
while True:
marker = struct.unpack(">H", stream.read(2))[0]
if marker == 0xFFD9:
raise RuntimeError("Can't find jpeg size")
if (
marker == 0xFFD8 # Start of image
or marker == 0xFF01 # Private marker
or (marker >= 0xFFD0 and marker <= 0xFFD7) # Restart markers
or 0xFFD0 <= marker <= 0xFFD7 # Restart markers
):
continue
elif marker == 0xFFD9:
raise RuntimeError("Can't find jpeg size")
# All other markers specify chunks with lengths
length = struct.unpack(">H", stream.read(2))[0]