Skip to content

Letting an empty text clear an overlay region - #75

Merged
wberube merged 1 commit into
OpenIPC:masterfrom
DeathCamel58:osd-clear-text
Nov 8, 2026
Merged

wberube merged 1 commit into
OpenIPC:masterfrom
DeathCamel58:osd-clear-text

Conversation

@DeathCamel58

Copy link
Copy Markdown
Contributor

doc/overlays.md says an empty string clears a region (/api/osd/1?text=), but the /api/osd query loop skipped every key with an empty value. So text= did nothing: the region kept its text, the API kept reporting it, and it stayed on the stream until Divinus restarted. An empty text now clears the text, and the region thread's existing removal path takes it off the stream. Every other key still needs a value. The web page's Apply sends text= for an emptied field, so clearing it there works too.

Tested on an Ambarella S3L camera (HAL in #71), H.264 over RTSP, checking a frame from the stream after each request:

Request Before After
?text=OSDTEST&size=96&pos=100,100 drawn drawn
?text= still drawn, API says "text":"OSDTEST" removed, API says "text":""
?text=AGAIN drawn
the web page's full query: img=&font=…&size=&text=&…&outl=&thick= removed; the other empty fields are still ignored
?text=$t, then ?text= time drawn, then removed

A region left with neither text nor image takes the default style (region_defaults()) on its next request, as before, so text set again after clearing comes back at the default size and colour unless the request sets them.

It also builds on master with the S3L toolchain. It touches only src/server.c, so every platform picks it up.

doc/overlays.md says an empty string clears a region
(/api/osd/1?text=), but the /api/osd query loop skips every key with an
empty value, so text= did nothing: the region kept its text, the API
went on reporting it, and it stayed on the stream until Divinus
restarted. An empty text is now accepted and clears the text, which lets
the region thread's existing removal path run; every other key still
needs a value. The web page's Apply sends text= for an emptied field,
so it clears the region too.

Tested on an Ambarella S3L camera (HAL not upstream yet), H.264 over
RTSP: text=OSDTEST drawn, text= removes it (the API reports ""), new
text draws again, the web page's full query with text= and other empty
fields removes it, and a $t time region is removed the same way.
@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Allow empty text to clear an OSD overlay

🐞 Bug fix 🕐 10-20 Minutes

Grey Divider

AI Description

• Accept text= to clear an overlay’s text, matching the documented API behavior.
• Continue ignoring empty values for other OSD parameters; the existing region thread handles
 removal.
Diagram

graph TD
  A["OSD API request"] --> B["Parse query"] --> C{"Empty value?"}
  C -->|text key| D["Clear stored text"] --> E["Region thread"] --> F["Remove overlay"]
  C -->|other key| G["Ignore parameter"]
Loading
High-Level Assessment

The narrow parser exception is appropriate: it restores the documented clearing behavior and reuses the existing region-removal path without changing how other empty parameters are handled. A separate clear endpoint would add API surface for the same operation.

Files changed (1) +3 / -1

Bug fix (1) +3 / -1
server.cPermit empty text in OSD queries +3/-1

Permit empty text in OSD queries

• The OSD query loop now accepts an empty value only for the 'text' key, allowing it to clear stored text. Empty values for all other keys remain ignored; the existing update and region-thread paths handle the resulting overlay state.

src/server.c

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

qodo-free-for-open-source-projects Bot commented Nov 8, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

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

Grey Divider


Action required

1. Reading a cleared overlay keeps it visible 🐞 Bug ≡ Correctness
Description
respond_request accepts text= as a clear, but its existing empty-region check calls
region_defaults(), which resets the pending updt flag and the region handle. If a client reads
the overlay before the region worker processes the clear, the worker skips destruction; on
handle-based platforms, the reset handle can also prevent a later clear from destroying the original
region.
Code

src/server.c[1405]

+                if (!*value && !EQUALS(key, "text")) continue;
Evidence
The newly accepted empty value writes an empty text string and the query handler sets updt=1. A
subsequent GET sees both text and image empty, calls region_defaults(), and resets updt=0 and
hand=-1; the worker's destruction branch requires updt, so it never runs in this ordering.

src/server.c[1350-1357]
src/server.c[1398-1414]
src/server.c[1454-1457]
src/region.c[5-20]
src/region.c[463-470]
src/region.c[555-574]

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 plain overlay GET after `text=` can reset the pending clear and the live region handle before the region worker removes the overlay.
## Fix Focus Areas
- src/server.c[1356-1357]
- src/server.c[1403-1405]
- src/region.c[5-14]
## Recommended Fix
Do not call `region_defaults()` on an empty region while a clear is pending or its rendered handle remains live. Separate initial/default style setup from live overlay state so a read cannot discard an update or hardware handle.

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



Remediation recommended

2. Clearing during rendering leaves old text 🐞 Bug ☼ Reliability
Description
The request handler can set text to empty and updt to one while the region worker is rendering
the previous text, but the worker unconditionally resets updt after rendering. If that timing
occurs, the next worker pass sees empty text with no pending update and does not destroy the
rendered overlay.
Code

src/server.c[1405]

+                if (!*value && !EQUALS(key, "text")) continue;
Evidence
The server and region worker run in separate threads. The worker renders a snapshot of nonempty
text, then clears updt unconditionally; a newly accepted text= request can change the shared
text and set updt between those operations, leaving its clear unprocessed.

src/server.c[1403-1414]
src/server.c[1454-1457]
src/server.c[1772-1785]
src/region.c[360-385]
src/region.c[463-465]
src/region.c[569-577]

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 clear arriving while the region worker renders an earlier text value can be lost when the worker resets the shared update flag.
## Fix Focus Areas
- src/server.c[1403-1414]
- src/server.c[1454-1457]
- src/region.c[360-373]
- src/region.c[463-574]
## Recommended Fix
Synchronize overlay state changes with worker processing, or use a per-region update generation that the worker acknowledges only after applying that generation. Ensure an update arriving during rendering remains pending for a subsequent worker pass.

ⓘ 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 pick a display mode instead of tweaking every Display option by hand

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

@wberube
wberube merged commit 7842fd8 into OpenIPC:master Nov 8, 2026
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.

2 participants