Skip to content

Commit c19fbad

Browse files
committed
fix motion onvif detection
1 parent ae787ab commit c19fbad

1 file changed

Lines changed: 91 additions & 0 deletions

File tree

src/video/unified_detection_thread.c

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
#include "video/detection_result.h"
4444
#include "video/api_detection.h"
4545
#include "video/motion_detection.h"
46+
#include "video/onvif_detection.h"
4647
#include "video/mp4_writer.h"
4748
#include "video/mp4_writer_internal.h"
4849
#include "video/mp4_recording.h"
@@ -120,6 +121,53 @@ static bool is_motion_detection_model(const char *model_path) {
120121
return strcmp(model_path, "motion") == 0;
121122
}
122123

124+
/**
125+
* Check if a model path indicates ONVIF event-based detection
126+
* Returns true if the path is exactly "onvif"
127+
*/
128+
static bool is_onvif_detection_model(const char *model_path) {
129+
if (!model_path || model_path[0] == '\0') {
130+
return false;
131+
}
132+
return strcmp(model_path, "onvif") == 0;
133+
}
134+
135+
/**
136+
* Derive an ONVIF base URL (http://host) from a stream URL.
137+
* Strips the scheme, credentials, port, and path, then prepends "http://".
138+
* Examples:
139+
* rtsp://admin:pass@192.168.1.100:554/stream → http://192.168.1.100
140+
* onvif://192.168.1.100/onvif/device_service → http://192.168.1.100
141+
*/
142+
static void extract_onvif_base_url(const char *stream_url, char *onvif_url, size_t onvif_url_size) {
143+
if (!stream_url || !onvif_url || onvif_url_size == 0) {
144+
return;
145+
}
146+
onvif_url[0] = '\0';
147+
148+
/* Skip scheme (rtsp://, onvif://, http://, etc.) */
149+
const char *host_start = strstr(stream_url, "://");
150+
if (!host_start) {
151+
snprintf(onvif_url, onvif_url_size, "http://%s", stream_url);
152+
return;
153+
}
154+
host_start += 3; /* skip "://" */
155+
156+
/* Skip optional credentials (user:pass@) */
157+
const char *at_sign = strchr(host_start, '@');
158+
if (at_sign) {
159+
host_start = at_sign + 1;
160+
}
161+
162+
/* Find end of bare hostname: stop at ':', '/', or NUL */
163+
const char *host_end = host_start;
164+
while (*host_end && *host_end != ':' && *host_end != '/') {
165+
host_end++;
166+
}
167+
168+
snprintf(onvif_url, onvif_url_size, "http://%.*s", (int)(host_end - host_start), host_start);
169+
}
170+
123171
/**
124172
* Initialize the unified detection thread system
125173
*/
@@ -1595,6 +1643,49 @@ static bool run_detection_on_frame(unified_detection_ctx_t *ctx, AVPacket *pkt)
15951643
return mot_triggered;
15961644
}
15971645

1646+
// ONVIF event-based detection — no frame decoding needed
1647+
if (is_onvif_detection_model(ctx->model_path)) {
1648+
// Fetch the stream config to obtain the camera URL and ONVIF credentials
1649+
stream_config_t onvif_cfg;
1650+
memset(&onvif_cfg, 0, sizeof(onvif_cfg));
1651+
if (get_stream_config_by_name(ctx->stream_name, &onvif_cfg) != 0) {
1652+
log_warn("[%s] ONVIF detection: failed to look up stream config", ctx->stream_name);
1653+
return false;
1654+
}
1655+
1656+
// Derive http://host from the stream's RTSP/ONVIF URL
1657+
char onvif_url[MAX_PATH_LENGTH];
1658+
extract_onvif_base_url(onvif_cfg.url, onvif_url, sizeof(onvif_url));
1659+
1660+
if (onvif_url[0] == '\0') {
1661+
log_warn("[%s] ONVIF detection: could not derive ONVIF URL from stream URL: %s",
1662+
ctx->stream_name, onvif_cfg.url);
1663+
return false;
1664+
}
1665+
1666+
log_debug("[%s] ONVIF detection: polling events at %s (user=%s)",
1667+
ctx->stream_name, onvif_url, onvif_cfg.onvif_username);
1668+
1669+
// detect_motion_onvif already handles DB storage, MQTT publish, and
1670+
// recording trigger internally — do not duplicate those calls here.
1671+
int onvif_ret = detect_motion_onvif(onvif_url,
1672+
onvif_cfg.onvif_username,
1673+
onvif_cfg.onvif_password,
1674+
&result,
1675+
ctx->stream_name);
1676+
if (onvif_ret != 0) {
1677+
log_warn("[%s] ONVIF detection failed with error %d", ctx->stream_name, onvif_ret);
1678+
return false;
1679+
}
1680+
1681+
bool onvif_triggered = (result.count > 0);
1682+
if (onvif_triggered) {
1683+
ctx->total_detections += result.count;
1684+
log_info("[%s] ONVIF motion detected (%d event(s))", ctx->stream_name, result.count);
1685+
}
1686+
return onvif_triggered;
1687+
}
1688+
15981689
// Embedded model detection - requires frame decoding
15991690
if (!pkt || !ctx->decoder_ctx) return false;
16001691

0 commit comments

Comments
 (0)