Repository navigation
feat: toy drones — FLOW-UFO, KY UFO RTSP and Jieli (#187) - #215
Conversation
A flowufo:// slot (flowufo://192.168.169.1:8800, host and port optional) plays the video of Wi-Fi toy drones with a FLOW-UFO-xxxxxx access point, in single view and in grid cells like an http:// MJPEG slot. Video only: no flight commands are sent. The client probes the drone until fragments arrive, collects the JPEG fragments of the last four frames, acknowledges them every 25 ms (masks of missing fragments, whole-frame requests for lagging slots and for the next frame after a pause) and probes again after 3 s of silence. The frames carry only the scan data: the headers are generated (IJG tables at the frame's quality, baseline 4:4:4, standard Huffman tables). Not yet checked on a drone: the log shows the raw header bytes of the first fragments and the start of the first frame, /stats.json the protocol counters under "flowufo". The socket is bound to the network whose subnet holds the drone, so that a Wi-Fi without internet is used even with mobile data on (ACCESS_NETWORK_STATE). Version 2.10 (35).
A single fragment far behind no longer resets the window: only a run of them counts as a drone restart. Stale fragments and duplicates do not extend the quiet time; frames at or below the base do not hold up the request for the next frame; a short fragment inside the body stays missing, a short last one ends the body. Send errors reopen the socket after 3 s by time and probe again from the new port. A cell's toy status is cleared with every status change. Refs #187.
…lots, dqt switch) and the KY UFO 7099 heartbeat (#187) Compared with marshallrichards/turbodrone (Apache-2.0, wifi_uav and cooingdv backends; no code taken over, credited in docs/toys.md and the comments): - ACK quality parameters 32 4B 14 2D by default; ?qpara= (or ?q=) with 8 hex digits - bytes 0x34/0x35 are main/flow camera status: shown in the stats, no family warning - slots 5 or more frames behind are left out of the ACK instead of a seq+4 request - port 8800 (default) probes 8801 too, one socket per port; locks onto the socket the first 0x93 packet arrives on (source address only, the drone sends from port 1234); BL618 timing on 8801: probes every 200 ms, ACKs every 50 ms only with a record - ?dqt=zigzag|raster|q50 for the JPEG quantisation tables, shown in the stats - no flight command in the ACK, with the reason in a comment - RTSP: 01 01 to UDP 7099 every second for rtsp://<host>:7070/webcam, or with ?heartbeat=<port> (off with ?heartbeat=off; the option is not sent to the camera); heartbeat object in /stats.json - subnet hint in the status when a flowufo:// slot targets the phone itself or another toy family's network - docs/toys.md: families by Wi-Fi name, the new options, KY UFO RTSP, credits (#196)
jieli://192.168.80.1 for toys with an HF_xxxxxxxx Wi-Fi (Jieli AC79, vendor app DVRunning 2), after the PCAPdroid capture in #196 and turbodrone's research notes (Apache-2.0, behaviour reference only, no code taken over): - CTP on TCP 3333 (CTP: + u16 topic length + topic + u32 JSON length + JSON), a reader that reassembles split and joined messages and skips what is not CTP - APP_ACCESS, DATE_TIME, CTP_KEEP_ALIVE every min(timeout / 4, 7.5 s), OPEN_RT_STREAM with the size of VIDEO_PARAM (else 640x480 at 25), CLOSE_RT_STREAM on stop - video expected on the phone's UDP 6666 (unverified): PT 26 into the RTP/JPEG path, PT 96 into the H.264 path, whole JPEG datagrams too; first packets logged with sender, PT and bytes; no video for 5 s: said in the status, UDP 1234 and 2224 opened for the log only, OPEN_RT_STREAM again every 10 s - options w, h, fps, rtp, format; sockets bound to the toy's network (TCP from Android 6) - jieli object in /stats.json; subnet hints both ways between flowufo:// and jieli:// - never FLIGHT_CONTROL, nothing to UDP 3456 - docs/toys.md: HF / Jieli section, credits; unit tests with a fake toy on loopback
…silence reset, network binding from Android 6 (Qodo on #188)
… video (Qodo on #198) - a KEEP_ALIVE_INTERVAL announced after the first keepalive applies at once: the next one is due interval ms after the last one sent, not on the old schedule; test with the announcement after the first keepalive - the quiet status from the CTP thread and "connected" from the UDP thread are serialised, and a quiet notice is dropped when video arrived meanwhile
…g from #188 with the shared network lookup)
feat: Jieli HF toy drones over CTP (#187)
…aries, so chatty graphics logs no longer push them out (#187)
…r-clockwise, ?rotate= to override (#200) The K200's camera is mounted sideways. For :7070/webcam slots the software MJPEG path draws the frames turned 90° CCW and reports the turned size, so the view fits a landscape picture; ?rotate=0|90|180|270 overrides it for any RTSP MJPEG slot and is not sent to the camera. H.264/H.265 are not turned (#201). /stats.json gets rotate; screenshot and debug snapshot copy the turned surface.
…e dropped, raw frames on the debug page (#187)
…en startup fails; Jieli: only usable video counts as receiving, a stopped slot cannot hang on a blocked CTP write, diagnostic ports freed after 30 s, topic stats bounded, a dropout after the stream request reconnects without back-off
|
Open Qodo findings from #188 and #198 (both on code that is now in this branch) are fixed in 3f4ae3e:
The rest of this PR waits for the YL3 raw frames (test build 4) in #187. |
PR Summary by QodoAdd video support for FLOW-UFO, Jieli, and KY UFO toys
AI Description
Diagram
High-Level Assessment
Files changed (25)
|
Code Review by Qodo
1. Rotated streams skip hardware decoding
|
| int[] render(Frame frame, Surface s, int rotate, JpegCodec.Current current) { | ||
| if (s == null || !s.isValid() || !current.holds()) return null; | ||
| // The hardware JPEG decoder first, where there is one (#132) | ||
| if (!hwFailed && !drawn && JpegCodec.candidate() != null) { | ||
| // The hardware JPEG decoder first, where there is one (#132); a turned frame is drawn | ||
| // by the app, which turns it while drawing (#200) | ||
| if (rotate == 0 && !hwFailed && !drawn && JpegCodec.candidate() != null) { |
There was a problem hiding this comment.
1. Rotated streams skip hardware decoding 📎 Requirement gap ➹ Performance
JpegRenderer.render skips the hardware JPEG decoder whenever rotate is nonzero and always decodes those frames through the bitmap path. Any MJPEG URL using 90, 180, or 270 degree rotation therefore consumes the slower software decoder even when a suitable hardware decoder is available, including the rotated camera path introduced here.
Agent Prompt
## Issue description
Rotated MJPEG streams bypass the available hardware JPEG decoder because `JpegRenderer.render` requires `rotate == 0` before attempting hardware decoding. This violates the hardware-decoding requirement for suitable decoders and forces rotated streams through the slower bitmap path.
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/JpegRenderer.java[50-54]
- android/app/src/main/java/com/openipc/decoder/JpegRenderer.java[90-108]
## Recommended Fix
Keep hardware JPEG decoding enabled for rotated streams when a suitable decoder is available, applying the rotation through the output surface or display transform. Use the bitmap renderer only when hardware decoder configuration fails or no suitable decoder exists.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
…t come late (Qodo on #215)
|
Qodo review on 776d32d:
|
Understood. The current review therefore has finding 1 intentionally left open for the planned per-slot rotation work in #201, while findings 2 and 3 were fixed in commit |
Part of #187, closes #200. Version 2.15.
flowufo://192.168.169.1:8800): UDP protocol of BL60x camera toys; checked with a D16.rtsp://…:7070/webcam): UDP heartbeat01 01to 7099; MJPEG turned 270° (the K200 camera is mounted sideways),?rotate=0|90|180|270overrides it; checked with a K200 (KY UFO toys (rtsp://…:7070/webcam): turn the picture 90° counter-clockwise #200). The single view draws only the newest MJPEG frame when drawing falls behind (the delay no longer grows).jieli://192.168.80.1, experimental): CTP on TCP 3333; video from the toy's own stream on UDP 2224 (pieces put together by their own length) or RTP on 6666; turned 90° by default. YL3 video arrives and plays; picture quality is still being checked with test build 5 in new feature: receiving udp video strem from cheap toys with wifi cam's #187./logkeeps the app's lines;flowufo/jieli/heartbeat/rotatein/stats.json;/jieli-frame.jpg,/jieli-dropped.bin.Tested by the reporter with test builds 1–5 (D16, K200, YL3); on Aceline-1 the grid and single view play as before.