From a6f111f7cfbbd0b393f813f4d5ad67c1881b26d0 Mon Sep 17 00:00:00 2001 From: Maxim Devaev Date: Thu, 22 Jan 2026 12:51:17 +0200 Subject: [PATCH] refactoring --- janus/src/au.c | 3 + linters/pylint.ini | 2 +- python/src/ustreamer.c | 22 +++ src/dump/file.c | 75 +++++---- src/dump/file.h | 4 +- src/dump/main.c | 41 ++--- src/libs/array.h | 4 +- src/libs/base64.c | 6 +- src/libs/capture.c | 93 +++++++----- src/libs/drm/drm.c | 16 +- src/libs/fpsi.c | 14 +- src/libs/fpsi.h | 2 +- src/libs/frametext.c | 20 ++- src/libs/logging.h | 2 +- src/libs/options.c | 16 +- src/libs/process.h | 12 +- src/libs/queue.c | 82 +++++----- src/libs/queue.h | 18 +-- src/libs/ring.c | 26 ++-- src/libs/ring.h | 12 +- src/libs/unjpeg.c | 2 +- src/ustreamer/encoder.c | 31 ++-- src/ustreamer/encoders/cpu/encoder.c | 13 ++ src/ustreamer/encoders/cpu/encoder.h | 11 +- src/ustreamer/encoders/hw/encoder.c | 26 +++- src/ustreamer/encoders/hw/encoder.h | 9 -- src/ustreamer/encoders/hw/huffman.h | 4 +- src/ustreamer/gpio/gpio.c | 74 ++++----- src/ustreamer/gpio/gpio.h | 26 ++-- src/ustreamer/http/mime.c | 4 +- src/ustreamer/http/server.c | 218 ++++++++++++++------------- src/ustreamer/http/server.h | 6 +- src/ustreamer/http/static.c | 6 +- src/ustreamer/http/static.h | 2 +- src/ustreamer/http/tools.c | 16 +- src/ustreamer/http/tools.h | 4 +- src/ustreamer/m2m.c | 209 ++++++++++++++----------- src/ustreamer/m2m.h | 12 +- src/ustreamer/main.c | 6 +- src/ustreamer/options.c | 117 +++++++++----- src/ustreamer/options.h | 31 ++-- src/ustreamer/stream.c | 67 ++++---- src/ustreamer/stream.h | 2 +- src/ustreamer/workers.c | 22 ++- src/ustreamer/workers.h | 7 +- tools/make-ico-h.py | 4 +- 46 files changed, 786 insertions(+), 613 deletions(-) diff --git a/janus/src/au.c b/janus/src/au.c index 128f7a7..494ddfa 100644 --- a/janus/src/au.c +++ b/janus/src/au.c @@ -107,11 +107,14 @@ void us_au_pcm_destroy(us_au_pcm_s *pcm) { void us_au_pcm_mix(us_au_pcm_s *dest, us_au_pcm_s *src) { const uz size = src->frames * US_RTP_OPUS_CH * 2; // 2 for 16 bit + if (src->frames == 0) { return; + } else if (dest->frames == 0) { memcpy(dest->data, src->data, size); dest->frames = src->frames; + } else if (dest->frames == src->frames) { // https://stackoverflow.com/questions/12089662 for (uz index = 0; index < size; ++index) { diff --git a/linters/pylint.ini b/linters/pylint.ini index 3955db1..abe6714 100644 --- a/linters/pylint.ini +++ b/linters/pylint.ini @@ -33,7 +33,7 @@ max-line-length = 160 [BASIC] # Good variable names which should always be accepted, separated by a comma -good-names = _, __, x, y, ws, make-html-h, make-ico-h +good-names = _, __, i, x, y, ws, make-html-h, make-ico-h # Regular expression matching correct method names method-rgx = [a-z_][a-z0-9_]{2,50}$ diff --git a/python/src/ustreamer.c b/python/src/ustreamer.c index 34bfa9e..72b624c 100644 --- a/python/src/ustreamer.c +++ b/python/src/ustreamer.c @@ -1,3 +1,25 @@ +/***************************************************************************** +# # +# uStreamer - Lightweight and fast MJPEG-HTTP streamer. # +# # +# Copyright (C) 2018-2024 Maxim Devaev # +# # +# 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 . # +# # +*****************************************************************************/ + + #include #include #include diff --git a/src/dump/file.c b/src/dump/file.c index 0700069..1537c88 100644 --- a/src/dump/file.c +++ b/src/dump/file.c @@ -24,56 +24,73 @@ us_output_file_s *us_output_file_init(const char *path, bool json) { - us_output_file_s *output; - US_CALLOC(output, 1); + us_output_file_s *out; + US_CALLOC(out, 1); if (!strcmp(path, "-")) { US_LOG_INFO("Using output: "); - output->fp = stdout; + out->fp = stdout; } else { US_LOG_INFO("Using output: %s", path); - if ((output->fp = fopen(path, "wb")) == NULL) { + if ((out->fp = fopen(path, "wb")) == NULL) { US_LOG_PERROR("Can't open output file"); goto error; } } - output->json = json; - return output; + out->json = json; + return out; error: - us_output_file_destroy(output); + us_output_file_destroy(out); return NULL; } -void us_output_file_write(void *v_output, const us_frame_s *frame) { - us_output_file_s *output = v_output; - if (output->json) { - us_base64_encode(frame->data, frame->used, &output->base64_data, &output->base64_allocated); - fprintf(output->fp, - "{\"size\": %zu, \"width\": %u, \"height\": %u," - " \"format\": %u, \"stride\": %u, \"online\": %u, \"key\": %u, \"gop\": %u," - " \"grab_begin_ts\": %.3Lf, \"grab_end_ts\": %.3Lf," - " \"encode_begin_ts\": %.3Lf, \"encode_end_ts\": %.3Lf," +void us_output_file_write(void *v_out, const us_frame_s *frame) { + us_output_file_s *out = v_out; + if (out->json) { + us_base64_encode(frame->data, frame->used, &out->base64_data, &out->base64_allocated); + fprintf( + out->fp, + "{\"size\": %zu," + " \"width\": %u," + " \"height\": %u," + " \"format\": %u," + " \"stride\": %u," + " \"online\": %u," + " \"key\": %u," + " \"gop\": %u," + " \"grab_begin_ts\": %.3Lf," + " \"grab_end_ts\": %.3Lf," + " \"encode_begin_ts\": %.3Lf," + " \"encode_end_ts\": %.3Lf," " \"data\": \"%s\"}\n", - frame->used, frame->width, frame->height, - frame->format, frame->stride, frame->online, frame->key, frame->gop, - frame->grab_begin_ts, frame->grab_end_ts, - frame->encode_begin_ts, frame->encode_end_ts, - output->base64_data); + frame->used, + frame->width, + frame->height, + frame->format, + frame->stride, + frame->online, + frame->key, + frame->gop, + frame->grab_begin_ts, + frame->grab_end_ts, + frame->encode_begin_ts, + frame->encode_end_ts, + out->base64_data); } else { - fwrite(frame->data, 1, frame->used, output->fp); + fwrite(frame->data, 1, frame->used, out->fp); } - fflush(output->fp); + fflush(out->fp); } -void us_output_file_destroy(void *v_output) { - us_output_file_s *output = v_output; - US_DELETE(output->base64_data, free); - if (output->fp && output->fp != stdout) { - if (fclose(output->fp) < 0) { +void us_output_file_destroy(void *v_out) { + us_output_file_s *out = v_out; + US_DELETE(out->base64_data, free); + if (out->fp && out->fp != stdout) { + if (fclose(out->fp) < 0) { US_LOG_PERROR("Can't close output file"); } } - free(output); + free(out); } diff --git a/src/dump/file.h b/src/dump/file.h index 91b0475..dc714a1 100644 --- a/src/dump/file.h +++ b/src/dump/file.h @@ -45,5 +45,5 @@ typedef struct { us_output_file_s *us_output_file_init(const char *path, bool json); -void us_output_file_write(void *v_output, const us_frame_s *frame); -void us_output_file_destroy(void *v_output); +void us_output_file_write(void *v_out, const us_frame_s *frame); +void us_output_file_destroy(void *v_out); diff --git a/src/dump/main.c b/src/dump/main.c index b31b6a6..814f2c3 100644 --- a/src/dump/main.c +++ b/src/dump/main.c @@ -90,17 +90,19 @@ volatile bool _g_stop = false; typedef struct { - void *v_output; - void (*write)(void *v_output, const us_frame_s *frame); - void (*destroy)(void *v_output); + void *v_out; + void (*write)(void *v_out, const us_frame_s *frame); + void (*destroy)(void *v_out); } _output_context_s; static void _signal_handler(int signum); static int _dump_sink( - const char *sink_name, unsigned sink_timeout, - long long count, long double interval, + const char *sink_name, + unsigned sink_timeout, + long long count, + long double interval, bool key_required, _output_context_s *ctx); @@ -113,8 +115,8 @@ int main(int argc, char *argv[]) { const char *sink_name = NULL; unsigned sink_timeout = 1; - const char *output_path = NULL; - bool output_json = false; + const char *out_path = NULL; + bool out_json = false; long long count = 0; long double interval = 0; bool key_required = false; @@ -151,8 +153,8 @@ int main(int argc, char *argv[]) { switch (ch) { case _O_SINK: OPT_SET(sink_name, optarg); case _O_SINK_TIMEOUT: OPT_NUMBER("--sink-timeout", sink_timeout, 1, 60, 0); - case _O_OUTPUT: OPT_SET(output_path, optarg); - case _O_OUTPUT_JSON: OPT_SET(output_json, true); + case _O_OUTPUT: OPT_SET(out_path, optarg); + case _O_OUTPUT_JSON: OPT_SET(out_json, true); case _O_COUNT: OPT_NUMBER("--count", count, 0, LLONG_MAX, 0); case _O_INTERVAL: OPT_LDOUBLE("--interval", interval, 0, 60); case _O_KEY_REQUIRED: OPT_SET(key_required, true); @@ -183,8 +185,8 @@ int main(int argc, char *argv[]) { _output_context_s ctx = {0}; - if (output_path && output_path[0] != '\0') { - if ((ctx.v_output = (void*)us_output_file_init(output_path, output_json)) == NULL) { + if (out_path && out_path[0] != '\0') { + if ((ctx.v_out = (void*)us_output_file_init(out_path, out_json)) == NULL) { return 1; } ctx.write = us_output_file_write; @@ -193,8 +195,8 @@ int main(int argc, char *argv[]) { us_install_signals_handler(_signal_handler, false); const int retval = abs(_dump_sink(sink_name, sink_timeout, count, interval, key_required, &ctx)); - if (ctx.v_output && ctx.destroy) { - ctx.destroy(ctx.v_output); + if (ctx.v_out && ctx.destroy) { + ctx.destroy(ctx.v_out); } return retval; } @@ -208,10 +210,13 @@ static void _signal_handler(int signum) { } static int _dump_sink( - const char *sink_name, unsigned sink_timeout, - long long count, long double interval, + const char *sink_name, + unsigned sink_timeout, + long long count, + long double interval, bool key_required, - _output_context_s *ctx) { + _output_context_s *ctx +) { int retval = -1; @@ -259,8 +264,8 @@ static int _dump_sink( us_fpsi_update(fpsi, true, NULL); - if (ctx->v_output != NULL) { - ctx->write(ctx->v_output, frame); + if (ctx->v_out != NULL) { + ctx->write(ctx->v_out, frame); } if (count >= 0) { diff --git a/src/libs/array.h b/src/libs/array.h index 1ee8c5a..c7e84db 100644 --- a/src/libs/array.h +++ b/src/libs/array.h @@ -30,8 +30,8 @@ #define US_ARRAY_ITERATE(x_array, x_start, x_item_ptr, ...) { \ const int m_len = US_ARRAY_LEN(x_array); \ assert(x_start <= m_len); \ - for (int m_index = x_start; m_index < m_len; ++m_index) { \ - __typeof__((x_array)[0]) *const x_item_ptr = &x_array[m_index]; \ + for (int m_i = x_start; m_i < m_len; ++m_i) { \ + __typeof__((x_array)[0]) *const x_item_ptr = &x_array[m_i]; \ __VA_ARGS__ \ } \ } diff --git a/src/libs/base64.c b/src/libs/base64.c index 832d1db..f2cf2ec 100644 --- a/src/libs/base64.c +++ b/src/libs/base64.c @@ -54,8 +54,8 @@ void us_base64_encode(const u8 *data, uz size, char **encoded, uz *allocated) { } } - for (uint data_index = 0, encoded_index = 0; data_index < size;) { -# define OCTET(_name) uint _name = (data_index < size ? (u8)data[data_index++] : 0) + for (uint data_i = 0, encoded_i = 0; data_i < size;) { +# define OCTET(_name) uint _name = (data_i < size ? (u8)data[data_i++] : 0) OCTET(octet_a); OCTET(octet_b); OCTET(octet_c); @@ -63,7 +63,7 @@ void us_base64_encode(const u8 *data, uz size, char **encoded, uz *allocated) { const uint triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; -# define ENCODE(_offset) (*encoded)[encoded_index++] = _ENCODING_TABLE[(triple >> _offset * 6) & 0x3F] +# define ENCODE(_offset) (*encoded)[encoded_i++] = _ENCODING_TABLE[(triple >> _offset * 6) & 0x3F] ENCODE(3); ENCODE(2); ENCODE(1); diff --git a/src/libs/capture.c b/src/libs/capture.c index 10b9147..0aa515b 100644 --- a/src/libs/capture.c +++ b/src/libs/capture.c @@ -103,12 +103,21 @@ static int _capture_open_export_to_dma(us_capture_s *cap); static int _capture_apply_resolution(us_capture_s *cap, uint width, uint height, float hz); static void _capture_apply_controls(const us_capture_s *cap); + static int _capture_query_control( - const us_capture_s *cap, struct v4l2_queryctrl *query, - const char *name, uint cid, bool quiet); + const us_capture_s *cap, + struct v4l2_queryctrl *query, + const char *name, + uint cid, + bool quiet); + static void _capture_set_control( - const us_capture_s *cap, const struct v4l2_queryctrl *query, - const char *name, uint cid, int value, bool quiet); + const us_capture_s *cap, + const struct v4l2_queryctrl *query, + const char *name, + uint cid, + int value, + bool quiet); static const char *_format_to_string_nullable(uint format); static const char *_format_to_string_supported(uint format); @@ -306,15 +315,15 @@ void us_capture_close(us_capture_s *cap) { if (run->bufs != NULL) { say = true; _LOG_DEBUG("Releasing HW buffers ..."); - for (uint index = 0; index < run->n_bufs; ++index) { - us_capture_hwbuf_s *hw = &run->bufs[index]; + for (uint i = 0; i < run->n_bufs; ++i) { + us_capture_hwbuf_s *hw = &run->bufs[i]; US_CLOSE_FD(hw->dma_fd); if (cap->io_method == V4L2_MEMORY_MMAP) { if (hw->raw.allocated > 0 && hw->raw.data != NULL) { if (munmap(hw->raw.data, hw->raw.allocated) < 0) { - _LOG_PERROR("Can't unmap HW buffer=%u", index); + _LOG_PERROR("Can't unmap HW buffer=%u", i); } } } else { // V4L2_MEMORY_USERPTR @@ -451,7 +460,8 @@ int us_capture_hwbuf_grab(us_capture_s *cap, us_capture_hwbuf_s **hw) { (*hw)->raw.grab_end_ts = us_get_now_monotonic(); _LOG_DEBUG("Grabbed HW buffer=%u: bytesused=%u, grab_begin_ts=%.3Lf, grab_end_ts=%.3Lf, latency=%.3Lf, skipped=%u", - buf.index, buf.bytesused, + buf.index, + buf.bytesused, (*hw)->raw.grab_begin_ts, (*hw)->raw.grab_end_ts, (*hw)->raw.grab_end_ts - (*hw)->raw.grab_begin_ts, @@ -462,14 +472,14 @@ int us_capture_hwbuf_grab(us_capture_s *cap, us_capture_hwbuf_s **hw) { int us_capture_hwbuf_release(const us_capture_s *cap, us_capture_hwbuf_s *hw) { assert(atomic_load(&hw->refs) == 0); - const uint index = hw->buf.index; - _LOG_DEBUG("Releasing HW buffer=%u ...", index); + const uint i = hw->buf.index; + _LOG_DEBUG("Releasing HW buffer=%u ...", i); if (us_xioctl(cap->run->fd, VIDIOC_QBUF, &hw->buf) < 0) { - _LOG_PERROR("Can't release HW buffer=%u", index); + _LOG_PERROR("Can't release HW buffer=%u", i); return -1; } hw->grabbed = false; - _LOG_DEBUG("HW buffer=%u released", index); + _LOG_DEBUG("HW buffer=%u released", i); return 0; } @@ -850,31 +860,31 @@ static void _capture_open_hw_fps(us_capture_s *cap) { // cppcheck-suppress const return; } -# define SETFPS_TPF(x_next) setfps.parm.capture.timeperframe.x_next +# define TPF(x_next) setfps.parm.capture.timeperframe.x_next US_MEMSET_ZERO(setfps); setfps.type = run->capture_type; - SETFPS_TPF(numerator) = 1; - SETFPS_TPF(denominator) = -1; // Request maximum possible FPS + TPF(numerator) = 1; + TPF(denominator) = -1; // Request maximum possible FPS if (us_xioctl(run->fd, VIDIOC_S_PARM, &setfps) < 0) { _LOG_PERROR("Can't set HW FPS"); return; } - if (SETFPS_TPF(numerator) != 1) { - _LOG_ERROR("Invalid HW FPS numerator: %u != 1", SETFPS_TPF(numerator)); + if (TPF(numerator) != 1) { + _LOG_ERROR("Invalid HW FPS numerator: %u != 1", TPF(numerator)); return; } - if (SETFPS_TPF(denominator) == 0) { // Не знаю, бывает ли так, но пускай на всякий случай + if (TPF(denominator) == 0) { // Не знаю, бывает ли так, но пускай на всякий случай _LOG_ERROR("Invalid HW FPS denominator: 0"); return; } - _LOG_INFO("Using HW FPS: %u/%u", SETFPS_TPF(numerator), SETFPS_TPF(denominator)); + _LOG_INFO("Using HW FPS: %u/%u", TPF(numerator), TPF(denominator)); -# undef SETFPS_TPF +# undef TPF } static void _capture_open_jpeg_quality(us_capture_s *cap) { @@ -1017,12 +1027,12 @@ static int _capture_open_io_method_userptr(us_capture_s *cap) { static int _capture_open_queue_buffers(us_capture_s *cap) { us_capture_runtime_s *const run = cap->run; - for (uint index = 0; index < run->n_bufs; ++index) { + for (uint i = 0; i < run->n_bufs; ++i) { struct v4l2_buffer buf = {0}; struct v4l2_plane planes[VIDEO_MAX_PLANES] = {0}; buf.type = run->capture_type; buf.memory = cap->io_method; - buf.index = index; + buf.index = i; if (run->capture_mplane) { buf.m.planes = planes; buf.length = 1; @@ -1031,11 +1041,11 @@ static int _capture_open_queue_buffers(us_capture_s *cap) { if (cap->io_method == V4L2_MEMORY_USERPTR) { // I am not sure, may be this is incorrect for mplane device, // but i don't have one which supports V4L2_MEMORY_USERPTR - buf.m.userptr = (unsigned long)run->bufs[index].raw.data; - buf.length = run->bufs[index].raw.allocated; + buf.m.userptr = (unsigned long)run->bufs[i].raw.data; + buf.length = run->bufs[i].raw.allocated; } - _LOG_DEBUG("Calling us_xioctl(VIDIOC_QBUF) for buffer=%u ...", index); + _LOG_DEBUG("Calling us_xioctl(VIDIOC_QBUF) for buffer=%u ...", i); if (us_xioctl(run->fd, VIDIOC_QBUF, &buf) < 0) { _LOG_PERROR("Can't VIDIOC_QBUF"); return -1; @@ -1047,23 +1057,23 @@ static int _capture_open_queue_buffers(us_capture_s *cap) { static int _capture_open_export_to_dma(us_capture_s *cap) { us_capture_runtime_s *const run = cap->run; - for (uint index = 0; index < run->n_bufs; ++index) { + for (uint i = 0; i < run->n_bufs; ++i) { struct v4l2_exportbuffer exp = { .type = run->capture_type, - .index = index, + .index = i, }; - _LOG_DEBUG("Exporting device buffer=%u to DMA ...", index); + _LOG_DEBUG("Exporting device buffer=%u to DMA ...", i); if (us_xioctl(run->fd, VIDIOC_EXPBUF, &exp) < 0) { - _LOG_PERROR("Can't export device buffer=%u to DMA", index); + _LOG_PERROR("Can't export device buffer=%u to DMA", i); goto error; } - run->bufs[index].dma_fd = exp.fd; + run->bufs[i].dma_fd = exp.fd; } return 0; error: - for (uint index = 0; index < run->n_bufs; ++index) { - US_CLOSE_FD(run->bufs[index].dma_fd); + for (uint i = 0; i < run->n_bufs; ++i) { + US_CLOSE_FD(run->bufs[i].dma_fd); } return -1; } @@ -1142,9 +1152,12 @@ static void _capture_apply_controls(const us_capture_s *cap) { } static int _capture_query_control( - const us_capture_s *cap, struct v4l2_queryctrl *query, - const char *name, uint cid, bool quiet) { - + const us_capture_s *cap, + struct v4l2_queryctrl *query, + const char *name, + uint cid, + bool quiet +) { // cppcheck-suppress redundantPointerOp US_MEMSET_ZERO(*query); query->id = cid; @@ -1159,9 +1172,13 @@ static int _capture_query_control( } static void _capture_set_control( - const us_capture_s *cap, const struct v4l2_queryctrl *query, - const char *name, uint cid, int value, bool quiet) { - + const us_capture_s *cap, + const struct v4l2_queryctrl *query, + const char *name, + uint cid, + int value, + bool quiet +) { if (value < query->minimum || value > query->maximum || value % query->step != 0) { if (!quiet) { _LOG_ERROR("Invalid value %d of control %s: min=%d, max=%d, default=%d, step=%u", diff --git a/src/libs/drm/drm.c b/src/libs/drm/drm.c index ea05ee8..6d9aac6 100644 --- a/src/libs/drm/drm.c +++ b/src/libs/drm/drm.c @@ -61,11 +61,11 @@ static const char *_connector_type_to_string(u32 type); static float _get_refresh_rate(const drmModeModeInfo *mode); -#define _LOG_ERROR(x_msg, ...) US_LOG_ERROR("DRM: " x_msg, ##__VA_ARGS__) -#define _LOG_PERROR(x_msg, ...) US_LOG_PERROR("DRM: " x_msg, ##__VA_ARGS__) +#define _LOG_ERROR(x_msg, ...) US_LOG_ERROR("DRM: " x_msg, ##__VA_ARGS__) +#define _LOG_PERROR(x_msg, ...) US_LOG_PERROR("DRM: " x_msg, ##__VA_ARGS__) #define _LOG_INFO(x_msg, ...) US_LOG_INFO("DRM: " x_msg, ##__VA_ARGS__) #define _LOG_VERBOSE(x_msg, ...) US_LOG_VERBOSE("DRM: " x_msg, ##__VA_ARGS__) -#define _LOG_DEBUG(x_msg, ...) US_LOG_DEBUG("DRM: " x_msg, ##__VA_ARGS__) +#define _LOG_DEBUG(x_msg, ...) US_LOG_DEBUG("DRM: " x_msg, ##__VA_ARGS__) us_drm_s *us_drm_init(void) { @@ -164,7 +164,12 @@ int us_drm_open(us_drm_s *drm, const us_capture_s *cap) { run->saved_crtc = drmModeGetCrtc(run->fd, run->crtc_id); _LOG_DEBUG("Setting up CRTC ..."); - if (drmModeSetCrtc(run->fd, run->crtc_id, run->bufs[0].id, 0, 0, &run->conn_id, 1, &run->mode) < 0) { + if (drmModeSetCrtc( + run->fd, + run->crtc_id, run->bufs[0].id, + 0, 0, // X, Y + &run->conn_id, 1, &run->mode + ) < 0) { _LOG_PERROR("Can't set CRTC"); goto error; } @@ -202,7 +207,8 @@ void us_drm_close(us_drm_s *drm) { if (run->saved_crtc != NULL) { _LOG_DEBUG("Restoring CRTC ..."); - if (drmModeSetCrtc(run->fd, + if (drmModeSetCrtc( + run->fd, run->saved_crtc->crtc_id, run->saved_crtc->buffer_id, run->saved_crtc->x, run->saved_crtc->y, &run->conn_id, 1, &run->saved_crtc->mode diff --git a/src/libs/fpsi.c b/src/libs/fpsi.c index 105e7fc..01c46f8 100644 --- a/src/libs/fpsi.c +++ b/src/libs/fpsi.c @@ -38,7 +38,7 @@ us_fpsi_s *us_fpsi_init(const char *name, bool with_meta) { US_CALLOC(fpsi, 1); fpsi->name = us_strdup(name); fpsi->with_meta = with_meta; - atomic_init(&fpsi->state_sec_ts, 0); + atomic_init(&fpsi->state_ts, 0); atomic_init(&fpsi->state, 0); return fpsi; } @@ -61,8 +61,8 @@ void us_fpsi_update(us_fpsi_s *fpsi, bool bump, const us_fpsi_meta_s *meta) { assert(!fpsi->with_meta); } - const sll now_sec_ts = us_floor_ms(us_get_now_monotonic()); - if (atomic_load(&fpsi->state_sec_ts) != now_sec_ts) { + const sll now_ts = us_floor_ms(us_get_now_monotonic()); + if (atomic_load(&fpsi->state_ts) != now_ts) { US_LOG_PERF_FPS("FPS: %s: %u", fpsi->name, fpsi->accum); // Fast mutex-less store method @@ -74,7 +74,7 @@ void us_fpsi_update(us_fpsi_s *fpsi, bool bump, const us_fpsi_meta_s *meta) { state |= (ull)(meta->online ? 1 : 0) << 48; } atomic_store(&fpsi->state, state); // Сначала инфа - atomic_store(&fpsi->state_sec_ts, now_sec_ts); // Потом время, это важно + atomic_store(&fpsi->state_ts, now_ts); // Потом время, это важно fpsi->accum = 0; } if (bump) { @@ -90,8 +90,8 @@ uint us_fpsi_get(us_fpsi_s *fpsi, us_fpsi_meta_s *meta) { // Между чтением инфы и времени может быть гонка, // но это неважно. Если время свежее, до данные тоже // будут свежмими, обратный случай не так важен. - const sll now_sec_ts = us_floor_ms(us_get_now_monotonic()); - const sll state_sec_ts = atomic_load(&fpsi->state_sec_ts); // Сначала время + const sll now_ts = us_floor_ms(us_get_now_monotonic()); + const sll state_ts = atomic_load(&fpsi->state_ts); // Сначала время const ull state = atomic_load(&fpsi->state); // Потом инфа uint current = state & 0xFFFF; @@ -101,7 +101,7 @@ uint us_fpsi_get(us_fpsi_s *fpsi, us_fpsi_meta_s *meta) { meta->online = (state >> 48) & 1; } - if (state_sec_ts != now_sec_ts && (state_sec_ts + 1) != now_sec_ts) { + if (state_ts != now_ts && (state_ts + 1) != now_ts) { // Только текущая или прошлая секунда current = 0; } diff --git a/src/libs/fpsi.h b/src/libs/fpsi.h index 655c1bf..77492e9 100644 --- a/src/libs/fpsi.h +++ b/src/libs/fpsi.h @@ -38,7 +38,7 @@ typedef struct { char *name; bool with_meta; uint accum; - atomic_llong state_sec_ts; + atomic_llong state_ts; atomic_ullong state; } us_fpsi_s; diff --git a/src/libs/frametext.c b/src/libs/frametext.c index 289bfdc..7429628 100644 --- a/src/libs/frametext.c +++ b/src/libs/frametext.c @@ -34,9 +34,12 @@ static void _frametext_draw_line( - us_frametext_s *ft, const char *line, - uint scale_x, uint scale_y, - uint start_x, uint start_y); + us_frametext_s *ft, + const char *line, + uint scale_x, + uint scale_y, + uint start_x, + uint start_y); us_frametext_s *us_frametext_init(void) { @@ -156,10 +159,13 @@ empty: } void _frametext_draw_line( - us_frametext_s *ft, const char *line, - uint scale_x, uint scale_y, - uint start_x, uint start_y) { - + us_frametext_s *ft, + const char *line, + uint scale_x, + uint scale_y, + uint start_x, + uint start_y +) { us_frame_s *const frame = ft->frame; const size_t len = strlen(line); diff --git a/src/libs/logging.h b/src/libs/logging.h index 21bc88f..5f17c1c 100644 --- a/src/libs/logging.h +++ b/src/libs/logging.h @@ -75,7 +75,7 @@ extern pthread_mutex_t us_g_log_mutex; #define US_SEP_INFO(x_ch) { \ US_LOGGING_LOCK; \ - for (int m_count = 0; m_count < 80; ++m_count) { \ + for (int m_i = 0; m_i < 80; ++m_i) { \ fputc((x_ch), stderr); \ } \ fputc('\n', stderr); \ diff --git a/src/libs/options.c b/src/libs/options.c index afae16c..8bc5943 100644 --- a/src/libs/options.c +++ b/src/libs/options.c @@ -32,14 +32,14 @@ void us_build_short_options(const struct option opts[], char *short_opts, uz size) { memset(short_opts, 0, size); - for (uint short_index = 0, opt_index = 0; opts[opt_index].name != NULL; ++opt_index) { - assert(short_index < size - 3); - if (isalpha(opts[opt_index].val)) { - short_opts[short_index] = opts[opt_index].val; - ++short_index; - if (opts[opt_index].has_arg == required_argument) { - short_opts[short_index] = ':'; - ++short_index; + for (uint short_i = 0, opt_i = 0; opts[opt_i].name != NULL; ++opt_i) { + assert(short_i < size - 3); + if (isalpha(opts[opt_i].val)) { + short_opts[short_i] = opts[opt_i].val; + ++short_i; + if (opts[opt_i].has_arg == required_argument) { + short_opts[short_i] = ':'; + ++short_i; } } } diff --git a/src/libs/process.h b/src/libs/process.h index edd0c09..d4433e0 100644 --- a/src/libs/process.h +++ b/src/libs/process.h @@ -71,13 +71,13 @@ INLINE int us_process_track_parent_death(void) { const pid_t parent = getppid(); int signum = SIGTERM; # if defined(__linux__) - const int retval = prctl(PR_SET_PDEATHSIG, signum); + const int result = prctl(PR_SET_PDEATHSIG, signum); # elif defined(__FreeBSD__) - const int retval = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum); + const int result = procctl(P_PID, 0, PROC_PDEATHSIG_CTL, &signum); # else # error WTF? # endif - if (retval < 0) { + if (result < 0) { US_LOG_PERROR("Can't set to receive SIGTERM on parent process death"); return -1; } @@ -103,15 +103,15 @@ INLINE void us_process_set_name_prefix(int argc, char *argv[], const char *prefi US_REALLOC(cmdline, allocated); cmdline[0] = '\0'; - for (int index = 0; index < argc; ++index) { - uz arg_len = strlen(argv[index]); + for (int i = 0; i < argc; ++i) { + uz arg_len = strlen(argv[i]); if (used + arg_len + 16 >= allocated) { allocated += arg_len + 2048; US_REALLOC(cmdline, allocated); // cppcheck-suppress memleakOnRealloc // False-positive (ok with assert) } strcat(cmdline, " "); - strcat(cmdline, argv[index]); + strcat(cmdline, argv[i]); used = strlen(cmdline); // Не считаем вручную, так надежнее } diff --git a/src/libs/queue.c b/src/libs/queue.c index 5172f16..c17180c 100644 --- a/src/libs/queue.c +++ b/src/libs/queue.c @@ -34,27 +34,27 @@ us_queue_s *us_queue_init(uint capacity) { - us_queue_s *queue; - US_CALLOC(queue, 1); - US_CALLOC(queue->items, capacity); - queue->capacity = capacity; - US_MUTEX_INIT(queue->mutex); + us_queue_s *q; + US_CALLOC(q, 1); + US_CALLOC(q->items, capacity); + q->capacity = capacity; + US_MUTEX_INIT(q->mutex); pthread_condattr_t attrs; assert(!pthread_condattr_init(&attrs)); assert(!pthread_condattr_setclock(&attrs, CLOCK_MONOTONIC)); - assert(!pthread_cond_init(&queue->full_cond, &attrs)); - assert(!pthread_cond_init(&queue->empty_cond, &attrs)); + assert(!pthread_cond_init(&q->full_cond, &attrs)); + assert(!pthread_cond_init(&q->empty_cond, &attrs)); assert(!pthread_condattr_destroy(&attrs)); - return queue; + return q; } -void us_queue_destroy(us_queue_s *queue) { - US_COND_DESTROY(queue->empty_cond); - US_COND_DESTROY(queue->full_cond); - US_MUTEX_DESTROY(queue->mutex); - free(queue->items); - free(queue); +void us_queue_destroy(us_queue_s *q) { + US_COND_DESTROY(q->empty_cond); + US_COND_DESTROY(q->full_cond); + US_MUTEX_DESTROY(q->mutex); + free(q->items); + free(q); } #define _WAIT_OR_UNLOCK(x_var, x_cond) { \ @@ -62,51 +62,51 @@ void us_queue_destroy(us_queue_s *queue) { assert(!clock_gettime(CLOCK_MONOTONIC, &m_ts)); \ us_ld_to_timespec(us_timespec_to_ld(&m_ts) + timeout, &m_ts); \ while (x_var) { \ - const int err = pthread_cond_timedwait(&(x_cond), &queue->mutex, &m_ts); \ + const int err = pthread_cond_timedwait(&(x_cond), &q->mutex, &m_ts); \ if (err == ETIMEDOUT) { \ - US_MUTEX_UNLOCK(queue->mutex); \ + US_MUTEX_UNLOCK(q->mutex); \ return -1; \ } \ assert(!err); \ } \ } -int us_queue_put(us_queue_s *queue, void *item, ldf timeout) { - US_MUTEX_LOCK(queue->mutex); +int us_queue_put(us_queue_s *q, void *item, ldf timeout) { + US_MUTEX_LOCK(q->mutex); if (timeout == 0) { - if (queue->size == queue->capacity) { - US_MUTEX_UNLOCK(queue->mutex); + if (q->size == q->capacity) { + US_MUTEX_UNLOCK(q->mutex); return -1; } } else { - _WAIT_OR_UNLOCK(queue->size == queue->capacity, queue->full_cond); + _WAIT_OR_UNLOCK(q->size == q->capacity, q->full_cond); } - queue->items[queue->in] = item; - ++queue->size; - ++queue->in; - queue->in %= queue->capacity; - US_MUTEX_UNLOCK(queue->mutex); - US_COND_BROADCAST(queue->empty_cond); + q->items[q->in] = item; + ++q->size; + ++q->in; + q->in %= q->capacity; + US_MUTEX_UNLOCK(q->mutex); + US_COND_BROADCAST(q->empty_cond); return 0; } -int us_queue_get(us_queue_s *queue, void **item, ldf timeout) { - US_MUTEX_LOCK(queue->mutex); - _WAIT_OR_UNLOCK(queue->size == 0, queue->empty_cond); - *item = queue->items[queue->out]; - --queue->size; - ++queue->out; - queue->out %= queue->capacity; - US_MUTEX_UNLOCK(queue->mutex); - US_COND_BROADCAST(queue->full_cond); +int us_queue_get(us_queue_s *q, void **item, ldf timeout) { + US_MUTEX_LOCK(q->mutex); + _WAIT_OR_UNLOCK(q->size == 0, q->empty_cond); + *item = q->items[q->out]; + --q->size; + ++q->out; + q->out %= q->capacity; + US_MUTEX_UNLOCK(q->mutex); + US_COND_BROADCAST(q->full_cond); return 0; } #undef _WAIT_OR_UNLOCK -bool us_queue_is_empty(us_queue_s *queue) { - US_MUTEX_LOCK(queue->mutex); - const uint size = queue->size; - US_MUTEX_UNLOCK(queue->mutex); - return (bool)(queue->capacity - size); +bool us_queue_is_empty(us_queue_s *q) { + US_MUTEX_LOCK(q->mutex); + const uint size = q->size; + US_MUTEX_UNLOCK(q->mutex); + return (bool)(q->capacity - size); } diff --git a/src/libs/queue.h b/src/libs/queue.h index 2041e26..df9fc52 100644 --- a/src/libs/queue.h +++ b/src/libs/queue.h @@ -43,22 +43,22 @@ typedef struct { } us_queue_s; -#define US_QUEUE_DELETE_WITH_ITEMS(x_queue, x_free_item) { \ - if (x_queue) { \ - while (!us_queue_is_empty(x_queue)) { \ +#define US_QUEUE_DELETE_WITH_ITEMS(x_q, x_free_item) { \ + if (x_q) { \ + while (!us_queue_is_empty(x_q)) { \ void *m_ptr; \ - if (!us_queue_get(x_queue, &m_ptr, 0)) { \ + if (!us_queue_get(x_q, &m_ptr, 0)) { \ US_DELETE(m_ptr, x_free_item); \ } \ } \ - us_queue_destroy(x_queue); \ + us_queue_destroy(x_q); \ } \ } us_queue_s *us_queue_init(uint capacity); -void us_queue_destroy(us_queue_s *queue); +void us_queue_destroy(us_queue_s *q); -int us_queue_put(us_queue_s *queue, void *item, ldf timeout); -int us_queue_get(us_queue_s *queue, void **item, ldf timeout); -bool us_queue_is_empty(us_queue_s *queue); +int us_queue_put(us_queue_s *q, void *item, ldf timeout); +int us_queue_get(us_queue_s *q, void **item, ldf timeout); +bool us_queue_is_empty(us_queue_s *q); diff --git a/src/libs/ring.c b/src/libs/ring.c index d43dd15..3444d5b 100644 --- a/src/libs/ring.c +++ b/src/libs/ring.c @@ -29,8 +29,8 @@ #include "queue.h" -int _acquire(us_ring_s *ring, us_queue_s *queue, ldf timeout); -void _release(us_ring_s *ring, us_queue_s *queue, uint index); +int _acquire(us_ring_s *ring, us_queue_s *q, ldf timeout); +void _release(us_ring_s *ring, us_queue_s *q, uint ri); us_ring_s *us_ring_init(uint capacity) { @@ -41,9 +41,9 @@ us_ring_s *us_ring_init(uint capacity) { ring->capacity = capacity; ring->producer = us_queue_init(capacity); ring->consumer = us_queue_init(capacity); - for (uint index = 0; index < capacity; ++index) { - ring->places[index] = index; // XXX: Just to avoid casting between pointer and uint - assert(!us_queue_put(ring->producer, (void*)(ring->places + index), 0)); + for (uint ri = 0; ri < capacity; ++ri) { + ring->places[ri] = ri; // XXX: Just to avoid casting between pointer and uint + assert(!us_queue_put(ring->producer, (void*)(ring->places + ri), 0)); } return ring; } @@ -60,27 +60,27 @@ int us_ring_producer_acquire(us_ring_s *ring, ldf timeout) { return _acquire(ring, ring->producer, timeout); } -void us_ring_producer_release(us_ring_s *ring, uint index) { - _release(ring, ring->consumer, index); +void us_ring_producer_release(us_ring_s *ring, uint ri) { + _release(ring, ring->consumer, ri); } int us_ring_consumer_acquire(us_ring_s *ring, ldf timeout) { return _acquire(ring, ring->consumer, timeout); } -void us_ring_consumer_release(us_ring_s *ring, uint index) { - _release(ring, ring->producer, index); +void us_ring_consumer_release(us_ring_s *ring, uint ri) { + _release(ring, ring->producer, ri); } -int _acquire(us_ring_s *ring, us_queue_s *queue, ldf timeout) { +int _acquire(us_ring_s *ring, us_queue_s *q, ldf timeout) { (void)ring; uint *place; - if (us_queue_get(queue, (void**)&place, timeout) < 0) { + if (us_queue_get(q, (void**)&place, timeout) < 0) { return -1; } return *place; } -void _release(us_ring_s *ring, us_queue_s *queue, uint index) { - assert(!us_queue_put(queue, (void*)(ring->places + index), 0)); +void _release(us_ring_s *ring, us_queue_s *q, uint ri) { + assert(!us_queue_put(q, (void*)(ring->places + ri), 0)); } diff --git a/src/libs/ring.h b/src/libs/ring.h index fb40341..66f061a 100644 --- a/src/libs/ring.h +++ b/src/libs/ring.h @@ -38,15 +38,15 @@ typedef struct { #define US_RING_INIT_WITH_ITEMS(x_ring, x_capacity, x_init_item) { \ (x_ring) = us_ring_init(x_capacity); \ - for (uz m_index = 0; m_index < (x_ring)->capacity; ++m_index) { \ - (x_ring)->items[m_index] = x_init_item(); \ + for (uz m_ri = 0; m_ri < (x_ring)->capacity; ++m_ri) { \ + (x_ring)->items[m_ri] = x_init_item(); \ } \ } #define US_RING_DELETE_WITH_ITEMS(x_ring, x_destroy_item) { \ if (x_ring) { \ - for (uz m_index = 0; m_index < (x_ring)->capacity; ++m_index) { \ - x_destroy_item((x_ring)->items[m_index]); \ + for (uz m_ri = 0; m_ri < (x_ring)->capacity; ++m_ri) { \ + x_destroy_item((x_ring)->items[m_ri]); \ } \ us_ring_destroy(x_ring); \ } \ @@ -57,7 +57,7 @@ us_ring_s *us_ring_init(uint capacity); void us_ring_destroy(us_ring_s *ring); int us_ring_producer_acquire(us_ring_s *ring, ldf timeout); -void us_ring_producer_release(us_ring_s *ring, uint index); +void us_ring_producer_release(us_ring_s *ring, uint ri); int us_ring_consumer_acquire(us_ring_s *ring, ldf timeout); -void us_ring_consumer_release(us_ring_s *ring, uint index); +void us_ring_consumer_release(us_ring_s *ring, uint ri); diff --git a/src/libs/unjpeg.c b/src/libs/unjpeg.c index 5c1ae72..0f21b61 100644 --- a/src/libs/unjpeg.c +++ b/src/libs/unjpeg.c @@ -77,7 +77,7 @@ int us_unjpeg(const us_frame_s *src, us_frame_s *dest, bool decode) { if (decode) { JSAMPARRAY scanlines; - scanlines = (*jpeg.mem->alloc_sarray)((j_common_ptr) &jpeg, JPOOL_IMAGE, dest->stride, 1); + scanlines = (*jpeg.mem->alloc_sarray)((j_common_ptr)&jpeg, JPOOL_IMAGE, dest->stride, 1); us_frame_realloc_data(dest, ((dest->width * dest->height) << 1) * 2); while (jpeg.output_scanline < jpeg.output_height) { diff --git a/src/ustreamer/encoder.c b/src/ustreamer/encoder.c index ff4d6f5..85826f8 100644 --- a/src/ustreamer/encoder.c +++ b/src/ustreamer/encoder.c @@ -81,8 +81,8 @@ us_encoder_s *us_encoder_init(void) { void us_encoder_destroy(us_encoder_s *enc) { us_encoder_runtime_s *const run = enc->run; if (run->m2ms != NULL) { - for (uint index = 0; index < run->n_m2ms; ++index) { - US_DELETE(run->m2ms[index], us_m2m_encoder_destroy); + for (uint i = 0; i < run->n_m2ms; ++i) { + US_DELETE(run->m2ms[i], us_m2m_encoder_destroy); } free(run->m2ms); } @@ -135,10 +135,13 @@ void us_encoder_open(us_encoder_s *enc, us_capture_s *cap) { } } else if (type == US_ENCODER_TYPE_M2M_VIDEO || type == US_ENCODER_TYPE_M2M_IMAGE) { - US_LOG_DEBUG("Preparing M2M-%s encoder ...", (type == US_ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE")); + US_LOG_DEBUG("Preparing M2M-%s encoder ...", + (type == US_ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE")); + if (run->m2ms == NULL) { US_CALLOC(run->m2ms, n_workers); } + for (; run->n_m2ms < n_workers; ++run->n_m2ms) { // Начинаем с нуля и доинициализируем на следующих заходах при необходимости char name[32]; @@ -163,8 +166,11 @@ void us_encoder_open(us_encoder_s *enc, us_capture_s *cap) { US_MUTEX_UNLOCK(run->mutex); enc->run->pool = us_workers_pool_init( - "JPEG", "jw", n_workers, - _worker_job_init, (void*)enc, + "JPEG", + "jw", + n_workers, + _worker_job_init, + (void*)enc, _worker_job_destroy, _worker_run_job); } @@ -201,20 +207,20 @@ static bool _worker_run_job(us_worker_s *wr) { us_encoder_runtime_s *const run = job->enc->run; const us_frame_s *const src = &job->hw->raw; us_frame_s *const dest = job->dest; + const uint i = job->hw->buf.index; if (run->type == US_ENCODER_TYPE_CPU) { - US_LOG_VERBOSE("Compressing JPEG using CPU: worker=%s, buffer=%u", - wr->name, job->hw->buf.index); + US_LOG_VERBOSE("Compressing JPEG using CPU: worker=%s, buffer=%u", wr->name, i); us_cpu_encoder_compress(src, dest, run->quality); } else if (run->type == US_ENCODER_TYPE_HW) { - US_LOG_VERBOSE("Compressing JPEG using HW (just copying): worker=%s, buffer=%u", - wr->name, job->hw->buf.index); + US_LOG_VERBOSE("Compressing JPEG using HW (just copying): worker=%s, buffer=%u", wr->name, i); us_hw_encoder_compress(src, dest); } else if (run->type == US_ENCODER_TYPE_M2M_VIDEO || run->type == US_ENCODER_TYPE_M2M_IMAGE) { US_LOG_VERBOSE("Compressing JPEG using M2M-%s: worker=%s, buffer=%u", - (run->type == US_ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE"), wr->name, job->hw->buf.index); + (run->type == US_ENCODER_TYPE_M2M_VIDEO ? "VIDEO" : "IMAGE"), + wr->name, i); if (us_m2m_encoder_compress(run->m2ms[wr->number], src, dest, false) < 0) { goto error; } @@ -226,11 +232,10 @@ static bool _worker_run_job(us_worker_s *wr) { US_LOG_VERBOSE("Compressed new JPEG: size=%zu, time=%0.3Lf, worker=%s, buffer=%u", job->dest->used, job->dest->encode_end_ts - job->dest->encode_begin_ts, - wr->name, - job->hw->buf.index); + wr->name, i); return true; error: - US_LOG_ERROR("Compression failed: worker=%s, buffer=%u", wr->name, job->hw->buf.index); + US_LOG_ERROR("Compression failed: worker=%s, buffer=%u", wr->name, i); return false; } diff --git a/src/ustreamer/encoders/cpu/encoder.c b/src/ustreamer/encoders/cpu/encoder.c index 1ea6229..75366b1 100644 --- a/src/ustreamer/encoders/cpu/encoder.c +++ b/src/ustreamer/encoders/cpu/encoder.c @@ -27,6 +27,19 @@ #include "encoder.h" +#include +#include +#include +#include + +#include + +#include + +#include "../../../libs/types.h" +#include "../../../libs/tools.h" +#include "../../../libs/frame.h" + typedef struct { struct jpeg_destination_mgr mgr; // Default manager diff --git a/src/ustreamer/encoders/cpu/encoder.h b/src/ustreamer/encoders/cpu/encoder.h index fdfc564..65aa031 100644 --- a/src/ustreamer/encoders/cpu/encoder.h +++ b/src/ustreamer/encoders/cpu/encoder.h @@ -22,16 +22,7 @@ #pragma once -#include -#include -#include -#include - -#include - -#include - -#include "../../../libs/tools.h" +#include "../../../libs/types.h" #include "../../../libs/frame.h" diff --git a/src/ustreamer/encoders/hw/encoder.c b/src/ustreamer/encoders/hw/encoder.c index cd6cbf4..326d31e 100644 --- a/src/ustreamer/encoders/hw/encoder.c +++ b/src/ustreamer/encoders/hw/encoder.c @@ -27,9 +27,19 @@ #include "encoder.h" +#include +#include + +#include + +#include "../../../libs/types.h" +#include "../../../libs/frame.h" + +#include "huffman.h" + void _copy_plus_huffman(const us_frame_s *src, us_frame_s *dest); -static bool _is_huffman(const uint8_t *data); +static bool _is_huffman(const u8 *data); void us_hw_encoder_compress(const us_frame_s *src, us_frame_s *dest) { @@ -41,8 +51,8 @@ void _copy_plus_huffman(const us_frame_s *src, us_frame_s *dest) { us_frame_encoding_begin(src, dest, V4L2_PIX_FMT_JPEG); if (!_is_huffman(src->data)) { - const uint8_t *src_ptr = src->data; - const uint8_t *const src_end = src->data + src->used; + const u8 *src_ptr = src->data; + const u8 *const src_end = src->data + src->used; while ((((src_ptr[0] << 8) | src_ptr[1]) != 0xFFC0) && (src_ptr < src_end)) { src_ptr += 1; @@ -52,7 +62,7 @@ void _copy_plus_huffman(const us_frame_s *src, us_frame_s *dest) { return; } - const size_t paste = src_ptr - src->data; + const uz paste = src_ptr - src->data; us_frame_set_data(dest, src->data, paste); us_frame_append_data(dest, US_HUFFMAN_TABLE, sizeof(US_HUFFMAN_TABLE)); @@ -65,14 +75,14 @@ void _copy_plus_huffman(const us_frame_s *src, us_frame_s *dest) { us_frame_encoding_end(dest); } -static bool _is_huffman(const uint8_t *data) { - unsigned count = 0; +static bool _is_huffman(const u8 *data) { + uint count = 0; - while ((((uint16_t)data[0] << 8) | data[1]) != 0xFFDA) { + while ((((u16)data[0] << 8) | data[1]) != 0xFFDA) { if (count++ > 2048) { return false; } - if ((((uint16_t)data[0] << 8) | data[1]) == 0xFFC4) { + if ((((u16)data[0] << 8) | data[1]) == 0xFFC4) { return true; } data += 1; diff --git a/src/ustreamer/encoders/hw/encoder.h b/src/ustreamer/encoders/hw/encoder.h index 1e6a2fe..d3c7d23 100644 --- a/src/ustreamer/encoders/hw/encoder.h +++ b/src/ustreamer/encoders/hw/encoder.h @@ -22,16 +22,7 @@ #pragma once -#include -#include -#include -#include - -#include - #include "../../../libs/frame.h" -#include "huffman.h" - void us_hw_encoder_compress(const us_frame_s *src, us_frame_s *dest); diff --git a/src/ustreamer/encoders/hw/huffman.h b/src/ustreamer/encoders/hw/huffman.h index 374b083..82e472c 100644 --- a/src/ustreamer/encoders/hw/huffman.h +++ b/src/ustreamer/encoders/hw/huffman.h @@ -27,10 +27,10 @@ #pragma once -#include +#include "../../../libs/types.h" -static const uint8_t US_HUFFMAN_TABLE[] = { +static const u8 US_HUFFMAN_TABLE[] = { 0xFF, 0xC4, 0x01, 0xA2, 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x01, 0x00, 0x03, diff --git a/src/ustreamer/gpio/gpio.c b/src/ustreamer/gpio/gpio.c index 87791a5..75029da 100644 --- a/src/ustreamer/gpio/gpio.c +++ b/src/ustreamer/gpio/gpio.c @@ -32,7 +32,7 @@ us_gpio_s us_g_gpio = { .role = x_role, \ .consumer = NULL, \ .line = NULL, \ - .state = false \ + .on = false \ } .prog_running = MAKE_OUTPUT("prog-running"), .stream_online = MAKE_OUTPUT("stream-online"), @@ -46,8 +46,8 @@ us_gpio_s us_g_gpio = { }; -static void _gpio_output_init(us_gpio_output_s *output, struct gpiod_chip *chip); -static void _gpio_output_destroy(us_gpio_output_s *output); +static void _gpio_output_init(us_gpio_output_s *out, struct gpiod_chip *chip); +static void _gpio_output_destroy(us_gpio_output_s *out); void us_gpio_init(void) { @@ -92,23 +92,23 @@ void us_gpio_destroy(void) { } } -int us_gpio_inner_set(us_gpio_output_s *output, bool state) { +int us_gpio_inner_set(us_gpio_output_s *out, bool on) { int retval = 0; # ifndef HAVE_GPIOD2 assert(us_g_gpio.chip != NULL); # endif - assert(output->line != NULL); - assert(output->state != state); // Must be checked in macro for the performance + assert(out->line != NULL); + assert(out->on != on); // Must be checked in macro for the performance US_MUTEX_LOCK(us_g_gpio.mutex); # ifdef HAVE_GPIOD2 - if (gpiod_line_request_set_value(output->line, output->pin, state) < 0) { + if (gpiod_line_request_set_value(out->line, out->pin, on) < 0) { # else - if (gpiod_line_set_value(output->line, (int)state) < 0) { + if (gpiod_line_set_value(out->line, (int)on) < 0) { # endif - US_LOG_PERROR("GPIO: Can't write value %d to line %s", state, output->consumer); \ - _gpio_output_destroy(output); + US_LOG_PERROR("GPIO: Can't write value %d to line %s", on, out->consumer); \ + _gpio_output_destroy(out); retval = -1; } @@ -116,12 +116,12 @@ int us_gpio_inner_set(us_gpio_output_s *output, bool state) { return retval; } -static void _gpio_output_init(us_gpio_output_s *output, struct gpiod_chip *chip) { - assert(output->line == NULL); +static void _gpio_output_init(us_gpio_output_s *out, struct gpiod_chip *chip) { + assert(out->line == NULL); - US_ASPRINTF(output->consumer, "%s::%s", us_g_gpio.consumer_prefix, output->role); + US_ASPRINTF(out->consumer, "%s::%s", us_g_gpio.consumer_prefix, out->role); - if (output->pin >= 0) { + if (out->pin >= 0) { # ifdef HAVE_GPIOD2 struct gpiod_line_settings *line_settings; assert(line_settings = gpiod_line_settings_new()); @@ -130,51 +130,51 @@ static void _gpio_output_init(us_gpio_output_s *output, struct gpiod_chip *chip) struct gpiod_line_config *line_config; assert(line_config = gpiod_line_config_new()); - const unsigned offset = output->pin; + const unsigned offset = out->pin; assert(!gpiod_line_config_add_line_settings(line_config, &offset, 1, line_settings)); - struct gpiod_request_config *request_config; - assert(request_config = gpiod_request_config_new()); - gpiod_request_config_set_consumer(request_config, output->consumer); + struct gpiod_request_config *req_config; + assert(req_config = gpiod_request_config_new()); + gpiod_request_config_set_consumer(req_config, out->consumer); - if ((output->line = gpiod_chip_request_lines(chip, request_config, line_config)) == NULL) { - US_LOG_PERROR("GPIO: Can't request pin=%d as %s", output->pin, output->consumer); + if ((out->line = gpiod_chip_request_lines(chip, req_config, line_config)) == NULL) { + US_LOG_PERROR("GPIO: Can't request pin=%d as %s", out->pin, out->consumer); } - gpiod_request_config_free(request_config); + gpiod_request_config_free(req_config); gpiod_line_config_free(line_config); gpiod_line_settings_free(line_settings); - if (output->line == NULL) { - _gpio_output_destroy(output); + if (out->line == NULL) { + _gpio_output_destroy(out); } # else - if ((output->line = gpiod_chip_get_line(chip, output->pin)) != NULL) { - if (gpiod_line_request_output(output->line, output->consumer, 0) < 0) { - US_LOG_PERROR("GPIO: Can't request pin=%d as %s", output->pin, output->consumer); - _gpio_output_destroy(output); + if ((out->line = gpiod_chip_get_line(chip, out->pin)) != NULL) { + if (gpiod_line_request_output(out->line, out->consumer, 0) < 0) { + US_LOG_PERROR("GPIO: Can't request pin=%d as %s", out->pin, out->consumer); + _gpio_output_destroy(out); } } else { - US_LOG_PERROR("GPIO: Can't get pin=%d as %s", output->pin, output->consumer); + US_LOG_PERROR("GPIO: Can't get pin=%d as %s", out->pin, out->consumer); } # endif } } -static void _gpio_output_destroy(us_gpio_output_s *output) { - if (output->line != NULL) { +static void _gpio_output_destroy(us_gpio_output_s *out) { + if (out->line != NULL) { # ifdef HAVE_GPIOD2 - gpiod_line_request_release(output->line); + gpiod_line_request_release(out->line); # else - gpiod_line_release(output->line); + gpiod_line_release(out->line); # endif - output->line = NULL; + out->line = NULL; } - if (output->consumer != NULL) { - free(output->consumer); - output->consumer = NULL; + if (out->consumer != NULL) { + free(out->consumer); + out->consumer = NULL; } - output->state = false; + out->on = false; } diff --git a/src/ustreamer/gpio/gpio.h b/src/ustreamer/gpio/gpio.h index 479d3f2..cc29b6f 100644 --- a/src/ustreamer/gpio/gpio.h +++ b/src/ustreamer/gpio/gpio.h @@ -44,7 +44,7 @@ typedef struct { # else struct gpiod_line *line; # endif - bool state; + bool on; } us_gpio_output_s; typedef struct { @@ -69,27 +69,27 @@ extern us_gpio_s us_g_gpio; void us_gpio_init(void); void us_gpio_destroy(void); -int us_gpio_inner_set(us_gpio_output_s *output, bool state); +int us_gpio_inner_set(us_gpio_output_s *out, bool on); -#define SET_STATE(x_output, x_state) { \ - if (x_output.line && x_output.state != x_state) { \ - if (!us_gpio_inner_set(&x_output, x_state)) { \ - x_output.state = x_state; \ +#define SET_ON(x_out, x_on) { \ + if (x_out.line && x_out.on != x_on) { \ + if (!us_gpio_inner_set(&x_out, x_on)) { \ + x_out.on = x_on; \ } \ } \ } -INLINE void us_gpio_set_prog_running(bool state) { - SET_STATE(us_g_gpio.prog_running, state); +INLINE void us_gpio_set_prog_running(bool on) { + SET_ON(us_g_gpio.prog_running, on); } -INLINE void us_gpio_set_stream_online(bool state) { - SET_STATE(us_g_gpio.stream_online, state); +INLINE void us_gpio_set_stream_online(bool on) { + SET_ON(us_g_gpio.stream_online, on); } -INLINE void us_gpio_set_has_http_clients(bool state) { - SET_STATE(us_g_gpio.has_http_clients, state); +INLINE void us_gpio_set_has_http_clients(bool on) { + SET_ON(us_g_gpio.has_http_clients, on); } -#undef SET_STATE +#undef SET_ON diff --git a/src/ustreamer/http/mime.c b/src/ustreamer/http/mime.c index ca861a9..8685b30 100644 --- a/src/ustreamer/http/mime.c +++ b/src/ustreamer/http/mime.c @@ -67,6 +67,6 @@ const char *us_guess_mime_type(const char *path) { } }); - misc: - return "application/misc"; +misc: + return "application/misc"; } diff --git a/src/ustreamer/http/server.c b/src/ustreamer/http/server.c index b9fdddd..1a83353 100644 --- a/src/ustreamer/http/server.c +++ b/src/ustreamer/http/server.c @@ -75,17 +75,17 @@ #endif -static int _http_preprocess_request(struct evhttp_request *request, us_server_s *server); +static int _http_preprocess_request(struct evhttp_request *req, us_server_s *server); -static int _http_check_run_compat_action(struct evhttp_request *request, void *v_server); +static int _http_check_run_compat_action(struct evhttp_request *req, void *v_server); -static void _http_callback_root(struct evhttp_request *request, void *v_server); -static void _http_callback_favicon(struct evhttp_request *request, void *v_server); -static void _http_callback_static(struct evhttp_request *request, void *v_server); -static void _http_callback_state(struct evhttp_request *request, void *v_server); -static void _http_callback_snapshot(struct evhttp_request *request, void *v_server); +static void _http_callback_root(struct evhttp_request *req, void *v_server); +static void _http_callback_favicon(struct evhttp_request *req, void *v_server); +static void _http_callback_static(struct evhttp_request *req, void *v_server); +static void _http_callback_state(struct evhttp_request *req, void *v_server); +static void _http_callback_snapshot(struct evhttp_request *req, void *v_server); -static void _http_callback_stream(struct evhttp_request *request, void *v_server); +static void _http_callback_stream(struct evhttp_request *req, void *v_server); static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_ctx); static void _http_callback_stream_error(struct bufferevent *buf_event, short what, void *v_ctx); @@ -96,18 +96,18 @@ static void _http_send_snapshot(us_server_s *server); static bool _expose_frame(us_server_s *server, const us_frame_s *frame); -#define _LOG_ERROR(x_msg, ...) US_LOG_ERROR("HTTP: " x_msg, ##__VA_ARGS__) -#define _LOG_PERROR(x_msg, ...) US_LOG_PERROR("HTTP: " x_msg, ##__VA_ARGS__) +#define _LOG_ERROR(x_msg, ...) US_LOG_ERROR("HTTP: " x_msg, ##__VA_ARGS__) +#define _LOG_PERROR(x_msg, ...) US_LOG_PERROR("HTTP: " x_msg, ##__VA_ARGS__) #define _LOG_INFO(x_msg, ...) US_LOG_INFO("HTTP: " x_msg, ##__VA_ARGS__) #define _LOG_VERBOSE(x_msg, ...) US_LOG_VERBOSE("HTTP: " x_msg, ##__VA_ARGS__) -#define _LOG_DEBUG(x_msg, ...) US_LOG_DEBUG("HTTP: " x_msg, ##__VA_ARGS__) +#define _LOG_DEBUG(x_msg, ...) US_LOG_DEBUG("HTTP: " x_msg, ##__VA_ARGS__) #define _A_EVBUFFER_NEW(x_buf) assert((x_buf = evbuffer_new()) != NULL) #define _A_EVBUFFER_ADD(x_buf, x_data, x_size) assert(!evbuffer_add(x_buf, x_data, x_size)) #define _A_EVBUFFER_ADD_PRINTF(x_buf, x_fmt, ...) assert(evbuffer_add_printf(x_buf, x_fmt, ##__VA_ARGS__) >= 0) -#define _A_ADD_HEADER(x_request, x_key, x_value) \ - assert(!evhttp_add_header(evhttp_request_get_output_headers(x_request), x_key, x_value)) +#define _A_ADD_HEADER(x_req, x_key, x_value) \ + assert(!evhttp_add_header(evhttp_request_get_output_headers(x_req), x_key, x_value)) us_server_s *us_server_init(us_stream_s *stream) { @@ -260,66 +260,66 @@ void us_server_loop_break(us_server_s *server) { event_base_loopbreak(server->run->base); } -static int _http_preprocess_request(struct evhttp_request *request, us_server_s *server) { +static int _http_preprocess_request(struct evhttp_request *req, us_server_s *server) { const us_server_runtime_s *const run = server->run; - atomic_store(&server->stream->run->http->last_request_ts, us_get_now_monotonic()); + atomic_store(&server->stream->run->http->last_req_ts, us_get_now_monotonic()); if (server->allow_origin[0] != '\0') { - const char *const cors_headers = us_evhttp_get_header(request, "Access-Control-Request-Headers"); - const char *const cors_method = us_evhttp_get_header(request, "Access-Control-Request-Method"); + const char *const cors_headers = us_evhttp_get_header(req, "Access-Control-Request-Headers"); + const char *const cors_method = us_evhttp_get_header(req, "Access-Control-Request-Method"); - _A_ADD_HEADER(request, "Access-Control-Allow-Origin", server->allow_origin); - _A_ADD_HEADER(request, "Access-Control-Allow-Credentials", "true"); + _A_ADD_HEADER(req, "Access-Control-Allow-Origin", server->allow_origin); + _A_ADD_HEADER(req, "Access-Control-Allow-Credentials", "true"); if (cors_headers != NULL) { - _A_ADD_HEADER(request, "Access-Control-Allow-Headers", cors_headers); + _A_ADD_HEADER(req, "Access-Control-Allow-Headers", cors_headers); } if (cors_method != NULL) { - _A_ADD_HEADER(request, "Access-Control-Allow-Methods", cors_method); + _A_ADD_HEADER(req, "Access-Control-Allow-Methods", cors_method); } } - if (evhttp_request_get_command(request) == EVHTTP_REQ_OPTIONS) { - evhttp_send_reply(request, HTTP_OK, "OK", NULL); + if (evhttp_request_get_command(req) == EVHTTP_REQ_OPTIONS) { + evhttp_send_reply(req, HTTP_OK, "OK", NULL); return -1; } if (run->auth_token != NULL) { - const char *const token = us_evhttp_get_header(request, "Authorization"); + const char *const token = us_evhttp_get_header(req, "Authorization"); if (token == NULL || strcmp(token, run->auth_token) != 0) { - _A_ADD_HEADER(request, "WWW-Authenticate", "Basic realm=\"Restricted area\""); - evhttp_send_reply(request, 401, "Unauthorized", NULL); + _A_ADD_HEADER(req, "WWW-Authenticate", "Basic realm=\"Restricted area\""); + evhttp_send_reply(req, 401, "Unauthorized", NULL); return -1; } } - if (evhttp_request_get_command(request) == EVHTTP_REQ_HEAD) { - evhttp_send_reply(request, HTTP_OK, "OK", NULL); + if (evhttp_request_get_command(req) == EVHTTP_REQ_HEAD) { + evhttp_send_reply(req, HTTP_OK, "OK", NULL); return -1; } return 0; } #define PREPROCESS_REQUEST { \ - if (_http_preprocess_request(request, server) < 0) { \ + if (_http_preprocess_request(req, server) < 0) { \ return; \ } \ } -static int _http_check_run_compat_action(struct evhttp_request *request, void *v_server) { +static int _http_check_run_compat_action(struct evhttp_request *req, void *v_server) { // MJPG-Streamer compatibility layer int retval = -1; struct evkeyvalq params; - evhttp_parse_query(evhttp_request_get_uri(request), ¶ms); + evhttp_parse_query(evhttp_request_get_uri(req), ¶ms); const char *const action = evhttp_find_header(¶ms, "action"); if (action && !strcmp(action, "snapshot")) { - _http_callback_snapshot(request, v_server); + _http_callback_snapshot(req, v_server); retval = 0; } else if (action && !strcmp(action, "stream")) { - _http_callback_stream(request, v_server); + _http_callback_stream(req, v_server); retval = 0; } @@ -328,12 +328,12 @@ static int _http_check_run_compat_action(struct evhttp_request *request, void *v } #define COMPAT_REQUEST { \ - if (_http_check_run_compat_action(request, v_server) == 0) { \ + if (_http_check_run_compat_action(req, v_server) == 0) { \ return; \ } \ } -static void _http_callback_root(struct evhttp_request *request, void *v_server) { +static void _http_callback_root(struct evhttp_request *req, void *v_server) { us_server_s *const server = v_server; PREPROCESS_REQUEST; @@ -342,13 +342,13 @@ static void _http_callback_root(struct evhttp_request *request, void *v_server) struct evbuffer *buf; _A_EVBUFFER_NEW(buf); _A_EVBUFFER_ADD_PRINTF(buf, "%s", US_HTML_INDEX_PAGE); - _A_ADD_HEADER(request, "Content-Type", "text/html"); - evhttp_send_reply(request, HTTP_OK, "OK", buf); + _A_ADD_HEADER(req, "Content-Type", "text/html"); + evhttp_send_reply(req, HTTP_OK, "OK", buf); evbuffer_free(buf); } -static void _http_callback_favicon(struct evhttp_request *request, void *v_server) { +static void _http_callback_favicon(struct evhttp_request *req, void *v_server) { us_server_s *const server = v_server; PREPROCESS_REQUEST; @@ -356,13 +356,13 @@ static void _http_callback_favicon(struct evhttp_request *request, void *v_serve struct evbuffer *buf; _A_EVBUFFER_NEW(buf); _A_EVBUFFER_ADD(buf, (const void*)US_FAVICON_ICO_DATA, US_FAVICON_ICO_DATA_SIZE); - _A_ADD_HEADER(request, "Content-Type", "image/x-icon"); - evhttp_send_reply(request, HTTP_OK, "OK", buf); + _A_ADD_HEADER(req, "Content-Type", "image/x-icon"); + evhttp_send_reply(req, HTTP_OK, "OK", buf); evbuffer_free(buf); } -static void _http_callback_static(struct evhttp_request *request, void *v_server) { +static void _http_callback_static(struct evhttp_request *req, void *v_server) { us_server_s *const server = v_server; PREPROCESS_REQUEST; @@ -376,7 +376,7 @@ static void _http_callback_static(struct evhttp_request *request, void *v_server { const char *uri_path; - if ((uri = evhttp_uri_parse(evhttp_request_get_uri(request))) == NULL) { + if ((uri = evhttp_uri_parse(evhttp_request_get_uri(req))) == NULL) { goto bad_request; } if ((uri_path = (char*)evhttp_uri_get_path(uri)) == NULL) { @@ -413,17 +413,17 @@ static void _http_callback_static(struct evhttp_request *request, void *v_server // and will close it when finished transferring data fd = -1; - _A_ADD_HEADER(request, "Content-Type", us_guess_mime_type(static_path)); - evhttp_send_reply(request, HTTP_OK, "OK", buf); + _A_ADD_HEADER(req, "Content-Type", us_guess_mime_type(static_path)); + evhttp_send_reply(req, HTTP_OK, "OK", buf); goto cleanup; } bad_request: - evhttp_send_error(request, HTTP_BADREQUEST, NULL); + evhttp_send_error(req, HTTP_BADREQUEST, NULL); goto cleanup; not_found: - evhttp_send_error(request, HTTP_NOTFOUND, NULL); + evhttp_send_error(req, HTTP_NOTFOUND, NULL); goto cleanup; cleanup: @@ -436,7 +436,7 @@ cleanup: #undef COMPAT_REQUEST -static void _http_callback_state(struct evhttp_request *request, void *v_server) { +static void _http_callback_state(struct evhttp_request *req, void *v_server) { us_server_s *const server = v_server; us_server_runtime_s *const run = server->run; us_server_exposed_s *const ex = run->exposed; @@ -451,60 +451,61 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server) struct evbuffer *buf; _A_EVBUFFER_NEW(buf); - _A_EVBUFFER_ADD_PRINTF(buf, + _A_EVBUFFER_ADD_PRINTF( + buf, "{\"ok\": true, \"result\": {" " \"instance_id\": \"%s\"," " \"encoder\": {\"type\": \"%s\", \"quality\": %u},", server->instance_id, us_encoder_type_to_string(enc_type), - enc_quality - ); + enc_quality); # ifdef WITH_V4P if (stream->drm != NULL) { us_fpsi_meta_s meta; const uint fps = us_fpsi_get(stream->run->http->drm_fpsi, &meta); - _A_EVBUFFER_ADD_PRINTF(buf, + _A_EVBUFFER_ADD_PRINTF( + buf, " \"drm\": {\"live\": %s, \"fps\": %u},", us_bool_to_string(meta.online), - fps - ); + fps); } # endif if (stream->h264_sink != NULL) { us_fpsi_meta_s meta; const uint fps = us_fpsi_get(stream->run->http->h264_fpsi, &meta); - _A_EVBUFFER_ADD_PRINTF(buf, + _A_EVBUFFER_ADD_PRINTF( + buf, " \"h264\": {\"bitrate\": %u, \"gop\": %u, \"online\": %s, \"fps\": %u},", stream->h264_bitrate, stream->h264_gop, us_bool_to_string(meta.online), - fps - ); + fps); } if (stream->jpeg_sink != NULL || stream->h264_sink != NULL) { _A_EVBUFFER_ADD_PRINTF(buf, " \"sinks\": {"); if (stream->jpeg_sink != NULL) { - _A_EVBUFFER_ADD_PRINTF(buf, + _A_EVBUFFER_ADD_PRINTF( + buf, "\"jpeg\": {\"has_clients\": %s}", - us_bool_to_string(atomic_load(&stream->jpeg_sink->has_clients)) - ); + us_bool_to_string(atomic_load(&stream->jpeg_sink->has_clients))); } if (stream->h264_sink != NULL) { - _A_EVBUFFER_ADD_PRINTF(buf, + _A_EVBUFFER_ADD_PRINTF( + buf, "%s\"h264\": {\"has_clients\": %s}", (stream->jpeg_sink ? ", " : ""), - us_bool_to_string(atomic_load(&stream->h264_sink->has_clients)) - ); + us_bool_to_string(atomic_load(&stream->h264_sink->has_clients))); } _A_EVBUFFER_ADD_PRINTF(buf, "},"); } us_fpsi_meta_s captured_meta; const uint captured_fps = us_fpsi_get(stream->run->http->captured_fpsi, &captured_meta); - _A_EVBUFFER_ADD_PRINTF(buf, + _A_EVBUFFER_ADD_PRINTF( + buf, " \"source\": {\"resolution\": {\"width\": %u, \"height\": %u}," " \"online\": %s, \"desired_fps\": %u, \"captured_fps\": %u}," " \"stream\": {\"queued_fps\": %u, \"clients\": %u, \"clients_stat\": {", @@ -514,11 +515,11 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server) stream->desired_fps, captured_fps, us_fpsi_get(ex->queued_fpsi, NULL), - run->stream_clients_count - ); + run->stream_clients_count); US_LIST_ITERATE(run->stream_clients, client, { // cppcheck-suppress constStatement - _A_EVBUFFER_ADD_PRINTF(buf, + _A_EVBUFFER_ADD_PRINTF( + buf, "\"%" PRIx64 "\": {\"fps\": %u, \"extra_headers\": %s, \"advance_headers\": %s," " \"dual_final_frames\": %s, \"zero_data\": %s, \"key\": \"%s\"}%s", client->id, @@ -528,18 +529,17 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server) us_bool_to_string(client->dual_final_frames), us_bool_to_string(client->zero_data), (client->key != NULL ? client->key : "0"), - (client->next ? ", " : "") - ); + (client->next ? ", " : "")); }); _A_EVBUFFER_ADD_PRINTF(buf, "}}}}"); - _A_ADD_HEADER(request, "Content-Type", "application/json"); - evhttp_send_reply(request, HTTP_OK, "OK", buf); + _A_ADD_HEADER(req, "Content-Type", "application/json"); + evhttp_send_reply(req, HTTP_OK, "OK", buf); evbuffer_free(buf); } -static void _http_callback_snapshot(struct evhttp_request *request, void *v_server) { +static void _http_callback_snapshot(struct evhttp_request *req, void *v_server) { us_server_s *const server = v_server; PREPROCESS_REQUEST; @@ -547,14 +547,14 @@ static void _http_callback_snapshot(struct evhttp_request *request, void *v_serv us_snapshot_client_s *client; US_CALLOC(client, 1); client->server = server; - client->request = request; - client->request_ts = us_get_now_monotonic(); + client->req = req; + client->req_ts = us_get_now_monotonic(); atomic_fetch_add(&server->stream->run->http->snapshot_requested, 1); US_LIST_APPEND(server->run->snapshot_clients, client); } -static void _http_callback_stream(struct evhttp_request *request, void *v_server) { +static void _http_callback_stream(struct evhttp_request *req, void *v_server) { // https://github.com/libevent/libevent/blob/29cc8386a2f7911eaa9336692a2c5544d8b4734f/http.c#L2814 // https://github.com/libevent/libevent/blob/29cc8386a2f7911eaa9336692a2c5544d8b4734f/http.c#L2789 // https://github.com/libevent/libevent/blob/29cc8386a2f7911eaa9336692a2c5544d8b4734f/http.c#L362 @@ -566,17 +566,17 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server PREPROCESS_REQUEST; - struct evhttp_connection *const conn = evhttp_request_get_connection(request); + struct evhttp_connection *const conn = evhttp_request_get_connection(req); if (conn != NULL) { us_stream_client_s *client; US_CALLOC(client, 1); client->server = server; - client->request = request; + client->req = req; client->need_initial = true; client->need_first_frame = true; struct evkeyvalq params; - evhttp_parse_query(evhttp_request_get_uri(request), ¶ms); + evhttp_parse_query(evhttp_request_get_uri(req), ¶ms); # define PARSE_PARAM(x_type, x_name) client->x_name = us_evkeyvalq_get_##x_type(¶ms, #x_name) PARSE_PARAM(string, key); PARSE_PARAM(true, extra_headers); @@ -586,7 +586,7 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server # undef PARSE_PARAM evhttp_clear_headers(¶ms); - client->hostport = us_evhttp_get_hostport(request); + client->hostport = us_evhttp_get_hostport(req); client->id = us_get_now_id(); { @@ -621,7 +621,7 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server bufferevent_setcb(buf_event, NULL, NULL, _http_callback_stream_error, (void*)client); bufferevent_enable(buf_event, EV_READ); } else { - evhttp_request_free(request); + evhttp_request_free(req); } } @@ -659,21 +659,24 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c # define BOUNDARY "boundarydonotcross" # define ADD_ADVANCE_HEADERS \ - _A_EVBUFFER_ADD_PRINTF(buf, \ - "Content-Type: image/jpeg" RN "X-Timestamp: %.06Lf" RN RN, us_get_now_real()) + _A_EVBUFFER_ADD_PRINTF( \ + buf, \ + "Content-Type: image/jpeg" RN "X-Timestamp: %.06Lf" RN RN, \ + us_get_now_real()) if (client->need_initial) { _A_EVBUFFER_ADD_PRINTF(buf, "HTTP/1.0 200 OK" RN); if (client->server->allow_origin[0] != '\0') { - const char *const cors_headers = us_evhttp_get_header(client->request, "Access-Control-Request-Headers"); - const char *const cors_method = us_evhttp_get_header(client->request, "Access-Control-Request-Method"); + const char *const cors_headers = us_evhttp_get_header(client->req, "Access-Control-Request-Headers"); + const char *const cors_method = us_evhttp_get_header(client->req, "Access-Control-Request-Method"); - _A_EVBUFFER_ADD_PRINTF(buf, + _A_EVBUFFER_ADD_PRINTF( + buf, "Access-Control-Allow-Origin: %s" RN "Access-Control-Allow-Credentials: true" RN, - client->server->allow_origin - ); + client->server->allow_origin); + if (cors_headers != NULL) { _A_EVBUFFER_ADD_PRINTF(buf, "Access-Control-Allow-Headers: %s" RN, cors_headers); } @@ -682,7 +685,8 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c } } - _A_EVBUFFER_ADD_PRINTF(buf, + _A_EVBUFFER_ADD_PRINTF( + buf, "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 @@ -693,8 +697,7 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c (server->instance_id[0] == '\0' ? "" : "_"), server->instance_id, (client->key != NULL ? client->key : "0"), - client->id - ); + client->id); if (client->advance_headers) { ADD_ADVANCE_HEADERS; @@ -705,18 +708,20 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c } if (!client->advance_headers) { - _A_EVBUFFER_ADD_PRINTF(buf, + _A_EVBUFFER_ADD_PRINTF( + buf, "Content-Type: image/jpeg" RN "Content-Length: %zu" RN "X-Timestamp: %.06Lf" RN "%s", (!client->zero_data ? ex->frame->used : 0), us_get_now_real(), - (client->extra_headers ? "" : RN) - ); + (client->extra_headers ? "" : RN)); + const ldf now_ts = us_get_now_monotonic(); if (client->extra_headers) { - _A_EVBUFFER_ADD_PRINTF(buf, + _A_EVBUFFER_ADD_PRINTF( + buf, "X-UStreamer-Online: %s" RN "X-UStreamer-Dropped: %u" RN "X-UStreamer-Width: %u" RN @@ -745,8 +750,7 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c ex->expose_cmp_ts, ex->expose_end_ts, now_ts, - now_ts - ex->frame->grab_begin_ts - ); + now_ts - ex->frame->grab_begin_ts); } } @@ -791,7 +795,7 @@ static void _http_callback_stream_error(struct bufferevent *buf_event, short wha run->stream_clients_count, client->hostport, client->id, reason); free(reason); - struct evhttp_connection *conn = evhttp_request_get_connection(client->request); + struct evhttp_connection *conn = evhttp_request_get_connection(client->req); US_DELETE(conn, evhttp_connection_free); us_fpsi_destroy(client->fpsi); @@ -808,7 +812,7 @@ static void _http_send_stream(us_server_s *server, bool stream_updated, bool fra bool has_clients = true; US_LIST_ITERATE(run->stream_clients, client, { // cppcheck-suppress constStatement - struct evhttp_connection *const conn = evhttp_request_get_connection(client->request); + struct evhttp_connection *const conn = evhttp_request_get_connection(client->req); if (conn != NULL) { // Фикс для бага WebKit. При включенной опции дропа одинаковых фреймов, // WebKit отрисовывает последний фрейм в серии с некоторой задержкой, @@ -852,22 +856,22 @@ static void _http_send_snapshot(us_server_s *server) { # define ADD_TIME_HEADER(x_key, x_value) { \ US_SNPRINTF(header_buf, 255, "%.06Lf", x_value); \ - _A_ADD_HEADER(request, x_key, header_buf); \ + _A_ADD_HEADER(req, x_key, header_buf); \ } # define ADD_UNSIGNED_HEADER(x_key, x_value) { \ US_SNPRINTF(header_buf, 255, "%u", x_value); \ - _A_ADD_HEADER(request, x_key, header_buf); \ + _A_ADD_HEADER(req, x_key, header_buf); \ } us_fpsi_meta_s captured_meta; us_fpsi_get(server->stream->run->http->captured_fpsi, &captured_meta); US_LIST_ITERATE(server->run->snapshot_clients, client, { // cppcheck-suppress constStatement - struct evhttp_request *request = client->request; + struct evhttp_request *req = client->req; const bool has_fresh_snapshot = (atomic_load(&server->stream->run->http->snapshot_requested) == 0); - const bool timed_out = (client->request_ts + US_MAX((uint)1, server->stream->error_delay * 3) < us_get_now_monotonic()); + const bool timed_out = (client->req_ts + US_MAX((uint)1, server->stream->error_delay * 3) < us_get_now_monotonic()); if (has_fresh_snapshot || timed_out) { us_frame_s *frame = ex->frame; @@ -883,15 +887,15 @@ static void _http_send_snapshot(us_server_s *server) { _A_EVBUFFER_NEW(buf); _A_EVBUFFER_ADD(buf, (const void*)frame->data, frame->used); - _A_ADD_HEADER(request, "Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate, pre-check=0, post-check=0, max-age=0"); - _A_ADD_HEADER(request, "Pragma", "no-cache"); - _A_ADD_HEADER(request, "Expires", "Mon, 3 Jan 2000 12:34:56 GMT"); + _A_ADD_HEADER(req, "Cache-Control", "no-store, no-cache, must-revalidate, proxy-revalidate, pre-check=0, post-check=0, max-age=0"); + _A_ADD_HEADER(req, "Pragma", "no-cache"); + _A_ADD_HEADER(req, "Expires", "Mon, 3 Jan 2000 12:34:56 GMT"); char header_buf[256]; ADD_TIME_HEADER("X-Timestamp", us_get_now_real()); - _A_ADD_HEADER(request, "X-UStreamer-Online", us_bool_to_string(frame->online)); + _A_ADD_HEADER(req, "X-UStreamer-Online", us_bool_to_string(frame->online)); ADD_UNSIGNED_HEADER("X-UStreamer-Width", frame->width); ADD_UNSIGNED_HEADER("X-UStreamer-Height", frame->height); ADD_TIME_HEADER("X-UStreamer-Grab-Begin-Timestamp", frame->grab_begin_ts); @@ -900,9 +904,9 @@ static void _http_send_snapshot(us_server_s *server) { ADD_TIME_HEADER("X-UStreamer-Encode-End-Timestamp", frame->encode_end_ts); ADD_TIME_HEADER("X-UStreamer-Send-Timestamp", us_get_now_monotonic()); - _A_ADD_HEADER(request, "Content-Type", "image/jpeg"); + _A_ADD_HEADER(req, "Content-Type", "image/jpeg"); - evhttp_send_reply(request, HTTP_OK, "OK", buf); + evhttp_send_reply(req, HTTP_OK, "OK", buf); evbuffer_free(buf); US_LIST_REMOVE(server->run->snapshot_clients, client); diff --git a/src/ustreamer/http/server.h b/src/ustreamer/http/server.h index 2d886f7..6bfe9b2 100644 --- a/src/ustreamer/http/server.h +++ b/src/ustreamer/http/server.h @@ -38,7 +38,7 @@ typedef struct { struct us_server_sx *server; - struct evhttp_request *request; + struct evhttp_request *req; char *key; bool extra_headers; @@ -59,8 +59,8 @@ typedef struct { typedef struct { struct us_server_sx *server; - struct evhttp_request *request; - ldf request_ts; + struct evhttp_request *req; + ldf req_ts; US_LIST_DECLARE; } us_snapshot_client_s; diff --git a/src/ustreamer/http/static.c b/src/ustreamer/http/static.c index 0313093..699ebde 100644 --- a/src/ustreamer/http/static.c +++ b/src/ustreamer/http/static.c @@ -36,12 +36,12 @@ #include "path.h" -char *us_find_static_file_path(const char *root_path, const char *request_path) { +char *us_find_static_file_path(const char *root_path, const char *req_path) { char *path = NULL; - char *const simplified_path = us_simplify_request_path(request_path); + char *const simplified_path = us_simplify_request_path(req_path); if (simplified_path[0] == '\0') { - US_LOG_VERBOSE("HTTP: Invalid request path %s to static", request_path); + US_LOG_VERBOSE("HTTP: Invalid request path %s to static", req_path); goto error; } diff --git a/src/ustreamer/http/static.h b/src/ustreamer/http/static.h index 464d532..694e05d 100644 --- a/src/ustreamer/http/static.h +++ b/src/ustreamer/http/static.h @@ -23,4 +23,4 @@ #pragma once -char *us_find_static_file_path(const char *root_path, const char *request_path); +char *us_find_static_file_path(const char *root_path, const char *req_path); diff --git a/src/ustreamer/http/tools.c b/src/ustreamer/http/tools.c index e1ff565..e6b2678 100644 --- a/src/ustreamer/http/tools.c +++ b/src/ustreamer/http/tools.c @@ -82,27 +82,27 @@ evutil_socket_t us_evhttp_bind_unix(struct evhttp *http, const char *path, bool return fd; } -const char *us_evhttp_get_header(struct evhttp_request *request, const char *key) { - return evhttp_find_header(evhttp_request_get_input_headers(request), key); +const char *us_evhttp_get_header(struct evhttp_request *req, const char *key) { + return evhttp_find_header(evhttp_request_get_input_headers(req), key); } -char *us_evhttp_get_hostport(struct evhttp_request *request) { +char *us_evhttp_get_hostport(struct evhttp_request *req) { char *addr = NULL; unsigned short port = 0; - struct evhttp_connection *conn = evhttp_request_get_connection(request); + struct evhttp_connection *conn = evhttp_request_get_connection(req); if (conn != NULL) { char *peer; evhttp_connection_get_peer(conn, &peer, &port); addr = us_strdup(peer); } - const char *xff = us_evhttp_get_header(request, "X-Forwarded-For"); + const char *xff = us_evhttp_get_header(req, "X-Forwarded-For"); if (xff != NULL) { US_DELETE(addr, free); assert((addr = strndup(xff, 1024)) != NULL); - for (uint index = 0; addr[index]; ++index) { - if (addr[index] == ',') { - addr[index] = '\0'; + for (uint i = 0; addr[i]; ++i) { + if (addr[i] == ',') { + addr[i] = '\0'; break; } } diff --git a/src/ustreamer/http/tools.h b/src/ustreamer/http/tools.h index 0c9fc59..8ae7229 100644 --- a/src/ustreamer/http/tools.h +++ b/src/ustreamer/http/tools.h @@ -32,8 +32,8 @@ evutil_socket_t us_evhttp_bind_unix(struct evhttp *http, const char *path, bool rm, mode_t mode); -const char *us_evhttp_get_header(struct evhttp_request *request, const char *key); -char *us_evhttp_get_hostport(struct evhttp_request *request); +const char *us_evhttp_get_header(struct evhttp_request *req, const char *key); +char *us_evhttp_get_hostport(struct evhttp_request *req); bool us_evkeyvalq_get_true(struct evkeyvalq *params, const char *key); char *us_evkeyvalq_get_string(struct evkeyvalq *params, const char *key); diff --git a/src/ustreamer/m2m.c b/src/ustreamer/m2m.c index f0b1b7d..5eef93e 100644 --- a/src/ustreamer/m2m.c +++ b/src/ustreamer/m2m.c @@ -42,25 +42,39 @@ static us_m2m_encoder_s *_m2m_encoder_init( - const char *name, const char *path, uint output_format, - uint bitrate, uint gop, uint quality, bool allow_dma, bool boost); + const char *name, + const char *path, + uint out_format, + uint bitrate, + uint gop, + uint quality, + bool allow_dma, + bool boost); static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame); static int _m2m_encoder_init_buffers( - us_m2m_encoder_s *enc, const char *name, enum v4l2_buf_type type, - us_m2m_buffer_s **bufs_ptr, uint *n_bufs_ptr, bool dma); + us_m2m_encoder_s *enc, + const char *name, + enum v4l2_buf_type type, + us_m2m_buffer_s **bufs_ptr, + uint *n_bufs_ptr, + bool dma); static void _m2m_encoder_cleanup(us_m2m_encoder_s *enc); -static int _m2m_encoder_compress_raw(us_m2m_encoder_s *enc, const us_frame_s *src, us_frame_s *dest, bool force_key); +static int _m2m_encoder_compress_raw( + us_m2m_encoder_s *enc, + const us_frame_s *src, + us_frame_s *dest, + bool force_key); -#define _LOG_ERROR(x_msg, ...) US_LOG_ERROR("%s: " x_msg, enc->name, ##__VA_ARGS__) -#define _LOG_PERROR(x_msg, ...) US_LOG_PERROR("%s: " x_msg, enc->name, ##__VA_ARGS__) +#define _LOG_ERROR(x_msg, ...) US_LOG_ERROR("%s: " x_msg, enc->name, ##__VA_ARGS__) +#define _LOG_PERROR(x_msg, ...) US_LOG_PERROR("%s: " x_msg, enc->name, ##__VA_ARGS__) #define _LOG_INFO(x_msg, ...) US_LOG_INFO("%s: " x_msg, enc->name, ##__VA_ARGS__) #define _LOG_VERBOSE(x_msg, ...) US_LOG_VERBOSE("%s: " x_msg, enc->name, ##__VA_ARGS__) -#define _LOG_DEBUG(x_msg, ...) US_LOG_DEBUG("%s: " x_msg, enc->name, ##__VA_ARGS__) +#define _LOG_DEBUG(x_msg, ...) US_LOG_DEBUG("%s: " x_msg, enc->name, ##__VA_ARGS__) us_m2m_encoder_s *us_m2m_h264_encoder_init(const char *name, const char *path, uint bitrate, uint gop, bool boost) { @@ -95,8 +109,8 @@ void us_m2m_encoder_destroy(us_m2m_encoder_s *enc) { int us_m2m_encoder_compress(us_m2m_encoder_s *enc, const us_frame_s *src, us_frame_s *dest, bool force_key) { us_m2m_encoder_runtime_s *const run = enc->run; - uint dest_format = enc->output_format; - switch (enc->output_format) { + uint dest_format = enc->out_format; + switch (enc->out_format) { case V4L2_PIX_FMT_JPEG: force_key = false; // fall through @@ -138,9 +152,15 @@ int us_m2m_encoder_compress(us_m2m_encoder_s *enc, const us_frame_s *src, us_fra } static us_m2m_encoder_s *_m2m_encoder_init( - const char *name, const char *path, uint output_format, - uint bitrate, uint gop, uint quality, bool allow_dma, bool boost) { - + const char *name, + const char *path, + uint out_format, + uint bitrate, + uint gop, + uint quality, + bool allow_dma, + bool boost +) { US_LOG_INFO("%s: Initializing encoder ...", name); us_m2m_encoder_runtime_s *run; @@ -152,11 +172,11 @@ static us_m2m_encoder_s *_m2m_encoder_init( US_CALLOC(enc, 1); enc->name = us_strdup(name); if (path == NULL) { - enc->path = us_strdup(output_format == V4L2_PIX_FMT_JPEG ? "/dev/video31" : "/dev/video11"); + enc->path = us_strdup(out_format == V4L2_PIX_FMT_JPEG ? "/dev/video31" : "/dev/video11"); } else { enc->path = us_strdup(path); } - enc->output_format = output_format; + enc->out_format = out_format; enc->bitrate = bitrate; enc->gop = gop; enc->quality = quality; @@ -180,7 +200,7 @@ static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame) if ( run->p_width == frame->width && run->p_height == frame->height - && run->p_input_format == frame->format + && run->p_in_format == frame->format && run->p_stride == frame->stride && run->p_dma == dma ) { @@ -189,18 +209,18 @@ static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame) _LOG_INFO("Configuring encoder: DMA=%d ...", dma); - _LOG_DEBUG("Encoder changes: width=%u->%u, height=%u->%u, input_format=%u->%u, stride=%u->%u, dma=%u->%u", - run->p_width, frame->width, - run->p_height, frame->height, - run->p_input_format, frame->format, - run->p_stride, frame->stride, - run->p_dma, dma); + _LOG_DEBUG("Encoder changes: width=%u->%u, height=%u->%u, in_format=%u->%u, stride=%u->%u, dma=%u->%u", + run->p_width, frame->width, + run->p_height, frame->height, + run->p_in_format, frame->format, + run->p_stride, frame->stride, + run->p_dma, dma); _m2m_encoder_cleanup(enc); run->p_width = frame->width; run->p_height = frame->height; - run->p_input_format = frame->format; + run->p_in_format = frame->format; run->p_stride = frame->stride; run->p_dma = dma; @@ -218,7 +238,7 @@ static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame) _LOG_DEBUG("Configuring option " #x_cid " ..."); \ _E_XIOCTL(VIDIOC_S_CTRL, &m_ctl, "Can't set option " #x_cid); \ } - if (enc->output_format == V4L2_PIX_FMT_H264) { + if (enc->out_format == V4L2_PIX_FMT_H264) { SET_OPTION(V4L2_CID_MPEG_VIDEO_BITRATE, enc->bitrate); SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_I_PERIOD, enc->gop); SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_PROFILE, V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE); @@ -234,9 +254,9 @@ static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame) SET_OPTION(V4L2_CID_MPEG_VIDEO_REPEAT_SEQ_HEADER, 1); SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 16); SET_OPTION(V4L2_CID_MPEG_VIDEO_H264_MAX_QP, 32); - } else if (enc->output_format == V4L2_PIX_FMT_MJPEG) { + } else if (enc->out_format == V4L2_PIX_FMT_MJPEG) { SET_OPTION(V4L2_CID_MPEG_VIDEO_BITRATE, enc->bitrate); - } else if (enc->output_format == V4L2_PIX_FMT_JPEG) { + } else if (enc->out_format == V4L2_PIX_FMT_JPEG) { SET_OPTION(V4L2_CID_JPEG_COMPRESSION_QUALITY, enc->quality); } # undef SET_OPTION @@ -246,7 +266,7 @@ static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame) fmt.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; fmt.fmt.pix_mp.width = run->p_width; fmt.fmt.pix_mp.height = run->p_height; - fmt.fmt.pix_mp.pixelformat = run->p_input_format; + fmt.fmt.pix_mp.pixelformat = run->p_in_format; fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_JPEG; // FIXME: Wrong colors fmt.fmt.pix_mp.num_planes = 1; @@ -260,22 +280,22 @@ static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame) fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; fmt.fmt.pix_mp.width = run->p_width; fmt.fmt.pix_mp.height = run->p_height; - fmt.fmt.pix_mp.pixelformat = enc->output_format; + fmt.fmt.pix_mp.pixelformat = enc->out_format; fmt.fmt.pix_mp.field = V4L2_FIELD_ANY; fmt.fmt.pix_mp.colorspace = V4L2_COLORSPACE_DEFAULT; fmt.fmt.pix_mp.num_planes = 1; // fmt.fmt.pix_mp.plane_fmt[0].bytesperline = 0; - if (enc->output_format == V4L2_PIX_FMT_H264) { + if (enc->out_format == V4L2_PIX_FMT_H264) { // https://github.com/pikvm/ustreamer/issues/169 // https://github.com/raspberrypi/linux/pull/5232 fmt.fmt.pix_mp.plane_fmt[0].sizeimage = (1024 + 512) << 10; // 1.5Mb } _LOG_DEBUG("Configuring OUTPUT format ..."); _E_XIOCTL(VIDIOC_S_FMT, &fmt, "Can't set OUTPUT format"); - if (fmt.fmt.pix_mp.pixelformat != enc->output_format) { + if (fmt.fmt.pix_mp.pixelformat != enc->out_format) { char fourcc_str[8]; _LOG_ERROR("The OUTPUT format can't be configured as %s", - us_fourcc_to_string(enc->output_format, fourcc_str, 8)); + us_fourcc_to_string(enc->out_format, fourcc_str, 8)); _LOG_ERROR("In case of Raspberry Pi, try to append 'start_x=1' to /boot/config.txt"); goto error; } @@ -283,7 +303,7 @@ static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame) if ( (run->p_width * run->p_height <= 1280 * 720) - || ((enc->output_format == V4L2_PIX_FMT_H264) && enc->boost) + || ((enc->out_format == V4L2_PIX_FMT_H264) && enc->boost) ) { // H264 требует каких-то лимитов. Больше 30 не поддерживается, а при 0 // через какое-то время начинает производить некорректные фреймы. @@ -306,14 +326,22 @@ static void _m2m_encoder_ensure(us_m2m_encoder_s *enc, const us_frame_s *frame) } if (_m2m_encoder_init_buffers( - enc, (dma ? "INPUT-DMA" : "INPUT"), V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, - &run->input_bufs, &run->n_input_bufs, dma + enc, + (dma ? "INPUT-DMA" : "INPUT"), + V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE, + &run->in_bufs, + &run->n_in_bufs, + dma ) < 0) { goto error; } if (_m2m_encoder_init_buffers( - enc, "OUTPUT", V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, - &run->output_bufs, &run->n_output_bufs, false + enc, + "OUTPUT", + V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE, + &run->out_bufs, + &run->n_out_bufs, + false ) < 0) { goto error; } @@ -338,9 +366,13 @@ error: } static int _m2m_encoder_init_buffers( - us_m2m_encoder_s *enc, const char *name, enum v4l2_buf_type type, - us_m2m_buffer_s **bufs_ptr, uint *n_bufs_ptr, bool dma) { - + us_m2m_encoder_s *enc, + const char *name, + enum v4l2_buf_type type, + us_m2m_buffer_s **bufs_ptr, + uint *n_bufs_ptr, + bool dma +) { us_m2m_encoder_runtime_s *const run = enc->run; _LOG_DEBUG("Initializing %s buffers ...", name); @@ -420,11 +452,11 @@ static void _m2m_encoder_cleanup(us_m2m_encoder_s *enc) { # define DELETE_BUFFERS(x_name, x_target) { \ if (run->x_target##_bufs != NULL) { \ say = true; \ - for (uint m_index = 0; m_index < run->n_##x_target##_bufs; ++m_index) { \ - us_m2m_buffer_s *m_buf = &run->x_target##_bufs[m_index]; \ + for (uint m_i = 0; m_i < run->n_##x_target##_bufs; ++m_i) { \ + us_m2m_buffer_s *m_buf = &run->x_target##_bufs[m_i]; \ if (m_buf->allocated > 0 && m_buf->data != NULL) { \ if (munmap(m_buf->data, m_buf->allocated) < 0) { \ - _LOG_PERROR("Can't unmap %s buffer=%u", #x_name, m_index); \ + _LOG_PERROR("Can't unmap %s buffer=%u", #x_name, m_i); \ } \ } \ } \ @@ -432,8 +464,8 @@ static void _m2m_encoder_cleanup(us_m2m_encoder_s *enc) { } \ run->n_##x_target##_bufs = 0; \ } - DELETE_BUFFERS("OUTPUT", output); - DELETE_BUFFERS("INPUT", input); + DELETE_BUFFERS("OUTPUT", out); + DELETE_BUFFERS("INPUT", in); # undef DELETE_BUFFERS if (run->fd >= 0) { @@ -452,7 +484,12 @@ static void _m2m_encoder_cleanup(us_m2m_encoder_s *enc) { } } -static int _m2m_encoder_compress_raw(us_m2m_encoder_s *enc, const us_frame_s *src, us_frame_s *dest, bool force_key) { +static int _m2m_encoder_compress_raw( + us_m2m_encoder_s *enc, + const us_frame_s *src, + us_frame_s *dest, + bool force_key +) { us_m2m_encoder_runtime_s *const run = enc->run; assert(run->ready); @@ -465,28 +502,28 @@ static int _m2m_encoder_compress_raw(us_m2m_encoder_s *enc, const us_frame_s *sr _E_XIOCTL(VIDIOC_S_CTRL, &ctl, "Can't force keyframe"); } - struct v4l2_buffer input_buf = {0}; - struct v4l2_plane input_plane = {0}; - input_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; - input_buf.length = 1; - input_buf.m.planes = &input_plane; + struct v4l2_buffer in_buf = {0}; + struct v4l2_plane in_plane = {0}; + in_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE; + in_buf.length = 1; + in_buf.m.planes = &in_plane; if (run->p_dma) { - input_buf.index = 0; - input_buf.memory = V4L2_MEMORY_DMABUF; - input_buf.field = V4L2_FIELD_NONE; - input_plane.m.fd = src->dma_fd; - _LOG_DEBUG("Using INPUT-DMA buffer=%u", input_buf.index); + in_buf.index = 0; + in_buf.memory = V4L2_MEMORY_DMABUF; + in_buf.field = V4L2_FIELD_NONE; + in_plane.m.fd = src->dma_fd; + _LOG_DEBUG("Using INPUT-DMA buffer=%u", in_buf.index); } else { - input_buf.memory = V4L2_MEMORY_MMAP; + in_buf.memory = V4L2_MEMORY_MMAP; _LOG_DEBUG("Grabbing INPUT buffer ..."); - _E_XIOCTL(VIDIOC_DQBUF, &input_buf, "Can't grab INPUT buffer"); - if (input_buf.index >= run->n_input_bufs) { + _E_XIOCTL(VIDIOC_DQBUF, &in_buf, "Can't grab INPUT buffer"); + if (in_buf.index >= run->n_in_bufs) { _LOG_ERROR("V4L2 error: grabbed invalid INPUT: buffer=%u, n_bufs=%u", - input_buf.index, run->n_input_bufs); + in_buf.index, run->n_in_bufs); goto error; } - _LOG_DEBUG("Grabbed INPUT buffer=%u", input_buf.index); + _LOG_DEBUG("Grabbed INPUT buffer=%u", in_buf.index); } const u64 now_ts = us_get_now_monotonic_u64(); @@ -495,21 +532,21 @@ static int _m2m_encoder_compress_raw(us_m2m_encoder_s *enc, const us_frame_s *sr .tv_usec = now_ts % 1000000, }; - input_buf.timestamp.tv_sec = ts.tv_sec; - input_buf.timestamp.tv_usec = ts.tv_usec; - input_plane.bytesused = src->used; - input_plane.length = src->used; + in_buf.timestamp.tv_sec = ts.tv_sec; + in_buf.timestamp.tv_usec = ts.tv_usec; + in_plane.bytesused = src->used; + in_plane.length = src->used; if (!run->p_dma) { - memcpy(run->input_bufs[input_buf.index].data, src->data, src->used); + memcpy(run->in_bufs[in_buf.index].data, src->data, src->used); } - const char *input_name = (run->p_dma ? "INPUT-DMA" : "INPUT"); + const char *in_name = (run->p_dma ? "INPUT-DMA" : "INPUT"); - _LOG_DEBUG("Sending%s %s buffer ...", (!run->p_dma ? " (releasing)" : ""), input_name); - _E_XIOCTL(VIDIOC_QBUF, &input_buf, "Can't send %s buffer", input_name); + _LOG_DEBUG("Sending%s %s buffer ...", (!run->p_dma ? " (releasing)" : ""), in_name); + _E_XIOCTL(VIDIOC_QBUF, &in_buf, "Can't send %s buffer", in_name); // Для не-DMA отправка буфера по факту являтся освобождением этого буфера - bool input_released = !run->p_dma; + bool in_released = !run->p_dma; // https://github.com/pikvm/ustreamer/issues/253 // За секунду точно должно закодироваться. @@ -529,37 +566,37 @@ static int _m2m_encoder_compress_raw(us_m2m_encoder_s *enc, const us_frame_s *sr } if (enc_poll.revents & POLLIN) { - if (!input_released) { - _LOG_DEBUG("Releasing %s buffer=%u ...", input_name, input_buf.index); - _E_XIOCTL(VIDIOC_DQBUF, &input_buf, "Can't release %s buffer=%u", - input_name, input_buf.index); - input_released = true; + if (!in_released) { + _LOG_DEBUG("Releasing %s buffer=%u ...", in_name, in_buf.index); + _E_XIOCTL(VIDIOC_DQBUF, &in_buf, "Can't release %s buffer=%u", + in_name, in_buf.index); + in_released = true; } - struct v4l2_buffer output_buf = {0}; - struct v4l2_plane output_plane = {0}; - output_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; - output_buf.memory = V4L2_MEMORY_MMAP; - output_buf.length = 1; - output_buf.m.planes = &output_plane; + struct v4l2_buffer out_buf = {0}; + struct v4l2_plane out_plane = {0}; + out_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; + out_buf.memory = V4L2_MEMORY_MMAP; + out_buf.length = 1; + out_buf.m.planes = &out_plane; _LOG_DEBUG("Fetching OUTPUT buffer ..."); - _E_XIOCTL(VIDIOC_DQBUF, &output_buf, "Can't fetch OUTPUT buffer"); + _E_XIOCTL(VIDIOC_DQBUF, &out_buf, "Can't fetch OUTPUT buffer"); bool done = false; - if (ts.tv_sec != output_buf.timestamp.tv_sec || ts.tv_usec != output_buf.timestamp.tv_usec) { + if (ts.tv_sec != out_buf.timestamp.tv_sec || ts.tv_usec != out_buf.timestamp.tv_usec) { // Енкодер первый раз может выдать буфер с мусором и нулевым таймстампом, // так что нужно убедиться, что мы читаем выходной буфер, соответствующий // входному (с тем же таймстампом). _LOG_DEBUG("Need to retry OUTPUT buffer due timestamp mismatch"); } else { - us_frame_set_data(dest, run->output_bufs[output_buf.index].data, output_plane.bytesused); - dest->key = output_buf.flags & V4L2_BUF_FLAG_KEYFRAME; + us_frame_set_data(dest, run->out_bufs[out_buf.index].data, out_plane.bytesused); + dest->key = out_buf.flags & V4L2_BUF_FLAG_KEYFRAME; dest->gop = enc->gop; done = true; } - _LOG_DEBUG("Releasing OUTPUT buffer=%u ...", output_buf.index); - _E_XIOCTL(VIDIOC_QBUF, &output_buf, "Can't release OUTPUT buffer=%u", output_buf.index); + _LOG_DEBUG("Releasing OUTPUT buffer=%u ...", out_buf.index); + _E_XIOCTL(VIDIOC_QBUF, &out_buf, "Can't release OUTPUT buffer=%u", out_buf.index); if (done) { break; diff --git a/src/ustreamer/m2m.h b/src/ustreamer/m2m.h index d97ee64..366eb45 100644 --- a/src/ustreamer/m2m.h +++ b/src/ustreamer/m2m.h @@ -34,14 +34,14 @@ typedef struct { typedef struct { int fd; uint fps_limit; - us_m2m_buffer_s *input_bufs; - uint n_input_bufs; - us_m2m_buffer_s *output_bufs; - uint n_output_bufs; + us_m2m_buffer_s *in_bufs; + uint n_in_bufs; + us_m2m_buffer_s *out_bufs; + uint n_out_bufs; uint p_width; uint p_height; - uint p_input_format; + uint p_in_format; uint p_stride; bool p_dma; @@ -53,7 +53,7 @@ typedef struct { typedef struct { char *name; char *path; - uint output_format; + uint out_format; uint bitrate; uint gop; uint quality; diff --git a/src/ustreamer/main.c b/src/ustreamer/main.c index bf7e71c..b828b2c 100644 --- a/src/ustreamer/main.c +++ b/src/ustreamer/main.c @@ -83,13 +83,13 @@ int main(int argc, char *argv[]) { US_LOGGING_INIT; US_THREAD_RENAME("main"); - us_options_s *options = us_options_init(argc, argv); + us_options_s *opts = us_options_init(argc, argv); us_capture_s *cap = us_capture_init(); us_encoder_s *enc = us_encoder_init(); _g_stream = us_stream_init(cap, enc); _g_server = us_server_init(_g_stream); - if ((exit_code = options_parse(options, cap, enc, _g_stream, _g_server)) == 0) { + if ((exit_code = us_options_parse(opts, cap, enc, _g_stream, _g_server)) == 0) { us_stream_update_blank(_g_stream, cap); # ifdef WITH_GPIO us_gpio_init(); @@ -120,7 +120,7 @@ int main(int argc, char *argv[]) { us_stream_destroy(_g_stream); us_encoder_destroy(enc); us_capture_destroy(cap); - us_options_destroy(options); + us_options_destroy(opts); if (exit_code == 0) { US_LOG_INFO("Bye-bye"); diff --git a/src/ustreamer/options.c b/src/ustreamer/options.c index d70b565..f766ed9 100644 --- a/src/ustreamer/options.c +++ b/src/ustreamer/options.c @@ -22,6 +22,35 @@ #include "options.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../libs/types.h" +#include "../libs/const.h" +#include "../libs/logging.h" +#include "../libs/process.h" +#include "../libs/frame.h" +#include "../libs/memsink.h" +#include "../libs/options.h" +#include "../libs/capture.h" +#ifdef WITH_V4P +# include "../libs/drm/drm.h" +#endif + +#include "encoder.h" +#include "stream.h" +#include "http/server.h" +#ifdef WITH_GPIO +# include "gpio/gpio.h" +#endif + enum _US_OPT_VALUES { _O_DEVICE = 'd', @@ -252,53 +281,65 @@ static const struct option _LONG_OPTS[] = { }; -static int _parse_resolution(const char *str, unsigned *width, unsigned *height, bool limited); +static int _parse_resolution(const char *str, uint *width, uint *height, bool limited); static int _check_instance_id(const char *str); static void _features(void); -static void _help(FILE *fp, const us_capture_s *cap, const us_encoder_s *enc, const us_stream_s *stream, const us_server_s *server); + +static void _help( + FILE *fp, + const us_capture_s *cap, + const us_encoder_s *enc, + const us_stream_s *stream, + const us_server_s *server); -us_options_s *us_options_init(unsigned argc, char *argv[]) { - us_options_s *options; - US_CALLOC(options, 1); - options->argc = argc; - options->argv = argv; +us_options_s *us_options_init(uint argc, char *argv[]) { + us_options_s *opts; + US_CALLOC(opts, 1); + opts->argc = argc; + opts->argv = argv; - US_CALLOC(options->argv_copy, argc); - for (unsigned index = 0; index < argc; ++index) { - options->argv_copy[index] = us_strdup(argv[index]); + US_CALLOC(opts->argv_copy, argc); + for (uint i = 0; i < argc; ++i) { + opts->argv_copy[i] = us_strdup(argv[i]); } - return options; + return opts; } -void us_options_destroy(us_options_s *options) { - US_DELETE(options->jpeg_sink, us_memsink_destroy); - US_DELETE(options->raw_sink, us_memsink_destroy); - US_DELETE(options->h264_sink, us_memsink_destroy); +void us_options_destroy(us_options_s *opts) { + US_DELETE(opts->jpeg_sink, us_memsink_destroy); + US_DELETE(opts->raw_sink, us_memsink_destroy); + US_DELETE(opts->h264_sink, us_memsink_destroy); # ifdef WITH_V4P - US_DELETE(options->drm, us_drm_destroy); + US_DELETE(opts->drm, us_drm_destroy); # endif - for (unsigned index = 0; index < options->argc; ++index) { - free(options->argv_copy[index]); + for (uint i = 0; i < opts->argc; ++i) { + free(opts->argv_copy[i]); } - free(options->argv_copy); + free(opts->argv_copy); - free(options); + free(opts); } -int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, us_stream_s *stream, us_server_s *server) { +int us_options_parse( + us_options_s *opts, + us_capture_s *cap, + us_encoder_s *enc, + us_stream_s *stream, + us_server_s *server +) { # define OPT_SET(x_dest, x_value) { \ x_dest = x_value; \ break; \ } # define OPT_NUMBER(x_name, x_dest, x_min, x_max, x_base) { \ - errno = 0; char *m_end = NULL; const long long m_tmp = strtoll(optarg, &m_end, x_base); \ + errno = 0; char *m_end = NULL; const sll m_tmp = strtoll(optarg, &m_end, x_base); \ if (errno || *m_end || m_tmp < x_min || m_tmp > x_max) { \ - printf("Invalid value for '%s=%s': min=%lld, max=%lld\n", x_name, optarg, (long long)x_min, (long long)x_max); \ + printf("Invalid value for '%s=%s': min=%lld, max=%lld\n", x_name, optarg, (sll)x_min, (sll)x_max); \ return -1; \ } \ x_dest = m_tmp; \ @@ -362,8 +403,8 @@ int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, u const char *x_prefix##_name = NULL; \ mode_t x_prefix##_mode = 0660; \ bool x_prefix##_rm = false; \ - unsigned x_prefix##_client_ttl = 10; \ - unsigned x_prefix##_timeout = 1; + uint x_prefix##_client_ttl = 10; \ + uint x_prefix##_timeout = 1; ADD_SINK(jpeg_sink); ADD_SINK(raw_sink); ADD_SINK(h264_sink); @@ -376,7 +417,7 @@ int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, u char short_opts[128]; us_build_short_options(_LONG_OPTS, short_opts, 128); - for (int ch; (ch = getopt_long(options->argc, options->argv_copy, short_opts, _LONG_OPTS, NULL)) >= 0;) { + for (int ch; (ch = getopt_long(opts->argc, opts->argv_copy, short_opts, _LONG_OPTS, NULL)) >= 0;) { switch (ch) { case _O_DEVICE: OPT_SET(cap->path, optarg); case _O_INPUT: OPT_NUMBER("--input", cap->input, 0, 128, 0); @@ -475,8 +516,8 @@ int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, u # ifdef WITH_V4P case _O_V4P: - options->drm = us_drm_init(); - stream->drm = options->drm; + opts->drm = us_drm_init(); + stream->drm = opts->drm; break; # endif @@ -522,7 +563,7 @@ int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, u # define ADD_SINK(x_label, x_prefix) { \ if (x_prefix##_name && x_prefix##_name[0] != '\0') { \ - options->x_prefix = us_memsink_init_opened( \ + opts->x_prefix = us_memsink_init_opened( \ x_label, \ x_prefix##_name, \ true, \ @@ -532,7 +573,7 @@ int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, u x_prefix##_timeout \ ); \ } \ - stream->x_prefix = options->x_prefix; \ + stream->x_prefix = opts->x_prefix; \ } ADD_SINK("JPEG", jpeg_sink); ADD_SINK("RAW", raw_sink); @@ -541,7 +582,7 @@ int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, u # ifdef WITH_SETPROCTITLE if (process_name_prefix != NULL) { - us_process_set_name_prefix(options->argc, options->argv, process_name_prefix); + us_process_set_name_prefix(opts->argc, opts->argv, process_name_prefix); } # endif @@ -555,9 +596,9 @@ int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, u return 0; } -static int _parse_resolution(const char *str, unsigned *width, unsigned *height, bool limited) { - unsigned tmp_width; - unsigned tmp_height; +static int _parse_resolution(const char *str, uint *width, uint *height, bool limited) { + uint tmp_width; + uint tmp_height; if (sscanf(str, "%ux%u", &tmp_width, &tmp_height) != 2) { return -1; } @@ -636,7 +677,13 @@ static void _features(void) { # endif } -static void _help(FILE *fp, const us_capture_s *cap, const us_encoder_s *enc, const us_stream_s *stream, const us_server_s *server) { +static void _help( + FILE *fp, + const us_capture_s *cap, + const us_encoder_s *enc, + const us_stream_s *stream, + const us_server_s *server +) { # define SAY(x_msg, ...) fprintf(fp, x_msg "\n", ##__VA_ARGS__) SAY("\nuStreamer - Lightweight and fast MJPEG-HTTP streamer"); SAY("═══════════════════════════════════════════════════"); diff --git a/src/ustreamer/options.h b/src/ustreamer/options.h index 611c414..60f69c9 100644 --- a/src/ustreamer/options.h +++ b/src/ustreamer/options.h @@ -22,23 +22,8 @@ #pragma once -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "../libs/const.h" -#include "../libs/logging.h" -#include "../libs/process.h" -#include "../libs/frame.h" +#include "../libs/types.h" #include "../libs/memsink.h" -#include "../libs/options.h" #include "../libs/capture.h" #ifdef WITH_V4P # include "../libs/drm/drm.h" @@ -47,13 +32,10 @@ #include "encoder.h" #include "stream.h" #include "http/server.h" -#ifdef WITH_GPIO -# include "gpio/gpio.h" -#endif typedef struct { - unsigned argc; + uint argc; char **argv; char **argv_copy; us_memsink_s *jpeg_sink; @@ -65,7 +47,12 @@ typedef struct { } us_options_s; -us_options_s *us_options_init(unsigned argc, char *argv[]); +us_options_s *us_options_init(uint argc, char *argv[]); void us_options_destroy(us_options_s *options); -int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, us_stream_s *stream, us_server_s *server); +int us_options_parse( + us_options_s *options, + us_capture_s *cap, + us_encoder_s *enc, + us_stream_s *stream, + us_server_s *server); diff --git a/src/ustreamer/stream.c b/src/ustreamer/stream.c index ab192cd..3201027 100644 --- a/src/ustreamer/stream.c +++ b/src/ustreamer/stream.c @@ -62,14 +62,14 @@ typedef struct { pthread_t tid; us_capture_s *cap; - us_queue_s *queue; + us_queue_s *q; pthread_mutex_t *mutex; atomic_bool *stop; } _releaser_context_s; typedef struct { pthread_t tid; - us_queue_s *queue; + us_queue_s *q; us_stream_s *stream; atomic_bool *stop; } _worker_context_s; @@ -83,7 +83,7 @@ static void *_h264_thread(void *v_ctx); static void *_drm_thread(void *v_ctx); #endif -static us_capture_hwbuf_s *_get_latest_hw(us_queue_s *queue); +static us_capture_hwbuf_s *_get_latest_hw(us_queue_s *q); static bool _stream_has_jpeg_clients_cached(us_stream_s *stream); static bool _stream_has_any_clients_cached(us_stream_s *stream); @@ -108,7 +108,7 @@ us_stream_s *us_stream_init(us_capture_s *cap, us_encoder_s *enc) { US_RING_INIT_WITH_ITEMS(http->jpeg_ring, 4, us_frame_init); atomic_init(&http->has_clients, false); atomic_init(&http->snapshot_requested, 0); - atomic_init(&http->last_request_ts, 0); + atomic_init(&http->last_req_ts, 0); http->captured_fpsi = us_fpsi_init("STREAM-CAPTURED", true); us_stream_runtime_s *run; @@ -154,7 +154,7 @@ void us_stream_loop(us_stream_s *stream) { us_stream_runtime_s *const run = stream->run; us_capture_s *const cap = stream->cap; - atomic_store(&run->http->last_request_ts, us_get_now_monotonic()); + atomic_store(&run->http->last_req_ts, us_get_now_monotonic()); if (stream->h264_sink != NULL) { run->h264_enc = us_m2m_h264_encoder_init( @@ -177,10 +177,10 @@ void us_stream_loop(us_stream_s *stream) { const uint n_releasers = cap->run->n_bufs; _releaser_context_s *releasers; US_CALLOC(releasers, n_releasers); - for (uint index = 0; index < n_releasers; ++index) { - _releaser_context_s *ctx = &releasers[index]; + for (uint i = 0; i < n_releasers; ++i) { + _releaser_context_s *ctx = &releasers[i]; ctx->cap = cap; - ctx->queue = us_queue_init(1); + ctx->q = us_queue_init(1); ctx->mutex = &release_mutex; ctx->stop = &threads_stop; US_THREAD_CREATE(ctx->tid, _releaser_thread, ctx); @@ -190,7 +190,7 @@ void us_stream_loop(us_stream_s *stream) { _worker_context_s *x_ctx = NULL; \ if (x_cond) { \ US_CALLOC(x_ctx, 1); \ - x_ctx->queue = us_queue_init(x_capacity); \ + x_ctx->q = us_queue_init(x_capacity); \ x_ctx->stream = stream; \ x_ctx->stop = &threads_stop; \ US_THREAD_CREATE(x_ctx->tid, (x_thread), x_ctx); \ @@ -222,7 +222,7 @@ void us_stream_loop(us_stream_s *stream) { # define QUEUE_HW(x_ctx) if (x_ctx != NULL) { \ us_capture_hwbuf_incref(hw); \ - us_queue_put(x_ctx->queue, hw, 0); \ + us_queue_put(x_ctx->q, hw, 0); \ } QUEUE_HW(jpeg_ctx); QUEUE_HW(raw_ctx); @@ -231,7 +231,7 @@ void us_stream_loop(us_stream_s *stream) { QUEUE_HW(drm_ctx); # endif # undef QUEUE_HW - us_queue_put(releasers[hw->buf.index].queue, hw, 0); // Plan to release + us_queue_put(releasers[hw->buf.index].q, hw, 0); // Plan to release // Мы не обновляем здесь состояние синков, потому что это происходит внутри обслуживающих их потоков _stream_check_suicide(stream); @@ -249,7 +249,7 @@ void us_stream_loop(us_stream_s *stream) { # define DELETE_WORKER(x_ctx) if (x_ctx != NULL) { \ US_THREAD_JOIN(x_ctx->tid); \ - us_queue_destroy(x_ctx->queue); \ + us_queue_destroy(x_ctx->q); \ free(x_ctx); \ } # ifdef WITH_V4P @@ -260,9 +260,9 @@ void us_stream_loop(us_stream_s *stream) { DELETE_WORKER(jpeg_ctx); # undef DELETE_WORKER - for (uint index = 0; index < n_releasers; ++index) { - US_THREAD_JOIN(releasers[index].tid); - us_queue_destroy(releasers[index].queue); + for (uint i = 0; i < n_releasers; ++i) { + US_THREAD_JOIN(releasers[i].tid); + us_queue_destroy(releasers[i].q); } free(releasers); US_MUTEX_DESTROY(release_mutex); @@ -292,7 +292,7 @@ static void *_releaser_thread(void *v_ctx) { while (!atomic_load(ctx->stop)) { us_capture_hwbuf_s *hw; - if (us_queue_get(ctx->queue, (void**)&hw, 0.1) < 0) { + if (us_queue_get(ctx->q, (void**)&hw, 0.1) < 0) { continue; } @@ -348,7 +348,7 @@ static void *_jpeg_thread(void *v_ctx) { } } - us_capture_hwbuf_s *hw = _get_latest_hw(ctx->queue); + us_capture_hwbuf_s *hw = _get_latest_hw(ctx->q); if (hw == NULL) { continue; } @@ -399,7 +399,7 @@ static void *_raw_thread(void *v_ctx) { _worker_context_s *ctx = v_ctx; while (!atomic_load(ctx->stop)) { - us_capture_hwbuf_s *hw = _get_latest_hw(ctx->queue); + us_capture_hwbuf_s *hw = _get_latest_hw(ctx->q); if (hw == NULL) { continue; } @@ -423,7 +423,7 @@ static void *_h264_thread(void *v_ctx) { uint step = 1; while (!atomic_load(ctx->stop)) { - us_capture_hwbuf_s *hw = _get_latest_hw(ctx->queue); + us_capture_hwbuf_s *hw = _get_latest_hw(ctx->q); if (hw == NULL) { continue; } @@ -472,7 +472,7 @@ static void *_drm_thread(void *v_ctx) { # define SLOWDOWN { \ const ldf m_next_ts = us_get_now_monotonic() + 1; \ while (!atomic_load(ctx->stop) && us_get_now_monotonic() < m_next_ts) { \ - us_capture_hwbuf_s *m_pass_hw = _get_latest_hw(ctx->queue); \ + us_capture_hwbuf_s *m_pass_hw = _get_latest_hw(ctx->q); \ if (m_pass_hw != NULL) { \ us_capture_hwbuf_decref(m_pass_hw); \ } \ @@ -485,7 +485,7 @@ static void *_drm_thread(void *v_ctx) { CHECK(us_drm_wait_for_vsync(stream->drm)); US_DELETE(prev_hw, us_capture_hwbuf_decref); - us_capture_hwbuf_s *hw = _get_latest_hw(ctx->queue); + us_capture_hwbuf_s *hw = _get_latest_hw(ctx->q); if (hw == NULL) { continue; } @@ -521,14 +521,14 @@ static void *_drm_thread(void *v_ctx) { } #endif -static us_capture_hwbuf_s *_get_latest_hw(us_queue_s *queue) { +static us_capture_hwbuf_s *_get_latest_hw(us_queue_s *q) { us_capture_hwbuf_s *hw; - if (us_queue_get(queue, (void**)&hw, 0.1) < 0) { + if (us_queue_get(q, (void**)&hw, 0.1) < 0) { return NULL; } - while (!us_queue_is_empty(queue)) { // Берем только самый свежий кадр + while (!us_queue_is_empty(q)) { // Берем только самый свежий кадр us_capture_hwbuf_decref(hw); - assert(!us_queue_get(queue, (void**)&hw, 0)); + assert(!us_queue_get(q, (void**)&hw, 0)); } return hw; } @@ -647,11 +647,11 @@ static int _stream_init_loop(us_stream_s *stream) { US_LOG_INFO("Device error, exiting ..."); us_process_suicide(); } - for (uint count = 0; count < stream->error_delay * 10; ++count) { + for (uint i = 0; i < stream->error_delay * 10; ++i) { if (atomic_load(&run->stop)) { break; } - if (count % 10 == 0) { + if (i % 10 == 0) { // Каждую секунду повторяем blank uint width = stream->cap->run->width; uint height = stream->cap->run->height; @@ -716,12 +716,14 @@ close: static void _stream_expose_jpeg(us_stream_s *stream, const us_frame_s *frame) { us_stream_runtime_s *const run = stream->run; + int ri; while ((ri = us_ring_producer_acquire(run->http->jpeg_ring, 0)) < 0) { if (atomic_load(&run->stop)) { return; } } + us_frame_s *const dest = run->http->jpeg_ring->items[ri]; us_frame_copy(frame, dest); us_ring_producer_release(run->http->jpeg_ring, ri); @@ -741,6 +743,7 @@ static void _stream_encode_expose_h264(us_stream_s *stream, const us_frame_s *fr if (stream->h264_sink == NULL) { return; } + us_stream_runtime_s *run = stream->run; us_fpsi_meta_s meta = {.online = false}; @@ -767,16 +770,16 @@ static void _stream_check_suicide(us_stream_s *stream) { if (stream->exit_on_no_clients == 0) { return; } - us_stream_runtime_s *const run = stream->run; + const atomic_ullong *last_req_ts = &stream->run->http->last_req_ts; const ldf now_ts = us_get_now_monotonic(); - const ull http_last_request_ts = atomic_load(&run->http->last_request_ts); // Seconds + if (_stream_has_any_clients_cached(stream)) { - atomic_store(&run->http->last_request_ts, now_ts); - } else if (http_last_request_ts + stream->exit_on_no_clients < now_ts) { + atomic_store(last_req_ts, now_ts); + } else if (atomic_load(last_req_ts) + stream->exit_on_no_clients < now_ts) { US_LOG_INFO("No requests or HTTP/sink clients found in last %u seconds, exiting ...", stream->exit_on_no_clients); + atomic_store(last_req_ts, now_ts); // Prevent a signal spam us_process_suicide(); - atomic_store(&run->http->last_request_ts, now_ts); } } diff --git a/src/ustreamer/stream.h b/src/ustreamer/stream.h index f8ac511..4629622 100644 --- a/src/ustreamer/stream.h +++ b/src/ustreamer/stream.h @@ -57,7 +57,7 @@ typedef struct { us_ring_s *jpeg_ring; atomic_bool has_clients; atomic_uint snapshot_requested; - atomic_ullong last_request_ts; // Seconds + atomic_ullong last_req_ts; // Seconds us_fpsi_s *captured_fpsi; } us_stream_http_s; diff --git a/src/ustreamer/workers.c b/src/ustreamer/workers.c index c5d4e70..5174a9d 100644 --- a/src/ustreamer/workers.c +++ b/src/ustreamer/workers.c @@ -37,11 +37,14 @@ static void *_worker_thread(void *v_worker); us_workers_pool_s *us_workers_pool_init( - const char *name, const char *wr_prefix, uint n_workers, - us_workers_pool_job_init_f job_init, void *job_init_arg, + const char *name, + const char *wr_prefix, + uint n_workers, + us_workers_pool_job_init_f job_init, + void *job_init_arg, us_workers_pool_job_destroy_f job_destroy, - us_workers_pool_run_job_f run_job) { - + us_workers_pool_run_job_f run_job +) { US_LOG_INFO("Creating pool %s with %u workers ...", name, n_workers); us_workers_pool_s *pool; @@ -57,12 +60,12 @@ us_workers_pool_s *us_workers_pool_init( US_MUTEX_INIT(pool->free_workers_mutex); US_COND_INIT(pool->free_workers_cond); - for (uint index = 0; index < pool->n_workers; ++index) { + for (uint i = 0; i < pool->n_workers; ++i) { us_worker_s *wr; US_CALLOC(wr, 1); - wr->number = index; - US_ASPRINTF(wr->name, "%s-%u", wr_prefix, index); + wr->number = i; + US_ASPRINTF(wr->name, "%s-%u", wr_prefix, i); US_MUTEX_INIT(wr->has_job_mutex); atomic_init(&wr->has_job, false); @@ -112,7 +115,10 @@ us_worker_s *us_workers_pool_wait(us_workers_pool_s *pool) { us_worker_s *found = NULL; US_LIST_ITERATE(pool->workers, wr, { // cppcheck-suppress constStatement - if (!atomic_load(&wr->has_job) && (found == NULL || found->job_start_ts <= wr->job_start_ts)) { + if ( + !atomic_load(&wr->has_job) + && (found == NULL || found->job_start_ts <= wr->job_start_ts) + ) { found = wr; } }); diff --git a/src/ustreamer/workers.h b/src/ustreamer/workers.h index 99f09c1..a856e23 100644 --- a/src/ustreamer/workers.h +++ b/src/ustreamer/workers.h @@ -75,8 +75,11 @@ typedef struct us_workers_pool_sx { us_workers_pool_s *us_workers_pool_init( - const char *name, const char *wr_prefix, uint n_workers, - us_workers_pool_job_init_f job_init, void *job_init_arg, + const char *name, + const char *wr_prefix, + uint n_workers, + us_workers_pool_job_init_f job_init, + void *job_init_arg, us_workers_pool_job_destroy_f job_destroy, us_workers_pool_run_job_f run_job); diff --git a/tools/make-ico-h.py b/tools/make-ico-h.py index 77b5474..18633b0 100755 --- a/tools/make-ico-h.py +++ b/tools/make-ico-h.py @@ -41,9 +41,9 @@ def main() -> None: data_text = "{\n\t" + ",\n\t".join( ", ".join( f"0x{ch:02X}" - for ch in data[index:index + 20] + for ch in data[i:i + 20] ) - for index in range(0, len(data), 20) + for i in range(0, len(data), 20) ) + ",\n}" text = f"{common.C_PREPEND}\n"