mirror of
https://github.com/pikvm/ustreamer.git
synced 2026-04-12 01:26:13 +00:00
deprecated --last-as-blank
This commit is contained in:
@@ -371,7 +371,7 @@ int options_parse(us_options_s *options, us_device_s *dev, us_encoder_s *enc, us
|
|||||||
case _O_ENCODER: OPT_PARSE_ENUM("encoder type", enc->type, us_encoder_parse_type, ENCODER_TYPES_STR);
|
case _O_ENCODER: OPT_PARSE_ENUM("encoder type", enc->type, us_encoder_parse_type, ENCODER_TYPES_STR);
|
||||||
case _O_GLITCHED_RESOLUTIONS: break; // Deprecated
|
case _O_GLITCHED_RESOLUTIONS: break; // Deprecated
|
||||||
case _O_BLANK: break; // Deprecated
|
case _O_BLANK: break; // Deprecated
|
||||||
case _O_LAST_AS_BLANK: OPT_NUMBER("--last-as-blank", stream->last_as_blank, 0, 86400, 0);
|
case _O_LAST_AS_BLANK: break; // Deprecated
|
||||||
case _O_SLOWDOWN: OPT_SET(stream->slowdown, true);
|
case _O_SLOWDOWN: OPT_SET(stream->slowdown, true);
|
||||||
case _O_DEVICE_TIMEOUT: OPT_NUMBER("--device-timeout", dev->timeout, 1, 60, 0);
|
case _O_DEVICE_TIMEOUT: OPT_NUMBER("--device-timeout", dev->timeout, 1, 60, 0);
|
||||||
case _O_DEVICE_ERROR_DELAY: OPT_NUMBER("--device-error-delay", stream->error_delay, 1, 60, 0);
|
case _O_DEVICE_ERROR_DELAY: OPT_NUMBER("--device-error-delay", stream->error_delay, 1, 60, 0);
|
||||||
@@ -624,13 +624,8 @@ static void _help(FILE *fp, const us_device_s *dev, const us_encoder_s *enc, con
|
|||||||
SAY(" * M2M-IMAGE ── GPU-accelerated JPEG encoding using V4L2 M2M image interface;");
|
SAY(" * M2M-IMAGE ── GPU-accelerated JPEG encoding using V4L2 M2M image interface;");
|
||||||
SAY(" * NOOP ─────── Don't compress MJPEG stream (do nothing).\n");
|
SAY(" * NOOP ─────── Don't compress MJPEG stream (do nothing).\n");
|
||||||
SAY(" -g|--glitched-resolutions <WxH,...> ─ It doesn't do anything. Still here for compatibility.\n");
|
SAY(" -g|--glitched-resolutions <WxH,...> ─ It doesn't do anything. Still here for compatibility.\n");
|
||||||
SAY(" -k|--blank <path> ─────────────────── It doesn't do anything. Still here for compatibility..\n");
|
SAY(" -k|--blank <path> ─────────────────── It doesn't do anything. Still here for compatibility.\n");
|
||||||
SAY(" during the streaming. Default: black screen 640x480 with 'NO SIGNAL'.\n");
|
SAY(" -K|--last-as-blank <sec> ──────────── It doesn't do anything. Still here for compatibility.\n");
|
||||||
SAY(" -K|--last-as-blank <sec> ──────────── Show the last frame received from the camera after it was disconnected,");
|
|
||||||
SAY(" but no more than specified time (or endlessly if 0 is specified).");
|
|
||||||
SAY(" If the device has not yet been online, display some error text.");
|
|
||||||
SAY(" Default: disabled.");
|
|
||||||
SAY(" Note: currently this option has no effect on memory sinks.\n");
|
|
||||||
SAY(" -l|--slowdown ─────────────────────── Slowdown capturing to 1 FPS or less when no stream or sink clients");
|
SAY(" -l|--slowdown ─────────────────────── Slowdown capturing to 1 FPS or less when no stream or sink clients");
|
||||||
SAY(" are connected. Useful to reduce CPU consumption. Default: disabled.\n");
|
SAY(" are connected. Useful to reduce CPU consumption. Default: disabled.\n");
|
||||||
SAY(" --device-timeout <sec> ────────────── Timeout for device querying. Default: %u.\n", dev->timeout);
|
SAY(" --device-timeout <sec> ────────────── Timeout for device querying. Default: %u.\n", dev->timeout);
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ static us_hw_buffer_s *_get_latest_hw(us_queue_s *queue);
|
|||||||
|
|
||||||
static bool _stream_has_any_clients(us_stream_s *stream);
|
static bool _stream_has_any_clients(us_stream_s *stream);
|
||||||
static int _stream_init_loop(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);
|
static void _stream_expose_http(us_stream_s *stream, us_frame_s *frame);
|
||||||
static void _stream_check_suicide(us_stream_s *stream);
|
static void _stream_check_suicide(us_stream_s *stream);
|
||||||
|
|
||||||
|
|
||||||
@@ -110,7 +110,6 @@ us_stream_s *us_stream_init(us_device_s *dev, us_encoder_s *enc) {
|
|||||||
US_CALLOC(stream, 1);
|
US_CALLOC(stream, 1);
|
||||||
stream->dev = dev;
|
stream->dev = dev;
|
||||||
stream->enc = enc;
|
stream->enc = enc;
|
||||||
stream->last_as_blank = -1;
|
|
||||||
stream->error_delay = 1;
|
stream->error_delay = 1;
|
||||||
stream->h264_bitrate = 5000; // Kbps
|
stream->h264_bitrate = 5000; // Kbps
|
||||||
stream->h264_gop = 30;
|
stream->h264_gop = 30;
|
||||||
@@ -326,10 +325,11 @@ static void *_jpeg_thread(void *v_ctx) {
|
|||||||
if (ready_wr->job_failed) {
|
if (ready_wr->job_failed) {
|
||||||
// pass
|
// pass
|
||||||
} else if (ready_wr->job_timely) {
|
} else if (ready_wr->job_timely) {
|
||||||
_stream_expose_frame(stream, ready_job->dest);
|
_stream_expose_http(stream, ready_job->dest);
|
||||||
if (atomic_load(&stream->run->http_snapshot_requested) > 0) { // Process real snapshots
|
if (atomic_load(&stream->run->http_snapshot_requested) > 0) { // Process real snapshots
|
||||||
atomic_fetch_sub(&stream->run->http_snapshot_requested, 1);
|
atomic_fetch_sub(&stream->run->http_snapshot_requested, 1);
|
||||||
}
|
}
|
||||||
|
_SINK_PUT(jpeg_sink, ready_job->dest);
|
||||||
US_LOG_PERF("##### Encoded JPEG exposed; worker=%s, latency=%.3Lf",
|
US_LOG_PERF("##### Encoded JPEG exposed; worker=%s, latency=%.3Lf",
|
||||||
ready_wr->name, us_get_now_monotonic() - ready_job->dest->grab_ts);
|
ready_wr->name, us_get_now_monotonic() - ready_job->dest->grab_ts);
|
||||||
} else {
|
} else {
|
||||||
@@ -355,7 +355,7 @@ static void *_jpeg_thread(void *v_ctx) {
|
|||||||
const ldf now_ts = us_get_now_monotonic();
|
const ldf now_ts = us_get_now_monotonic();
|
||||||
if (now_ts < grab_after) {
|
if (now_ts < grab_after) {
|
||||||
fluency_passed += 1;
|
fluency_passed += 1;
|
||||||
US_LOG_VERBOSE("Passed %u frames for fluency: now=%.03Lf, grab_after=%.03Lf",
|
US_LOG_VERBOSE("Passed %u JPEG frames for fluency: now=%.03Lf, grab_after=%.03Lf",
|
||||||
fluency_passed, now_ts, grab_after);
|
fluency_passed, now_ts, grab_after);
|
||||||
us_device_buffer_decref(hw);
|
us_device_buffer_decref(hw);
|
||||||
continue;
|
continue;
|
||||||
@@ -440,15 +440,15 @@ static int _stream_init_loop(us_stream_s *stream) {
|
|||||||
us_blank_draw(run->blank, "< NO SIGNAL >", width, height);
|
us_blank_draw(run->blank, "< NO SIGNAL >", width, height);
|
||||||
|
|
||||||
_stream_set_capture_state(stream, width, height, false, 0);
|
_stream_set_capture_state(stream, width, height, false, 0);
|
||||||
_stream_expose_frame(stream, NULL);
|
|
||||||
# ifdef WITH_GPIO
|
# ifdef WITH_GPIO
|
||||||
us_gpio_set_stream_online(false);
|
us_gpio_set_stream_online(false);
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
_stream_expose_http(stream, run->blank->jpeg);
|
||||||
|
_SINK_PUT(jpeg_sink, run->blank->jpeg);
|
||||||
if (run->h264 != NULL) {
|
if (run->h264 != NULL) {
|
||||||
us_h264_stream_process(run->h264, run->blank->raw, true);
|
us_h264_stream_process(run->h264, run->blank->raw, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_SINK_PUT(raw_sink, run->blank->raw);
|
_SINK_PUT(raw_sink, run->blank->raw);
|
||||||
|
|
||||||
stream->dev->dma_export = (
|
stream->dev->dma_export = (
|
||||||
@@ -482,75 +482,29 @@ static int _stream_init_loop(us_stream_s *stream) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _stream_expose_frame(us_stream_s *stream, us_frame_s *frame) {
|
static void _stream_expose_http(us_stream_s *stream, us_frame_s *frame) {
|
||||||
us_stream_runtime_s *const run = stream->run;
|
us_stream_runtime_s *const run = stream->run;
|
||||||
|
int ri;
|
||||||
us_frame_s *new = NULL;
|
while ((ri = us_ring_producer_acquire(run->http_jpeg_ring, 0)) < 0) {
|
||||||
|
if (atomic_load(&run->stop)) {
|
||||||
if (frame != NULL) {
|
return;
|
||||||
new = frame;
|
|
||||||
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 = 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;
|
|
||||||
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 = 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()
|
|
||||||
) {
|
|
||||||
new = run->blank->jpeg;
|
|
||||||
run->last_as_blank_ts = 0; // Останавливаем таймер
|
|
||||||
US_LOG_INFO("Changed last ALIVE video frame to BLANK");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int ri = -1;
|
|
||||||
while (
|
|
||||||
!atomic_load(&run->stop)
|
|
||||||
&& ((ri = us_ring_producer_acquire(run->http_jpeg_ring, 0)) < 0)
|
|
||||||
) {
|
|
||||||
// US_LOG_ERROR("Can't push JPEG to HTTP ring (no free slots)");
|
|
||||||
}
|
|
||||||
if (ri < 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
us_frame_s *const dest = run->http_jpeg_ring->items[ri];
|
us_frame_s *const dest = run->http_jpeg_ring->items[ri];
|
||||||
if (new == NULL) {
|
us_frame_copy(frame, dest);
|
||||||
dest->used = 0;
|
|
||||||
dest->online = false;
|
|
||||||
} else {
|
|
||||||
us_frame_copy(new, dest);
|
|
||||||
dest->online = true;
|
|
||||||
}
|
|
||||||
run->last_online = (frame != NULL);
|
|
||||||
us_ring_producer_release(run->http_jpeg_ring, ri);
|
us_ring_producer_release(run->http_jpeg_ring, ri);
|
||||||
|
|
||||||
_SINK_PUT(jpeg_sink, (frame != NULL ? frame : run->blank->jpeg));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _stream_check_suicide(us_stream_s *stream) {
|
static void _stream_check_suicide(us_stream_s *stream) {
|
||||||
if (stream->exit_on_no_clients == 0) {
|
if (stream->exit_on_no_clients == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
us_stream_runtime_s *const run = stream->run;
|
us_stream_runtime_s *const run = stream->run;
|
||||||
|
|
||||||
const ldf now_ts = us_get_now_monotonic();
|
const ldf now_ts = us_get_now_monotonic();
|
||||||
const ull http_last_request_ts = atomic_load(&run->http_last_request_ts); // Seconds
|
const ull http_last_request_ts = atomic_load(&run->http_last_request_ts); // Seconds
|
||||||
|
|
||||||
if (_stream_has_any_clients(stream)) {
|
if (_stream_has_any_clients(stream)) {
|
||||||
atomic_store(&run->http_last_request_ts, now_ts);
|
atomic_store(&run->http_last_request_ts, now_ts);
|
||||||
} else if (http_last_request_ts + stream->exit_on_no_clients < now_ts) {
|
} else if (http_last_request_ts + stream->exit_on_no_clients < now_ts) {
|
||||||
|
|||||||
@@ -46,9 +46,6 @@ typedef struct {
|
|||||||
atomic_ullong http_last_request_ts; // Seconds
|
atomic_ullong http_last_request_ts; // Seconds
|
||||||
atomic_ullong http_capture_state; // Bits
|
atomic_ullong http_capture_state; // Bits
|
||||||
|
|
||||||
bool last_online;
|
|
||||||
long double last_as_blank_ts;
|
|
||||||
|
|
||||||
us_blank_s *blank;
|
us_blank_s *blank;
|
||||||
|
|
||||||
atomic_bool stop;
|
atomic_bool stop;
|
||||||
|
|||||||
Reference in New Issue
Block a user