refactoring

This commit is contained in:
Maxim Devaev 2024-03-02 02:09:54 +02:00
parent cfc5ae1b94
commit 6145b69c97

View File

@ -30,8 +30,6 @@ static int _stream_init_loop(us_stream_s *stream);
static void _stream_expose_frame(us_stream_s *stream, us_frame_s *frame);
#define _RUN(x_next) stream->run->x_next
#define _SINK_PUT(x_sink, x_frame) { \
if (stream->x_sink && us_memsink_server_check(stream->x_sink, x_frame)) {\
bool m_key_requested; /* Unused */ \
@ -40,8 +38,8 @@ static void _stream_expose_frame(us_stream_s *stream, us_frame_s *frame);
}
#define _H264_PUT(x_frame, x_force_key) { \
if (_RUN(h264)) { \
us_h264_stream_process(_RUN(h264), x_frame, x_force_key); \
if (stream->run->h264) { \
us_h264_stream_process(stream->run->h264, x_frame, x_force_key); \
} \
}
@ -76,13 +74,15 @@ 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_LOG_INFO("Using V4L2 device: %s", stream->dev->path);
US_LOG_INFO("Using desired FPS: %u", stream->dev->desired_fps);
atomic_store(&stream->run->http_last_request_ts, us_get_now_monotonic());
atomic_store(&run->http_last_request_ts, us_get_now_monotonic());
if (stream->h264_sink != NULL) {
_RUN(h264) = us_h264_stream_init(stream->h264_sink, stream->h264_m2m_path, stream->h264_bitrate, stream->h264_gop);
run->h264 = us_h264_stream_init(stream->h264_sink, stream->h264_m2m_path, stream->h264_bitrate, stream->h264_gop);
}
while (!_stream_init_loop(stream)) {
@ -102,7 +102,7 @@ void us_stream_loop(us_stream_s *stream) {
if (ready_job->hw != NULL) {
if (us_device_release_buffer(stream->dev, ready_job->hw) < 0) {
break;
goto close;
}
if (ready_wr->job_failed) {
// pass
@ -117,7 +117,7 @@ void us_stream_loop(us_stream_s *stream) {
const bool h264_force_key = _stream_slowdown(stream);
if (_stream_is_stopped(stream)) {
break;
goto close;
}
bool has_read;
@ -127,7 +127,7 @@ void us_stream_loop(us_stream_s *stream) {
if (selected < 0) {
if (errno != EINTR) {
US_LOG_PERROR("Mainloop select() error");
break;
goto close;
}
} else if (selected == 0) { // Persistent timeout
# ifdef WITH_GPIO
@ -151,14 +151,14 @@ void us_stream_loop(us_stream_s *stream) {
US_LOG_VERBOSE("Passed %u frames for fluency: now=%.03Lf, grab_after=%.03Lf",
fluency_passed, now, grab_after);
if (us_device_release_buffer(stream->dev, hw) < 0) {
break;
goto close;
}
} else {
fluency_passed = 0;
if (now_second != captured_fps_second) {
US_LOG_PERF_FPS("A new second has come; captured_fps=%u", captured_fps_accum);
atomic_store(&stream->run->captured_fps, captured_fps_accum);
atomic_store(&run->captured_fps, captured_fps_accum);
captured_fps_accum = 0;
captured_fps_second = now_second;
}
@ -176,16 +176,17 @@ void us_stream_loop(us_stream_s *stream) {
_H264_PUT(&hw->raw, h264_force_key);
}
} else if (buf_index != -2) { // -2 for broken frame
break;
goto close;
}
}
if (has_error && us_device_consume_event(stream->dev) < 0) {
break;
goto close;
}
}
}
close:
us_encoder_close(stream->enc);
us_device_close(stream->dev);
@ -194,39 +195,41 @@ void us_stream_loop(us_stream_s *stream) {
# endif
}
US_DELETE(_RUN(h264), us_h264_stream_destroy);
US_DELETE(run->h264, us_h264_stream_destroy);
}
void us_stream_loop_break(us_stream_s *stream) {
atomic_store(&_RUN(stop), true);
atomic_store(&stream->run->stop, true);
}
static bool _stream_is_stopped(us_stream_s *stream) {
const bool stop = atomic_load(&_RUN(stop));
us_stream_runtime_s *const run = stream->run;
const bool stop = atomic_load(&run->stop);
if (stop) {
return true;
}
if (stream->exit_on_no_clients > 0) {
const long double now = us_get_now_monotonic();
const uint64_t http_last_request_ts = atomic_load(&_RUN(http_last_request_ts)); // Seconds
const uint64_t http_last_request_ts = atomic_load(&run->http_last_request_ts); // Seconds
if (_stream_has_any_clients(stream)) {
atomic_store(&_RUN(http_last_request_ts), now);
atomic_store(&run->http_last_request_ts, now);
} else if (http_last_request_ts + stream->exit_on_no_clients < now) {
US_LOG_INFO("No requests or HTTP/sink clients found in last %u seconds, exiting ...",
stream->exit_on_no_clients);
us_process_suicide();
atomic_store(&_RUN(http_last_request_ts), now);
atomic_store(&run->http_last_request_ts, now);
}
}
return false;
}
static bool _stream_has_any_clients(us_stream_s *stream) {
us_stream_runtime_s *const run = stream->run;
return (
atomic_load(&_RUN(http_has_clients))
atomic_load(&run->http_has_clients)
// has_clients синков НЕ обновляются в реальном времени
|| (stream->sink != NULL && atomic_load(&stream->sink->has_clients))
|| (_RUN(h264) != NULL && /*_RUN(h264->sink) == NULL ||*/ atomic_load(&_RUN(h264->sink->has_clients)))
|| (run->h264 != NULL && /*run->h264->sink == NULL ||*/ atomic_load(&run->h264->sink->has_clients))
);
}
@ -243,6 +246,8 @@ static bool _stream_slowdown(us_stream_s *stream) {
}
static int _stream_init_loop(us_stream_s *stream) {
us_stream_runtime_s *const run = stream->run;
int access_errno = 0;
while (!_stream_is_stopped(stream)) {
unsigned width = stream->dev->run->width;
@ -251,13 +256,13 @@ static int _stream_init_loop(us_stream_s *stream) {
width = stream->dev->width;
height = stream->dev->height;
}
us_blank_draw(stream->run->blank, "< NO SIGNAL >", width, height);
us_blank_draw(run->blank, "< NO SIGNAL >", width, height);
atomic_store(&stream->run->captured_fps, 0);
atomic_store(&run->captured_fps, 0);
_stream_expose_frame(stream, NULL);
_SINK_PUT(raw_sink, stream->run->blank->raw);
_H264_PUT(stream->run->blank->raw, false);
_SINK_PUT(raw_sink, run->blank->raw);
_H264_PUT(run->blank->raw, false);
if (access(stream->dev->path, R_OK|W_OK) < 0) {
if (access_errno != errno) {
@ -275,7 +280,7 @@ static int _stream_init_loop(us_stream_s *stream) {
stream->dev->dma_export = (
stream->enc->type == US_ENCODER_TYPE_M2M_VIDEO
|| stream->enc->type == US_ENCODER_TYPE_M2M_IMAGE
|| _RUN(h264) != NULL
|| run->h264 != NULL
);
if (us_device_open(stream->dev) == 0) {
us_encoder_open(stream->enc, stream->dev);
@ -291,38 +296,37 @@ static int _stream_init_loop(us_stream_s *stream) {
static void _stream_expose_frame(us_stream_s *stream, us_frame_s *frame) {
us_stream_runtime_s *const run = stream->run;
us_blank_s *const blank = run->blank;
us_frame_s *new = NULL;
if (frame != NULL) {
new = frame;
_RUN(last_as_blank_ts) = 0; // Останавливаем таймер
run->last_as_blank_ts = 0; // Останавливаем таймер
US_LOG_DEBUG("Exposed ALIVE video frame");
} else {
if (run->last_online) { // Если переходим из online в offline
if (stream->last_as_blank < 0) { // Если last_as_blank выключен, просто покажем старую картинку
new = blank->jpeg;
new = run->blank->jpeg;
US_LOG_INFO("Changed video frame to BLANK");
} else if (stream->last_as_blank > 0) { // // Если нужен таймер - запустим
_RUN(last_as_blank_ts) = us_get_now_monotonic() + stream->last_as_blank;
run->last_as_blank_ts = us_get_now_monotonic() + stream->last_as_blank;
US_LOG_INFO("Freezed last ALIVE video frame for %d seconds", stream->last_as_blank);
} else { // last_as_blank == 0 - показываем последний фрейм вечно
US_LOG_INFO("Freezed last ALIVE video frame forever");
}
} else if (stream->last_as_blank < 0) {
new = blank->jpeg;
new = run->blank->jpeg;
// US_LOG_INFO("Changed video frame to BLANK");
}
if ( // Если уже оффлайн, включена фича last_as_blank с таймером и он запущен
stream->last_as_blank > 0
&& _RUN(last_as_blank_ts) != 0
&& _RUN(last_as_blank_ts) < us_get_now_monotonic()
&& run->last_as_blank_ts != 0
&& run->last_as_blank_ts < us_get_now_monotonic()
) {
new = blank->jpeg;
_RUN(last_as_blank_ts) = 0; // Останавливаем таймер
new = run->blank->jpeg;
run->last_as_blank_ts = 0; // Останавливаем таймер
US_LOG_INFO("Changed last ALIVE video frame to BLANK");
}
}
@ -349,5 +353,5 @@ static void _stream_expose_frame(us_stream_s *stream, us_frame_s *frame) {
run->last_online = (frame != NULL);
us_ring_producer_release(run->http_jpeg_ring, ri);
_SINK_PUT(sink, (frame != NULL ? frame : blank->jpeg));
_SINK_PUT(sink, (frame != NULL ? frame : run->blank->jpeg));
}