Skip to content

i6: software motion detection with ONVIF MotionAlarm events - #54

Open
Jamp wants to merge 21 commits into
OpenIPC:masterfrom
Jamp:motion-detection
Open

Jamp wants to merge 21 commits into
OpenIPC:masterfrom
Jamp:motion-detection

Conversation

@Jamp

@Jamp Jamp commented Oct 4, 2026

Copy link
Copy Markdown
Contributor

Depends on #53 (ONVIF events); this branch is on top of it, so the first commits here are #53's.

For "Motion detection" on the roadmap. infinity6 has no hardware motion detector available here
(no IVE, no vendor MD library in OpenIPC's SDK for this family), so this adds a small one in C:
a 320x180 NV12 copy from a free VPE port (port 3 hands out buffers that are never written on
SSC323, so port 2), read at 5 fps; a fixed-point running background, 16x16 blocks, a
whole-frame change (lights, IR cut) ignored and relearnt. motion_detect: enable, sensitivity (1-10), hold_s. Encoders no longer take the port the detector reads. State changes feed the
ONVIF event service from #53 as tns1:VideoSource/MotionAlarm.

Under 1 % CPU on SSC323. Host tests for the detector core (make -C test). Running for days on
a camera watched by an NVR that records on these events: people and a small dog detected, day
and IR night.

The HAL changes are kept inside src/hal/star/i6_* and conditioned on the series where they
are specific to SSC32x; glad to rebase once the HAL naming refactor you mentioned in #43 lands.

Jamp added 20 commits September 30, 2026 14:47
- ISO 8601 durations are parsed in 64 bits
- A failed PullMessages allocation is answered with an error
- RelatesTo has room for the longest message ID
Measured on SSC323: port 2 gives 320x180 NV12 frames with a 320 stride.
Port 3 returns buffers with fresh timestamps whose memory is never
written, even through an uncached mapping.
- Encoders no longer take the port the motion detector reads
- Frames smaller than the detector input are skipped
- More headroom for MI_SYS_BufInfo_t
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Add infinity6 software motion detection and ONVIF PullPoint events

✨ Enhancement 🐞 Bug fix 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Detect motion on infinity6 without hardware motion-detection support and publish MotionAlarm state
 changes.
• Add ONVIF PullPoint subscriptions so clients can discover and retrieve motion events.
• Add detection settings, SOAP interoperability fixes, and host tests for the detector and event
 service.
Diagram

graph TD
  VPE["infinity6 VPE"] --> Media["Raw frame API"] --> Worker["Motion worker"] --> Core["Detection core"] --> Store["Event subscriptions"] --> HTTP["ONVIF HTTP"] --> NVR(["ONVIF client"])
  Config["Motion settings"] --> Worker
  NVR -->|"Subscribe and pull"| HTTP
  HTTP -->|"Manage subscriptions"| Store
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Reserve the detector port before allocating encoders
  • ➕ Prevents an encoder from taking port 2 before motion detection starts.
  • ➖ Requires earlier reservation in the media lifecycle and coordination with encoder allocation.
2. Detect motion from encoded streams
  • ➕ Avoids reserving a dedicated VPE output port.
  • ➖ Decoding or extracting suitable frames adds CPU cost and complexity on the target device.

Recommendation: Keep the dedicated low-resolution raw-frame path and separate detector core: they fit the hardware constraint and permit host testing. Consider reserving port 2 before encoder allocation when detection is enabled, since the current startup order can leave it occupied.

Files changed (40) +1689 / -147

Enhancement (30) +1301 / -144
capabilities.xmlAdvertise PullPoint support +1/-1

Advertise PullPoint support

• Marks ONVIF event PullPoint support as available in device capabilities.

res/onvif/capabilities.xml

event.xmlAdd event SOAP envelope template +9/-0

Add event SOAP envelope template

• Defines the envelope and namespaces used for event responses and WS-Addressing headers.

res/onvif/event.xml

eventcaps.xmlDeclare event-service capabilities +3/-0

Declare event-service capabilities

• Advertises PullPoint support and a four-subscription limit.

res/onvif/eventcaps.xml

eventprops.xmlDescribe the MotionAlarm topic +22/-0

Describe the MotionAlarm topic

• Declares the VideoSource/MotionAlarm topic, its source and state fields, and supported dialects.

res/onvif/eventprops.xml

fault.xmlAdd SOAP fault template +16/-0

Add SOAP fault template

• Provides structured SOAP fault codes, subcodes, and reasons for ONVIF errors.

res/onvif/fault.xml

notification.xmlAdd motion notification template +13/-0

Add motion notification template

• Formats timestamped MotionAlarm notifications with source, state, and property operation.

res/onvif/notification.xml

pullmessages.xmlAdd PullMessages response template +4/-0

Add PullMessages response template

• Wraps notifications with current and subscription termination times.

res/onvif/pullmessages.xml

pullpoint.xmlAdd subscription creation response +7/-0

Add subscription creation response

• Returns a subscription URL and its current and termination times.

res/onvif/pullpoint.xml

renew.xmlAdd renewal response template +4/-0

Add renewal response template

• Reports the renewed subscription's current and termination times.

res/onvif/renew.xml

services.xmlList ONVIF service endpoints +22/-0

List ONVIF service endpoints

• Adds a GetServices response for the device, media, and event endpoints.

res/onvif/services.xml

syncpoint.xmlAdd synchronization response +1/-0

Add synchronization response

• Provides the response for SetSynchronizationPoint.

res/onvif/syncpoint.xml

unsubscribe.xmlAdd unsubscribe response +1/-0

Add unsubscribe response

• Provides the response for subscription removal.

res/onvif/unsubscribe.xml

i6_hal.cAcquire raw frames from infinity6 VPE +63/-0

Acquire raw frames from infinity6 VPE

• Configures VPE port 2 for 320×180 NV12 output and adds buffer acquisition, cache invalidation, release, and teardown.

src/hal/star/i6_hal.c

i6_hal.hDeclare infinity6 raw-frame operations +8/-0

Declare infinity6 raw-frame operations

• Defines the selected VPE port and exposes raw-frame lifecycle functions.

src/hal/star/i6_hal.h

i6_sys.hLoad MI_SYS raw-buffer functions +38/-0

Load MI_SYS raw-buffer functions

• Adds the measured SSC323 buffer layout and dynamically loads buffer and cache functions.

src/hal/star/i6_sys.h

types.hDefine a raw-frame descriptor +7/-0

Define a raw-frame descriptor

• Adds luma address, dimensions, stride, and release handle for raw-frame consumers.

src/hal/types.h

main.cManage motion and subscription lifecycles +9/-0

Manage motion and subscription lifecycles

• Starts and stops configured motion detection and expires ONVIF subscriptions in the main loop.

src/main.c

media.cExpose raw frames and reserve their channel +51/-1

Expose raw frames and reserve their channel

• Routes raw-frame operations to the infinity6 HAL and excludes the active raw port from encoder channel allocation.

src/media.c

media.hDeclare media raw-frame API +5/-0

Declare media raw-frame API

• Exposes raw-frame creation, retrieval, release, and teardown to the detector.

src/media.h

motion.cRun and recover the motion detector +111/-0

Run and recover the motion detector

• Samples raw frames at 5 fps, reports state changes to ONVIF, and attempts one port restart after a frame stall.

src/motion.c

motion.hDeclare motion worker controls +16/-0

Declare motion worker controls

• Exposes detector start, stop, and temporary pause operations.

src/motion.h

motion_core.cImplement block-based motion analysis +114/-0

Implement block-based motion analysis

• Uses a fixed-point running background, 16×16 activity blocks, transition and hold thresholds, and relearning after whole-frame changes.

src/motion_core.c

motion_core.hDefine the portable detector interface +23/-0

Define the portable detector interface

• Declares detector state, event types, tuning, feed, pause, and reset operations.

src/motion_core.h

onvif.cImplement ONVIF event responses +233/-138

Implement ONVIF event responses

• Adds service discovery and PullPoint SOAP responses, faults, duration handling, and notification formatting. It also centralizes response-length handling and switches authentication parsing to SOAP helpers.

src/onvif.c

onvif.hDeclare ONVIF event response API +22/-1

Declare ONVIF event response API

• Exposes event actions, fault responses, and parsed PullMessages request fields.

src/onvif.h

onvif_event.cImplement concurrent PullPoint subscriptions +187/-0

Implement concurrent PullPoint subscriptions

• Maintains bounded per-subscription event queues, monotonic expirations, long-poll waits, renewal, synchronization, and idle-slot replacement.

src/onvif_event.c

onvif_event.hDefine the event-store interface +26/-0

Define the event-store interface

• Declares subscription and queue limits, event records, and store lifecycle operations.

src/onvif_event.h

server.cRoute ONVIF event and subscription actions +89/-3

Route ONVIF event and subscription actions

• Adds event endpoints and detached PullMessages workers so waits do not block request handling. Malformed or unsupported actions now receive SOAP faults.

src/server.c

soap.cAdd namespace-agnostic SOAP helpers +179/-0

Add namespace-agnostic SOAP helpers

• Parses local-name tags and actions, credentials, ISO 8601 durations and dates, and password digests. Duration arithmetic is checked before scaling.

src/soap.c

soap.hDeclare SOAP parsing and digest helpers +17/-0

Declare SOAP parsing and digest helpers

• Exposes tag, action, time, termination, and credential-digest utilities.

src/soap.h

Bug fix (1) +3 / -3
tools.cCorrect Base64 padding handling +3/-3

Correct Base64 padding handling

• Avoids copying a padding byte into decoded output, supporting correct SOAP password-digest validation.

src/hal/tools.c

Tests (5) +349 / -0
MakefileAdd a host test runner +20/-0

Add a host test runner

• Builds and runs SOAP, event-store, and motion-core tests without target hardware.

test/Makefile

check.hAdd lightweight test assertions +25/-0

Add lightweight test assertions

• Provides shared failure counting, assertion output, and test exit handling.

test/check.h

motion_core_test.cTest motion-state behavior +101/-0

Test motion-state behavior

• Covers still scenes, moving objects, hold time, lighting changes, noise, pause, reset, and padded strides.

test/motion_core_test.c

onvif_event_test.cTest PullPoint queue and concurrency +117/-0

Test PullPoint queue and concurrency

• Exercises initial and changed notifications, overflow, waits, renewal, expiration, replacement, and waiting-pull protection.

test/onvif_event_test.c

soap_test.cTest SOAP parsing and credentials +86/-0

Test SOAP parsing and credentials

• Covers namespaced actions, durations and overflow, time zones, Base64 padding, and password-digest vectors.

test/soap_test.c

Documentation (1) +9 / -0
config.mdDocument infinity6 motion settings +9/-0

Document infinity6 motion settings

• Explains motion enablement, sensitivity, hold time, and ONVIF MotionAlarm delivery.

doc/config.md

Other (3) +27 / -0
divinus.yamlAdd default motion-detection settings +5/-0

Add default motion-detection settings

• Provides a disabled-by-default motion section with sensitivity and hold-time defaults.

divinus.yaml

app_config.cParse and persist detector settings +17/-0

Parse and persist detector settings

• Defaults motion detection to off, bounds sensitivity and hold time when enabled, and writes the settings to configuration.

src/app_config.c

app_config.hAdd detector configuration fields +5/-0

Add detector configuration fields

• Stores motion enablement, sensitivity, and hold duration in AppConfig.

src/app_config.h

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Oct 4, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (4) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Motion detection never starts when snapshots are on 🐞 Bug ≡ Correctness
Description
rawChannel is only set inside raw_create, called from motion_start() after sdk_start(),
while sdk_start() already ran media_mp4_enable (channel 0), media_mjpeg_enable (channel 1) and
jpeg_init (channel 2 via take_next_free_channel). With mp4, mjpeg and jpeg all enabled,
i6_raw_create sees i6_state[I6_RAW_PORT].enable set, prints "VPE port 2 is already used by an
encoder", and detection is disabled; the new skip in take_next_free_channel only protects port 2
from channels created later.
Code

src/main.c[R99-100]

+    if (app_config.motion_detect_enable)
+        motion_start();
Evidence
main.c calls sdk_start() before motion_start(). sdk_start enables MP4, MJPEG and then jpeg_init,
which calls take_next_free_channel(false). At that point rawChannel is still -1, so channel/VPE port
2 is handed to the JPEG encoder (i6_channel_create configures VPE port index). Later i6_raw_create
rejects port 2 because i6_state[2].enable is set.

src/main.c[93-100]
src/media.c[983-990]
src/jpeg.c[23-25]
src/media.c[374-385]
src/media.c[424-432]
src/hal/star/i6_hal.c[386-389]
src/hal/star/i6_hal.c[171-182]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The raw VPE port (I6_RAW_PORT = 2) is only reserved when motion_start() runs, which is after sdk_start() has already handed channel 2 to the JPEG encoder. With mp4, mjpeg and jpeg all enabled, motion detection then fails to start.
## Fix Focus Areas
- src/main.c[93-100]
- src/media.c[374-393]
- src/media.c[983-990]
## Recommended Fix
Reserve the raw channel before any encoder channel is taken. For example, when `app_config.motion_detect_enable` is set on HAL_PLATFORM_I6, set `rawChannel = I6_RAW_PORT` at the top of sdk_start(), before media_mp4_enable/media_mjpeg_enable/jpeg_init run, and clear it again if raw_create fails. Another option is to call raw_create inside sdk_start right after the pipeline is created and before the encoders, with motion_start() only starting the thread.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. A new subscriber evicts an active client 🐞 Bug ☼ Reliability
Description
onvif_event_subscribe selects an occupied slot even when every subscription has a waiting pull,
then clears that slot for the newcomer. Once four clients are long-polling, a fifth subscription
invalidates one active client's subscription and its pending pull returns an unknown-subscription
fault.
Code

src/onvif_event.c[R77-80]

+    for (int i = 0; i < ONVIF_EVENT_MAX_SUBS && sub->id; i++)
+        if (!subs[i].id || (!subs[i].waiting && sub->waiting) ||
+            (!subs[i].waiting == !sub->waiting && subs[i].lastSeen < sub->lastSeen))
+            sub = &subs[i];
Evidence
The selection starts with the occupied first slot and has no no-candidate outcome; it broadcasts and
overwrites the selected subscription. A waiting pull looks its ID up again after waking and returns
a negative result when that ID has been replaced.

src/onvif_event.c[70-88]
src/onvif_event.c[146-166]
src/onvif.c[438-443]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Creating a fifth subscription replaces a client whose pull is actively waiting when all four slots are in use.
## Fix Focus Areas
- src/onvif_event.c[70-88]
- src/onvif.c[399-414]
## Recommended Fix
Select only free or non-waiting slots for replacement. If none exists, return a failure from the store and send an appropriate SOAP fault instead of invalidating an active subscription.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Expired subscriptions can be renewed 🐞 Bug ≡ Correctness
Description
onvif_event_renew checks only whether the ID remains in the store and replaces its expiration
without checking the previous deadline. Between the termination time and the main loop's next
once-per-second expiry sweep, a Renew request revives the subscription; PullMessages can also use it
during that interval.
Code

src/onvif_event.c[R95-98]

+    onvif_event_sub *sub = find_sub(id);
+    if (sub) {
+        sub->expires = *expires = now + seconds;
+        sub->lastSeen = now;
Evidence
Renew and pull find subscriptions by ID without testing expires; only the periodic expiry function
removes overdue IDs, and the main loop calls it once per iteration before sleeping.

src/onvif_event.c[93-102]
src/onvif_event.c[129-176]
src/main.c[111-115]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
Subscription operations can accept an expired ID until a separate periodic sweep removes it.
## Fix Focus Areas
- src/onvif_event.c[93-102]
- src/onvif_event.c[129-163]
- src/onvif_event.c[169-176]
## Recommended Fix
Compare the stored expiration with the supplied monotonic time while holding the event mutex, and treat expired subscriptions as unknown before renewing or returning messages. Keep the periodic sweep for idle subscriptions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


4. A second frame stall stops motion detection for good ✓ Resolved
Description
In motion_thread, a stall-recovery reopen sets reopened to true, but successful frame reads
reset only missed, leaving reopened set after frames resume. If another 10-second stall occurs
later in the same run, the thread logs “Frames did not come back” and exits without attempting
another reopen, stopping motion events until the process restarts.
Code

src/motion.c[R52-62]

+            if (reopened) {
+                HAL_DANGER("motion", "Frames did not come back, detection stopped!\n");
+                break;
+            }
+            raw_destroy();
+            if (raw_create(MOTION_WIDTH, MOTION_HEIGHT)) break;
+            reopened = true;
+            missed = 0;
+            continue;
+        }
+        missed = 0;
Evidence
The first stall recreates the raw port and sets reopened to true at line 58, while the
successful-read path at line 62 resets only missed. Because reopened is otherwise initialized to
false only at line 29, a later stall reaches the already-reopened branch and breaks out of the loop.

src/motion.c[25-73]
src/motion.c[48-63]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
A recovered frame stall leaves `reopened` set, so a later independent stall stops the detection thread without another recovery attempt.
## Fix Focus Areas
- src/motion.c[48-63]
## Recommended Fix
In the success path after `raw_get` returns a frame, set `reopened = false;` next to `missed = 0;`. This gives each new stall one reopen attempt while retaining the exit path when frames do not return after that attempt.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

5. Motion pause function is never called 🐞 Bug ⚙ Maintainability
Description
motion_pause is exported in motion.h and writes pauseFrames, which motion_thread reads under
pauseMtx, but nothing in the tree calls it (night mode / IR cut switching does not use it). The
mutex, the pauseFrames plumbing and motion_core_pause in production are dead code, and a later
reader may assume IR-cut switches are already suppressed through this path.
Code

src/motion.c[R13-17]

+void motion_pause(int ms) {
+    pthread_mutex_lock(&pauseMtx);
+    pauseFrames = ms * MOTION_FPS / 1000;
+    pthread_mutex_unlock(&pauseMtx);
+}
Evidence
A grep for motion_pause in src/ finds only its definition in motion.c and its declaration in
motion.h; there are no callers.

src/motion.c[8-17]
src/motion.h[16-16]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
motion_pause() is declared and implemented but never called, so the pause path is dead code.
## Fix Focus Areas
- src/motion.c[8-17]
- src/motion.h[16-16]
## Recommended Fix
Either call `motion_pause(<ms>)` from the night-mode code wherever the IR cut filter or IR LEDs are switched, or remove motion_pause, pauseMtx, pauseFrames and the matching block in motion_thread.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can turn on the rule miner and Qodo learns your standards from review history

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/onvif_event.c
Comment on lines +77 to +80
for (int i = 0; i < ONVIF_EVENT_MAX_SUBS && sub->id; i++)
if (!subs[i].id || (!subs[i].waiting && sub->waiting) ||
(!subs[i].waiting == !sub->waiting && subs[i].lastSeen < sub->lastSeen))
sub = &subs[i];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

2. A new subscriber evicts an active client 🐞 Bug ☼ Reliability

onvif_event_subscribe selects an occupied slot even when every subscription has a waiting pull,
then clears that slot for the newcomer. Once four clients are long-polling, a fifth subscription
invalidates one active client's subscription and its pending pull returns an unknown-subscription
fault.
Agent Prompt
## Issue description
Creating a fifth subscription replaces a client whose pull is actively waiting when all four slots are in use.
## Fix Focus Areas
- src/onvif_event.c[70-88]
- src/onvif.c[399-414]
## Recommended Fix
Select only free or non-waiting slots for replacement. If none exists, return a failure from the store and send an appropriate SOAP fault instead of invalidating an active subscription.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/onvif_event.c
Comment on lines +95 to +98
onvif_event_sub *sub = find_sub(id);
if (sub) {
sub->expires = *expires = now + seconds;
sub->lastSeen = now;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remediation recommended

3. Expired subscriptions can be renewed 🐞 Bug ≡ Correctness

onvif_event_renew checks only whether the ID remains in the store and replaces its expiration
without checking the previous deadline. Between the termination time and the main loop's next
once-per-second expiry sweep, a Renew request revives the subscription; PullMessages can also use it
during that interval.
Agent Prompt
## Issue description
Subscription operations can accept an expired ID until a separate periodic sweep removes it.
## Fix Focus Areas
- src/onvif_event.c[93-102]
- src/onvif_event.c[129-163]
- src/onvif_event.c[169-176]
## Recommended Fix
Compare the stored expiration with the supplied monotonic time while holding the event mutex, and treat expired subscriptions as unknown before renewing or returning messages. Keep the periodic sweep for idle subscriptions.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/main.c
Comment on lines +99 to +100
if (app_config.motion_detect_enable)
motion_start();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Motion detection never starts when snapshots are on 🐞 Bug ≡ Correctness

rawChannel is only set inside raw_create, called from motion_start() after sdk_start(),
while sdk_start() already ran media_mp4_enable (channel 0), media_mjpeg_enable (channel 1) and
jpeg_init (channel 2 via take_next_free_channel). With mp4, mjpeg and jpeg all enabled,
i6_raw_create sees i6_state[I6_RAW_PORT].enable set, prints "VPE port 2 is already used by an
encoder", and detection is disabled; the new skip in take_next_free_channel only protects port 2
from channels created later.
Agent Prompt
## Issue description
The raw VPE port (I6_RAW_PORT = 2) is only reserved when motion_start() runs, which is after sdk_start() has already handed channel 2 to the JPEG encoder. With mp4, mjpeg and jpeg all enabled, motion detection then fails to start.

## Fix Focus Areas
- src/main.c[93-100]
- src/media.c[374-393]
- src/media.c[983-990]

## Recommended Fix
Reserve the raw channel before any encoder channel is taken. For example, when `app_config.motion_detect_enable` is set on HAL_PLATFORM_I6, set `rawChannel = I6_RAW_PORT` at the top of sdk_start(), before media_mp4_enable/media_mjpeg_enable/jpeg_init run, and clear it again if raw_create fails. Another option is to call raw_create inside sdk_start right after the pipeline is created and before the encoders, with motion_start() only starting the thread.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment thread src/motion.c Outdated
Comment thread src/motion.c
Comment on lines +13 to +17
void motion_pause(int ms) {
pthread_mutex_lock(&pauseMtx);
pauseFrames = ms * MOTION_FPS / 1000;
pthread_mutex_unlock(&pauseMtx);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Informational

5. Motion pause function is never called 🐞 Bug ⚙ Maintainability

motion_pause is exported in motion.h and writes pauseFrames, which motion_thread reads under
pauseMtx, but nothing in the tree calls it (night mode / IR cut switching does not use it). The
mutex, the pauseFrames plumbing and motion_core_pause in production are dead code, and a later
reader may assume IR-cut switches are already suppressed through this path.
Agent Prompt
## Issue description
motion_pause() is declared and implemented but never called, so the pause path is dead code.

## Fix Focus Areas
- src/motion.c[8-17]
- src/motion.h[16-16]

## Recommended Fix
Either call `motion_pause(<ms>)` from the night-mode code wherever the IR cut filter or IR LEDs are switched, or remove motion_pause, pauseMtx, pauseFrames and the matching block in motion_thread.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@Jamp

Jamp commented Oct 5, 2026

Copy link
Copy Markdown
Contributor Author

Pushed 7109f2c for the frame stall finding (details in its thread). The other findings are not addressed in this PR:

  • Port 2 taken when mp4, mjpeg and jpeg are all enabled: true, the detector then stays off with a warning. Reserving the port before the encoders are created needs a change in the startup order, so I would rather keep it separate.
  • Subscription replacement and the renewal of expired subscriptions: acknowledged, left as they are here.
  • motion_pause(): it is called by the night mode thread in night: switch day/night from the ISP gain when there is no light sensor #55, which builds on this PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant