Skip to content

feat: Auto as the default transport (#112) - #128

Merged
compot-dev merged 2 commits into
v2from
feat/auto-default
Oct 13, 2026
Merged

compot-dev merged 2 commits into
v2from
feat/auto-default

Conversation

@compot-dev

Copy link
Copy Markdown
Collaborator

Closes #112 (the second half; the first half — the transport in use — came with #117).

Device check: a fresh slot on Aceline-1 shows Auto in the dialog and plays over UDP (or TCP (auto) after a fallback); existing TCP slots unchanged.

@compot-dev

Copy link
Copy Markdown
Collaborator Author

/review

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

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

Copy link
Copy Markdown

Code Review by Qodo

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

Grey Divider


Action required

1. New single-view slots can stay black ✓ Resolved
Description
RtspSession.receiveUdp() stops waiting for video when RtspClient.processVideo() accepts a
well-formed RTP packet, even if NalAssembler has not emitted a complete key frame. If UDP
repeatedly loses pieces of key frames while other video packets keep arriving, neither the
first-video timeout nor the inactivity watchdog switches the newly defaulted slot to TCP; the
decoded-frame stall check exists only for multi-view cells.
Code

android/app/src/main/java/com/openipc/decoder/Decoder.java[519]

+            mTransports[i] = Transport.Mode.stored(pref.getString("transport_" + i, null));
Evidence
An absent transport preference now selects Auto and starts UDP. NalAssembler.assemble() returns
true for valid RTP even when a fragmented NAL is incomplete, and RtspClient.processVideo() passes
that result to the session. receiveUdp() then clears its first-video flag and updates the
last-packet time, disabling both existing fallback conditions; unlike QuadCell, the single-view
client has no decoded-frame stall check.

android/app/src/main/java/com/openipc/decoder/Decoder.java[515-519]
android/app/src/main/java/com/openipc/decoder/NalAssembler.java[91-110]
android/app/src/main/java/com/openipc/decoder/RtspClient.java[119-137]
android/app/src/main/java/com/openipc/decoder/RtspSession.java[656-683]
android/app/src/main/java/com/openipc/decoder/QuadCell.java[358-382]

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

## Issue description
New single-view slots use Auto, but receiving valid RTP without decodable frames prevents the UDP-to-TCP fallback.
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/Decoder.java[518-519]
- android/app/src/main/java/com/openipc/decoder/RtspSession.java[656-683]
- android/app/src/main/java/com/openipc/decoder/RtspClient.java[119-137]
## Recommended Fix
Track whether single-view video frames are actually decoded while RTP arrives over Auto UDP. After a bounded no-frame interval, report the UDP stream as broken and reconnect over TCP, while avoiding a fallback during ordinary key-frame startup.

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



Remediation recommended

2. New slots lose audio when UDP audio fails ✓ Resolved
Description
RtspSession.connect() disables audio when its UDP audio SETUP fails or selects an unusable
transport, without marking Auto's UDP attempt as failed. On a camera that accepts UDP video but
needs TCP for audio, a newly defaulted slot continues playing video over UDP without audio rather
than reconnecting over TCP for both tracks.
Code

android/app/src/main/java/com/openipc/decoder/Decoder.java[519]

+            mTransports[i] = Transport.Mode.stored(pref.getString("transport_" + i, null));
Evidence
The new default reaches the UDP branch in connect(). Both the single-view client and multi-view
cells request audio, but a failed UDP audio SETUP or unusable audio transport merely sets `audio =
false`, and the session proceeds to PLAY over UDP; the video-only fallback cannot respond to this
failure.

android/app/src/main/java/com/openipc/decoder/Decoder.java[515-519]
android/app/src/main/java/com/openipc/decoder/RtspClient.java[65-68]
android/app/src/main/java/com/openipc/decoder/QuadCell.java[199-203]
android/app/src/main/java/com/openipc/decoder/RtspSession.java[317-345]
android/app/src/main/java/com/openipc/decoder/RtspSession.java[375-407]

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

## Issue description
Auto can accept UDP video but silently omit audio when the camera rejects or changes the UDP audio transport.
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/Decoder.java[518-519]
- android/app/src/main/java/com/openipc/decoder/RtspSession.java[375-407]
## Recommended Fix
For Auto sessions with an advertised audio track, treat a transport-specific UDP audio setup failure as a reason to close the UDP attempt, record the failure, and retry the session over TCP instead of silently disabling audio.

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


3. New slots cannot play when UDP ports fail ✓ Resolved
Description
RtspSession.connect() calls UdpReceiver.addTrack() for Auto before reaching its fallback branch,
which handles only a rejected video SETUP response. If a local UDP port pair cannot be bound, the
exception reaches networkLoop() and subsequent attempts try UDP again instead of TCP, now
affecting slots with no stored transport.
Code

android/app/src/main/java/com/openipc/decoder/Decoder.java[519]

+            mTransports[i] = Transport.Mode.stored(pref.getString("transport_" + i, null));
Evidence
Unset preferences now select Auto. That mode binds a UDP video port before issuing SETUP;
addTrack() throws if its attempts fail, while the fallback branch requires a returned RTSP
response. The outer network loop catches the exception and retries without marking UDP unavailable.

android/app/src/main/java/com/openipc/decoder/Decoder.java[515-519]
android/app/src/main/java/com/openipc/decoder/UdpReceiver.java[82-116]
android/app/src/main/java/com/openipc/decoder/RtspSession.java[317-345]
android/app/src/main/java/com/openipc/decoder/RtspSession.java[204-239]

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

## Issue description
An Auto slot repeatedly retries UDP when local receiver allocation fails, although TCP remains available.
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/Decoder.java[518-519]
- android/app/src/main/java/com/openipc/decoder/RtspSession.java[317-345]
- android/app/src/main/java/com/openipc/decoder/UdpReceiver.java[82-116]
## Recommended Fix
Catch receiver creation and port-binding failures in Auto mode, clean up any allocated receiver, mark UDP unavailable, and retry the connection using TCP. Preserve explicit UDP mode's failure behavior.

ⓘ 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 these tips off under Display > Comment parts

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread android/app/src/main/java/com/openipc/decoder/Decoder.java
Comment thread android/app/src/main/java/com/openipc/decoder/Decoder.java
Comment thread android/app/src/main/java/com/openipc/decoder/Decoder.java
…s, on UDP audio failure and on UDP port failure (Qodo on #128)
@compot-dev

Copy link
Copy Markdown
Collaborator Author

Qodo review — all three accepted and fixed (they matter now that new slots use Auto):

  1. New single-view slots can stay black — the single view gets the same check as the cells (fix: Auto falls back to TCP when UDP delivers packets but no frame decodes (#113) #125): over UDP, with bytes arriving and no decoded frame for 8 s, it reports the stream broken and Auto reconnects over TCP (RtspClient.playsOverUdp() / reportUdpBroken(), checked once a second while resumed).
  2. New slots lose audio when UDP audio fails — with Auto, a failed or unusable UDP audio SETUP marks UDP failed and reconnects over TCP for both tracks instead of dropping the sound; explicit UDP keeps the old behaviour (video without audio).
  3. New slots cannot play when UDP ports fail — a failed local port binding marks UDP failed for Auto/Multicast, so the next attempt uses TCP; explicit UDP keeps retrying UDP.

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

Copy link
Copy Markdown

Qodo review — all three accepted and fixed (they matter now that new slots use Auto):

  1. New single-view slots can stay black — the single view gets the same check as the cells (fix: Auto falls back to TCP when UDP delivers packets but no frame decodes (#113) #125): over UDP, with bytes arriving and no decoded frame for 8 s, it reports the stream broken and Auto reconnects over TCP (RtspClient.playsOverUdp() / reportUdpBroken(), checked once a second while resumed).
  2. New slots lose audio when UDP audio fails — with Auto, a failed or unusable UDP audio SETUP marks UDP failed and reconnects over TCP for both tracks instead of dropping the sound; explicit UDP keeps the old behaviour (video without audio).
  3. New slots cannot play when UDP ports fail — a failed local port binding marks UDP failed for Auto/Multicast, so the next attempt uses TCP; explicit UDP keeps retrying UDP.

Confirmed from the diff: all three findings appear addressed:

  • finding 1: Single-view UDP stall detection now triggers TCP fallback after 8 seconds without decoded frames.
  • finding 2: Auto treats UDP audio setup or transport mismatches as a session failure and retries over TCP; explicit UDP behavior is preserved.
  • finding 3: Auto/Multicast now marks UDP unavailable when local port allocation fails, allowing a TCP retry.

The changes align with the reported fixes.

@compot-dev

Copy link
Copy Markdown
Collaborator Author

Device check (Aceline-1, 37c83ea): stored TCP slots unchanged (TCP/TCP); slot 3 on Auto plays over UDP in the grid and in single view (transport UDP, transport_mode AUTO, video + Opus audio over UDP), no false fallback in 20 s; the U cell UDP push. A brand-new slot's default (Auto) is covered by the unit test — a fresh install would wipe the bench's slots.

@compot-dev
compot-dev merged commit 36722aa into v2 Oct 13, 2026
4 checks passed
@compot-dev
compot-dev deleted the feat/auto-default branch October 13, 2026 12:59
compot-dev added a commit that referenced this pull request Oct 15, 2026
…s, on UDP audio failure and on UDP port failure (Qodo on #128)
compot-dev added a commit that referenced this pull request Oct 15, 2026
feat: Auto as the default transport (#112)
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.

Transport: show the transport actually in use, and Auto as the default

1 participant