Compare commits

...

9 Commits
v1.7 ... v1.11

Author SHA1 Message Date
Devaev Maxim
e3e2c5cead Bump version: 1.10 → 1.11 2020-01-14 16:49:50 +03:00
Devaev Maxim
ef4150877b check for 8 bits 2020-01-14 16:46:31 +03:00
Devaev Maxim
cc00d0fea3 Bump version: 1.9 → 1.10 2019-10-21 08:20:45 +03:00
Devaev Maxim
91a1e48a7c refactoring; renamed X-UStreamer-*-Time to X-UStreamer-*-Timestamp 2019-10-21 08:16:19 +03:00
Devaev Maxim
f381113d50 new arch pkg extension 2019-10-17 02:58:56 +03:00
Devaev Maxim
a6304959f4 Bump version: 1.8 → 1.9 2019-10-11 23:37:25 +03:00
Devaev Maxim
57bc6e160d keep original argv 2019-10-11 23:37:05 +03:00
Devaev Maxim
03dd5dfebb Bump version: 1.7 → 1.8 2019-10-11 08:23:40 +03:00
Devaev Maxim
00ef8928b3 temporary disabled setproctitle to avoid memory corruption 2019-10-11 08:23:04 +03:00
16 changed files with 108 additions and 68 deletions

View File

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

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@
/pkg/arch/src/
/pkg/arch/v*.tar.gz
/pkg/arch/ustreamer-*.pkg.tar.xz
/pkg/arch/ustreamer-*.pkg.tar.zst
/build/
/config.mk
/vgcore.*

View File

@@ -109,5 +109,5 @@ push:
clean-all: clean
clean:
rm -rf pkg/arch/pkg pkg/arch/src pkg/arch/v*.tar.gz pkg/arch/ustreamer-*.pkg.tar.xz
rm -rf pkg/arch/pkg pkg/arch/src pkg/arch/v*.tar.gz pkg/arch/ustreamer-*.pkg.tar.{xz,zst}
rm -rf $(PROG) $(BUILD) vgcore.* *.sock

View File

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

View File

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

View File

@@ -23,5 +23,5 @@
#pragma once
#ifndef VERSION
# define VERSION "1.7"
# define VERSION "1.11"
#endif

View File

@@ -286,7 +286,7 @@ int device_grab_buffer(struct device_t *dev) {
dev->run->hw_buffers[buf_info.index].used = buf_info.bytesused;
memcpy(&dev->run->hw_buffers[buf_info.index].buf_info, &buf_info, sizeof(struct v4l2_buffer));
dev->run->pictures[buf_info.index]->grab_time = get_now_monotonic();
dev->run->pictures[buf_info.index]->grab_ts = get_now_monotonic();
return buf_info.index;
}

View File

@@ -201,7 +201,7 @@ int encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, uns
assert(encoder->run->type != ENCODER_TYPE_UNKNOWN);
dev->run->pictures[buf_index]->encode_begin_time = get_now_monotonic();
dev->run->pictures[buf_index]->encode_begin_ts = get_now_monotonic();
if (encoder->run->type == ENCODER_TYPE_CPU) {
cpu_encoder_compress_buffer(dev, buf_index, encoder->run->quality);
@@ -216,7 +216,7 @@ int encoder_compress_buffer(struct encoder_t *encoder, struct device_t *dev, uns
}
# endif
dev->run->pictures[buf_index]->encode_end_time = get_now_monotonic();
dev->run->pictures[buf_index]->encode_end_ts = get_now_monotonic();
dev->run->pictures[buf_index]->width = dev->run->width;
dev->run->pictures[buf_index]->height = dev->run->height;

View File

@@ -172,9 +172,9 @@ int http_server_listen(struct http_server_t *server) {
# define EXPOSED(_next) server->run->exposed->_next
// See _expose_blank_picture()
picture_copy(server->run->blank, EXPOSED(picture));
EXPOSED(expose_begin_time) = get_now_monotonic();
EXPOSED(expose_cmp_time) = EXPOSED(expose_begin_time);
EXPOSED(expose_end_time) = EXPOSED(expose_begin_time);
EXPOSED(expose_begin_ts) = get_now_monotonic();
EXPOSED(expose_cmp_ts) = EXPOSED(expose_begin_ts);
EXPOSED(expose_end_ts) = EXPOSED(expose_begin_ts);
# undef EXPOSED
{
@@ -446,17 +446,17 @@ static void _http_callback_snapshot(struct evhttp_request *request, void *v_serv
ADD_TIME_HEADER("X-Timestamp", get_now_real());
ADD_HEADER("X-UStreamer-Online", bool_to_string(EXPOSED(online)));
ADD_UNSIGNED_HEADER("X-UStreamer-Dropped", EXPOSED(dropped));
ADD_UNSIGNED_HEADER("X-UStreamer-Width", EXPOSED(picture->width));
ADD_UNSIGNED_HEADER("X-UStreamer-Height", EXPOSED(picture->height));
ADD_TIME_HEADER("X-UStreamer-Grab-Time", EXPOSED(picture->grab_time));
ADD_TIME_HEADER("X-UStreamer-Encode-Begin-Time", EXPOSED(picture->encode_begin_time));
ADD_TIME_HEADER("X-UStreamer-Encode-End-Time", EXPOSED(picture->encode_end_time));
ADD_TIME_HEADER("X-UStreamer-Expose-Begin-Time", EXPOSED(expose_begin_time));
ADD_TIME_HEADER("X-UStreamer-Expose-Cmp-Time", EXPOSED(expose_cmp_time));
ADD_TIME_HEADER("X-UStreamer-Expose-End-Time", EXPOSED(expose_end_time));
ADD_TIME_HEADER("X-UStreamer-Send-Time", get_now_monotonic());
ADD_HEADER("X-UStreamer-Online", bool_to_string(EXPOSED(online)));
ADD_UNSIGNED_HEADER("X-UStreamer-Dropped", EXPOSED(dropped));
ADD_UNSIGNED_HEADER("X-UStreamer-Width", EXPOSED(picture->width));
ADD_UNSIGNED_HEADER("X-UStreamer-Height", EXPOSED(picture->height));
ADD_TIME_HEADER("X-UStreamer-Grab-Timestamp", EXPOSED(picture->grab_ts));
ADD_TIME_HEADER("X-UStreamer-Encode-Begin-Timestamp", EXPOSED(picture->encode_begin_ts));
ADD_TIME_HEADER("X-UStreamer-Encode-End-Timestamp", EXPOSED(picture->encode_end_ts));
ADD_TIME_HEADER("X-UStreamer-Expose-Begin-Timestamp", EXPOSED(expose_begin_ts));
ADD_TIME_HEADER("X-UStreamer-Expose-Cmp-Timestamp", EXPOSED(expose_cmp_ts));
ADD_TIME_HEADER("X-UStreamer-Expose-End-Timestamp", EXPOSED(expose_end_ts));
ADD_TIME_HEADER("X-UStreamer-Send-Timestamp", get_now_monotonic());
# undef ADD_UNSUGNED_HEADER
# undef ADD_TIME_HEADER
@@ -637,12 +637,12 @@ static void _http_callback_stream_write(struct bufferevent *buf_event, void *v_c
EXPOSED(picture->width),
EXPOSED(picture->height),
client->fps,
EXPOSED(picture->grab_time),
EXPOSED(picture->encode_begin_time),
EXPOSED(picture->encode_end_time),
EXPOSED(expose_begin_time),
EXPOSED(expose_cmp_time),
EXPOSED(expose_end_time),
EXPOSED(picture->grab_ts),
EXPOSED(picture->encode_begin_ts),
EXPOSED(picture->encode_end_ts),
EXPOSED(expose_begin_ts),
EXPOSED(expose_cmp_ts),
EXPOSED(expose_end_ts),
now
));
}
@@ -797,7 +797,7 @@ static bool _expose_new_picture_unsafe(struct http_server_t *server) {
# define STREAM(_next) server->run->stream->_next
EXPOSED(captured_fps) = STREAM(captured_fps);
EXPOSED(expose_begin_time) = get_now_monotonic();
EXPOSED(expose_begin_ts) = get_now_monotonic();
if (server->drop_same_frames) {
if (
@@ -805,16 +805,16 @@ static bool _expose_new_picture_unsafe(struct http_server_t *server) {
&& EXPOSED(dropped) < server->drop_same_frames
&& picture_compare(EXPOSED(picture), STREAM(picture))
) {
EXPOSED(expose_cmp_time) = get_now_monotonic();
EXPOSED(expose_end_time) = EXPOSED(expose_cmp_time);
EXPOSED(expose_cmp_ts) = get_now_monotonic();
EXPOSED(expose_end_ts) = EXPOSED(expose_cmp_ts);
LOG_VERBOSE("HTTP: Dropped same frame number %u; cmp_time=%.06Lf",
EXPOSED(dropped), EXPOSED(expose_cmp_time) - EXPOSED(expose_begin_time));
EXPOSED(dropped), EXPOSED(expose_cmp_ts) - EXPOSED(expose_begin_ts));
EXPOSED(dropped) += 1;
return false; // Not updated
} else {
EXPOSED(expose_cmp_time) = get_now_monotonic();
EXPOSED(expose_cmp_ts) = get_now_monotonic();
LOG_VERBOSE("HTTP: Passed same frame check (frames are differ); cmp_time=%.06Lf",
EXPOSED(expose_cmp_time) - EXPOSED(expose_begin_time));
EXPOSED(expose_cmp_ts) - EXPOSED(expose_begin_ts));
}
}
@@ -824,11 +824,11 @@ static bool _expose_new_picture_unsafe(struct http_server_t *server) {
EXPOSED(online) = true;
EXPOSED(dropped) = 0;
EXPOSED(expose_cmp_time) = EXPOSED(expose_begin_time);
EXPOSED(expose_end_time) = get_now_monotonic();
EXPOSED(expose_cmp_ts) = EXPOSED(expose_begin_ts);
EXPOSED(expose_end_ts) = get_now_monotonic();
LOG_VERBOSE("HTTP: Exposed new frame; full exposition time = %.06Lf",
EXPOSED(expose_end_time) - EXPOSED(expose_begin_time));
EXPOSED(expose_end_ts) - EXPOSED(expose_begin_ts));
# undef EXPOSED
return true; // Updated
@@ -837,8 +837,8 @@ static bool _expose_new_picture_unsafe(struct http_server_t *server) {
static bool _expose_blank_picture(struct http_server_t *server) {
# define EXPOSED(_next) server->run->exposed->_next
EXPOSED(expose_begin_time) = get_now_monotonic();
EXPOSED(expose_cmp_time) = EXPOSED(expose_begin_time);
EXPOSED(expose_begin_ts) = get_now_monotonic();
EXPOSED(expose_cmp_ts) = EXPOSED(expose_begin_ts);
# define EXPOSE_BLANK picture_copy(server->run->blank, EXPOSED(picture))
@@ -848,7 +848,7 @@ static bool _expose_blank_picture(struct http_server_t *server) {
EXPOSE_BLANK;
} else if (server->last_as_blank > 0) { // Если нужен таймер - запустим
LOG_INFO("HTTP: Freezing last alive frame for %d seconds", server->last_as_blank);
EXPOSED(last_as_blank_time) = get_now_monotonic();
EXPOSED(last_as_blank_ts) = get_now_monotonic();
} else { // last_as_blank == 0 - показываем последний фрейм вечно
LOG_INFO("HTTP: Freezing last alive frame forever");
}
@@ -857,12 +857,12 @@ static bool _expose_blank_picture(struct http_server_t *server) {
if ( // Если уже оффлайн, включена фича last_as_blank с таймером и он запущен
server->last_as_blank > 0
&& EXPOSED(last_as_blank_time) > 0
&& EXPOSED(last_as_blank_time) + server->last_as_blank < EXPOSED(expose_begin_time)
&& EXPOSED(last_as_blank_ts) > 0
&& EXPOSED(last_as_blank_ts) + server->last_as_blank < EXPOSED(expose_begin_ts)
) {
LOG_INFO("HTTP: Changed last alive frame to BLANK");
EXPOSE_BLANK;
EXPOSED(last_as_blank_time) = 0; // Останавливаем таймер
EXPOSED(last_as_blank_ts) = 0; // Останавливаем таймер
goto updated;
}
@@ -871,7 +871,7 @@ static bool _expose_blank_picture(struct http_server_t *server) {
if (EXPOSED(dropped) < server->run->drop_same_frames_blank) {
LOG_PERF("HTTP: Dropped same frame (BLANK) number %u", EXPOSED(dropped));
EXPOSED(dropped) += 1;
EXPOSED(expose_end_time) = get_now_monotonic();
EXPOSED(expose_end_ts) = get_now_monotonic();
return false; // Not updated
}
@@ -879,7 +879,7 @@ static bool _expose_blank_picture(struct http_server_t *server) {
EXPOSED(captured_fps) = 0;
EXPOSED(online) = false;
EXPOSED(dropped) = 0;
EXPOSED(expose_end_time) = get_now_monotonic();
EXPOSED(expose_end_ts) = get_now_monotonic();
return true; // Updated
# undef EXPOSED

View File

@@ -61,10 +61,10 @@ struct exposed_t {
unsigned queued_fps;
bool online;
unsigned dropped;
long double expose_begin_time;
long double expose_cmp_time;
long double expose_end_time;
long double last_as_blank_time;
long double expose_begin_ts;
long double expose_cmp_ts;
long double expose_end_ts;
long double last_as_blank_ts;
};
struct http_server_runtime_t {

View File

@@ -25,6 +25,11 @@
# error WTF dude? Asserts are good things!
#endif
#include <limits.h>
#if CHAR_BIT != 8
# error There are not 8 bits in a char!
#endif
#include <stdio.h>
#include <signal.h>
@@ -98,6 +103,7 @@ static void _install_signal_handlers(void) {
}
int main(int argc, char *argv[]) {
struct options_t *options;
struct device_t *dev;
struct encoder_t *encoder;
struct stream_t *stream;
@@ -105,8 +111,8 @@ int main(int argc, char *argv[]) {
int exit_code = 0;
LOGGING_INIT;
A_THREAD_RENAME("main");
options = options_init(argc, argv);
# ifdef WITH_GPIO
GPIO_INIT;
@@ -117,7 +123,7 @@ int main(int argc, char *argv[]) {
stream = stream_init(dev, encoder);
server = http_server_init(stream);
if ((exit_code = parse_options(argc, argv, dev, encoder, server)) == 0) {
if ((exit_code = options_parse(options, dev, encoder, server)) == 0) {
# ifdef WITH_GPIO
GPIO_INIT_PINOUT;
# endif
@@ -153,6 +159,7 @@ int main(int argc, char *argv[]) {
GPIO_SET_LOW(prog_running);
# endif
options_destroy(options);
if (exit_code == 0) {
LOG_INFO("Bye-bye");
}

View File

@@ -25,9 +25,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#ifdef WITH_OMX
# include <string.h>
#endif
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <getopt.h>
@@ -212,7 +210,31 @@ static void _features(void);
static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_server_t *server);
int parse_options(int argc, char *argv[], struct device_t *dev, struct encoder_t *encoder, struct http_server_t *server) {
struct options_t *options_init(int argc, char *argv[]) {
struct options_t *options;
A_CALLOC(options, 1);
options->argc = argc;
options->argv = argv;
A_CALLOC(options->argv_copy, argc);
for (int index = 0; index < argc; ++index) {
assert(options->argv_copy[index] = strdup(argv[index]));
}
return options;
}
void options_destroy(struct options_t *options) {
for (int index = 0; index < options->argc; ++index) {
free(options->argv_copy[index]);
}
free(options->argv_copy);
free(options);
}
int options_parse(struct options_t *options, struct device_t *dev, struct encoder_t *encoder, struct http_server_t *server) {
# define OPT_SET(_dest, _value) { \
_dest = _value; \
break; \
@@ -285,7 +307,7 @@ int parse_options(int argc, char *argv[], struct device_t *dev, struct encoder_t
}
}
while ((ch = getopt_long(argc, argv, short_opts, _LONG_OPTS, NULL)) >= 0) {
while ((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);
@@ -378,7 +400,7 @@ int parse_options(int argc, char *argv[], struct device_t *dev, struct encoder_t
# ifdef WITH_SETPROCTITLE
if (process_name_prefix != NULL) {
process_set_name_prefix(argc, argv, process_name_prefix);
process_set_name_prefix(options->argc, options->argv, process_name_prefix);
}
# endif

View File

@@ -27,4 +27,14 @@
#include "http/server.h"
int parse_options(int argc, char *argv[], struct device_t *dev, struct encoder_t *encoder, struct http_server_t *server);
struct options_t {
int argc;
char **argv;
char **argv_copy;
};
struct options_t *options_init(int argc, char *argv[]);
void options_destroy(struct options_t *options);
int options_parse(struct options_t *options, struct device_t *dev, struct encoder_t *encoder, struct http_server_t *server);

View File

@@ -84,9 +84,9 @@ void picture_copy(const struct picture_t *src, struct picture_t *dest) {
COPY(width);
COPY(height);
COPY(grab_time);
COPY(encode_begin_time);
COPY(encode_end_time);
COPY(grab_ts);
COPY(encode_begin_ts);
COPY(encode_end_ts);
# undef COPY
}

View File

@@ -32,9 +32,9 @@ struct picture_t {
size_t allocated;
unsigned width;
unsigned height;
long double grab_time;
long double encode_begin_time;
long double encode_end_time;
long double grab_ts;
long double encode_begin_ts;
long double encode_end_ts;
};

View File

@@ -55,7 +55,7 @@ struct _worker_t {
atomic_bool has_job;
bool job_timely;
bool job_failed;
long double job_start_time;
long double job_start_ts;
pthread_cond_t has_job_cond;
pthread_mutex_t *free_workers_mutex;
@@ -454,10 +454,10 @@ static void *_worker_thread(void *v_worker) {
}
if (device_release_buffer(worker->dev, worker->buf_index) == 0) {
worker->job_start_time = PICTURE(encode_begin_time);
worker->job_start_ts = PICTURE(encode_begin_ts);
atomic_store(&worker->has_job, false);
worker->last_comp_time = PICTURE(encode_end_time) - worker->job_start_time;
worker->last_comp_time = PICTURE(encode_end_ts) - worker->job_start_ts;
LOG_VERBOSE("Compressed new JPEG: size=%zu, time=%0.3Lf, worker=%u, buffer=%u",
PICTURE(used), worker->last_comp_time, worker->number, worker->buf_index);
@@ -498,7 +498,7 @@ static struct _worker_t *_workers_pool_wait(struct _workers_pool_t *pool) {
if (
!atomic_load(&pool->workers[number].has_job) && (
ready_worker == NULL
|| ready_worker->job_start_time < pool->workers[number].job_start_time
|| ready_worker->job_start_ts < pool->workers[number].job_start_ts
)
) {
ready_worker = &pool->workers[number];