diff --git a/settings.txt b/settings.txt index 5916491..0f45f10 100644 --- a/settings.txt +++ b/settings.txt @@ -12,13 +12,13 @@ #height = 576 # Requested image refresh rate -#source-fps = 50 +#source-fps = 60 # Application drawing target framerate. This can responsiveness. # If the setting is lower than source-fps the framse will be dropped # If the setting is not multiple of source-fps can still cause frame drops cause out-of-sync # source images and drawing times -#fps = 50 +#fps = 60 # Application window mode # 0 - windowed @@ -108,16 +108,18 @@ # This is happening or Raspberry Pi Zero 2W. Disable this to use SW decoding for that case. #hw-decode = true -# Use double buffering for drawing video. May smooth rendering but increase CPU usage -#double-buffered = true; +# Rendeing buffer size, increse for smoothness but can introduce lag. Minimum size is 3 +#rendering-buffer = 5 + +# Skip several frames on processing events if FPS drops. Can increase responsivenes and reduce lag. +#draw-skip-events = 3 # Request extra frames onevery key press. Usefull if you do not see last updates after key press # Enable for RPI hardware decoding and other systems where hardware decoder tends to buffer frames # 0 - disabled, enter number of frames to request (find minimal value that get all screen updates) +# Combine with force-redraw-timeout to request not imideately but with delay (also find minimal one) #force-redraw = 0 - -# Skip several frames on processing events if FPS drops. Can increase responsivenes and reduce lag. -#draw-skip-events = 0 +#force-redraw-timeout = 0 # Corrects aspect of UI #aspect-correction = 1 @@ -127,18 +129,19 @@ #renderer-driver = # Use alternative video rendering method. May reduce CPU load and increase smoothness. -#alternative-rendering = true +#alternative-rendering = false # Select faster method of scaling image to window size (nearest) or better quality (linear) #fast-render-scale = false # USB read pipeline tuning, number of libusb bulk transfers kept in flight and size of each USB transfer # Increase amount of async-usb-calls if you have issues with audio and video lagging behind -#async-usb-calls = 16 -#usb-buffer-size = 20480 +# If you have mallformed message errors on RPI try to increase async-usb-calls +#async-usb-calls = 32 +#usb-buffer-size = 2048 # Number of buffered USB data slots queued for processing -#usb-buffer = 64 +#usb-buffer = 128 # Size of video and audio buffers. Increase if you see artifacts #video-buffer-size = 64 @@ -237,3 +240,6 @@ # Enable FFMPEG AV_CODEC_FLAG2_FAST for HW decoder. # Allow non spec compliant speedup tricks. #decode-fast = true + +# Draw debug info overlay on top of the video output. +#debug-overlay = false diff --git a/src/application.cpp b/src/application.cpp index ebca340..decb125 100644 --- a/src/application.cpp +++ b/src/application.cpp @@ -371,15 +371,12 @@ void Application::loop() } } - if (_state.requestFrame > 0 && Settings::forceRedraw > 0) + if (_state.requestFrame > 0 && Settings::forceRedraw > 0 && ++_state.requestFrame - Settings::forceRedrawTimeout > 0) { - if (++_state.requestFrame % Settings::forceRedraw == 0) - { - log_d("Request screen update"); - protocol.send(Message::Control(BTN_SCREEN_REFRESH)); - if (_state.requestFrame >= Settings::forceRedraw * REDRAW_REQUEST) - _state.requestFrame = 0; - } + log_d("Request screen update"); + protocol.send(Message::Control(BTN_SCREEN_REFRESH)); + if (_state.requestFrame > Settings::forceRedrawTimeout + Settings::forceRedraw) + _state.requestFrame = 0; } } @@ -478,8 +475,8 @@ const std::string Application::status() const if (SDL_GetRendererInfo(renderer, &info) == 0) { out << " " << info.name - << ((info.flags & SDL_RENDERER_ACCELERATED) != 0?" accelerated":"") - << ((info.flags & SDL_RENDERER_PRESENTVSYNC) != 0?" vsync":""); + << ((info.flags & SDL_RENDERER_ACCELERATED) != 0 ? " accelerated" : "") + << ((info.flags & SDL_RENDERER_PRESENTVSYNC) != 0 ? " vsync" : ""); } } } diff --git a/src/common/functions.h b/src/common/functions.h index 142c37f..5a25dcb 100644 --- a/src/common/functions.h +++ b/src/common/functions.h @@ -46,4 +46,22 @@ inline void pushEvent(Uint32 evt, int code) SDL_PushEvent(&event); } +#include +#include + +inline std::string bytes(uint8_t *data, uint32_t length, uint16_t max) +{ + std::ostringstream out; + + if (data && length >= 4) + { + for (size_t i = 0; (i < length) && (i < max); ++i) + { + out << std::setw(4) << static_cast(data[i]); + } + } + + return out.str(); +} + #endif /* SRC_COMMON_FUNCTIONS */ diff --git a/src/protocol/connection_reader.cpp b/src/protocol/connection_reader.cpp index 19d84a6..1e33557 100644 --- a/src/protocol/connection_reader.cpp +++ b/src/protocol/connection_reader.cpp @@ -12,6 +12,7 @@ #include "common/threading.h" #include "protocol/protocol_const.h" #include "libavcodec/defs.h" +#include "common/functions.h" ConnectionReader::ConnectionReader() : _active(false), @@ -133,7 +134,7 @@ void ConnectionReader::onUsbRead(libusb_transfer *transfer) if (!c->owner->_active) return; - log_p("USB read > status %d length %d", transfer->status, transfer->actual_length); + log_p("Read %d [%d]: %s", transfer->actual_length, transfer->status, bytes(transfer->buffer, transfer->actual_length, 40).c_str()); if (transfer->status == LIBUSB_TRANSFER_CANCELLED) return; @@ -197,7 +198,7 @@ void ConnectionReader::processLoop() if (!message->valid()) { - log_w("Received mallformed message"); + log_w("Mallformed message %s", message->toString(20).c_str()); continue; } diff --git a/src/protocol/message.h b/src/protocol/message.h index 74207ae..50de96b 100644 --- a/src/protocol/message.h +++ b/src/protocol/message.h @@ -299,6 +299,56 @@ public: int32_t length() const { return _header.length - _offset; } uint8_t *data() const { return _data ? _data + _offset : nullptr; } + const std::string toString(int count) const + { + const char *cmds = "Unknown"; + for (size_t i = 0; i < sizeof(protocolCmdList) / sizeof(protocolCmdList[0]); ++i) + { + if (protocolCmdList[i].cmd == static_cast(_header.type)) + { + cmds = protocolCmdList[i].name; + break; + } + } + + char len[32]; + std::snprintf(len, sizeof(len), "[%d]", _header.length); + + char magic = '!'; + if (_header.magic == MAGIC) + magic = ' '; + else if (_header.magic == MAGIC_ENC) + magic = '*'; + + char check = _header.typecheck == ~_header.type ? '+' : 'x'; + + char prefix[64]; + std::snprintf(prefix, sizeof(prefix), ">%c%c%3u%-8s%-15s", + magic, + check, + static_cast(_header.type), + len, + cmds); + + std::string result(prefix); + uint8_t *payload = data(); + int32_t payloadLength = length(); + + if (payload && payloadLength > 0 && count > 0) + { + int limit = std::min(count, payloadLength); + result.reserve(result.size() + static_cast(limit)); + + for (int i = 0; i < limit; ++i) + { + char ch = static_cast(payload[i]); + result += (ch == '\n' || ch == '\r' || ch < 32 || ch > 126) ? '.' : ch; + } + } + + return result; + } + private: static inline void write_uint32_le(uint8_t *dst, uint32_t value) { diff --git a/src/settings.h b/src/settings.h index dab6298..7514aad 100644 --- a/src/settings.h +++ b/src/settings.h @@ -42,6 +42,7 @@ public: static inline Setting renderingBuffer{"rendering-buffer", 5}; static inline Setting eventsSkip{"draw-skip-events", 3}; static inline Setting forceRedraw{"force-redraw", 0}; + static inline Setting forceRedrawTimeout{"force-redraw-timeout", 0}; static inline Setting aspectCorrection{"aspect-correction", 1}; static inline Setting renderDriver{"renderer-driver", ""}; static inline Setting alternativeRendering{"alternative-rendering", false};