ArduPilot / ArduPilot/MissionPlanner

CaptureMJPEG fails when `Content-Type` and/or per-part `Content-Length` are missing (MJPEG over HTTP)

Open
#3,604 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
C#
Stars
2.4k
Forks
2.9k
Avg merge
19h 16m
Merged PRs (30d)
4

Description

## Summary

CaptureMJPEG assumes MJPEG streams always include:

- a top-level `Content-Type: multipart/x-mixed-replace; boundary=...`
- and per-part `Content-Length` headers

Many valid MJPEG sources (e.g., FFmpeg’s `-f mpjpeg`, some IP cams, microcontroller streams) omit one or both. As a result, Mission Planner throws and the video pipeline stops.

## Environment

- OS: Windows 10/11 (x64)
- Camera: Logitech BRIO (MJPEG 1280×720 @ 60 fps)
- FFmpeg: 8.0 (essentials build by gyan.dev)
- Mission Planner: current (master/latest)
- .NET Framework: (project targets 4.6–4.7)

## Steps to Reproduce

1. Start a simple HTTP MJPEG stream (FFmpeg acts as a tiny server):
```shell
ffmpeg -f dshow -thread_queue_size 512 -rtbufsize 512M -framerate 60 -video_size 1280x720 -input_format mjpeg -i video="" -an -map 0:v:0 -c:v copy -f mpjpeg -boundary_tag frame -fflags nobuffer -muxdelay 0 -listen 1 http://:/stream.mjpg
```
(This produces multipart MJPEG without per-part `Content-Length`.)

2. In Mission Planner, set video source to:
`http://:/stream.mjpg`

3. Observe: MP throws an exception and shows no video.

## Expected behavior

Mission Planner should display the MJPEG stream even when:

- `Content-Type` is absent or lacks `boundary=...`
- individual parts omit `Content-Length` (client should read until the next boundary)

## Actual behavior

MP crashes or stops the pipeline with:
```log
System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at MissionPlanner.Utilities.CaptureMJPEG.getUrl() in ...\CaptureMJPEG.cs:line 138
```
In other cases, MP logs a connection error if a browser has already connected (FFmpeg `-listen 1` serves only one client):
```log
System.Net.WebException: Unable to connect to the remote server
---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 127.0.0.1:1889
```
## Additional context

Browsers handle these streams fine. Many MJPEG servers legally omit per-part lengths; clients are expected to read until the next boundary delimiter (RFC 2046 multipart).

Some endpoints also omit the top-level `Content-Type` header; clients should detect the boundary from the first boundary line in the body (e.g., `--frame`).

## Proposed fix

Make `CaptureMJPEG` tolerant to missing headers:

1. **Boundary detection**
- Parse from `Content-Type` if present.
- If missing, **sniff boundary from body** (read lines until `--`).

2. **Part reading**
- If `Content-Length` exists → read exact bytes (current behavior).
- If missing → **stream until the next boundary** sequence `\r\n--`, without over-reading (network stream is non-seekable).

3. **Header parsing**
- Case-insensitive dictionary; skip malformed lines gracefully.

4. **HTTP request hardening**
- `req.KeepAlive = true`, `req.Accept = "multipart/x-mixed-replace"`, optional read timeout.

## Workarounds

- Use a MJPEG server that always sets per-part `Content-Length` (not always possible).

- Patch CaptureMJPEG per the proposed fix (see related PR).

## Related PR

- **PR**: #3603
Implements boundary sniffing and lengthless frame reads, keeps behavior backward-compatible for compliant streams.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start with CaptureMJPEG.cs, especially the getUrl() path around line 138, and compare it with related PR #3603. Reproduce the FFmpeg multipart MJPEG stream and inspect how headers, boundaries, and frame data are read. Done means streams without a top-level Content-Type or per-part Content-Length display without stopping the video pipeline.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
audio-video-rtc, networking
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.