mirror of
https://github.com/pikvm/ustreamer.git
synced 2025-12-24 03:00:01 +00:00
atomic capture state for http
This commit is contained in:
parent
c24d6338e2
commit
33b9bff0b9
@ -31,7 +31,7 @@
|
||||
|
||||
|
||||
#define US_VIDEO_MIN_WIDTH ((uint)160)
|
||||
#define US_VIDEO_MAX_WIDTH ((uint)15360)
|
||||
#define US_VIDEO_MAX_WIDTH ((uint)15360) // Remember about stream->run->http_capture_state;
|
||||
|
||||
#define US_VIDEO_MIN_HEIGHT ((uint)120)
|
||||
#define US_VIDEO_MAX_HEIGHT ((uint)8640)
|
||||
|
||||
@ -503,15 +503,20 @@ static void _http_callback_state(struct evhttp_request *request, void *v_server)
|
||||
_A_EVBUFFER_ADD_PRINTF(buf, "},");
|
||||
}
|
||||
|
||||
uint width;
|
||||
uint height;
|
||||
bool online;
|
||||
uint captured_fps;
|
||||
us_stream_get_capture_state(stream, &width, &height, &online, &captured_fps);
|
||||
_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\": {",
|
||||
(server->fake_width ? server->fake_width : ex->frame->width),
|
||||
(server->fake_height ? server->fake_height : ex->frame->height),
|
||||
us_bool_to_string(ex->frame->online),
|
||||
(server->fake_width ? server->fake_width : width),
|
||||
(server->fake_height ? server->fake_height : height),
|
||||
us_bool_to_string(online),
|
||||
stream->dev->desired_fps,
|
||||
atomic_load(&stream->run->http_captured_fps),
|
||||
captured_fps,
|
||||
ex->queued_fps,
|
||||
run->stream_clients_count
|
||||
);
|
||||
|
||||
@ -76,6 +76,7 @@ static void *_jpeg_thread(void *v_ctx);
|
||||
static void *_h264_thread(void *v_ctx);
|
||||
static void *_releaser_thread(void *v_ctx);
|
||||
|
||||
static void _stream_set_capture_state(us_stream_s *stream, uint width, uint height, bool online, uint captured_fps);
|
||||
static bool _stream_has_any_clients(us_stream_s *stream);
|
||||
static int _stream_init_loop(us_stream_s *stream);
|
||||
static void _stream_expose_frame(us_stream_s *stream, us_frame_s *frame);
|
||||
@ -97,7 +98,7 @@ us_stream_s *us_stream_init(us_device_s *dev, us_encoder_s *enc) {
|
||||
atomic_init(&run->http_has_clients, false);
|
||||
atomic_init(&run->http_snapshot_requested, 0);
|
||||
atomic_init(&run->http_last_request_ts, 0);
|
||||
atomic_init(&run->http_captured_fps, 0);
|
||||
atomic_init(&run->http_capture_state, 0);
|
||||
atomic_init(&run->stop, false);
|
||||
run->blank = us_blank_init();
|
||||
|
||||
@ -110,6 +111,9 @@ us_stream_s *us_stream_init(us_device_s *dev, us_encoder_s *enc) {
|
||||
stream->h264_bitrate = 5000; // Kbps
|
||||
stream->h264_gop = 30;
|
||||
stream->run = run;
|
||||
|
||||
us_blank_draw(run->blank, "< NO SIGNAL >", dev->width, dev->height);
|
||||
_stream_set_capture_state(stream, dev->width, dev->height, false, 0);
|
||||
return stream;
|
||||
}
|
||||
|
||||
@ -122,9 +126,10 @@ void us_stream_destroy(us_stream_s *stream) {
|
||||
|
||||
void us_stream_loop(us_stream_s *stream) {
|
||||
us_stream_runtime_s *const run = stream->run;
|
||||
us_device_s *const dev = stream->dev;
|
||||
|
||||
US_LOG_INFO("Using V4L2 device: %s", stream->dev->path);
|
||||
US_LOG_INFO("Using desired FPS: %u", stream->dev->desired_fps);
|
||||
US_LOG_INFO("Using V4L2 device: %s", dev->path);
|
||||
US_LOG_INFO("Using desired FPS: %u", dev->desired_fps);
|
||||
|
||||
atomic_store(&run->http_last_request_ts, us_get_now_monotonic());
|
||||
|
||||
@ -138,12 +143,12 @@ void us_stream_loop(us_stream_s *stream) {
|
||||
|
||||
pthread_mutex_t release_mutex;
|
||||
US_MUTEX_INIT(release_mutex);
|
||||
const uint n_releasers = stream->dev->run->n_bufs;
|
||||
const uint n_releasers = dev->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];
|
||||
ctx->dev = stream->dev;
|
||||
ctx->dev = dev;
|
||||
ctx->queue = us_queue_init(1);
|
||||
ctx->mutex = &release_mutex;
|
||||
ctx->stop = &threads_stop;
|
||||
@ -151,7 +156,7 @@ void us_stream_loop(us_stream_s *stream) {
|
||||
}
|
||||
|
||||
_jpeg_context_s jpeg_ctx = {
|
||||
.queue = us_queue_init(stream->dev->run->n_bufs),
|
||||
.queue = us_queue_init(dev->run->n_bufs),
|
||||
.stream = stream,
|
||||
.stop = &threads_stop,
|
||||
};
|
||||
@ -159,8 +164,8 @@ void us_stream_loop(us_stream_s *stream) {
|
||||
|
||||
_h264_context_s h264_ctx;
|
||||
if (run->h264 != NULL) {
|
||||
h264_ctx.dev = stream->dev;
|
||||
h264_ctx.queue = us_queue_init(stream->dev->run->n_bufs);
|
||||
h264_ctx.dev = dev;
|
||||
h264_ctx.queue = us_queue_init(dev->run->n_bufs);
|
||||
h264_ctx.h264 = run->h264;
|
||||
h264_ctx.stop = &threads_stop;
|
||||
US_THREAD_CREATE(h264_ctx.tid, _h264_thread, &h264_ctx);
|
||||
@ -168,6 +173,7 @@ void us_stream_loop(us_stream_s *stream) {
|
||||
|
||||
uint captured_fps_accum = 0;
|
||||
sll captured_fps_ts = 0;
|
||||
uint captured_fps = 0;
|
||||
|
||||
US_LOG_INFO("Capturing ...");
|
||||
|
||||
@ -183,7 +189,7 @@ void us_stream_loop(us_stream_s *stream) {
|
||||
}
|
||||
|
||||
us_hw_buffer_s *hw;
|
||||
const int buf_index = us_device_grab_buffer(stream->dev, &hw);
|
||||
const int buf_index = us_device_grab_buffer(dev, &hw);
|
||||
switch (buf_index) {
|
||||
case -3: continue; // Broken frame
|
||||
case -2: // Persistent timeout
|
||||
@ -193,13 +199,14 @@ void us_stream_loop(us_stream_s *stream) {
|
||||
|
||||
const sll now_sec_ts = us_floor_ms(us_get_now_monotonic());
|
||||
if (now_sec_ts != captured_fps_ts) {
|
||||
US_LOG_PERF_FPS("A new second has come; captured_fps=%u", captured_fps_accum);
|
||||
atomic_store(&run->http_captured_fps, captured_fps_accum);
|
||||
captured_fps = captured_fps_accum;
|
||||
captured_fps_accum = 0;
|
||||
captured_fps_ts = now_sec_ts;
|
||||
US_LOG_PERF_FPS("A new second has come; captured_fps=%u", captured_fps);
|
||||
}
|
||||
captured_fps_accum += 1;
|
||||
|
||||
_stream_set_capture_state(stream, dev->run->width, dev->run->height, true, captured_fps);
|
||||
# ifdef WITH_GPIO
|
||||
us_gpio_set_stream_online(true);
|
||||
# endif
|
||||
@ -236,11 +243,7 @@ void us_stream_loop(us_stream_s *stream) {
|
||||
atomic_store(&threads_stop, false);
|
||||
|
||||
us_encoder_close(stream->enc);
|
||||
us_device_close(stream->dev);
|
||||
|
||||
# ifdef WITH_GPIO
|
||||
us_gpio_set_stream_online(false);
|
||||
# endif
|
||||
us_device_close(dev);
|
||||
}
|
||||
|
||||
US_DELETE(run->h264, us_h264_stream_destroy);
|
||||
@ -250,6 +253,24 @@ void us_stream_loop_break(us_stream_s *stream) {
|
||||
atomic_store(&stream->run->stop, true);
|
||||
}
|
||||
|
||||
void us_stream_get_capture_state(us_stream_s *stream, uint *width, uint *height, bool *online, uint *captured_fps) {
|
||||
const u64 state = atomic_load(&stream->run->http_capture_state);
|
||||
*width = state & 0xFFFF;
|
||||
*height = (state >> 16) & 0xFFFF;
|
||||
*captured_fps = (state >> 32) & 0xFFFF;
|
||||
*online = (state >> 48) & 1;
|
||||
}
|
||||
|
||||
void _stream_set_capture_state(us_stream_s *stream, uint width, uint height, bool online, uint captured_fps) {
|
||||
const u64 state = (
|
||||
(u64)(width & 0xFFFF)
|
||||
| ((u64)(height & 0xFFFF) << 16)
|
||||
| ((u64)(captured_fps & 0xFFFF) << 32)
|
||||
| ((u64)(online ? 1 : 0) << 48)
|
||||
);
|
||||
atomic_store(&stream->run->http_capture_state, state);
|
||||
}
|
||||
|
||||
static void *_jpeg_thread(void *v_ctx) {
|
||||
_jpeg_context_s *ctx = v_ctx;
|
||||
us_stream_s *stream = ctx->stream;
|
||||
@ -380,8 +401,11 @@ static int _stream_init_loop(us_stream_s *stream) {
|
||||
}
|
||||
us_blank_draw(run->blank, "< NO SIGNAL >", width, height);
|
||||
|
||||
atomic_store(&run->http_captured_fps, 0);
|
||||
_stream_set_capture_state(stream, width, height, true, 0);
|
||||
_stream_expose_frame(stream, NULL);
|
||||
# ifdef WITH_GPIO
|
||||
us_gpio_set_stream_online(false);
|
||||
# endif
|
||||
|
||||
if (run->h264 != NULL) {
|
||||
us_h264_stream_process(run->h264, run->blank->raw, true);
|
||||
|
||||
@ -44,7 +44,7 @@ typedef struct {
|
||||
atomic_bool http_has_clients;
|
||||
atomic_uint http_snapshot_requested;
|
||||
atomic_ullong http_last_request_ts; // Seconds
|
||||
atomic_uint http_captured_fps;
|
||||
atomic_ullong http_capture_state; // Bits
|
||||
|
||||
bool last_online;
|
||||
long double last_as_blank_ts;
|
||||
@ -80,3 +80,5 @@ void us_stream_destroy(us_stream_s *stream);
|
||||
|
||||
void us_stream_loop(us_stream_s *stream);
|
||||
void us_stream_loop_break(us_stream_s *stream);
|
||||
|
||||
void us_stream_get_capture_state(us_stream_s *stream, uint *width, uint *height, bool *online, uint *captured_fps);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user