Repository navigation
fix: udp:// slots read the socket on a thread of their own; no slot checks during a push (#251) - #252
Conversation
…hecks during a push (#251) An app cannot get a socket buffer above rmem_max (256 KiB on the Aceline box), about one 1080p key frame, so any stall of the receive loop lost datagrams of the burst. A high-priority thread now only reads the socket into a ring of 1024 datagrams; reordering, assembly and the decoder run as before on the session thread. Stream checks of other slots in the U view pause while the U cell receives a push. /stats.json gets a udp object per cell: rcvbuf, received, ring_dropped, rtp_lost and socket_drops where /proc/net/udp is readable.
PR Summary by QodoPrevent UDP push drops with a dedicated receive thread
AI Description
Diagram
High-Level Assessment
Files changed (9)
|
Code Review by Qodo
1.
|
…e hold, bounded ring (#251) Qodo on #252: the session thread handles at most 64 datagrams before it checks the stop condition and the reorder deadlines; rtp_lost and socket_drops are published by the session thread (/proc read at most once a second, never on the UI thread) and count only the known video payload type; a slot grown for a long datagram is not kept in the ring; stream checks are held from the one-second cell tick, not only on debug requests; isConnected() no longer splits showsVideo() from its javadoc.
|
Qodo review addressed in ebf5785. Checked with a local build in
|
|
/review |
Thanks for the update. Based on the details provided, commit |
| return pushReceived() ? "Not checked while the U cell receives a push" | ||
| : "Waiting for a stream check"; |
There was a problem hiding this comment.
8. Pushes leave probe state marked waiting 🐞 Bug ≡ Correctness
probeText() now says a slot is not checked during a U-cell push, but probeSlots() still assigns that slot's probe.state to waiting when it has no previous result. During a push, consumers of /stats.json receive contradictory text and state for the same slot, despite probing being held.
Agent Prompt
## Issue description
During a U-cell push, a slot without a prior result reports that checks are paused in its text but remains `waiting` in its JSON probe state.
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/Decoder.java[1771-1776]
- android/app/src/main/java/com/openipc/decoder/Decoder.java[1839-1847]
## Recommended Fix
Use the active-push condition when assigning the JSON probe state so an unprobed slot is `not checked` while checks are held. Keep the text and state consistent.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
|
Code review by qodo was updated up to the latest commit ebf5785 |
|
New Qodo findings addressed in 8882ce6. Checked with a local build in
|
|
/review |
|
Code review by qodo was updated up to the latest commit 8882ce6 |
… not checked (#251) Qodo on #252: /proc/net/udp{,6} rows are matched by the bound address and port (the group of a multicast slot, the wildcard otherwise), so another group on the same port is not counted; a slot not checked because the U cell receives a push has probe state "not checked", as its text says.
|
Findings 8 and 9 addressed in 926ecd9. Checked with a local build in
|
|
/review |
|
Code review by qodo was updated up to the latest commit 926ecd9 |
Test on hardwareTest box: Aceline TV box (Android 10, 3×3 grid (eight decoders, the box overloaded at load average ~26 on 4 cores), drops per second:
2.18.3 is much steadier: its worst run is 80/s, against 218/s for 2.18.2, while the best runs are about the same. The drops don't go away under this load, though:
U view:
The remaining kernel-buffer drops under heavy load are tracked separately. |
Fixes #251.
What changes
RtpListener(udp://slots and the U cell): a thread of its own atMAX_PRIORITYonly reads the socket into a ring of 1024 datagrams. Reordering, NAL assembly and the decoder stay on the session thread and no longer hold upreceive(). When the socket opens, the log shows the buffer the kernel actually gave (getReceiveBufferSize()). An app can't go pastrmem_max, so the 2 MiB request becomes ~512 KiB on the Aceline box.connected), the other slots get no stream checks. A running check is cancelled on the next debug-page update, and the page saysNot checked while the U cell receives a push./stats.json,cells[]: newudpobject for a listening slot withrcvbuf,received,ring_dropped,rtp_lost(sequence gaps of the video payload type) andsocket_drops(from/proc/net/udp{,6}for the port, only when the app may read it; newer Android versions hide it from apps).docs/debug.md(cells table, slots note),docs/transports.md.versionCode46),CHANGELOG.md.Tests
Local build in
compot/android:2026.10, as in CI:testDebugUnitTest lintDebug assembleDebug. 369 tests pass, and lint finds nothing new in the changed files. New tests:udpStatsCountWhatArrivedAndWhatIsMissing: received and lost counters.socketDropsAreReadForThePort: the/proc/net/udpparser.Still to do: a check on the Aceline box (.145) with a CI build. We'll push H.265 1080p from Majestic
outgoingto the U cell without pacing and compare theudpcounters andnal_droppedwith 2.18.2 (≈47 drops/s).