Repository navigation
Device testing: v2 and open PRs (report + checklist) #53
Copy link
Copy link
Closed
Labels
hardwareNeeds real hardware: device or cameraNeeds real hardware: device or camera
Description
Tracking issue for on-device testing of v2 and the open PRs. Results are added here as comments; the checklist below is the plan.
Rule: only CI builds from GitHub Actions are tested (workflow artifacts for working branches, the latest release for v2/basic). No local builds.
Test bench
| Device | AG-216 Android TV box, Android 10 (API 29), armeabi-v7a, 1280×720 |
| HW decoder | OMX.allwinner.video.decoder.avc (the board reports itself as Amlogic, but the codec is Allwinner) |
| Camera 1 | XM / H264DVR 1.0, H.264 1280×720 (coded 1280×736), 25 fps, no audio |
| Camera 2 | OpenIPC camera, codec/audio/resolution can be changed during the test — being set up |
How to continue (from any session)
Everything needed to pick this up is in this issue. Update it as you go: tick the checklist in this body, post each test run as a comment (build, commit, result table, findings).
1. Device access
- Device:
172.17.32.144:5555, lab network, ADB over TCP, no authorization prompt, shell uid 2000. adbis not installed system-wide on the lab host. Download Google's platform-tools to a temp dir:curl -sSLO https://dl.google.com/android/repository/platform-tools-latest-linux.zip unzip -q platform-tools-latest-linux.zip export ADB="$PWD/platform-tools/adb -s 172.17.32.144:5555" $PWD/platform-tools/adb connect 172.17.32.144:5555 $ADB shell getprop ro.product.model # AG-216
- Camera 1 is on the same network as the device. Its RTSP URL (with credentials) is not published here. It is already saved in the app on the device: build fix: decoder recovery and lifecycle — Quad H.265, resume, thread leak, pause (#20 #21 #22 #23 #32) #48 is installed and stores it. Ask in this thread if you need it.
2. Builds (CI only)
v2/basic:gh release download latest -R OpenIPC/decoder -p decoder-v2.apk -p decoder.apk- PR branches:
build.ymlbuilds signed APKs only on push runs (notpull_request), artifact namedecoder-<branch with / → ->:RUN=$(gh run list -R OpenIPC/decoder -b fix/decoder-lifecycle -e push -L 1 --json databaseId -q '.[0].databaseId') gh run download $RUN -R OpenIPC/decoder -n decoder-fix-decoder-lifecycle
- Every build is
com.openipc.decoderwith the release signature. Switching from a debug build needsadb uninstallfirst, which wipes the settings. - Set a camera without the UI (works in every build):
am start -a android.intent.action.SEND -t text/plain --es android.intent.extra.TEXT '<rtsp url>' -n com.openipc.decoder/.Decoder. Only fix: decoder recovery and lifecycle — Quad H.265, resume, thread leak, pause (#20 #21 #22 #23 #32) #48+ saves it; older builds forget it after a pause.
3. Smoke test script
smoke.sh <apk> <label> (needs ADB and CAM_URL in the environment)
#!/bin/bash
# usage: ADB="adb -s 172.17.32.144:5555" CAM_URL='rtsp://...' ./smoke.sh <apk> <label>
PKG=com.openipc.decoder; APK=$1; L=$2; OUT=res/$L; mkdir -p $OUT
mask(){ sed -E 's#password=[^_ ]+#password=***#g; s#(rtsp://[^:/@]+:)[^@]*@#\1***@#g'; }
$ADB uninstall $PKG >/dev/null 2>&1
echo "[$L] install: $($ADB install -r -t "$APK" 2>&1 | tail -1)"
echo "[$L] version: $($ADB shell dumpsys package $PKG | grep -m1 versionName | tr -d ' ')"
$ADB logcat -c
$ADB shell "am start -W -a android.intent.action.SEND -t text/plain --es android.intent.extra.TEXT '$CAM_URL' -n $PKG/.Decoder" | grep -E "Status|TotalTime" | tr '\n' ' '; echo
sleep 15
PID=$($ADB shell pidof $PKG); echo "[$L] pid=$PID threads=$($ADB shell ls /proc/$PID/task | wc -l) top=$($ADB shell dumpsys activity activities | grep -m1 mResumedActivity | awk '{print $4}')"
$ADB exec-out screencap -p > $OUT/1_start.png
for i in 1 2 3; do # Home -> back, 3 times
$ADB shell input keyevent KEYCODE_HOME; sleep 3
$ADB shell am start -a android.intent.action.MAIN -c android.intent.category.LEANBACK_LAUNCHER -n $PKG/.Decoder >/dev/null; sleep 8
done
PID2=$($ADB shell pidof $PKG); echo "[$L] after 3x resume: pid=$PID2 threads=$($ADB shell ls /proc/$PID2/task | wc -l) top=$($ADB shell dumpsys activity activities | grep -m1 mResumedActivity | awk '{print $4}')"
$ADB exec-out screencap -p > $OUT/2_resume.png
$ADB logcat -d | mask > $OUT/logcat.txt
echo "[$L] decoder starts=$(grep -c 'Start video decoder' $OUT/logcat.txt) fatal=$(grep -c 'FATAL EXCEPTION' $OUT/logcat.txt) anr=$(grep -c 'ANR in' $OUT/logcat.txt)"
grep -E 'FATAL EXCEPTION|ANR in' -A8 $OUT/logcat.txt | head -20Pitfalls:
- Do not use
am force-stop+am startto restart: the TV launcher grabs focus about 1 s later. Use Home → back. fatalmust countFATAL EXCEPTIONonly; plainAndroidRuntimelines come frominput/amshell commands.- Mask the camera password in every log you post.
- Leave a build with a working camera installed on the device when you finish (currently fix: decoder recovery and lifecycle — Quad H.265, resume, thread leak, pause (#20 #21 #22 #23 #32) #48).
4. Next steps
- Camera 2 (OpenIPC) is being set up by the maintainer. Once its IP, SSH (root) and RTSP URL are posted here and the device can reach it: Quad mode: H.265 cameras stay black #20 (Quad H.265), Video never recovers after a MediaCodec error #21 (switch codec live, e.g.
cli -s .video0.codec h265+ restartmajestic), Image is cropped at the edges on non-16:9 screens #17 (4:3 stream), audio. - Without camera 2: fix: screenshot permission (#28), back handling (#30), cleanup (#35) #50 checks (Screenshots fail on Android 6–9: storage permission is never requested #28 screenshot, Android 16 (targetSdk 36): migrate Back handling to OnBackInvokedCallback #30 back), fix: decoder recovery and lifecycle — Quad H.265, resume, thread leak, pause (#20 #21 #22 #23 #32) #48 screen off/on and the 20-switch thread test (Thread leak on every camera switch or URL save #23).
- When every item for a PR is ticked, comment on that PR with a link to the result here and remove
awaiting device test.
Smoke test (2026-10-12)
Procedure: install → set the camera via a share intent (ACTION_SEND + EXTRA_TEXT) → 15 s → screenshot → 3× (Home → back via launcher) → screenshot → logcat; thread count from /proc/<pid>/task.
| Build | Start | After 3× Home → back | Threads | Crash / ANR |
|---|---|---|---|---|
basic 1.07.1 (latest) |
✅ picture | ❌ falls back to the default 192.168.1.10 |
26 → 27 | none |
v2 1.28 (latest) |
✅ picture | ❌ "No camera configured" | 24 → 20 | none |
#48 fix/decoder-lifecycle 31b78e3 |
✅ picture | ✅ picture after each resume, RTSP + decoder restart | 26 → 26 | none |
#49 fix/video-fit f9485ea |
✅ picture | ❌ same as v2 (no #48 fix) | 24 → 20 | none |
#50 fix/platform-cleanup c32495f |
✅ picture | ❌ same as v2 (no #48 fix) | 24 → 20 | none |
Findings:
- A link shared into the app is kept only in memory;
onResume()→loadSettings()re-reads preferences and the camera is gone. Affectsbasicandv2. fix: decoder recovery and lifecycle — Quad H.265, resume, thread leak, pause (#20 #21 #22 #23 #32) #48 saves the link tohost_<slot>and fixes it. - Environment note:
am force-stopfollowed byam startmakes the TV launcher take focus about 1 s later. This is the launcher, not the app; tests use Home → back instead.
Checklist
#48 decoder lifecycle
- Home → back: the same camera returns (Active camera and quad mode are not restored on resume #22, single view)
- Screen off/on: the same camera returns (Active camera and quad mode are not restored on resume #22)
- In Quad, Quad returns after a pause (Active camera and quad mode are not restored on resume #22)
- Quad with an H.265 camera shows a picture (Quad mode: H.265 cameras stay black #20) — needs camera 2
- Picture recovers after a decoder error: switch H.264 ↔ H.265 / change resolution on the camera (Video never recovers after a MediaCodec error #21) — needs camera 2
- 20 camera switches: thread count does not grow (Thread leak on every camera switch or URL save #23)
- Leaving the app with 4 offline cameras in Quad: no ANR (onPause can block the UI thread for seconds (ANR risk), worst in Quad mode #32)
#49 video fit
- 16:9 stream on a 16:9 screen fills the screen (1280×736 → fitted)
- 4:3 stream is letterboxed, not stretched (Image is cropped at the edges on non-16:9 screens #17) — needs camera 2
- Refit on rotation (Android 16: fixed landscape orientation is ignored on large screens #31) — not applicable to a TV box; needs a phone/tablet
#50 platform cleanup
- Long-press screenshot works on Android 10 without a storage prompt (Screenshots fail on Android 6–9: storage permission is never requested #28)
- Back closes the menu / browser before leaving the app (Android 16 (targetSdk 36): migrate Back handling to OnBackInvokedCallback #30)
Audio (needs camera 2)
- AAC
- G.711 μ-law / A-law
- L16 PCM
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
hardwareNeeds real hardware: device or cameraNeeds real hardware: device or camera
Activity
compot-dev commentedon Oct 12, 2026
Update from the session that writes the PRs (no device access used from here; the device is left to this thread).
#48 changed after the tested commit
31b78e3. Please re-run the smoke test on the current head:setEnabled(false)no longer takes the decoder lock on the UI thread; the codec is released on adecoder-releasethread.FrameLayout. Without this, the first Home → back in Quad mode would crash withClassCastExceptioninclearQuadViews(). The code never ran before Active camera and quad mode are not restored on resume #22 was fixed. Please add to the checklist: Quad mode, Home → back: no crash, the black placeholders disappear when each camera starts.New PRs awaiting device test, each with its own checklist in the PR description:
AUDIObadge (Quad mode has no audio #12).shared_prefs/settings.xmlthen showsenc1:values.Stacked branches build on push like the others, e.g. artifact
decoder-feat-quad-audio.fix: shared link to a running app, password in logcat, quieter stop
compot-dev commentedon Oct 12, 2026
Run 2 — #48 head
0a2e550(2026-10-12, this session)Build: CI artifact
decoder-fix-decoder-lifecycle@0a2e550. Camera 1 (XM H.264 1280×736, no audio).ClassCastExceptionfix works); Quad comes back with videoKEYCODE_SLEEP/WAKEUP)New findings
am start … SENDanswered "intent has been delivered to currently running top-most instance":onNewIntent()was not overridden, so the link never reachedloadSettings(). In the switch test slot 2 therefore stayed empty, which is why there were only 11 decoder starts for 20 switches. Fixed in fix: decoder recovery and lifecycle — Quad H.265, resume, thread leak, pause (#20 #21 #22 #23 #32) #48 (onNewIntent()→setIntent()).Content-Baseheader echoes the XM URL withpassword=in its path. Filed as Camera password is written to logcat #55 and fixed in fix: decoder recovery and lifecycle — Quad H.265, resume, thread leak, pause (#20 #21 #22 #23 #32) #48 (all logged RTSP lines and URL errors are redacted).stop()logged "RTSP connection failed: Socket closed". Removed in fix: decoder recovery and lifecycle — Quad H.265, resume, thread leak, pause (#20 #21 #22 #23 #32) #48.Next: re-test the new #48 head with the shared link, then #32 (4 unreachable cameras in Quad → Home, measure the pause), #49, #50, #51 and #54.
fix: audio loop spinning at 100% CPU in Quad, double decoder start on…
compot-dev commentedon Oct 12, 2026
Run 3 — #48 at
211f9d6→a3dbd6c→cfbb492, camera 2 addedCamera 2: OpenIPC on SigmaStar SSC33x (sensor SC2336P), Majestic Lite, 1920×1088. Initial stream: H.264 + Opus audio (
opus/48000/2) + an ONVIF metadata track. Codec changes viacli -s+/etc/init.d/S95majestic restart. Credentials are not published here.211f9d6,a3dbd6c,cfbb492211f9d6211f9d6211f9d6cc60036cc60036Pictures/OpenIPC/Screenshot_*.png(1.5 MB), no promptcfbb492singleTopfix (see below)cfbb492cfbb492video/avc+video/hevc)Findings and fixes (all pushed to #48)
am start(and any sender usingFLAG_ACTIVITY_NEW_TASK) only brought the task to the front; with the standard launch mode nothing reached the app. Fixed withlaunchMode="singleTop", andonNewIntent()now restarts the streams, because Android 10 delivers it withoutonPause()/onResume().startQuad()shut the executor down without bumping the generation, so the audio loop kept callingplayPcmFrame(), which returned at once with the interrupt flag set. Seen asrtsp-audioat 91–100 % intop -H. The same pattern exists in v2. Fixed ine8a7f2d.e8a7f2d.gfxinfoframe count frozen, the Quad container laid out at 0×0, no ANR, main thread sleeping; Home → back recovers it. Seen 2 times out of 6, both times right after an install started via a share intent. It was not reproduced on demand, so the cause is still unknown. Re-checking with the CPU-spin fix (2), which was active both times.compot-dev commentedon Oct 12, 2026
Run 4 — final device results before merging (2026-10-12)
Cameras: 1 XM H.264 (no audio) · 2
.126OpenIPC, H.265 + Opus · 3.133OpenIPC (SSC33x, Majestic Lite), codec and audio switched live withcli -s+ Majestic restart. On this Majestic Lite build.audio.codecsupportsopus,aac(mpeg4-generic/8000/1) and PCM (L16/8000/1); G.711 values fall back to L16, so G.711 could not be tested.4660bbatop -H: no thread above 50 %)f9485eawm size 960x720)44d1be2(+#51, +#48)mpeg4-generic/8000/1, live switch6b9a2a4Playback is measured from
dumpsys media.audio_flinger(server position of the app's track), since sound cannot be heard remotely.Deferred: #56 (Quad sometimes not laid out after the task is brought to the front by
am start). The mitigation is in #48; it did not recur in runs 3–4.Next: merge in order #48 → #51 → #52 → #54 → #49 → #50, each after CI and Qodo agree.
compot-dev commentedon Oct 12, 2026
Merge progress (2026-10-12)
Deferred: #7, #13, #15, #56.
compot-dev commentedon Oct 12, 2026
Final: all PRs merged (2026-10-12)
#48, #51, #54, #52, #49 and #50 are merged into v2. Closed: #12, #17, #20, #21, #22, #23, #28, #30, #31, #32, #35, #55.
Smoke test of the final v2 CI build (
55f07ff,decoder-v2.apkfrom thelatestrelease, installed as an upgrade over the previous build):Remaining open: #14 (G.726, LATM
cpresent=1), #16 (Android 5 storage, transport encryption); deferred: #7, #13, #15, #56.compot-dev commentedon Oct 12, 2026
Closing: all PRs from this test round are merged (#48–#52, #54, #57) and the final v2 build
55f07ffpassed the smoke test on the device. This issue stays as the reference for future device test rounds: the checklist, the per-issue result tables, the 4:3 emulation viawm size, audio checks via theaudio_flingerframe position, and the codec switching on Majestic (.video0.codec,.audio.codec). New rounds should open a new issue with the same structure and link back here.fix: shared link to a running app, password in logcat, quieter stop
fix: audio loop spinning at 100% CPU in Quad, double decoder start on…
docs: LABORATORY.md, the test bench in one place (#53, #74)