diff --git a/src/libs/capture.c b/src/libs/capture.c index a46d95d..d60082b 100644 --- a/src/libs/capture.c +++ b/src/libs/capture.c @@ -828,8 +828,6 @@ static int _capture_open_format(us_capture_s *cap, bool first) { static void _capture_open_hw_fps(us_capture_s *cap) { us_capture_runtime_s *const run = cap->run; - run->hw_fps = 0; - struct v4l2_streamparm setfps = {.type = run->capture_type}; _LOG_DEBUG("Querying HW FPS ..."); if (us_xioctl(run->fd, VIDIOC_G_PARM, &setfps) < 0) { @@ -851,7 +849,7 @@ static void _capture_open_hw_fps(us_capture_s *cap) { US_MEMSET_ZERO(setfps); setfps.type = run->capture_type; SETFPS_TPF(numerator) = 1; - SETFPS_TPF(denominator) = (cap->desired_fps == 0 ? 255 : cap->desired_fps); + SETFPS_TPF(denominator) = -1; // Request maximum possible FPS if (us_xioctl(run->fd, VIDIOC_S_PARM, &setfps) < 0) { _LOG_PERROR("Can't set HW FPS"); @@ -868,12 +866,7 @@ static void _capture_open_hw_fps(us_capture_s *cap) { return; } - run->hw_fps = SETFPS_TPF(denominator); - if (cap->desired_fps != run->hw_fps) { - _LOG_INFO("Using HW FPS: %u -> %u (coerced)", cap->desired_fps, run->hw_fps); - } else { - _LOG_INFO("Using HW FPS: %u", run->hw_fps); - } + _LOG_INFO("Using HW FPS: %u/%u", SETFPS_TPF(numerator), SETFPS_TPF(denominator)); # undef SETFPS_TPF } diff --git a/src/libs/capture.h b/src/libs/capture.h index c766c95..e113021 100644 --- a/src/libs/capture.h +++ b/src/libs/capture.h @@ -58,7 +58,6 @@ typedef struct { uint format; uint stride; float hz; - uint hw_fps; uint jpeg_quality; uz raw_size; uint n_bufs; @@ -113,7 +112,6 @@ typedef struct { uint n_bufs; bool dma_export; bool dma_required; - uint desired_fps; uz min_frame_size; bool allow_truncated_frames; bool persistent; diff --git a/src/ustreamer/http/server.c b/src/ustreamer/http/server.c index d26deed..12b1fa6 100644 --- a/src/ustreamer/http/server.c +++ b/src/ustreamer/http/server.c @@ -198,16 +198,8 @@ int us_server_listen(us_server_s *server) { us_frame_copy(stream->run->blank->jpeg, ex->frame); - { - struct timeval interval = {0}; - if (stream->cap->desired_fps > 0) { - interval.tv_usec = 1000000 / (stream->cap->desired_fps * 2); - } else { - interval.tv_usec = 16000; // ~60fps - } - assert((run->refresher = event_new(run->base, -1, EV_PERSIST, _http_refresher, server)) != NULL); - assert(!event_add(run->refresher, &interval)); - } + assert((run->refresher = event_new(run->base, -1, 0, _http_refresher, server)) != NULL); + stream->run->http->jpeg_refresher = run->refresher; evhttp_set_timeout(run->http, server->timeout); @@ -519,7 +511,7 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server) (server->fake_width ? server->fake_width : captured_meta.width), (server->fake_height ? server->fake_height : captured_meta.height), us_bool_to_string(captured_meta.online), - stream->cap->desired_fps, + stream->desired_fps, captured_fps, us_fpsi_get(ex->queued_fpsi, NULL), run->stream_clients_count @@ -932,13 +924,15 @@ static void _http_refresher(int fd, short what, void *v_server) { bool stream_updated = false; bool frame_updated = false; - const int ri = us_ring_consumer_acquire(ring, 0); - if (ri >= 0) { + int ri; + while ((ri = us_ring_consumer_acquire(ring, 0)) >= 0) { const us_frame_s *const frame = ring->items[ri]; frame_updated = _expose_frame(server, frame); stream_updated = true; us_ring_consumer_release(ring, ri); - } else if (ex->expose_end_ts + 1 < us_get_now_monotonic()) { + } + + if (!stream_updated && (ex->expose_end_ts + 1 < us_get_now_monotonic())) { _LOG_DEBUG("Repeating exposed ..."); ex->expose_begin_ts = us_get_now_monotonic(); ex->expose_cmp_ts = ex->expose_begin_ts; diff --git a/src/ustreamer/options.c b/src/ustreamer/options.c index 248899d..d8f4134 100644 --- a/src/ustreamer/options.c +++ b/src/ustreamer/options.c @@ -386,7 +386,7 @@ int options_parse(us_options_s *options, us_capture_s *cap, us_encoder_s *enc, u case _O_FORMAT_SWAP_RGB: OPT_SET(cap->format_swap_rgb, true); case _O_TV_STANDARD: OPT_PARSE_ENUM("TV standard", cap->standard, us_capture_parse_standard, US_STANDARDS_STR); case _O_IO_METHOD: OPT_PARSE_ENUM("IO method", cap->io_method, us_capture_parse_io_method, US_IO_METHODS_STR); - case _O_DESIRED_FPS: OPT_NUMBER("--desired-fps", cap->desired_fps, 0, US_VIDEO_MAX_FPS, 0); + case _O_DESIRED_FPS: OPT_NUMBER("--desired-fps", stream->desired_fps, 0, US_VIDEO_MAX_FPS, 0); case _O_MIN_FRAME_SIZE: OPT_NUMBER("--min-frame-size", cap->min_frame_size, 1, 8192, 0); case _O_ALLOW_TRUNCATED_FRAMES: OPT_SET(cap->allow_truncated_frames, true); case _O_PERSISTENT: OPT_SET(cap->persistent, true); diff --git a/src/ustreamer/stream.c b/src/ustreamer/stream.c index 1d8194c..4414b3a 100644 --- a/src/ustreamer/stream.c +++ b/src/ustreamer/stream.c @@ -31,6 +31,8 @@ #include +#include // jpeg_refresher + #include "../libs/types.h" #include "../libs/errors.h" #include "../libs/tools.h" @@ -696,6 +698,7 @@ static void _stream_expose_jpeg(us_stream_s *stream, const us_frame_s *frame) { 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); + event_active(run->http->jpeg_refresher, 0, 0); if (stream->jpeg_sink != NULL) { us_memsink_server_put(stream->jpeg_sink, dest, NULL); } diff --git a/src/ustreamer/stream.h b/src/ustreamer/stream.h index c56424f..5c5279d 100644 --- a/src/ustreamer/stream.h +++ b/src/ustreamer/stream.h @@ -26,6 +26,8 @@ #include +#include // jpeg_refresher + #include "../libs/types.h" #include "../libs/queue.h" #include "../libs/ring.h" @@ -51,6 +53,7 @@ typedef struct { atomic_bool h264_online; us_fpsi_s *h264_fpsi; + struct event *jpeg_refresher; us_ring_s *jpeg_ring; atomic_bool has_clients; atomic_uint snapshot_requested; @@ -77,6 +80,7 @@ typedef struct { us_capture_s *cap; us_encoder_s *enc; + uint desired_fps; bool notify_parent; bool slowdown; uint error_delay;