Repository navigation
feat: MJPEG over RTSP (RTP/JPEG, RFC 2435) in the single view (#119) - #131
Conversation
|
/review |
…r byte (no ImageIO in unit tests)
Code Review by Qodo
1.
|
| if (jpeg) { | ||
| // MJPEG is drawn by the app (#119): no MediaCodec may hold the surface | ||
| closeDecoder(); |
There was a problem hiding this comment.
2. Mjpeg never uses hardware decoding 📎 Requirement gap ➹ Performance
drawJpeg always decodes assembled frames with BitmapFactory, while the MJPEG branch closes the MediaCodec decoder instead of selecting a video/jpeg codec. Whenever an RTSP session advertises MJPEG, rendering therefore bypasses available hardware JPEG decoders and relies exclusively on the bitmap path.
Agent Prompt
## Issue description
RTSP MJPEG sessions unconditionally close the MediaCodec decoder and decode every frame through `BitmapFactory`, so devices with a usable hardware JPEG decoder cannot use it.
## Fix Focus Areas
- android/app/src/main/java/com/openipc/decoder/Decoder.java[199-206]
- android/app/src/main/java/com/openipc/decoder/Decoder.java[1591-1605]
## Recommended Fix
Detect and configure a `video/jpeg` MediaCodec when the device provides one, queue assembled JPEG frames through that decoder, and retain the existing `BitmapFactory` path as the fallback when hardware JPEG decoding is unavailable.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
…16-bit and once-sent tables, old-codec frames dropped, MJPEG counted in the UDP check, MJPEG cells paused
|
Qodo review — decisions:
|
Thanks for the decisions. Based on the diff, findings 1, 3, 4, 5, 6, 7, and 8 are addressed as described. |
|
Device check of the final build (Aceline-1, df65bb7): |
…16-bit and once-sent tables, old-codec frames dropped, MJPEG counted in the UDP check, MJPEG cells paused
feat: MJPEG over RTSP (RTP/JPEG, RFC 2435) in the single view (#119)
Part of #119 (single view first, as decided; multi-view later; HTTP MJPEG is #121).
JPEG/90000(or the static payload type 26 without an rtpmap) is accepted when no H.264/H.265 is offered —Sdp.videoJpeg.JpegAssembler(RFC 2435): collects the fragments of a frame (fragment offsets must follow each other, the marker bit ends it; a gap drops the frame, joining mid-frame waits for the next one) and rebuilds the JPEG headers — SOI, DQT from the in-band quantization table header (Q ≥ 128) or from Q with the standard tables, DRI for types 64–127, SOF0 (type 0 = 4:2:2, type 1 = 4:2:0), the standard Huffman tables (JPEG Annex K), SOS, scan, EOI.BitmapFactory(reusing the bitmap) and draws it over the TextureView's surface; the view's fit transform keeps the aspect ratio,updateResolutiongets the size. A surface used withlockCanvas()is replaced before a MediaCodec stream follows. Status line:Connected • TCP • MJPEG • Opus • …(Opus was missing from that line before);/stats.jsonsingle.codecMJPEG; snapshots andvideowork.Decoder: MJPEG in the single view only(no garbage into the H.264 decoder).JpegAssemblerTestwith RTP fixtures cut from a real baseline JPEG (Q = 255 with tables, Q = 50) decoded back with ImageIO; missing fragment; joining mid-frame; Q tables. The same algorithm was checked in a prototype against a capture of.133 /stream=2: all 29 frames (1280×720, type 0, Q = 255) decode.Device check: Aceline-1, a slot with
rtsp://<.133>/stream=2in single view — picture at 5 fps, Opus audio, status line, debug page.