mirror of
https://github.com/pikvm/ustreamer.git
synced 2025-12-23 18:50:00 +00:00
Fixed #290: improved blank diagnostics
This commit is contained in:
parent
7a1d4816ed
commit
620a0ec847
@ -11,7 +11,7 @@
|
||||
|----------|---------------|-------------------|
|
||||
| Multithreaded JPEG encoding | ✔ | ✘ |
|
||||
| Hardware image encoding<br>on Raspberry Pi | ✔ | ✘ |
|
||||
| Behavior when the device<br>is disconnected while streaming | ✔ Shows a black screen<br>with ```NO SIGNAL``` on it<br>until reconnected | ✘ Stops the streaming <sup>1</sup> |
|
||||
| Behavior when the device<br>is disconnected while streaming | ✔ Shows a black screen<br>with ```NO LIVE VIDEO``` on it<br>until reconnected | ✘ Stops the streaming <sup>1</sup> |
|
||||
| [DV-timings](https://linuxtv.org/downloads/v4l-dvb-apis-new/userspace-api/v4l/dv-timings.html) support -<br>the ability to change resolution<br>on the fly by source signal | ✔ | ☹ Partially yes <sup>1</sup> |
|
||||
| Option to skip frames when streaming<br>static images by HTTP to save the traffic | ✔ <sup>2</sup> | ✘ |
|
||||
| Streaming via UNIX domain socket | ✔ | ✘ |
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
#include "threading.h"
|
||||
#include "frame.h"
|
||||
#include "xioctl.h"
|
||||
#include "tc358743.h"
|
||||
|
||||
|
||||
static const struct {
|
||||
@ -200,11 +201,11 @@ int us_capture_open(us_capture_s *cap) {
|
||||
}
|
||||
}
|
||||
_LOG_DEBUG("Probing DV-timings or QuerySTD ...");
|
||||
if (_capture_open_dv_timings(cap, false) < 0) {
|
||||
US_ONCE_FOR(run->open_error_once, __LINE__, {
|
||||
_LOG_ERROR("No signal from source");
|
||||
});
|
||||
goto error_no_signal;
|
||||
switch (_capture_open_dv_timings(cap, false)) {
|
||||
case 0: break;
|
||||
case US_ERROR_NO_SIGNAL: goto error_no_signal;
|
||||
case US_ERROR_NO_SYNC: goto error_no_sync;
|
||||
default: goto error;
|
||||
}
|
||||
}
|
||||
|
||||
@ -222,6 +223,15 @@ int us_capture_open(us_capture_s *cap) {
|
||||
if (_capture_open_format(cap, true) < 0) {
|
||||
goto error;
|
||||
}
|
||||
if (cap->dv_timings && cap->persistent) {
|
||||
struct v4l2_control ctl = {.id = TC358743_CID_LANES_ENOUGH};
|
||||
if (!us_xioctl(run->fd, VIDIOC_G_CTRL, &ctl)) {
|
||||
if (!ctl.value) {
|
||||
_LOG_ERROR("Not enough lanes, hardware can't handle this signal");
|
||||
goto error_no_lanes;
|
||||
}
|
||||
}
|
||||
}
|
||||
_capture_open_hw_fps(cap);
|
||||
_capture_open_jpeg_quality(cap);
|
||||
if (_capture_open_io_method(cap) < 0) {
|
||||
@ -259,8 +269,18 @@ error_no_cable:
|
||||
return US_ERROR_NO_CABLE;
|
||||
|
||||
error_no_signal:
|
||||
US_ONCE_FOR(run->open_error_once, __LINE__, { _LOG_ERROR("No signal from source"); });
|
||||
us_capture_close(cap);
|
||||
return US_ERROR_NO_DATA;
|
||||
return US_ERROR_NO_SIGNAL;
|
||||
|
||||
error_no_sync:
|
||||
US_ONCE_FOR(run->open_error_once, __LINE__, { _LOG_ERROR("No sync on signal"); });
|
||||
us_capture_close(cap);
|
||||
return US_ERROR_NO_SYNC;
|
||||
|
||||
error_no_lanes:
|
||||
us_capture_close(cap);
|
||||
return US_ERROR_NO_LANES;
|
||||
|
||||
error:
|
||||
run->open_error_once = 0;
|
||||
@ -630,6 +650,10 @@ static int _capture_open_dv_timings(us_capture_s *cap, bool apply) {
|
||||
// TC358743 errors here (see in the kernel: drivers/media/i2c/tc358743.c):
|
||||
// - ENOLINK: No valid signal (SYS_STATUS & MASK_S_TMDS)
|
||||
// - ENOLCK: No sync on signal (SYS_STATUS & MASK_S_SYNC)
|
||||
switch (errno) {
|
||||
case ENOLINK: return US_ERROR_NO_SIGNAL;
|
||||
case ENOLCK: return US_ERROR_NO_SYNC;
|
||||
}
|
||||
dv_errno = errno;
|
||||
goto querystd;
|
||||
} else if (!apply) {
|
||||
|
||||
@ -378,7 +378,7 @@ int us_drm_expose_stub(us_drm_s *drm, us_drm_stub_e stub, const us_capture_s *ca
|
||||
DRAW_MSG("=== PiKVM ===\n \n< UNSUPPORTED CAPTURE FORMAT >");
|
||||
break;
|
||||
case US_DRM_STUB_NO_SIGNAL:
|
||||
DRAW_MSG("=== PiKVM ===\n \n< NO SIGNAL >");
|
||||
DRAW_MSG("=== PiKVM ===\n \n< NO LIVE VIDEO >");
|
||||
break;
|
||||
case US_DRM_STUB_BUSY:
|
||||
DRAW_MSG("=== PiKVM ===\n \n< ONLINE IS ACTIVE >");
|
||||
|
||||
@ -25,4 +25,7 @@
|
||||
#define US_ERROR_COMMON -1
|
||||
#define US_ERROR_NO_DEVICE -2
|
||||
#define US_ERROR_NO_CABLE -3
|
||||
#define US_ERROR_NO_DATA -4
|
||||
#define US_ERROR_NO_SIGNAL -4
|
||||
#define US_ERROR_NO_SYNC -5
|
||||
#define US_ERROR_NO_LANES -6
|
||||
#define US_ERROR_NO_DATA -7
|
||||
|
||||
@ -33,17 +33,6 @@
|
||||
#include "xioctl.h"
|
||||
|
||||
|
||||
#ifndef V4L2_CID_USER_TC358743_BASE
|
||||
# define V4L2_CID_USER_TC358743_BASE (V4L2_CID_USER_BASE + 0x1080)
|
||||
#endif
|
||||
#ifndef TC358743_CID_AUDIO_PRESENT
|
||||
# define TC358743_CID_AUDIO_PRESENT (V4L2_CID_USER_TC358743_BASE + 1)
|
||||
#endif
|
||||
#ifndef TC358743_CID_AUDIO_SAMPLING_RATE
|
||||
# define TC358743_CID_AUDIO_SAMPLING_RATE (V4L2_CID_USER_TC358743_BASE + 0)
|
||||
#endif
|
||||
|
||||
|
||||
int us_tc358743_xioctl_get_audio_hz(int fd, uint *audio_hz) {
|
||||
*audio_hz = 0;
|
||||
|
||||
|
||||
@ -22,7 +22,26 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <linux/v4l2-controls.h>
|
||||
|
||||
#include "types.h"
|
||||
|
||||
|
||||
#ifndef V4L2_CID_USER_TC358743_BASE
|
||||
# define V4L2_CID_USER_TC358743_BASE (V4L2_CID_USER_BASE + 0x1080)
|
||||
#endif
|
||||
|
||||
#ifndef TC358743_CID_AUDIO_SAMPLING_RATE
|
||||
# define TC358743_CID_AUDIO_SAMPLING_RATE (V4L2_CID_USER_TC358743_BASE + 0)
|
||||
#endif
|
||||
|
||||
#ifndef TC358743_CID_AUDIO_PRESENT
|
||||
# define TC358743_CID_AUDIO_PRESENT (V4L2_CID_USER_TC358743_BASE + 1)
|
||||
#endif
|
||||
|
||||
#ifndef TC358743_CID_LANES_ENOUGH
|
||||
# define TC358743_CID_LANES_ENOUGH (V4L2_CID_USER_TC358743_BASE + 2)
|
||||
#endif
|
||||
|
||||
|
||||
int us_tc358743_xioctl_get_audio_hz(int fd, uint *audio_hz);
|
||||
|
||||
@ -36,7 +36,7 @@ us_blank_s *us_blank_init(void) {
|
||||
blank->ft = us_frametext_init();
|
||||
blank->raw = blank->ft->frame;
|
||||
blank->jpeg = us_frame_init();
|
||||
us_blank_draw(blank, "< NO SIGNAL >", 640, 480);
|
||||
us_blank_draw(blank, "< NO LIVE VIDEO >", 640, 480);
|
||||
return blank;
|
||||
}
|
||||
|
||||
|
||||
@ -880,7 +880,7 @@ static void _http_send_snapshot(us_server_s *server) {
|
||||
if (!captured_meta.online) {
|
||||
if (blank == NULL) {
|
||||
blank = us_blank_init();
|
||||
us_blank_draw(blank, "< NO SIGNAL >", captured_meta.width, captured_meta.height);
|
||||
us_blank_draw(blank, "< NO LIVE VIDEO >", captured_meta.width, captured_meta.height);
|
||||
}
|
||||
frame = blank->jpeg;
|
||||
}
|
||||
|
||||
@ -129,7 +129,7 @@ us_stream_s *us_stream_init(us_capture_s *cap, us_encoder_s *enc) {
|
||||
|
||||
void us_stream_update_blank(us_stream_s *stream, const us_capture_s *cap) {
|
||||
us_stream_runtime_s *const run = stream->run;
|
||||
us_blank_draw(run->blank, "< NO SIGNAL >", cap->width, cap->height);
|
||||
us_blank_draw(run->blank, "< NO LIVE VIDEO >", cap->width, cap->height);
|
||||
us_fpsi_frame_to_meta(run->blank->raw, &run->notify_meta); // Initial "unchanged" meta
|
||||
_stream_update_captured_fpsi(stream, run->blank->raw, false);
|
||||
}
|
||||
@ -529,7 +529,7 @@ static int _stream_init_loop(us_stream_s *stream) {
|
||||
|
||||
int once = 0;
|
||||
while (!atomic_load(&stream->run->stop)) {
|
||||
char *blank_reason = "< NO SIGNAL >";
|
||||
const char *blank_reason = "< NO LIVE VIDEO >";
|
||||
|
||||
# ifdef WITH_GPIO
|
||||
us_gpio_set_stream_online(false);
|
||||
@ -556,24 +556,58 @@ static int _stream_init_loop(us_stream_s *stream) {
|
||||
switch (us_capture_open(stream->cap)) {
|
||||
case 0: break;
|
||||
case US_ERROR_NO_DEVICE:
|
||||
blank_reason = "< NO CAPTURE DEVICE >";
|
||||
goto known_error;
|
||||
blank_reason = (
|
||||
"< NO CAPTURE DEVICE >\n \n"
|
||||
" Possible reasons: \n \n"
|
||||
" - Device unplugged \n \n"
|
||||
" - Bad config \n \n"
|
||||
" - Malfunction "
|
||||
);
|
||||
goto silent_error;
|
||||
case US_ERROR_NO_CABLE:
|
||||
blank_reason = "< NO VIDEO SOURCE >";
|
||||
goto known_error;
|
||||
case US_ERROR_NO_DATA:
|
||||
goto known_error;
|
||||
blank_reason = (
|
||||
"< NO VIDEO SOURCE >\n \n"
|
||||
" Possible reasons: \n \n"
|
||||
" - Source is off \n \n"
|
||||
" - Cable problems "
|
||||
);
|
||||
goto silent_error;
|
||||
case US_ERROR_NO_SIGNAL:
|
||||
blank_reason = (
|
||||
"< NO SIGNAL DETECTED >\n \n"
|
||||
" Possible reasons: \n \n"
|
||||
" - Video suspended \n \n"
|
||||
" - Cable problems "
|
||||
);
|
||||
goto silent_error;
|
||||
case US_ERROR_NO_SYNC:
|
||||
blank_reason = (
|
||||
"< NO SYNC WITH SIGNAL >\n \n"
|
||||
" Possible reasons: \n \n"
|
||||
" - Source is crazy \n \n"
|
||||
" - Cable problems "
|
||||
);
|
||||
goto silent_error;
|
||||
case US_ERROR_NO_LANES:
|
||||
blank_reason = (
|
||||
"< UNSUPPORTED SIGNAL TIMINGS >\n \n"
|
||||
" Possible reasons: \n \n"
|
||||
" - Too high frequency \n \n"
|
||||
" - Source ignores EDID \n \n"
|
||||
" - Invalid EDID "
|
||||
);
|
||||
goto verbose_error;
|
||||
default:
|
||||
goto unknown_error;
|
||||
goto verbose_error;
|
||||
}
|
||||
us_encoder_open(stream->enc, stream->cap);
|
||||
return 0;
|
||||
|
||||
known_error:
|
||||
silent_error:
|
||||
US_ONCE({ US_LOG_INFO("Waiting for the capture device ..."); });
|
||||
goto offline_and_retry;
|
||||
|
||||
unknown_error:
|
||||
verbose_error:
|
||||
once = 0;
|
||||
goto offline_and_retry;
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user