Rename applies to Go2RTC, Janus, and RTSP2Web streaming options.
Update enum values from Primary/Secondary to Restream/CameraDirectPrimary/CameraDirectSecondary.
- Add db migration zm_update-1.37.79.sql to rename column and migrate data
- Update C++ enum StreamChannelOption and member stream_channel
- Update PHP getStreamChannelOptions() method
- Update all JavaScript references
- Auto-select CameraDirectPrimary when Restream option becomes disabled
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Rename Janus-specific restream fields to be more generic since they are
now used by Go2RTC and RTSP2Web as well:
- Janus_Use_RTSP_Restream → Restream
- Janus_RTSP_User → RTSP_User
Update visibility logic so the Restream checkbox appears when RTSPServer
is enabled AND any streaming service (Janus, Go2RTC, or RTSP2Web) is
selected, rather than only when Janus is enabled.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add early return in findMarker() when size < 3 to prevent unsigned
underflow in loop condition (size-2 with size_t)
- Change remainingSize from int to size_t in extractFrame() to match
the unsigned types used in the calculation
- Update Debug format specifier from %d to %zu for size_t
- Change Info to Debug for "No marker found" log message
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Two issues fixed:
1. Null soap context on retry: After a failed subscription attempt,
soap_free() was called but the context was never recreated. Added
InitSoapContext() to reinitialize the soap context, proxy, and
endpoint when needed.
2. Use-after-free in Renew/PullMessages: soap_end() frees all gSOAP
allocated memory including response.SubscriptionReference.Address.
Subsequent calls to Renew() used the freed pointer, causing DNS
errors on valid IP addresses. Added subscription_address_ member
to cache the address before soap_end() is called.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add optional libunwind support for better stack traces on ARM
(glibc's backtrace() doesn't work well on ARM due to missing
frame pointers)
- Fix misleading signal info: si_pid/si_uid/si_status are only
valid for SIGCHLD, not for SIGSEGV/SIGBUS - they were showing
garbage values (the fault address misinterpreted as PID)
- Add human-readable fault descriptions for SIGSEGV, SIGBUS,
SIGFPE, and SIGILL signals
- Use clearer terminology in error messages
To enable libunwind on ARM: apt install libunwind-dev
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Extract H264 SPS/PPS and H265 VPS/SPS/PPS from video stream and pass
to xop sources for inclusion in SDP sprop-parameter-sets. This allows
RTSP clients like go2rtc to properly decode video with correct
dimensions.
Also adds auth_hash refresh support to go2rtc manager to prevent
authentication timeout after 2 hours.
Changes:
- zm_rtsp_server_fifo_h264_source.cpp: Re-enable SPS/PPS extraction
- zm_rtsp_server_fifo_video_source.h: Add xop source pointers
- zm_rtsp_server.cpp: Connect FIFO sources to xop sources
- zm_monitor_go2rtc.cpp: Add periodic auth_hash refresh
- zm_monitor.h: Add refresh tracking members to Go2RTCManager
- dep/RtspServer: Update xop H264/H265Source with sprop support
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Fix inverted logic in ReadRun(): was returning when NOT stopping,
now correctly returns when stopping or terminating
- Remove redundant "1 and" condition in WriteRun NAL size check
- Add input validation for content length parsing using strtoul
with bounds checking to prevent overflow/invalid data issues
- Store m_rtspServer by value instead of reference to prevent
potential dangling reference if original shared_ptr changes
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When analysis_image is set to ANALYSISIMAGE_YCHANNEL but in_frame is
not populated (e.g., LocalCamera which captures directly to image),
get_y_image() returns nullptr. The code was dereferencing this null
pointer in DetectMotion and Blend calls, causing a segfault.
Now checks if y_image is valid before use and skips the operation
with a debug message if unavailable.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add soap_destroy() and soap_end() calls after SOAP operations in:
- WaitForMessage(): after PullMessages processing
- Renew(): after Renew response processing (all return paths)
- Subscribe(): after initial PullMessages call
Also clear initialized_count map and warned_initialized_repeat flag
when creating new subscription to prevent unbounded map growth.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Wrap all GSOAP-dependent code in a single #ifdef WITH_GSOAP block
- Move GSOAP-specific members and methods inside the conditional
- Provide minimal stubs (constructor, destructor, start) for non-GSOAP builds
- Remove unnecessary stub methods for private members that can't be called
- Code now compiles cleanly with or without GSOAP support
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Monitor::Decode():
- Reorganize into 5 clear phases with descriptive comments
- Phase 1: Receive decoded frame from decoder
- Phase 2: Get and send new packet to decoder
- Phase 3: Convert decoded frame to Image
- Phase 4: Prepare Y-channel for analysis
- Phase 5: Process RGB image (deinterlace, rotate, privacy, timestamp)
- Extract applyOrientation() and applyDeinterlacing() helper functions
- Keep slow send_packet detection timing for diagnostics
PacketQueue locking fixes:
- Move lock acquisition before accessing shared state in queuePacket()
- Keep lock held while iterating in stop()
- Add lock to addStream()
- Remove duplicate packet_counts allocation in clear()
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Cameras like Reolink send alarm=true but never send the corresponding
false, causing alarms to stick indefinitely. Use the TerminationTime
from PullMessagesResponse to auto-expire stale per-topic alarms.
- Add AlarmEntry struct with value and termination_time fields
- Extract TerminationTime from each PullMessagesResponse and attach
it to alarm entries; refresh on re-trigger so active alarms persist
- Sweep expired alarms after processing messages and on poll timeout
- Add expire_alarms option (default: true) to disable via onvif_options
- Fix TOCTOU race: remove unsynchronized alarms.empty() check before
acquiring mutex in the timeout sweep path
- Simplify SetNoteSet with C++17 structured bindings
- Add Catch2 tests for alarm expiry logic (mirrored struct to avoid
gSOAP header dependency)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>