From 6687548ba90d053b87718654f1516efa000fe1c1 Mon Sep 17 00:00:00 2001 From: Devaev Maxim Date: Sat, 2 Jan 2021 06:12:44 +0300 Subject: [PATCH] refactoring --- src/libs/common/frame.c | 3 - src/libs/common/tools.h | 4 +- src/libs/h264/encoder.c | 16 ++-- src/libs/h264/unjpeg.c | 15 ++-- src/libs/memsink/memsink.c | 9 +- src/libs/memsink/memsink.h | 2 +- src/ustreamer/blank.c | 10 +-- src/ustreamer/device.c | 29 ++----- src/ustreamer/encoder.c | 3 +- src/ustreamer/encoders/cpu/encoder.c | 83 +++++++----------- src/ustreamer/encoders/hw/encoder.c | 5 +- src/ustreamer/encoders/omx/component.c | 8 +- src/ustreamer/encoders/omx/encoder.c | 13 ++- src/ustreamer/http/base64.c | 2 +- src/ustreamer/http/mime.c | 7 +- src/ustreamer/http/server.c | 113 +++++++++++++------------ src/ustreamer/http/static.c | 5 +- src/ustreamer/http/unix.c | 2 +- src/ustreamer/http/uri.c | 10 +-- src/ustreamer/main.c | 26 +++--- src/ustreamer/options.c | 31 +++---- src/ustreamer/options.h | 4 +- src/ustreamer/stream.c | 24 ++---- 23 files changed, 177 insertions(+), 247 deletions(-) diff --git a/src/libs/common/frame.c b/src/libs/common/frame.c index 6f22533..6ae2fc9 100644 --- a/src/libs/common/frame.c +++ b/src/libs/common/frame.c @@ -25,7 +25,6 @@ frame_s *frame_init(const char *role) { frame_s *frame; - A_CALLOC(frame, 1); frame->role = role; frame->managed = true; @@ -60,9 +59,7 @@ void frame_set_data(frame_s *frame, const uint8_t *data, size_t size) { void frame_append_data(frame_s *frame, const uint8_t *data, size_t size) { assert(frame->managed); - size_t new_used = frame->used + size; - frame_realloc_data(frame, new_used); memcpy(frame->data + frame->used, data, size); frame->used = new_used; diff --git a/src/libs/common/tools.h b/src/libs/common/tools.h index f394ee4..79e75a3 100644 --- a/src/libs/common/tools.h +++ b/src/libs/common/tools.h @@ -98,9 +98,7 @@ INLINE long double get_now_real(void) { } INLINE unsigned get_cores_available(void) { - long cores_sysconf; - - cores_sysconf = sysconf(_SC_NPROCESSORS_ONLN); + long cores_sysconf = sysconf(_SC_NPROCESSORS_ONLN); cores_sysconf = (cores_sysconf < 0 ? 0 : cores_sysconf); return max_u(min_u(cores_sysconf, 4), 1); } diff --git a/src/libs/h264/encoder.c b/src/libs/h264/encoder.c index f008231..5c85a0c 100644 --- a/src/libs/h264/encoder.c +++ b/src/libs/h264/encoder.c @@ -40,11 +40,10 @@ static const char *_mmal_error_to_string(MMAL_STATUS_T error); h264_encoder_s *h264_encoder_init(void) { h264_encoder_runtime_s *run; - h264_encoder_s *encoder; - A_CALLOC(run, 1); run->tmp = frame_init("h264_tmp"); + h264_encoder_s *encoder; A_CALLOC(encoder, 1); encoder->gop = 60; encoder->bps = 5000 * 1000; // Kbps * 1000 @@ -280,17 +279,13 @@ static void _h264_encoder_cleanup(h264_encoder_s *encoder) { } static int _h264_encoder_compress_raw(h264_encoder_s *encoder, const frame_s *src, frame_s *dest, bool force_key) { - MMAL_STATUS_T error; - MMAL_BUFFER_HEADER_T *out = NULL; - MMAL_BUFFER_HEADER_T *in = NULL; - bool eos = false; - bool sent = false; - assert(src->used > 0); assert(src->width == encoder->width); assert(src->height == encoder->height); assert(src->format == encoder->format); + MMAL_STATUS_T error; + LOG_DEBUG("Compressing new H264 frame; force_key=%d ...", force_key); frame_copy_meta(src, dest); @@ -309,6 +304,11 @@ static int _h264_encoder_compress_raw(h264_encoder_s *encoder, const frame_s *sr } } + MMAL_BUFFER_HEADER_T *out = NULL; + MMAL_BUFFER_HEADER_T *in = NULL; + bool eos = false; + bool sent = false; + while (!eos) { out = NULL; while (mmal_wrapper_buffer_get_empty(RUN(output_port), &out, 0) == MMAL_SUCCESS) { diff --git a/src/libs/h264/unjpeg.c b/src/libs/h264/unjpeg.c index b975071..163070f 100644 --- a/src/libs/h264/unjpeg.c +++ b/src/libs/h264/unjpeg.c @@ -33,20 +33,19 @@ static void _jpeg_error_handler(j_common_ptr jpeg); int unjpeg(const frame_s *src, frame_s *dest) { - struct jpeg_decompress_struct jpeg; - _jpeg_error_manager_s jpeg_error; - JSAMPARRAY scanlines; - unsigned row_stride; volatile int retval = 0; + struct jpeg_decompress_struct jpeg; + jpeg_create_decompress(&jpeg); + frame_realloc_data(dest, ((src->width * src->height) << 1) * 2); frame_copy_meta(src, dest); dest->format = V4L2_PIX_FMT_RGB24; dest->used = 0; - jpeg_create_decompress(&jpeg); - // https://stackoverflow.com/questions/19857766/error-handling-in-libjpeg + + _jpeg_error_manager_s jpeg_error; jpeg.err = jpeg_std_error((struct jpeg_error_mgr *)&jpeg_error); jpeg_error.mgr.error_exit = _jpeg_error_handler; if (setjmp(jpeg_error.jmp) < 0) { @@ -59,7 +58,9 @@ int unjpeg(const frame_s *src, frame_s *dest) { jpeg.out_color_space = JCS_RGB; jpeg_start_decompress(&jpeg); - row_stride = jpeg.output_width * jpeg.output_components; + const unsigned row_stride = jpeg.output_width * jpeg.output_components; + + JSAMPARRAY scanlines; scanlines = (*jpeg.mem->alloc_sarray)((j_common_ptr) &jpeg, JPOOL_IMAGE, row_stride, 1); while (jpeg.output_scanline < jpeg.output_height) { diff --git a/src/libs/memsink/memsink.c b/src/libs/memsink/memsink.c index 79d969c..28fe522 100644 --- a/src/libs/memsink/memsink.c +++ b/src/libs/memsink/memsink.c @@ -29,8 +29,6 @@ static int _flock_timedwait_monotonic(int fd, long double timeout); memsink_s *memsink_open(const char *role, const char *name, bool server, mode_t mode, bool rm, unsigned timeout) { memsink_s *memsink; - int flags = (server ? O_RDWR | O_CREAT : O_RDWR); - A_CALLOC(memsink, 1); memsink->role = role; memsink->server = server; @@ -48,6 +46,7 @@ memsink_s *memsink_open(const char *role, const char *name, bool server, mode_t LOG_INFO("Using %s sink: %s.{mem,sig}", role, name); + const int flags = (server ? O_RDWR | O_CREAT : O_RDWR); # define OPEN_SIGNAL { \ if ((memsink->sig_sem = sem_open(memsink->sig_name, flags, mode, 0)) == SEM_FAILED) { \ LOG_PERROR("Can't open %s sink signal semaphore", role); \ @@ -130,11 +129,11 @@ void memsink_close(memsink_s *memsink) { free(memsink); } -int memsink_server_put(memsink_s *memsink, frame_s *frame) { - long double now = get_now_monotonic(); - +int memsink_server_put(memsink_s *memsink, const frame_s *frame) { assert(memsink->server); + const long double now = get_now_monotonic(); + if (frame->used > MEMSINK_MAX_DATA) { LOG_ERROR("%s sink: Can't put frame: is too big (%zu > %zu)", memsink->role, frame->used, MEMSINK_MAX_DATA); diff --git a/src/libs/memsink/memsink.h b/src/libs/memsink/memsink.h index 5f0fc35..7493041 100644 --- a/src/libs/memsink/memsink.h +++ b/src/libs/memsink/memsink.h @@ -76,5 +76,5 @@ typedef struct { memsink_s *memsink_open(const char *role, const char *name, bool server, mode_t mode, bool rm, unsigned timeout); void memsink_close(memsink_s *memsink); -int memsink_server_put(memsink_s *memsink, frame_s *frame); +int memsink_server_put(memsink_s *memsink, const frame_s *frame); int memsink_client_get(memsink_s *memsink, frame_s *frame); diff --git a/src/ustreamer/blank.c b/src/ustreamer/blank.c index ade7dd0..da8d60e 100644 --- a/src/ustreamer/blank.c +++ b/src/ustreamer/blank.c @@ -53,9 +53,7 @@ frame_s *blank_frame_init(const char *path) { } static frame_s *_init_internal(void) { - frame_s *blank; - - blank = frame_init("blank_internal"); + frame_s *blank = frame_init("blank_internal"); frame_set_data(blank, BLANK_JPEG_DATA, BLANK_JPEG_DATA_SIZE); blank->width = BLANK_JPEG_WIDTH; blank->height = BLANK_JPEG_HEIGHT; @@ -65,9 +63,8 @@ static frame_s *_init_internal(void) { static frame_s *_init_external(const char *path) { FILE *fp = NULL; - frame_s *blank; - blank = frame_init("blank_external"); + frame_s *blank = frame_init("blank_external"); blank->format = V4L2_PIX_FMT_JPEG; if ((fp = fopen(path, "rb")) == NULL) { @@ -118,11 +115,10 @@ static frame_s *_init_external(const char *path) { static int _jpeg_read_geometry(FILE *fp, unsigned *width, unsigned *height) { struct jpeg_decompress_struct jpeg; - _jpeg_error_manager_s jpeg_error; - jpeg_create_decompress(&jpeg); // https://stackoverflow.com/questions/19857766/error-handling-in-libjpeg + _jpeg_error_manager_s jpeg_error; jpeg.err = jpeg_std_error((struct jpeg_error_mgr *)&jpeg_error); jpeg_error.mgr.error_exit = _jpeg_error_handler; if (setjmp(jpeg_error.jmp) < 0) { diff --git a/src/ustreamer/device.c b/src/ustreamer/device.c index 2887bd1..54beed2 100644 --- a/src/ustreamer/device.c +++ b/src/ustreamer/device.c @@ -84,11 +84,10 @@ static const char *_io_method_to_string_supported(enum v4l2_memory io_method); device_s *device_init(void) { device_runtime_s *run; - device_s *dev; - A_CALLOC(run, 1); run->fd = -1; + device_s *dev; A_CALLOC(dev, 1); dev->path = "/dev/video0"; dev->width = 640; @@ -226,7 +225,6 @@ int device_switch_capturing(device_s *dev, bool enable) { } int device_select(device_s *dev, bool *has_read, bool *has_write, bool *has_error) { - struct timeval timeout; int retval; # define INIT_FD_SET(_set) \ @@ -238,6 +236,7 @@ int device_select(device_s *dev, bool *has_read, bool *has_write, bool *has_erro # undef INIT_FD_SET + struct timeval timeout; timeout.tv_sec = dev->timeout; timeout.tv_usec = 0; @@ -273,7 +272,6 @@ int device_select(device_s *dev, bool *has_read, bool *has_write, bool *has_erro int device_grab_buffer(device_s *dev) { struct v4l2_buffer buf_info; - MEMSET_ZERO(buf_info); buf_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf_info.memory = dev->io_method; @@ -371,8 +369,6 @@ int device_consume_event(device_s *dev) { static int _device_open_check_cap(device_s *dev) { struct v4l2_capability cap; - int input = dev->input; // Needs pointer to int for ioctl() - MEMSET_ZERO(cap); LOG_DEBUG("Calling ioctl(VIDIOC_QUERYCAP) ..."); @@ -391,6 +387,7 @@ static int _device_open_check_cap(device_s *dev) { return -1; } + int input = dev->input; // Needs a pointer to int for ioctl() LOG_INFO("Using input channel: %d", input); if (xioctl(RUN(fd), VIDIOC_S_INPUT, &input) < 0) { LOG_ERROR("Can't set input channel"); @@ -434,7 +431,6 @@ static int _device_open_dv_timings(device_s *dev) { static int _device_apply_dv_timings(device_s *dev) { struct v4l2_dv_timings dv; - MEMSET_ZERO(dv); LOG_DEBUG("Calling ioctl(VIDIOC_QUERY_DV_TIMINGS) ..."); @@ -467,7 +463,6 @@ static int _device_apply_dv_timings(device_s *dev) { static int _device_open_format(device_s *dev) { struct v4l2_format fmt; - MEMSET_ZERO(fmt); fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; fmt.fmt.pix.width = RUN(width); @@ -518,10 +513,9 @@ static int _device_open_format(device_s *dev) { } static void _device_open_hw_fps(device_s *dev) { - struct v4l2_streamparm setfps; - RUN(hw_fps) = 0; + struct v4l2_streamparm setfps; MEMSET_ZERO(setfps); setfps.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -584,7 +578,6 @@ static int _device_open_io_method(device_s *dev) { static int _device_open_io_method_mmap(device_s *dev) { struct v4l2_requestbuffers req; - MEMSET_ZERO(req); req.count = dev->n_buffers; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -608,7 +601,6 @@ static int _device_open_io_method_mmap(device_s *dev) { A_CALLOC(RUN(hw_buffers), req.count); for (RUN(n_buffers) = 0; RUN(n_buffers) < req.count; ++RUN(n_buffers)) { struct v4l2_buffer buf_info; - MEMSET_ZERO(buf_info); buf_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf_info.memory = V4L2_MEMORY_MMAP; @@ -645,9 +637,6 @@ static int _device_open_io_method_mmap(device_s *dev) { static int _device_open_io_method_userptr(device_s *dev) { struct v4l2_requestbuffers req; - unsigned page_size = getpagesize(); - unsigned buf_size = align_size(RUN(raw_size), page_size); - MEMSET_ZERO(req); req.count = dev->n_buffers; req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; @@ -669,13 +658,15 @@ static int _device_open_io_method_userptr(device_s *dev) { LOG_DEBUG("Allocating device buffers ..."); A_CALLOC(RUN(hw_buffers), req.count); + + const unsigned page_size = getpagesize(); + const unsigned buf_size = align_size(RUN(raw_size), page_size); + for (RUN(n_buffers) = 0; RUN(n_buffers) < req.count; ++RUN(n_buffers)) { # define HW(_next) RUN(hw_buffers)[RUN(n_buffers)]._next - assert(HW(raw.data) = aligned_alloc(page_size, buf_size)); memset(HW(raw.data), 0, buf_size); HW(raw.allocated) = buf_size; - # undef HW } return 0; @@ -684,7 +675,6 @@ static int _device_open_io_method_userptr(device_s *dev) { static int _device_open_queue_buffers(device_s *dev) { for (unsigned index = 0; index < RUN(n_buffers); ++index) { struct v4l2_buffer buf_info; - MEMSET_ZERO(buf_info); buf_info.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; buf_info.memory = dev->io_method; @@ -795,8 +785,6 @@ static void _device_set_control( device_s *dev, struct v4l2_queryctrl *query, const char *name, unsigned cid, int value, bool quiet) { - struct v4l2_control ctl; - 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", @@ -805,6 +793,7 @@ static void _device_set_control( return; } + struct v4l2_control ctl; MEMSET_ZERO(ctl); ctl.id = cid; ctl.value = value; diff --git a/src/ustreamer/encoder.c b/src/ustreamer/encoder.c index ddfa1a8..6913e6a 100644 --- a/src/ustreamer/encoder.c +++ b/src/ustreamer/encoder.c @@ -44,13 +44,12 @@ static const struct { encoder_s *encoder_init(void) { encoder_runtime_s *run; - encoder_s *encoder; - A_CALLOC(run, 1); run->type = ENCODER_TYPE_CPU; run->quality = 80; A_MUTEX_INIT(&run->mutex); + encoder_s *encoder; A_CALLOC(encoder, 1); encoder->type = run->type; encoder->quality = run->quality; diff --git a/src/ustreamer/encoders/cpu/encoder.c b/src/ustreamer/encoders/cpu/encoder.c index e7855f0..c122a59 100644 --- a/src/ustreamer/encoders/cpu/encoder.c +++ b/src/ustreamer/encoders/cpu/encoder.c @@ -37,21 +37,10 @@ typedef struct { static void _jpeg_set_dest_frame(j_compress_ptr jpeg, frame_s *frame); -static void _jpeg_write_scanlines_yuyv( - struct jpeg_compress_struct *jpeg, const uint8_t *data, - unsigned width, unsigned height); - -static void _jpeg_write_scanlines_uyvy( - struct jpeg_compress_struct *jpeg, const uint8_t *data, - unsigned width, unsigned height); - -static void _jpeg_write_scanlines_rgb565( - struct jpeg_compress_struct *jpeg, const uint8_t *data, - unsigned width, unsigned height); - -static void _jpeg_write_scanlines_rgb24( - struct jpeg_compress_struct *jpeg, const uint8_t *data, - unsigned width, unsigned height); +static void _jpeg_write_scanlines_yuyv(struct jpeg_compress_struct *jpeg, const frame_s *frame); +static void _jpeg_write_scanlines_uyvy(struct jpeg_compress_struct *jpeg, const frame_s *frame); +static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, const frame_s *frame); +static void _jpeg_write_scanlines_rgb24(struct jpeg_compress_struct *jpeg, const frame_s *frame); static void _jpeg_init_destination(j_compress_ptr jpeg); static boolean _jpeg_empty_output_buffer(j_compress_ptr jpeg); @@ -80,7 +69,7 @@ void cpu_encoder_compress(frame_s *src, frame_s *dest, unsigned quality) { jpeg_start_compress(&jpeg, TRUE); # define WRITE_SCANLINES(_format, _func) \ - case _format: { _func(&jpeg, src->data, src->width, src->height); break; } + case _format: { _func(&jpeg, src); break; } switch (src->format) { // https://www.fourcc.org/yuv.php @@ -100,15 +89,13 @@ void cpu_encoder_compress(frame_s *src, frame_s *dest, unsigned quality) { } static void _jpeg_set_dest_frame(j_compress_ptr jpeg, frame_s *frame) { - _jpeg_dest_manager_s *dest; - if (jpeg->dest == NULL) { assert((jpeg->dest = (struct jpeg_destination_mgr *)(*jpeg->mem->alloc_small)( (j_common_ptr) jpeg, JPOOL_PERMANENT, sizeof(_jpeg_dest_manager_s) ))); } - dest = (_jpeg_dest_manager_s *)jpeg->dest; + _jpeg_dest_manager_s *dest = (_jpeg_dest_manager_s *)jpeg->dest; dest->mgr.init_destination = _jpeg_init_destination; dest->mgr.empty_output_buffer = _jpeg_empty_output_buffer; dest->mgr.term_destination = _jpeg_term_destination; @@ -122,20 +109,17 @@ static void _jpeg_set_dest_frame(j_compress_ptr jpeg, frame_s *frame) { #define YUV_B(_y, _u, _) (((_y) + (454 * (_u))) >> 8) #define NORM_COMPONENT(_x) (((_x) > 255) ? 255 : (((_x) < 0) ? 0 : (_x))) -static void _jpeg_write_scanlines_yuyv( - struct jpeg_compress_struct *jpeg, const uint8_t *data, - unsigned width, unsigned height) { - +static void _jpeg_write_scanlines_yuyv(struct jpeg_compress_struct *jpeg, const frame_s *frame) { uint8_t *line_buffer; - JSAMPROW scanlines[1]; + A_CALLOC(line_buffer, frame->width * 3); + + const uint8_t *data = frame->data; unsigned z = 0; - A_CALLOC(line_buffer, width * 3); - - while (jpeg->next_scanline < height) { + while (jpeg->next_scanline < frame->height) { uint8_t *ptr = line_buffer; - for (unsigned x = 0; x < width; ++x) { + for (unsigned x = 0; x < frame->width; ++x) { int y = (!z ? data[0] << 8 : data[2] << 8); int u = data[1] - 128; int v = data[3] - 128; @@ -154,6 +138,7 @@ static void _jpeg_write_scanlines_yuyv( } } + JSAMPROW scanlines[1]; scanlines[0] = line_buffer; jpeg_write_scanlines(jpeg, scanlines, 1); } @@ -161,20 +146,17 @@ static void _jpeg_write_scanlines_yuyv( free(line_buffer); } -static void _jpeg_write_scanlines_uyvy( - struct jpeg_compress_struct *jpeg, const uint8_t *data, - unsigned width, unsigned height) { - +static void _jpeg_write_scanlines_uyvy(struct jpeg_compress_struct *jpeg, const frame_s *frame) { uint8_t *line_buffer; - JSAMPROW scanlines[1]; + A_CALLOC(line_buffer, frame->width * 3); + + const uint8_t *data = frame->data; unsigned z = 0; - A_CALLOC(line_buffer, width * 3); - - while (jpeg->next_scanline < height) { + while (jpeg->next_scanline < frame->height) { uint8_t *ptr = line_buffer; - for(unsigned x = 0; x < width; ++x) { + for(unsigned x = 0; x < frame->width; ++x) { int y = (!z ? data[1] << 8 : data[3] << 8); int u = data[0] - 128; int v = data[2] - 128; @@ -193,6 +175,7 @@ static void _jpeg_write_scanlines_uyvy( } } + JSAMPROW scanlines[1]; scanlines[0] = line_buffer; jpeg_write_scanlines(jpeg, scanlines, 1); } @@ -205,19 +188,16 @@ static void _jpeg_write_scanlines_uyvy( #undef YUV_G #undef YUV_R -static void _jpeg_write_scanlines_rgb565( - struct jpeg_compress_struct *jpeg, const uint8_t *data, - unsigned width, unsigned height) { - +static void _jpeg_write_scanlines_rgb565(struct jpeg_compress_struct *jpeg, const frame_s *frame) { uint8_t *line_buffer; - JSAMPROW scanlines[1]; + A_CALLOC(line_buffer, frame->width * 3); - A_CALLOC(line_buffer, width * 3); + const uint8_t *data = frame->data; - while (jpeg->next_scanline < height) { + while (jpeg->next_scanline < frame->height) { uint8_t *ptr = line_buffer; - for(unsigned x = 0; x < width; ++x) { + for(unsigned x = 0; x < frame->width; ++x) { unsigned int two_byte = (data[1] << 8) + data[0]; *(ptr++) = data[1] & 248; // Red @@ -227,6 +207,7 @@ static void _jpeg_write_scanlines_rgb565( data += 2; } + JSAMPROW scanlines[1]; scanlines[0] = line_buffer; jpeg_write_scanlines(jpeg, scanlines, 1); } @@ -234,14 +215,10 @@ static void _jpeg_write_scanlines_rgb565( free(line_buffer); } -static void _jpeg_write_scanlines_rgb24( - struct jpeg_compress_struct *jpeg, const uint8_t *data, - unsigned width, unsigned height) { - - JSAMPROW scanlines[1]; - - while (jpeg->next_scanline < height) { - scanlines[0] = (uint8_t *)(data + jpeg->next_scanline * width * 3); +static void _jpeg_write_scanlines_rgb24(struct jpeg_compress_struct *jpeg, const frame_s *frame) { + while (jpeg->next_scanline < frame->height) { + JSAMPROW scanlines[1]; + scanlines[0] = (uint8_t *)(frame->data + jpeg->next_scanline * frame->width * 3); jpeg_write_scanlines(jpeg, scanlines, 1); } } diff --git a/src/ustreamer/encoders/hw/encoder.c b/src/ustreamer/encoders/hw/encoder.c index f107f85..014198a 100644 --- a/src/ustreamer/encoders/hw/encoder.c +++ b/src/ustreamer/encoders/hw/encoder.c @@ -34,7 +34,6 @@ static bool _is_huffman(const uint8_t *data); int hw_encoder_prepare(device_s *dev, unsigned quality) { struct v4l2_jpegcompression comp; - MEMSET_ZERO(comp); if (xioctl(dev->run->fd, VIDIOC_G_JPEGCOMP, &comp) < 0) { @@ -60,7 +59,6 @@ void _copy_plus_huffman(const frame_s *src, frame_s *dest) { if (!_is_huffman(src->data)) { const uint8_t *src_ptr = src->data; const uint8_t *src_end = src->data + src->used; - size_t paste; while ((((src_ptr[0] << 8) | src_ptr[1]) != 0xFFC0) && (src_ptr < src_end)) { src_ptr += 1; @@ -69,7 +67,8 @@ void _copy_plus_huffman(const frame_s *src, frame_s *dest) { dest->used = 0; // Error return; } - paste = src_ptr - src->data; + + const size_t paste = src_ptr - src->data; frame_set_data(dest, src->data, paste); frame_append_data(dest, HUFFMAN_TABLE, sizeof(HUFFMAN_TABLE)); diff --git a/src/ustreamer/encoders/omx/component.c b/src/ustreamer/encoders/omx/component.c index 87fa128..01a9282 100644 --- a/src/ustreamer/encoders/omx/component.c +++ b/src/ustreamer/encoders/omx/component.c @@ -78,10 +78,10 @@ int component_set_portdef(OMX_HANDLETYPE *component, OMX_PARAM_PORTDEFINITIONTYP int component_set_state(OMX_HANDLETYPE *component, OMX_STATETYPE state) { const char *state_str = omx_state_to_string(state); OMX_ERRORTYPE error; - int retries = 50; LOG_DEBUG("Switching component state to %s ...", state_str); + int retries = 50; do { error = OMX_SendCommand(*component, OMX_CommandStateSet, state, NULL); if (error == OMX_ErrorNone) { @@ -103,12 +103,12 @@ int component_set_state(OMX_HANDLETYPE *component, OMX_STATETYPE state) { static int _component_wait_port_changed(OMX_HANDLETYPE *component, OMX_U32 port, OMX_BOOL enabled) { OMX_ERRORTYPE error; - OMX_PARAM_PORTDEFINITIONTYPE portdef; - int retries = 50; + OMX_PARAM_PORTDEFINITIONTYPE portdef; OMX_INIT_STRUCTURE(portdef); portdef.nPortIndex = port; + int retries = 50; do { if ((error = OMX_GetParameter(*component, OMX_IndexParamPortDefinition, &portdef)) != OMX_ErrorNone) { LOG_ERROR_OMX(error, "Can't get OMX port %u definition for waiting", port); @@ -129,8 +129,8 @@ static int _component_wait_port_changed(OMX_HANDLETYPE *component, OMX_U32 port, static int _component_wait_state_changed(OMX_HANDLETYPE *component, OMX_STATETYPE wanted) { OMX_ERRORTYPE error; OMX_STATETYPE state; - int retries = 50; + int retries = 50; do { if ((error = OMX_GetState(*component, &state)) != OMX_ErrorNone) { LOG_ERROR_OMX(error, "Failed to get OMX component state"); diff --git a/src/ustreamer/encoders/omx/encoder.c b/src/ustreamer/encoders/omx/encoder.c index 0cfc926..ef875de 100644 --- a/src/ustreamer/encoders/omx/encoder.c +++ b/src/ustreamer/encoders/omx/encoder.c @@ -63,8 +63,6 @@ omx_encoder_s *omx_encoder_init(void) { // - http://home.nouwen.name/RaspberryPi/documentation/ilcomponents/image_encode.html omx_encoder_s *omx; - OMX_ERRORTYPE error; - A_CALLOC(omx, 1); assert(_i_omx >= 0); @@ -73,7 +71,7 @@ omx_encoder_s *omx_encoder_init(void) { bcm_host_init(); LOG_INFO("Initializing OMX ..."); - if ((error = OMX_Init()) != OMX_ErrorNone) { + if ((OMX_ERRORTYPE error = OMX_Init()) != OMX_ErrorNone) { LOG_ERROR_OMX(error, "Can't initialize OMX"); goto error; } @@ -104,8 +102,6 @@ omx_encoder_s *omx_encoder_init(void) { } void omx_encoder_destroy(omx_encoder_s *omx) { - OMX_ERRORTYPE error; - LOG_INFO("Destroying OMX encoder ..."); component_set_state(&omx->encoder, OMX_StateIdle); @@ -117,7 +113,7 @@ void omx_encoder_destroy(omx_encoder_s *omx) { } if (omx->i_encoder) { - if ((error = OMX_FreeHandle(omx->encoder)) != OMX_ErrorNone) { + if ((OMX_ERRORTYPE error = OMX_FreeHandle(omx->encoder)) != OMX_ErrorNone) { LOG_ERROR_OMX(error, "Can't free OMX.broadcom.image_encode"); } } @@ -159,8 +155,6 @@ int omx_encoder_compress(omx_encoder_s *omx, frame_s *src, frame_s *dest) { # define OUT(_next) omx->output_buffer->_next OMX_ERRORTYPE error; - size_t slice_size = (IN(nAllocLen) < src->used ? IN(nAllocLen) : src->used); - size_t pos = 0; if ((error = OMX_FillThisBuffer(omx->encoder, omx->output_buffer)) != OMX_ErrorNone) { LOG_ERROR_OMX(error, "Failed to request filling of the output buffer on encoder"); @@ -171,6 +165,9 @@ int omx_encoder_compress(omx_encoder_s *omx, frame_s *src, frame_s *dest) { omx->output_available = false; omx->input_required = true; + const size_t slice_size = (IN(nAllocLen) < src->used ? IN(nAllocLen) : src->used); + size_t pos = 0; + while (true) { if (omx->failed) { return -1; diff --git a/src/ustreamer/http/base64.c b/src/ustreamer/http/base64.c index 49ad5d0..6b13aa2 100644 --- a/src/ustreamer/http/base64.c +++ b/src/ustreamer/http/base64.c @@ -40,8 +40,8 @@ static const unsigned _MOD_TABLE[] = {0, 2, 1}; char *base64_encode(const uint8_t *str) { size_t str_len = strlen((const char *)str); size_t encoded_size = 4 * ((str_len + 2) / 3) + 1; // +1 for '\0' - char *encoded; + char *encoded; A_CALLOC(encoded, encoded_size); for (unsigned str_index = 0, encoded_index = 0; str_index < str_len;) { diff --git a/src/ustreamer/http/mime.c b/src/ustreamer/http/mime.c index ad2f2e4..ab321d6 100644 --- a/src/ustreamer/http/mime.c +++ b/src/ustreamer/http/mime.c @@ -47,16 +47,13 @@ static const struct { const char *guess_mime_type(const char *path) { - char *dot; - char *ext; - // FIXME: false-positive cppcheck - dot = strrchr(path, '.'); // cppcheck-suppress ctunullpointer + char *dot = strrchr(path, '.'); // cppcheck-suppress ctunullpointer if (dot == NULL || strchr(dot, '/') != NULL) { goto misc; } - ext = dot + 1; + char *ext = dot + 1; for (unsigned index = 0; index < ARRAY_LEN(_MIME_TYPES); ++index) { if (!evutil_ascii_strcasecmp(ext, _MIME_TYPES[index].ext)) { return _MIME_TYPES[index].mime; diff --git a/src/ustreamer/http/server.c b/src/ustreamer/http/server.c index 58d9f6a..e8dcfdd 100644 --- a/src/ustreamer/http/server.c +++ b/src/ustreamer/http/server.c @@ -48,17 +48,16 @@ static void _format_bufferevent_reason(short what, char *reason); server_s *server_init(stream_s *stream) { - server_runtime_s *run; - server_s *server; exposed_s *exposed; - A_CALLOC(exposed, 1); exposed->frame = frame_init("http_exposed"); + server_runtime_s *run; A_CALLOC(run, 1); run->stream = stream; run->exposed = exposed; + server_s *server; A_CALLOC(server, 1); server->host = "127.0.0.1"; server->port = 8080; @@ -95,7 +94,6 @@ void server_destroy(server_s *server) { for (stream_client_s *client = RUN(stream_clients); client != NULL;) { stream_client_s *next = client->next; - free(client->key); free(client); client = next; @@ -233,20 +231,19 @@ static int _http_preprocess_request(struct evhttp_request *request, server_s *se static void _http_callback_root(struct evhttp_request *request, void *v_server) { server_s *server = (server_s *)v_server; - struct evbuffer *buf; - struct evkeyvalq params; // For mjpg-streamer compatibility - const char *action; // Ditto PREPROCESS_REQUEST; + struct evkeyvalq params; // For mjpg-streamer compatibility evhttp_parse_query(evhttp_request_get_uri(request), ¶ms); - action = evhttp_find_header(¶ms, "action"); + const char *action = evhttp_find_header(¶ms, "action"); if (action && !strcmp(action, "snapshot")) { _http_callback_snapshot(request, v_server); } else if (action && !strcmp(action, "stream")) { _http_callback_stream(request, v_server); } else { + struct evbuffer *buf; assert((buf = evbuffer_new())); assert(evbuffer_add_printf(buf, "%s", HTML_INDEX_PAGE)); ADD_HEADER("Content-Type", "text/html"); @@ -261,23 +258,25 @@ static void _http_callback_static(struct evhttp_request *request, void *v_server server_s *server = (server_s *)v_server; struct evbuffer *buf = NULL; struct evhttp_uri *uri = NULL; - char *uri_path; char *decoded_path = NULL; char *static_path = NULL; int fd = -1; - struct stat st; PREPROCESS_REQUEST; - if ((uri = evhttp_uri_parse(evhttp_request_get_uri(request))) == NULL) { - goto bad_request; - } - if ((uri_path = (char *)evhttp_uri_get_path(uri)) == NULL) { - uri_path = "/"; - } + { + char *uri_path; - if ((decoded_path = evhttp_uridecode(uri_path, 0, NULL)) == NULL) { - goto bad_request; + if ((uri = evhttp_uri_parse(evhttp_request_get_uri(request))) == NULL) { + goto bad_request; + } + if ((uri_path = (char *)evhttp_uri_get_path(uri)) == NULL) { + uri_path = "/"; + } + + if ((decoded_path = evhttp_uridecode(uri_path, 0, NULL)) == NULL) { + goto bad_request; + } } assert((buf = evbuffer_new())); @@ -291,18 +290,22 @@ static void _http_callback_static(struct evhttp_request *request, void *v_server goto not_found; } - if (fstat(fd, &st) < 0) { - LOG_PERROR("HTTP: Can't stat() found static file %s", static_path); - goto not_found; - } + { + struct stat st; - if (st.st_size > 0 && evbuffer_add_file(buf, fd, 0, st.st_size) < 0) { - LOG_ERROR("HTTP: Can't serve static file %s", static_path); - goto not_found; + if (fstat(fd, &st) < 0) { + LOG_PERROR("HTTP: Can't stat() found static file %s", static_path); + goto not_found; + } + if (st.st_size > 0 && evbuffer_add_file(buf, fd, 0, st.st_size) < 0) { + LOG_ERROR("HTTP: Can't serve static file %s", static_path); + goto not_found; + } + + ADD_HEADER("Content-Type", guess_mime_type(static_path)); + evhttp_send_reply(request, HTTP_OK, "OK", buf); + goto cleanup; } - ADD_HEADER("Content-Type", guess_mime_type(static_path)); - evhttp_send_reply(request, HTTP_OK, "OK", buf); - goto cleanup; bad_request: evhttp_send_error(request, HTTP_BADREQUEST, NULL); @@ -332,14 +335,14 @@ static void _http_callback_static(struct evhttp_request *request, void *v_server static void _http_callback_state(struct evhttp_request *request, void *v_server) { server_s *server = (server_s *)v_server; - struct evbuffer *buf; - encoder_type_e encoder_type; - unsigned encoder_quality; PREPROCESS_REQUEST; + encoder_type_e encoder_type; + unsigned encoder_quality; encoder_get_runtime_params(STREAM(encoder), &encoder_type, &encoder_quality); + struct evbuffer *buf; assert((buf = evbuffer_new())); assert(evbuffer_add_printf(buf, @@ -380,11 +383,10 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server) static void _http_callback_snapshot(struct evhttp_request *request, void *v_server) { server_s *server = (server_s *)v_server; - struct evbuffer *buf; - char header_buf[64]; PREPROCESS_REQUEST; + struct evbuffer *buf; assert((buf = evbuffer_new())); assert(!evbuffer_add(buf, (const void *)EX(frame->data), EX(frame->used))); @@ -395,6 +397,8 @@ static void _http_callback_snapshot(struct evhttp_request *request, void *v_serv ADD_HEADER("Pragma", "no-cache"); ADD_HEADER("Expires", "Mon, 3 Jan 2000 12:34:56 GMT"); + char header_buf[256]; + # define ADD_TIME_HEADER(_key, _value) { \ sprintf(header_buf, "%.06Lf", _value); \ ADD_HEADER(_key, header_buf); \ @@ -438,24 +442,21 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server // https://github.com/libevent/libevent/blob/29cc8386a2f7911eaa9336692a2c5544d8b4734f/http.c#L1458 server_s *server = (server_s *)v_server; - struct evhttp_connection *conn; - struct evkeyvalq params; - struct bufferevent *buf_event; - stream_client_s *client; - char *client_addr; - unsigned short client_port; - uuid_t uuid; PREPROCESS_REQUEST; + struct evhttp_connection *conn; conn = evhttp_request_get_connection(request); + if (conn) { + stream_client_s *client; A_CALLOC(client, 1); client->server = server; client->request = request; client->need_initial = true; client->need_first_frame = true; + struct evkeyvalq params; evhttp_parse_query(evhttp_request_get_uri(request), ¶ms); client->key = uri_get_string(¶ms, "key"); client->extra_headers = uri_get_true(¶ms, "extra_headers"); @@ -463,6 +464,7 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server client->dual_final_frames = uri_get_true(¶ms, "dual_final_frames"); evhttp_clear_headers(¶ms); + uuid_t uuid; uuid_generate(uuid); uuid_unparse_lower(uuid, client->id); @@ -487,11 +489,15 @@ static void _http_callback_stream(struct evhttp_request *request, void *v_server # endif } + char *client_addr; + unsigned short client_port; evhttp_connection_get_peer(conn, &client_addr, &client_port); + LOG_INFO("HTTP: Registered client: [%s]:%u, id=%s; clients now: %u", client_addr, client_port, client->id, RUN(stream_clients_count)); - buf_event = evhttp_connection_get_bufferevent(conn); + + struct bufferevent *buf_event = evhttp_connection_get_bufferevent(conn); if (server->tcp_nodelay && !RUN(unix_fd)) { evutil_socket_t fd; int on = 1; @@ -517,7 +523,7 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c stream_client_s *client = (stream_client_s *)v_client; server_s *server = client->server; - struct evbuffer *buf; + long double now = get_now_monotonic(); long long now_second = floor_ms(now); @@ -528,6 +534,7 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c } client->fps_accum += 1; + struct evbuffer *buf; assert((buf = evbuffer_new())); // В хроме и его производных есть фундаментальный баг: он отрисовывает @@ -640,11 +647,8 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UNUSED short what, void *v_client) { stream_client_s *client = (stream_client_s *)v_client; server_s *server = client->server; - struct evhttp_connection *conn; - char *client_addr = "???"; - unsigned short client_port = 0; - char reason[2048] = {0}; + char reason[2048] = {0}; _format_bufferevent_reason(what, reason); assert(RUN(stream_clients_count) > 0); @@ -660,13 +664,17 @@ static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UN # endif } - conn = evhttp_request_get_connection(client->request); + char *client_addr = "???"; + unsigned short client_port = 0; + + struct evhttp_connection *conn = evhttp_request_get_connection(client->request); if (conn) { evhttp_connection_get_peer(conn, &client_addr, &client_port); } LOG_INFO("HTTP: Disconnected client: [%s]:%u, id=%s, %s; clients now: %u", client_addr, client_port, client->id, reason, RUN(stream_clients_count)); + if (conn) { evhttp_connection_free(conn); } @@ -684,14 +692,11 @@ static void _http_callback_stream_error(UNUSED struct bufferevent *buf_event, UN } static void _http_queue_send_stream(server_s *server, bool stream_updated, bool frame_updated) { - struct evhttp_connection *conn; - struct bufferevent *buf_event; - long long now; bool has_clients = false; bool queued = false; for (stream_client_s *client = RUN(stream_clients); client != NULL; client = client->next) { - conn = evhttp_request_get_connection(client->request); + struct evhttp_connection *conn = evhttp_request_get_connection(client->request); if (conn) { // Фикс для бага WebKit. При включенной опции дропа одинаковых фреймов, // WebKit отрисовывает последний фрейм в серии с некоторой задержкой, @@ -708,7 +713,7 @@ static void _http_queue_send_stream(server_s *server, bool stream_updated, bool ); if (dual_update || frame_updated || client->need_first_frame) { - buf_event = evhttp_connection_get_bufferevent(conn); + struct bufferevent *buf_event = evhttp_connection_get_bufferevent(conn); bufferevent_setcb(buf_event, NULL, _http_callback_stream_write, _http_callback_stream_error, (void *)client); bufferevent_enable(buf_event, EV_READ|EV_WRITE); @@ -726,8 +731,8 @@ static void _http_queue_send_stream(server_s *server, bool stream_updated, bool if (queued) { static unsigned queued_fps_accum = 0; static long long queued_fps_second = 0; - - if ((now = floor_ms(get_now_monotonic())) != queued_fps_second) { + long long now = floor_ms(get_now_monotonic()); + if (now != queued_fps_second) { EX(queued_fps) = queued_fps_accum; queued_fps_accum = 0; queued_fps_second = now; diff --git a/src/ustreamer/http/static.c b/src/ustreamer/http/static.c index c90c967..7aaac9b 100644 --- a/src/ustreamer/http/static.c +++ b/src/ustreamer/http/static.c @@ -24,11 +24,9 @@ char *find_static_file_path(const char *root_path, const char *request_path) { - char *simplified_path; char *path = NULL; - struct stat st; - simplified_path = simplify_request_path(request_path); + char *simplified_path = simplify_request_path(request_path); if (simplified_path[0] == '\0') { LOG_VERBOSE("HTTP: Invalid request path %s to static", request_path); goto error; @@ -37,6 +35,7 @@ char *find_static_file_path(const char *root_path, const char *request_path) { A_CALLOC(path, strlen(root_path) + strlen(simplified_path) + 32); sprintf(path, "%s/%s", root_path, simplified_path); + struct stat st; # define LOAD_STAT { \ if (lstat(path, &st) < 0) { \ LOG_VERBOSE_PERROR("HTTP: Can't stat() static path %s", path); \ diff --git a/src/ustreamer/http/unix.c b/src/ustreamer/http/unix.c index 9f5a6a8..66f0323 100644 --- a/src/ustreamer/http/unix.c +++ b/src/ustreamer/http/unix.c @@ -24,7 +24,6 @@ evutil_socket_t evhttp_my_bind_unix(struct evhttp *http, const char *path, bool rm, mode_t mode) { - evutil_socket_t fd = -1; struct sockaddr_un addr; # define MAX_SUN_PATH (sizeof(addr.sun_path) - 1) @@ -40,6 +39,7 @@ evutil_socket_t evhttp_my_bind_unix(struct evhttp *http, const char *path, bool # undef MAX_SUN_PATH + evutil_socket_t fd = -1; assert((fd = socket(AF_UNIX, SOCK_STREAM, 0)) >= 0); assert(!evutil_make_socket_nonblocking(fd)); diff --git a/src/ustreamer/http/uri.c b/src/ustreamer/http/uri.c index b47755e..bafea7d 100644 --- a/src/ustreamer/http/uri.c +++ b/src/ustreamer/http/uri.c @@ -24,9 +24,8 @@ bool uri_get_true(struct evkeyvalq *params, const char *key) { - const char *value_str; - - if ((value_str = evhttp_find_header(params, key)) != NULL) { + const char *value_str = evhttp_find_header(params, key); + if (value_str != NULL) { if ( value_str[0] == '1' || !evutil_ascii_strcasecmp(value_str, "true") @@ -39,9 +38,8 @@ bool uri_get_true(struct evkeyvalq *params, const char *key) { } char *uri_get_string(struct evkeyvalq *params, const char *key) { - const char *value_str; - - if ((value_str = evhttp_find_header(params, key)) != NULL) { + const char *value_str = evhttp_find_header(params, key); + if (value_str != NULL) { return evhttp_encode_uri(value_str); } return NULL; diff --git a/src/ustreamer/main.c b/src/ustreamer/main.c index e63048e..52afec8 100644 --- a/src/ustreamer/main.c +++ b/src/ustreamer/main.c @@ -87,8 +87,8 @@ static void _signal_handler(int signum) { static void _install_signal_handlers(void) { struct sigaction sig_act; - MEMSET_ZERO(sig_act); + assert(!sigemptyset(&sig_act.sa_mask)); sig_act.sa_handler = _signal_handler; assert(!sigaddset(&sig_act.sa_mask, SIGINT)); @@ -105,21 +105,18 @@ static void _install_signal_handlers(void) { } int main(int argc, char *argv[]) { - options_s *options; - device_s *dev; - encoder_s *encoder; - stream_s *stream; - server_s *server; - int exit_code = 0; + assert(argc >= 0); LOGGING_INIT; A_THREAD_RENAME("main"); - options = options_init(argc, argv); - dev = device_init(); - encoder = encoder_init(); - stream = stream_init(dev, encoder); - server = server_init(stream); + options_s *options = options_init(argc, argv); + device_s *dev = device_init(); + encoder_s *encoder = encoder_init(); + stream_s *stream = stream_init(dev, encoder); + server_s *server = server_init(stream); + + int exit_code = 0; if ((exit_code = options_parse(options, dev, encoder, stream, server)) == 0) { # ifdef WITH_GPIO @@ -128,10 +125,7 @@ int main(int argc, char *argv[]) { _install_signal_handlers(); - pthread_t stream_loop_tid; - pthread_t server_loop_tid; _main_context_s ctx; - ctx.stream = stream; ctx.server = server; _ctx = &ctx; @@ -141,6 +135,8 @@ int main(int argc, char *argv[]) { gpio_set_prog_running(true); # endif + pthread_t stream_loop_tid; + pthread_t server_loop_tid; A_THREAD_CREATE(&stream_loop_tid, _stream_loop_thread, NULL); A_THREAD_CREATE(&server_loop_tid, _server_loop_thread, NULL); A_THREAD_JOIN(server_loop_tid); diff --git a/src/ustreamer/options.c b/src/ustreamer/options.c index 1df78f4..780b442 100644 --- a/src/ustreamer/options.c +++ b/src/ustreamer/options.c @@ -214,18 +214,16 @@ static void _features(void); static void _help(device_s *dev, encoder_s *encoder, stream_s *stream, server_s *server); -options_s *options_init(int argc, char *argv[]) { +options_s *options_init(unsigned argc, char *argv[]) { options_s *options; - A_CALLOC(options, 1); options->argc = argc; options->argv = argv; A_CALLOC(options->argv_copy, argc); - for (int index = 0; index < argc; ++index) { + for (unsigned index = 0; index < argc; ++index) { assert(options->argv_copy[index] = strdup(argv[index])); } - return options; } @@ -238,7 +236,7 @@ void options_destroy(options_s *options) { if (options->blank) { frame_destroy(options->blank); } - for (int index = 0; index < options->argc; ++index) { + for (unsigned index = 0; index < options->argc; ++index) { free(options->argv_copy[index]); } free(options->argv_copy); @@ -313,11 +311,6 @@ int options_parse(options_s *options, device_s *dev, encoder_s *encoder, stream_ break; \ } - int ch; - int short_index; - int opt_index; - char short_opts[1024] = {0}; - char *blank_path = NULL; # ifdef WITH_MEMSINK @@ -331,7 +324,9 @@ int options_parse(options_s *options, device_s *dev, encoder_s *encoder, stream_ char *process_name_prefix = NULL; # endif - for (short_index = 0, opt_index = 0; _LONG_OPTS[opt_index].name != NULL; ++opt_index) { + char short_opts[1024] = {0}; + + for (int short_index = 0, opt_index = 0; _LONG_OPTS[opt_index].name != NULL; ++opt_index) { if (isalpha(_LONG_OPTS[opt_index].val)) { short_opts[short_index] = _LONG_OPTS[opt_index].val; ++short_index; @@ -342,7 +337,7 @@ int options_parse(options_s *options, device_s *dev, encoder_s *encoder, stream_ } } - while ((ch = getopt_long(options->argc, options->argv_copy, short_opts, _LONG_OPTS, NULL)) >= 0) { + for (int ch; (ch = getopt_long(options->argc, options->argv_copy, short_opts, _LONG_OPTS, NULL)) >= 0;) { switch (ch) { case _O_DEVICE: OPT_SET(dev->path, optarg); case _O_INPUT: OPT_NUMBER("--input", dev->input, 0, 128, 0); @@ -494,7 +489,6 @@ int options_parse(options_s *options, device_s *dev, encoder_s *encoder, stream_ static int _parse_resolution(const char *str, unsigned *width, unsigned *height, bool limited) { unsigned tmp_width; unsigned tmp_height; - if (sscanf(str, "%ux%u", &tmp_width, &tmp_height) != 2) { return -1; } @@ -514,20 +508,19 @@ static int _parse_resolution(const char *str, unsigned *width, unsigned *height, #ifdef WITH_OMX static int _parse_glitched_resolutions(const char *str, encoder_s *encoder) { char *str_copy; - char *ptr; - unsigned count = 0; - unsigned width; - unsigned height; - assert((str_copy = strdup(str)) != NULL); - ptr = strtok(str_copy, ",;:\n\t "); + char *ptr = strtok(str_copy, ",;:\n\t "); + unsigned count = 0; + while (ptr != NULL) { if (count >= MAX_GLITCHED_RESOLUTIONS) { printf("Too big '--glitched-resolutions' list: maxlen=%u\n", MAX_GLITCHED_RESOLUTIONS); goto error; } + unsigned width; + unsigned height; switch (_parse_resolution(ptr, &width, &height, true)) { case -1: printf("Invalid resolution format of '%s' in '--glitched-resolutions=%s\n", ptr, str_copy); diff --git a/src/ustreamer/options.h b/src/ustreamer/options.h index ea1d6e8..1175bac 100644 --- a/src/ustreamer/options.h +++ b/src/ustreamer/options.h @@ -52,7 +52,7 @@ typedef struct { - int argc; + unsigned argc; char **argv; char **argv_copy; frame_s *blank; @@ -62,7 +62,7 @@ typedef struct { } options_s; -options_s *options_init(int argc, char *argv[]); +options_s *options_init(unsigned argc, char *argv[]); void options_destroy(options_s *options); int options_parse(options_s *options, device_s *dev, encoder_s *encoder, stream_s *stream, server_s *server); diff --git a/src/ustreamer/stream.c b/src/ustreamer/stream.c index 00d620f..0556a00 100644 --- a/src/ustreamer/stream.c +++ b/src/ustreamer/stream.c @@ -85,18 +85,17 @@ static long double _workers_pool_get_fluency_delay(_pool_s *pool, _worker_s *rea stream_s *stream_init(device_s *dev, encoder_s *encoder) { process_s *proc; - video_s *video; - stream_s *stream; - A_CALLOC(proc, 1); atomic_init(&proc->stop, false); atomic_init(&proc->slowdown, false); + video_s *video; A_CALLOC(video, 1); video->frame = frame_init("stream_video"); atomic_init(&video->updated, false); A_MUTEX_INIT(&video->mutex); + stream_s *stream; A_CALLOC(stream, 1); stream->last_as_blank = -1; stream->error_delay = 1; @@ -117,12 +116,11 @@ void stream_destroy(stream_s *stream) { void stream_loop(stream_s *stream) { # define DEV(_next) stream->dev->_next - _pool_s *pool; LOG_INFO("Using V4L2 device: %s", DEV(path)); LOG_INFO("Using desired FPS: %u", DEV(desired_fps)); - while ((pool = _stream_init_loop(stream)) != NULL) { + for (_pool_s *pool; (pool = _stream_init_loop(stream)) != NULL;) { long double grab_after = 0; unsigned fluency_passed = 0; unsigned captured_fps = 0; @@ -132,12 +130,10 @@ void stream_loop(stream_s *stream) { LOG_INFO("Capturing ..."); while (!atomic_load(&stream->proc->stop)) { - _worker_s *ready_wr; - SEP_DEBUG('-'); LOG_DEBUG("Waiting for worker ..."); - ready_wr = _workers_pool_wait(pool); + _worker_s *ready_wr = _workers_pool_wait(pool); if (!ready_wr->job_failed) { if (ready_wr->job_timely) { @@ -373,10 +369,9 @@ static _pool_s *_workers_pool_init(stream_s *stream) { # define DEV(_next) stream->dev->_next # define RUN(_next) stream->dev->run->_next - _pool_s *pool; - LOG_INFO("Creating pool with %u workers ...", stream->encoder->run->n_workers); + _pool_s *pool; A_CALLOC(pool, 1); pool->n_workers = stream->encoder->run->n_workers; @@ -470,7 +465,6 @@ static void *_worker_thread(void *v_worker) { # define PIC(_next) wr->frame->_next LOG_DEBUG("Worker %u compressing JPEG from buffer %u ...", wr->number, wr->buf_index); - wr->job_failed = (bool)encoder_compress( wr->stream->encoder, wr->number, @@ -482,7 +476,6 @@ static void *_worker_thread(void *v_worker) { if (!wr->job_failed) { wr->job_start_ts = PIC(encode_begin_ts); wr->last_comp_time = PIC(encode_end_ts) - wr->job_start_ts; - LOG_VERBOSE("Compressed new JPEG: size=%zu, time=%0.3Lf, worker=%u, buffer=%u", PIC(used), wr->last_comp_time, wr->number, wr->buf_index); } else { @@ -567,17 +560,14 @@ static void _workers_pool_assign(_pool_s *pool, _worker_s *ready_wr, unsigned bu } static long double _workers_pool_get_fluency_delay(_pool_s *pool, _worker_s *ready_wr) { - long double approx_comp_time; - long double min_delay; - - approx_comp_time = pool->approx_comp_time * 0.9 + ready_wr->last_comp_time * 0.1; + const long double approx_comp_time = pool->approx_comp_time * 0.9 + ready_wr->last_comp_time * 0.1; LOG_VERBOSE("Correcting approx_comp_time: %.3Lf -> %.3Lf (last_comp_time=%.3Lf)", pool->approx_comp_time, approx_comp_time, ready_wr->last_comp_time); pool->approx_comp_time = approx_comp_time; - min_delay = pool->approx_comp_time / pool->n_workers; // Среднее время работы размазывается на N воркеров + const long double min_delay = pool->approx_comp_time / pool->n_workers; // Среднее время работы размазывается на N воркеров if (pool->desired_frames_interval > 0 && min_delay > 0 && pool->desired_frames_interval > min_delay) { // Искусственное время задержки на основе желаемого FPS, если включен --desired-fps