From 0827cb2b65eeb5458217de9948f90575d381c8bd Mon Sep 17 00:00:00 2001 From: Devaev Maxim Date: Tue, 17 Sep 2019 09:50:14 +0300 Subject: [PATCH] Issue #9: --last-as-blank accept timeout or 0 --- src/http/server.c | 43 ++++++++++++++++++++++++++++++++++++------- src/http/server.h | 3 ++- src/options.c | 7 ++++--- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/http/server.c b/src/http/server.c index 4f13709..b3ffedc 100644 --- a/src/http/server.c +++ b/src/http/server.c @@ -108,6 +108,7 @@ struct http_server_t *http_server_init(struct stream_t *stream) { server->passwd = ""; server->static_path = ""; server->timeout = 10; + server->last_as_blank = -1; server->run = run; assert(!evthread_use_pthreads()); @@ -169,7 +170,14 @@ int http_server_listen(struct http_server_t *server) { server->run->drop_same_frames_blank = max_u(server->drop_same_frames, server->run->drop_same_frames_blank); server->run->blank = blank_picture_init(server->blank_path); - _expose_blank_picture(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); +# undef EXPOSED { struct timeval refresh_interval; @@ -887,20 +895,39 @@ 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 +# define EXPOSED(_next) server->run->exposed->_next EXPOSED(expose_begin_time) = get_now_monotonic(); EXPOSED(expose_cmp_time) = EXPOSED(expose_begin_time); - if (EXPOSED(online) || EXPOSED(picture->used) == 0) { - if (!(server->last_as_blank && EXPOSED(picture->used) > 0)) { - picture_copy(server->run->blank, EXPOSED(picture)); +# define EXPOSE_BLANK picture_copy(server->run->blank, EXPOSED(picture)) + + if (EXPOSED(online)) { // Если переходим из online в offline + if (server->last_as_blank < 0) { // Если last_as_blank выключено, просто покажем картинку + LOG_INFO("HTTP: changed picture to BLANK"); + 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(); + } else { // last_as_blank == 0 - показываем последний фрейм вечно + LOG_INFO("HTTP: freezing last alive frame forever"); } - EXPOSED(captured_fps) = 0; - EXPOSED(online) = false; goto updated; } + 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) + ) { + LOG_INFO("HTTP: changed last alive frame to BLANK"); + EXPOSE_BLANK; + EXPOSED(last_as_blank_time) = 0; // Останавливаем таймер + goto updated; + } + +# undef EXPOSE_BLANK + if (EXPOSED(dropped) < server->run->drop_same_frames_blank) { LOG_PERF("HTTP: dropped same frame (BLANK) number %u", EXPOSED(dropped)); EXPOSED(dropped) += 1; @@ -909,6 +936,8 @@ static bool _expose_blank_picture(struct http_server_t *server) { } updated: + EXPOSED(captured_fps) = 0; + EXPOSED(online) = false; EXPOSED(dropped) = 0; EXPOSED(expose_end_time) = get_now_monotonic(); return true; // Updated diff --git a/src/http/server.h b/src/http/server.h index aa85fb7..3b5b898 100644 --- a/src/http/server.h +++ b/src/http/server.h @@ -67,6 +67,7 @@ struct exposed_t { long double expose_begin_time; long double expose_cmp_time; long double expose_end_time; + long double last_as_blank_time; }; struct http_server_runtime_t { @@ -96,7 +97,7 @@ struct http_server_t { char *static_path; char *blank_path; - bool last_as_blank; + int last_as_blank; unsigned drop_same_frames; bool slowdown; unsigned fake_width; diff --git a/src/options.c b/src/options.c index 271b78c..9238b8e 100644 --- a/src/options.c +++ b/src/options.c @@ -157,7 +157,7 @@ static const struct option _LONG_OPTS[] = { {"passwd", required_argument, NULL, _O_PASSWD}, {"static", required_argument, NULL, _O_STATIC}, {"blank", required_argument, NULL, _O_BLANK}, - {"last-as-blank", no_argument, NULL, _O_LAST_AS_BLANK}, + {"last-as-blank", required_argument, NULL, _O_LAST_AS_BLANK}, {"drop-same-frames", required_argument, NULL, _O_DROP_SAME_FRAMES}, {"slowdown", no_argument, NULL, _O_SLOWDOWN}, {"fake-resolution", required_argument, NULL, _O_FAKE_RESOLUTION}, @@ -319,7 +319,7 @@ int parse_options(int argc, char *argv[], struct device_t *dev, struct encoder_t case _O_PASSWD: OPT_SET(server->passwd, optarg); case _O_STATIC: OPT_SET(server->static_path, optarg); case _O_BLANK: OPT_SET(server->blank_path, optarg); - case _O_LAST_AS_BLANK: OPT_SET(server->last_as_blank, true); + case _O_LAST_AS_BLANK: OPT_NUMBER("--last-as-blank", server->last_as_blank, 0, 86400, 0); case _O_DROP_SAME_FRAMES: OPT_NUMBER("--drop-same-frames", server->drop_same_frames, 0, VIDEO_MAX_FPS, 0); case _O_SLOWDOWN: OPT_SET(server->slowdown, true); case _O_FAKE_RESOLUTION: OPT_RESOLUTION("--fake-resolution", server->fake_width, server->fake_height, false); @@ -517,7 +517,8 @@ static void _help(struct device_t *dev, struct encoder_t *encoder, struct http_s printf(" Symlinks are not supported for security reasons. Default: disabled.\n\n"); printf(" -k|--blank ────────── Path to JPEG file that will be shown when the device is disconnected\n"); printf(" during the streaming. Default: black screen 640x480 with 'NO SIGNAL'.\n\n"); - printf(" -K|--last-as-blank ───────── Show the last frame received from the camera after it was disconnected.\n"); + printf(" -K|--last-as-blank ─── Show the last frame received from the camera after it was disconnected,\n"); + printf(" but no more than specified time (or endlessly if 0 is specified).\n"); printf(" If the device has not yet been online, display 'NO SIGNAL' or the image\n"); printf(" specified by option --blank. Default: disabled.\n\n"); printf(" -e|--drop-same-frames ── Don't send identical frames to clients, but no more than specified number.\n");