refactor(streamer): remove gstreamer and legacy rtmp paths
This commit is contained in:
+50
-239
@@ -1,286 +1,97 @@
|
||||
# Operational Caveats
|
||||
|
||||
This document captures known environment constraints, behavioral edge cases, and operational considerations for the cv-mmap streamer.
|
||||
This document captures the current runtime constraints for `cvmmap-streamer` after the FFmpeg-only cleanup.
|
||||
|
||||
## Environment Constraints
|
||||
## Input Model
|
||||
|
||||
### Simulator Label Length Limit
|
||||
### cvmmap URI Only
|
||||
|
||||
The cv-mmap simulator uses POSIX shared memory naming that imposes a 24-byte maximum on the `--label` parameter.
|
||||
|
||||
**Constraint:**
|
||||
- Maximum label length: 24 bytes
|
||||
- Exceeding this causes immediate exit with code 2
|
||||
|
||||
**Error message:**
|
||||
```
|
||||
--label exceeds 24 bytes
|
||||
```
|
||||
|
||||
**Workaround:**
|
||||
Use compact deterministic labels:
|
||||
```bash
|
||||
# Good (19 bytes)
|
||||
./build/cvmmap_streamer --run-mode pipeline --input-mode dummy --dummy-label acc_1_rtp_h264 ...
|
||||
|
||||
# Bad (28 bytes, will fail)
|
||||
./build/cvmmap_streamer --run-mode pipeline --input-mode dummy --dummy-label acceptance_rtp_h264_test ...
|
||||
```
|
||||
|
||||
### Deterministic Simulator Sizing
|
||||
|
||||
Small frame sizes can trigger GStreamer caps negotiation failures before the first encoded access unit on certain hosts.
|
||||
|
||||
**Constraint:**
|
||||
- Minimum recommended frame size: 640x360
|
||||
- Smaller sizes may cause `not-negotiated` pipeline errors
|
||||
|
||||
**Recommended simulator parameters for validation:**
|
||||
```bash
|
||||
./build/cvmmap_streamer \
|
||||
--run-mode pipeline \
|
||||
--input-mode dummy \
|
||||
--dummy-label acc_1_rtp_h264 \
|
||||
--dummy-width 640 \
|
||||
--dummy-height 360 \
|
||||
--dummy-fps 200 \
|
||||
--dummy-frames 320
|
||||
```
|
||||
|
||||
### Build Path Isolation
|
||||
|
||||
The downstream project must use its own build directory. Sharing the root `build/` folder with the main cv-mmap project causes cache collision.
|
||||
|
||||
**Constraint:**
|
||||
- Use `downstream/cvmmap-streamer/build`
|
||||
- Do not use root `build/`
|
||||
|
||||
**Error symptom:**
|
||||
Configure errors referencing sibling repo paths or stale cache entries.
|
||||
|
||||
**Resolution:**
|
||||
```bash
|
||||
cmake --fresh -B downstream/cvmmap-streamer/build -S downstream/cvmmap-streamer
|
||||
```
|
||||
|
||||
### GStreamer Version Requirements
|
||||
|
||||
The NVENC pipeline requires GStreamer 1.20+ with full development headers. Missing elements are detected at configure time.
|
||||
|
||||
**Constraint:**
|
||||
- GStreamer 1.20+ required
|
||||
- Development headers required for build
|
||||
- `nvh264enc` and `nvh265enc` elements checked at runtime
|
||||
|
||||
**Missing NVENC error:**
|
||||
```
|
||||
FATAL: NVENC encoder not available (nvh264enc/nvh265enc)
|
||||
Run: gst-inspect-1.0 nvh264enc nvh265enc
|
||||
```
|
||||
|
||||
**Note:** The pipeline falls back to software encoding (`x264enc`, `x265enc`) if NVENC produces zero encoded access units after 60 frames.
|
||||
|
||||
## Dual-Mode H.265 RTMP Caveats
|
||||
|
||||
### Mode Selection is Binding
|
||||
|
||||
Once selected, the RTMP mode cannot be changed without restarting the streamer process. The mode determines packetization format for the entire session.
|
||||
|
||||
**Enhanced-RTMP mode:**
|
||||
- Uses `0x90`/`0x91` header bytes
|
||||
- FourCC signaling (`hvc1`)
|
||||
- Compatible with FFmpeg 6.0+, OBS 29+, SRS 6.0+, ZLMediaKit
|
||||
|
||||
**Domestic extension mode:**
|
||||
- Uses `0x1c`/`0x2c` header bytes
|
||||
- FLV codec-id 12 signaling
|
||||
- Legacy Chinese CDN compatibility
|
||||
- Not supported by all players
|
||||
|
||||
### Server Configuration Requirements
|
||||
|
||||
**ZLMediaKit:**
|
||||
Must set `enhanced=1` in config.ini for Enhanced-RTMP mode:
|
||||
```ini
|
||||
[rtmp]
|
||||
port=1935
|
||||
enhanced=1 # 1 = Enhanced RTMP, 0 = Domestic extension
|
||||
```
|
||||
|
||||
**SRS:**
|
||||
Use `hevc.flv.conf` or `hevc.ts.conf` for HEVC support:
|
||||
```bash
|
||||
docker run --rm -it -p 1935:1935 ossrs/srs:6 \
|
||||
./objs/srs -c conf/hevc.flv.conf
|
||||
```
|
||||
|
||||
### Player Compatibility
|
||||
|
||||
| Player | H.264 RTMP | H.265 Enhanced | H.265 Domestic |
|
||||
|--------|------------|----------------|----------------|
|
||||
| FFmpeg 6.0+ | Yes | Yes | With patch |
|
||||
| ffplay | Yes | Yes | Variable |
|
||||
| VLC 3.0+ | Yes | Yes | No |
|
||||
| Chrome 105+ (MSE) | Yes | HTTP-FLV/TS only | No |
|
||||
| OBS 29+ | Yes | Yes | No |
|
||||
|
||||
### Mode Mismatch Detection
|
||||
|
||||
The `rtmp_stub_tester` validates mode expectations and fails with exit code 6 on mismatch:
|
||||
The runtime ingests from a cvmmap URI, for example:
|
||||
|
||||
```bash
|
||||
# Start stub expecting domestic mode
|
||||
./build/rtmp_stub_tester --mode h265-domestic ...
|
||||
|
||||
# Streamer sends enhanced mode
|
||||
./build/cvmmap_streamer --codec h265 --rtmp-mode enhanced ...
|
||||
|
||||
# Result: tester exits 6 (ModeMismatch)
|
||||
./build/cvmmap_streamer --run-mode pipeline --input-uri 'cvmmap://zed@/tmp/cvmmap'
|
||||
```
|
||||
|
||||
## Low-Latency Configuration Trade-offs
|
||||
Legacy flags such as `--shm-name`, `--zmq-endpoint`, `--input-mode`, and the dummy-input options are no longer supported.
|
||||
|
||||
### Queue Size
|
||||
## Encoder Path
|
||||
|
||||
| Setting | Latency | Behavior |
|
||||
|---------|---------|----------|
|
||||
| `--queue-size 1` | Lowest | Latest-frame semantics, drops old frames |
|
||||
| `--queue-size 5` | Medium | Small backlog, some frame retention |
|
||||
| `--queue-size 0` | N/A | Unbounded (NOT recommended) |
|
||||
### FFmpeg Is The Only Encoder Backend
|
||||
|
||||
### Encoder Settings
|
||||
The public backend surface is:
|
||||
|
||||
| Setting | Low-Latency Value | Trade-off |
|
||||
|---------|-------------------|-----------|
|
||||
| `--b-frames 0` | Disabled | Slightly lower compression efficiency |
|
||||
| `--gop 30` | 1 second at 30fps | Larger GOP = better compression, higher seek latency |
|
||||
| `rc-lookahead` | 0 (NVENC) | Slightly lower quality prediction |
|
||||
| `zerolatency` | true | Disables encoder buffering |
|
||||
- `--encoder-backend auto`
|
||||
- `--encoder-backend ffmpeg`
|
||||
|
||||
### Server-Side Latency (Optional)
|
||||
Both resolve to the FFmpeg encoder path. The removed GStreamer backend is no longer available.
|
||||
|
||||
When using SRS or ZLMediaKit, additional latency can be introduced by server buffering.
|
||||
### NVENC Is Optional
|
||||
|
||||
**SRS low-latency settings:**
|
||||
```
|
||||
publish { mr off; }
|
||||
play { gop_cache off; queue_length 5; tcp_nodelay on; }
|
||||
When `--encoder-device nvidia` is selected, FFmpeg must expose `h264_nvenc` and `hevc_nvenc`.
|
||||
|
||||
Useful local checks:
|
||||
|
||||
```bash
|
||||
ffmpeg -hide_banner -encoders | rg 'nvenc|libx264|libx265'
|
||||
```
|
||||
|
||||
**Trade-offs:**
|
||||
- `gop_cache off`: Players wait for next I-frame (startup delay)
|
||||
- `mr off`: Higher CPU usage
|
||||
- `queue_length 5`: More susceptible to network jitter
|
||||
If NVENC is unavailable, use:
|
||||
|
||||
## Fault Scenario Behaviors
|
||||
|
||||
### Torn Frame Handling
|
||||
|
||||
When the coherent snapshot detects a torn read (metadata changed during copy):
|
||||
|
||||
1. Frame is dropped
|
||||
2. `torn_frames` counter increments
|
||||
3. Ingest loop continues
|
||||
4. Next sync message triggers new snapshot attempt
|
||||
|
||||
**Expected log:**
|
||||
```
|
||||
SNAPSHOT_TORN frame_count=A/B timestamp=X/Y
|
||||
```bash
|
||||
--encoder-device software
|
||||
```
|
||||
|
||||
### Stream Reset Handling
|
||||
### Low-Latency Defaults
|
||||
|
||||
When `MODULE_STATUS_STREAM_RESET` is received:
|
||||
The current low-latency defaults are:
|
||||
|
||||
1. Ingest queue is flushed
|
||||
2. Frame counters reset
|
||||
3. Pipeline may rebuild if resolution/format changed
|
||||
4. RTMP publishers send sequence header rebase
|
||||
5. `resets` counter increments
|
||||
- `gop=30`
|
||||
- `b_frames=0`
|
||||
- NVENC preset/tune tuned for low latency
|
||||
|
||||
**Expected log:**
|
||||
```
|
||||
STREAM_RESET_RECEIVED
|
||||
RTMP_STREAM_RESET_REBASE mode=<mode>
|
||||
```
|
||||
This favors immediacy over compression efficiency.
|
||||
|
||||
### Backpressure Containment
|
||||
## Transport Caveats
|
||||
|
||||
When downstream sinks are slower than ingest:
|
||||
### RTMP Is Enhanced RTMP Only
|
||||
|
||||
1. Queue fills to capacity
|
||||
2. Oldest frames evicted before push
|
||||
3. `dropped_frames` counter increments
|
||||
4. Latest frame always prioritized
|
||||
5. Latency remains bounded
|
||||
The repo now supports:
|
||||
|
||||
**Expected log:**
|
||||
```
|
||||
QUEUE_DROP dropped_frames=N queue_depth=1
|
||||
```
|
||||
- `libavformat` RTMP output
|
||||
- `ffmpeg_process` RTMP output
|
||||
|
||||
## Known Limitations
|
||||
The removed custom RTMP packetizer and `domestic` mode are no longer available. RTMP is always Enhanced RTMP.
|
||||
|
||||
### No Audio Support
|
||||
### RTP SDP Is Optional
|
||||
|
||||
Version 1.0 does not support audio capture or muxing. Video-only streams.
|
||||
The RTP publisher can write an SDP sidecar when `--rtp-sdp` is set. This is only for generic receivers that need an out-of-band description. If the consumer is preconfigured, skip the SDP output.
|
||||
|
||||
### No Direct RTSP/WebRTC Publishing
|
||||
|
||||
RTSP and WebRTC are not direct publisher outputs. They require server-side conversion from RTMP or RTP.
|
||||
This repo does not contain a direct RTSP publisher or a direct WebRTC/WHEP publisher.
|
||||
|
||||
### Single Codec Per Session
|
||||
If you want browser playback or WHEP, publish RTMP to a media server such as SRS and let that server expose WHEP/WebRTC.
|
||||
|
||||
Runtime codec switching is not supported. To change codecs, restart the streamer process.
|
||||
## Media Scope
|
||||
|
||||
### NVENC Requires NVIDIA GPU
|
||||
### No Audio Support
|
||||
|
||||
NVENC hardware encoding requires an NVIDIA GPU with encode support. Falls back to software encoding on non-NVIDIA systems or when NVENC is unavailable.
|
||||
This project is video-only. It publishes or records encoded video access units only.
|
||||
|
||||
### UDP RTP Only
|
||||
If you need audio transport, muxing, or A/V sync, that is outside the current repo scope.
|
||||
|
||||
RTP output uses UDP unicast only. No multicast or TCP interleaving support in v1.
|
||||
## Recording Caveats
|
||||
|
||||
## Debugging Tips
|
||||
### MCAP Stores Encoded Video Frames
|
||||
|
||||
### Enable Verbose Logging
|
||||
MCAP recording stores one `foxglove.CompressedVideo` message per encoded access unit. Replay depends on encoded keyframes carrying decoder configuration; this is handled by the current writer on keyframes.
|
||||
|
||||
All binaries use spdlog. Set the environment variable for debug output:
|
||||
## External Server Caveats
|
||||
|
||||
```bash
|
||||
export SPDLOG_LEVEL=debug
|
||||
./build/cvmmap_streamer ...
|
||||
```
|
||||
### Local SRS Defaults Can Hit `ulimit`
|
||||
|
||||
### Check Evidence Logs
|
||||
On this machine, stock SRS configs can fail at startup if `max_connections` exceeds the local `ulimit -n`. The checked-in smoke profile uses `max_connections 64` to avoid that local failure mode.
|
||||
|
||||
Failed runs leave detailed logs:
|
||||
### Server Latency Still Matters
|
||||
|
||||
```bash
|
||||
# Find latest run
|
||||
ls -lt .sisyphus/evidence/task-14-acceptance/ | head
|
||||
|
||||
# Examine specific row logs
|
||||
cat .sisyphus/evidence/task-14-acceptance/RUN_ID/1-rtp_h264/streamer.log
|
||||
```
|
||||
|
||||
### Verify Binary Existence
|
||||
|
||||
Before running scripts, verify all binaries are built:
|
||||
|
||||
```bash
|
||||
for bin in cvmmap_streamer rtp_receiver_tester rtmp_stub_tester; do
|
||||
test -x "build/$bin" || echo "Missing: $bin"
|
||||
done
|
||||
```
|
||||
|
||||
### Test Individual Components
|
||||
|
||||
```bash
|
||||
# Test simulator only
|
||||
./build/cvmmap_streamer --run-mode pipeline --help
|
||||
|
||||
# Test streamer config validation only
|
||||
./build/cvmmap_streamer --codec h264 --shm-name test --zmq-endpoint ipc:///tmp/test.ipc
|
||||
# (Will fail with "No output enabled" but validates config parsing)
|
||||
```
|
||||
Low encoder latency does not guarantee low end-to-end latency. SRS, ZLMediaKit, HTTP-FLV players, and browser buffering can all add delay on top of the encoder path.
|
||||
|
||||
+52
-166
@@ -1,188 +1,74 @@
|
||||
# Compatibility Matrix
|
||||
|
||||
This document defines the complete protocol, codec, and RTMP mode compatibility matrix for cv-mmap streamer. It explicitly separates mandatory (blocking) checks from optional (non-blocking) checks.
|
||||
## Mandatory Acceptance Matrix
|
||||
|
||||
## Mandatory Checks (Blocking for Release)
|
||||
The deterministic acceptance matrix is driven by tester binaries, not by a dummy pipeline source.
|
||||
|
||||
These checks must ALL pass for a release to be considered valid. They require no external servers and run entirely in standalone mode.
|
||||
Run it with:
|
||||
|
||||
### Protocol/Codec Matrix
|
||||
```bash
|
||||
cmake -B build -S .
|
||||
cmake --build build
|
||||
./scripts/acceptance_standalone.sh
|
||||
```
|
||||
|
||||
| Row | Protocol | Codec | RTMP Mode | Test Command | Evidence |
|
||||
|-----|----------|-------|-----------|--------------|----------|
|
||||
| 1 | RTP | H.264 | N/A | `./scripts/acceptance_standalone.sh` (row 1) | task-14-acceptance.txt |
|
||||
| 2 | RTP | H.265 | N/A | `./scripts/acceptance_standalone.sh` (row 2) | task-14-acceptance.txt |
|
||||
| 3 | RTMP | H.264 | enhanced | `./scripts/acceptance_standalone.sh` (row 3) | task-14-acceptance.txt |
|
||||
| 4 | RTMP | H.265 | enhanced | `./scripts/acceptance_standalone.sh` (row 4) | task-14-acceptance.txt |
|
||||
| 5 | RTMP | H.265 | domestic | `./scripts/acceptance_standalone.sh` (row 5) | task-14-acceptance.txt |
|
||||
Covered rows:
|
||||
|
||||
**Pass Criteria:**
|
||||
- Exit code 0 from `acceptance_standalone.sh`
|
||||
- JSON summary shows `total=5 pass=5 fail=0 skip=0`
|
||||
- All tester processes receive expected packet/frame counts
|
||||
| Row | Protocol | Codec | Transport | Runner |
|
||||
|-----|----------|-------|-----------|--------|
|
||||
| 1 | RTP | H.264 | UDP RTP | `./scripts/acceptance_standalone.sh` |
|
||||
| 2 | RTP | H.265 | UDP RTP | `./scripts/acceptance_standalone.sh` |
|
||||
| 3 | RTMP | H.264 | `libavformat` | `./scripts/acceptance_standalone.sh` |
|
||||
| 4 | RTMP | H.265 | `libavformat` | `./scripts/acceptance_standalone.sh` |
|
||||
| 5 | RTMP | H.264 | `ffmpeg_process` | `./scripts/acceptance_standalone.sh` |
|
||||
| 6 | RTMP | H.265 | `ffmpeg_process` | `./scripts/acceptance_standalone.sh` |
|
||||
|
||||
### Fault Scenarios
|
||||
Notes:
|
||||
|
||||
| Scenario | Description | Test Command | Evidence |
|
||||
|----------|-------------|--------------|----------|
|
||||
| Torn Read | Coherent snapshot rejects torn frames | `./scripts/fault_suite.sh` | task-15-fault-suite.txt |
|
||||
| Sink Stall | Backpressure containment under slow consumer | `./scripts/fault_suite.sh` | task-15-fault-suite.txt |
|
||||
| Reset Storm | Stream reset recovery | `./scripts/fault_suite.sh` | task-15-fault-suite.txt |
|
||||
|
||||
**Pass Criteria:**
|
||||
- Exit code 0 from `fault_suite.sh`
|
||||
- All fault scenarios PASS status
|
||||
- No violations of latency/drop thresholds
|
||||
|
||||
## Invalid Combinations (Explicitly Rejected)
|
||||
|
||||
These combinations are rejected at startup with clear error messages and non-zero exit codes.
|
||||
|
||||
| Combination | Error | Exit Code |
|
||||
|-------------|-------|-----------|
|
||||
| RTMP + H.264 + domestic mode | H.264 does not support domestic mode | 1 |
|
||||
| RTP without --rtp-endpoint | Missing required RTP endpoint | 1 |
|
||||
| RTMP without --rtmp-url | Missing required RTMP URL | 1 |
|
||||
| --rtmp-mode without H.265 codec | Domestic mode requires H.265 | 1 |
|
||||
- RTMP is Enhanced RTMP only.
|
||||
- The custom RTMP packetizer and domestic mode are removed.
|
||||
- `encoder.backend` remains `auto|ffmpeg`; both resolve to FFmpeg.
|
||||
|
||||
## Optional Checks (Non-Blocking)
|
||||
|
||||
These checks are provided for interoperability validation but are NOT required for release acceptance. If the environment is unavailable, these should be skipped.
|
||||
These are useful interoperability checks, but they are not part of the mandatory acceptance gate:
|
||||
|
||||
### Server Smoke Tests
|
||||
- `./scripts/rtmp_srs_smoke.sh`
|
||||
- `./scripts/live_srs_forward_smoke.sh '<cvmmap-uri>'`
|
||||
- manual WHEP playback through SRS
|
||||
- manual ZLMediaKit interoperability checks
|
||||
- live MCAP capture, validation, and paced replay
|
||||
|
||||
| Server | Protocols | H.265 Support | Status |
|
||||
|--------|-----------|---------------|--------|
|
||||
| SRS 6.0+ | RTMP, HTTP-FLV, HLS, WebRTC | Enhanced-RTMP | Optional |
|
||||
| ZLMediaKit | RTMP, HTTP-FLV, HTTP-TS, RTSP, WebRTC | Enhanced + Domestic | Optional |
|
||||
## Recording Coverage
|
||||
|
||||
**Skip Conditions:**
|
||||
- Docker not available
|
||||
- Port 1935 in use by another service
|
||||
- Server container fails to start
|
||||
- Network isolation prevents connection
|
||||
MCAP support is validated separately with:
|
||||
|
||||
**Expected Behavior When Skipped:**
|
||||
- Script exits with status 0 (SKIP)
|
||||
- Evidence file notes the skip reason
|
||||
- Mandatory acceptance still proceeds
|
||||
- `./build/mcap_reader_tester`
|
||||
- `./build/mcap_replay_tester`
|
||||
- `./scripts/replay_mcap.sh`
|
||||
|
||||
## RTMP H.265 Dual Mode Details
|
||||
Current recording scope:
|
||||
|
||||
### Enhanced-RTMP Mode (Recommended)
|
||||
| Output | Codec | Notes |
|
||||
|--------|-------|-------|
|
||||
| MCAP `foxglove.CompressedVideo` | H.264 | Stored as Annex B access units |
|
||||
| MCAP `foxglove.CompressedVideo` | H.265 | Stored as Annex B access units |
|
||||
|
||||
**Specification:** [Enhanced RTMP](https://github.com/veovera/enhanced-rtmp)
|
||||
## Current Defaults
|
||||
|
||||
**Characteristics:**
|
||||
- Video codec header byte: `0x90` (sequence) / `0x91` (frame)
|
||||
- FourCC: `hvc1` or `hev1`
|
||||
- Standardized, widely supported
|
||||
- FFmpeg 6.0+ native support
|
||||
- OBS 29+ support
|
||||
- SRS 6.0+ native support
|
||||
- ZLMediaKit default mode
|
||||
| Setting | Value |
|
||||
|---------|-------|
|
||||
| Encoder backend | `auto` -> FFmpeg |
|
||||
| RTMP transport | `libavformat` |
|
||||
| RTMP mode | Enhanced only |
|
||||
| Encoder device | `auto` |
|
||||
| Low-latency GOP | `30` |
|
||||
| B-frames | `0` |
|
||||
|
||||
**When to use:**
|
||||
- Greenfield deployments
|
||||
- Modern CDN ingestion
|
||||
- Cross-platform compatibility requirements
|
||||
## What Is No Longer Supported
|
||||
|
||||
### Domestic Extension Mode (Legacy Compatibility)
|
||||
|
||||
**Specification:** Proprietary FLV extension using codec-id 12
|
||||
|
||||
**Characteristics:**
|
||||
- Video codec header byte: `0x1c` (keyframe) / `0x2c` (inter)
|
||||
- FLV codec-id: 12 (non-standard)
|
||||
- Legacy Chinese CDN compatibility
|
||||
- Requires explicit config in ZLMediaKit (`enhanced=0`)
|
||||
- Not supported by all players
|
||||
|
||||
**When to use:**
|
||||
- Legacy CDN requirements
|
||||
- Existing domestic-mode infrastructure
|
||||
- Backward compatibility with older systems
|
||||
|
||||
### Mode Selection Decision Tree
|
||||
|
||||
```
|
||||
Is codec H.265?
|
||||
├── No (H.264) ──> Use enhanced mode only (domestic invalid)
|
||||
└── Yes (H.265)
|
||||
├── Target is modern CDN/player? ──> enhanced
|
||||
├── Target requires domestic mode? ──> domestic
|
||||
└── Unknown? ──> enhanced (safer default)
|
||||
```
|
||||
|
||||
## Validation Commands
|
||||
|
||||
### Verify Mandatory Matrix
|
||||
|
||||
```bash
|
||||
cd downstream/cvmmap-streamer
|
||||
./scripts/acceptance_standalone.sh
|
||||
echo "Exit code: $?"
|
||||
```
|
||||
|
||||
### Verify Individual Row (RTP H.264)
|
||||
|
||||
```bash
|
||||
# Terminal 1: Tester
|
||||
./build/rtp_receiver_tester \
|
||||
--port 51040 \
|
||||
--expect-pt 96 \
|
||||
--packet-threshold 1 \
|
||||
--timeout-ms 10000
|
||||
|
||||
# Terminal 2: Streamer in dummy input mode
|
||||
./build/cvmmap_streamer \
|
||||
--run-mode pipeline \
|
||||
--input-mode dummy \
|
||||
--shm-name test_rtp_h264 \
|
||||
--zmq-endpoint "ipc:///tmp/test_rtp_h264.ipc" \
|
||||
--dummy-label rtp_h264 \
|
||||
--dummy-frames 320 \
|
||||
--dummy-fps 200 \
|
||||
--dummy-width 640 \
|
||||
--dummy-height 360 &
|
||||
|
||||
./build/cvmmap_streamer \
|
||||
--run-mode pipeline \
|
||||
--codec h264 \
|
||||
--shm-name test_rtp_h264 \
|
||||
--zmq-endpoint "ipc:///tmp/test_rtp_h264.ipc" \
|
||||
--queue-size 1 \
|
||||
--gop 30 \
|
||||
--b-frames 0 \
|
||||
--ingest-max-frames 120 \
|
||||
--rtp \
|
||||
--rtp-endpoint "127.0.0.1:51040" \
|
||||
--rtp-payload-type 96 \
|
||||
--rtp-sdp /tmp/test_rtp_h264.sdp
|
||||
```
|
||||
|
||||
### Verify Invalid Combination Rejection
|
||||
|
||||
```bash
|
||||
# Should fail with clear error
|
||||
./build/cvmmap_streamer \
|
||||
--codec h264 \
|
||||
--rtmp-mode domestic \
|
||||
--shm-name test \
|
||||
--zmq-endpoint "ipc:///tmp/test.ipc"
|
||||
|
||||
echo "Exit code: $?" # Expected: 2 (invalid mode matrix)
|
||||
```
|
||||
|
||||
## Evidence Locations
|
||||
|
||||
All test evidence is written to `.sisyphus/evidence/`:
|
||||
|
||||
| Evidence File | Description |
|
||||
|---------------|-------------|
|
||||
| task-14-acceptance.txt | Latest acceptance run pointer |
|
||||
| task-14-acceptance-summary.json | Acceptance summary JSON |
|
||||
| task-14-acceptance/RUN_ID/ | Per-run logs for each matrix row |
|
||||
| task-15-fault-suite.txt | Latest fault suite run pointer |
|
||||
| task-15-fault-suite-summary.json | Fault suite summary JSON |
|
||||
| task-15-fault-suite/RUN_ID/ | Per-run logs for each scenario |
|
||||
- GStreamer encoder backend
|
||||
- custom RTMP packetizer
|
||||
- RTMP domestic mode
|
||||
- dummy input flags in the main runtime
|
||||
- direct in-repo RTSP/WebRTC publishing
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Local SRS config for manual RTMP and WHEP testing with cvmmap-streamer.
|
||||
# Start with:
|
||||
# cd ~/Code/srs/trunk
|
||||
# ./objs/srs -c /home/crosstyan/Code/cvmmap-streamer-ffmpeg-mcap/docs/smoke/srs.local.conf
|
||||
# ./objs/srs -c /home/crosstyan/Code/cvmmap-streamer/docs/smoke/srs.local.conf
|
||||
#
|
||||
# If WebRTC/WHEP is consumed from another host and SRS chooses the wrong NIC,
|
||||
# replace `candidate *;` with the reachable host IP.
|
||||
|
||||
+9
-39
@@ -21,8 +21,6 @@ Use these checks when you want to verify RTMP interoperability or a real cvmmap-
|
||||
|
||||
## Reproducible Test: Synthetic RTMP Matrix
|
||||
|
||||
This is the fast interoperability smoke for the RTMP sink implementations:
|
||||
|
||||
```bash
|
||||
cmake -B build -S .
|
||||
cmake --build build
|
||||
@@ -42,12 +40,10 @@ What it verifies:
|
||||
- `ffmpeg_process` RTMP output with `h264`
|
||||
- `libavformat` RTMP output with `h265`
|
||||
- `ffmpeg_process` RTMP output with `h265`
|
||||
- Pullback from SRS HTTP-FLV with `ffprobe`
|
||||
- pullback from SRS HTTP-FLV with `ffprobe`
|
||||
|
||||
## Reproducible Test: Live cvmmap Forward
|
||||
|
||||
This is the end-to-end live test for a real cvmmap source:
|
||||
|
||||
```bash
|
||||
cmake -B build -S .
|
||||
cmake --build build
|
||||
@@ -60,7 +56,6 @@ The script defaults to:
|
||||
- `ENCODER_BACKEND=ffmpeg`
|
||||
- `ENCODER_DEVICE=nvidia`
|
||||
- `RTMP_TRANSPORT=libavformat`
|
||||
- `RTMP_MODE=enhanced`
|
||||
- `INGEST_MAX_FRAMES=120`
|
||||
- `STREAM_NAME=<instance>_live`, derived from `INPUT_URI`
|
||||
|
||||
@@ -69,7 +64,7 @@ Useful overrides:
|
||||
```bash
|
||||
INPUT_URI='cvmmap://zed@/tmp/cvmmap' ./scripts/live_srs_forward_smoke.sh
|
||||
./scripts/live_srs_forward_smoke.sh 'cvmmap://front_cam@/tmp/cvmmap' front_cam_smoke
|
||||
ENCODER_DEVICE=software ./scripts/live_srs_forward_smoke.sh 'cvmmap://zed@/tmp/cvmmap'
|
||||
ENCODER_BACKEND=auto ENCODER_DEVICE=software ./scripts/live_srs_forward_smoke.sh 'cvmmap://zed@/tmp/cvmmap'
|
||||
STREAM_NAME=zed_test INGEST_MAX_FRAMES=300 ./scripts/live_srs_forward_smoke.sh 'cvmmap://zed@/tmp/cvmmap'
|
||||
SRS_ROOT=~/Code/srs ./scripts/live_srs_forward_smoke.sh 'cvmmap://zed@/tmp/cvmmap'
|
||||
```
|
||||
@@ -78,9 +73,7 @@ What it does:
|
||||
|
||||
1. Reuses a healthy local SRS instance if one is already listening on `127.0.0.1:1985`
|
||||
2. Otherwise starts SRS from `~/Code/srs`
|
||||
3. Writes a temporary SRS config with:
|
||||
- `daemon off`
|
||||
- `max_connections` reduced to avoid the common local `ulimit -n 1024` failure
|
||||
3. Writes a temporary SRS config with `daemon off` and a lowered `max_connections`
|
||||
4. Publishes the cvmmap stream to `rtmp://127.0.0.1/live/<stream>`
|
||||
5. Verifies the forwarded HTTP-FLV mount at `http://127.0.0.1:8080/live/<stream>.flv`
|
||||
6. Attempts to decode a short sample through `ffmpeg`
|
||||
@@ -99,7 +92,7 @@ The HTTP-FLV probe is the authoritative pass/fail signal. The optional `ffmpeg`
|
||||
|
||||
SRS supports WHEP playback, and it is the better path when RTMP or HTTP-FLV playback feels too slow.
|
||||
|
||||
This repo includes a local SRS config copy at [srs.local.conf](/home/crosstyan/Code/cvmmap-streamer-ffmpeg-mcap/docs/smoke/srs.local.conf). It enables:
|
||||
This repo includes a local SRS config copy at [srs.local.conf](/home/crosstyan/Code/cvmmap-streamer/docs/smoke/srs.local.conf). It enables:
|
||||
|
||||
- RTMP publish on `:1935`
|
||||
- HTTP API on `:1985`
|
||||
@@ -111,14 +104,14 @@ Start SRS with that config:
|
||||
|
||||
```bash
|
||||
cd ~/Code/srs/trunk
|
||||
./objs/srs -t -c /home/crosstyan/Code/cvmmap-streamer-ffmpeg-mcap/docs/smoke/srs.local.conf
|
||||
./objs/srs -c /home/crosstyan/Code/cvmmap-streamer-ffmpeg-mcap/docs/smoke/srs.local.conf
|
||||
./objs/srs -t -c /home/crosstyan/Code/cvmmap-streamer/docs/smoke/srs.local.conf
|
||||
./objs/srs -c /home/crosstyan/Code/cvmmap-streamer/docs/smoke/srs.local.conf
|
||||
```
|
||||
|
||||
Publish from the streamer:
|
||||
|
||||
```bash
|
||||
cd ~/Code/cvmmap-streamer-ffmpeg-mcap
|
||||
cd ~/Code/cvmmap-streamer
|
||||
./build/cvmmap_streamer \
|
||||
--run-mode pipeline \
|
||||
--input-uri 'cvmmap://zed@/tmp/cvmmap' \
|
||||
@@ -127,8 +120,7 @@ cd ~/Code/cvmmap-streamer-ffmpeg-mcap
|
||||
--encoder-device nvidia \
|
||||
--rtmp \
|
||||
--rtmp-url 'rtmp://127.0.0.1/live/zed_live' \
|
||||
--rtmp-transport libavformat \
|
||||
--rtmp-mode enhanced
|
||||
--rtmp-transport libavformat
|
||||
```
|
||||
|
||||
Open the WHEP player page in a browser:
|
||||
@@ -140,20 +132,7 @@ Notes:
|
||||
|
||||
- VLC is not the right client for WHEP. Use a browser or another WebRTC/WHEP-capable player.
|
||||
- Keep the stream codec on `h264` for browser compatibility.
|
||||
- If the browser runs on another host and SRS picks the wrong NIC, replace `candidate *;` in [srs.local.conf](/home/crosstyan/Code/cvmmap-streamer-ffmpeg-mcap/docs/smoke/srs.local.conf) with the reachable host IP.
|
||||
- On this machine, likely candidates are `192.168.2.13` or `192.168.2.184`.
|
||||
|
||||
## Example Live Result
|
||||
|
||||
For a ZED source running at `cvmmap://zed@/tmp/cvmmap`, the successful forward probe looked like:
|
||||
|
||||
```text
|
||||
index=0
|
||||
codec_name=h264
|
||||
width=1280
|
||||
height=720
|
||||
avg_frame_rate=30/1
|
||||
```
|
||||
- If the browser runs on another host and SRS picks the wrong NIC, replace `candidate *;` in [srs.local.conf](/home/crosstyan/Code/cvmmap-streamer/docs/smoke/srs.local.conf) with the reachable host IP.
|
||||
|
||||
## Artifacts
|
||||
|
||||
@@ -165,15 +144,6 @@ Both smoke scripts write evidence under `build/`:
|
||||
- `live_srs_forward_smoke_*/ffmpeg_decode_httpflv.log`
|
||||
- `live_srs_forward_smoke_*/srs_api_streams.json`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Cause | Action |
|
||||
|-------|-------|--------|
|
||||
| SRS exits immediately | `max_connections` too high for local `ulimit` | Use the script-generated config or raise `ulimit -n` |
|
||||
| HTTP-FLV never mounts | Publish failed or source is idle | Check `streamer.log` and confirm the cvmmap URI is active |
|
||||
| NVENC unavailable | FFmpeg cannot open `h264_nvenc` / `hevc_nvenc` | Set `ENCODER_DEVICE=software` |
|
||||
| RTMP probe hangs | Live RTMP playback probe can block on some builds | Use the HTTP-FLV verification path; this is what the script treats as authoritative |
|
||||
|
||||
## References
|
||||
|
||||
- [SRS RTMP Documentation](https://ossrs.io/lts/en-us/docs/v7/doc/rtmp)
|
||||
|
||||
+48
-198
@@ -4,230 +4,80 @@
|
||||
|
||||
**OPTIONAL / NON-BLOCKING**
|
||||
|
||||
This document provides optional interoperability checks for ZLMediaKit. These checks are not mandatory for acceptance. If the ZLMediaKit environment is unavailable, skip these tests without failing the mandatory acceptance criteria.
|
||||
Use these checks when you want to verify external interoperability with ZLMediaKit. They are not part of the mandatory acceptance matrix.
|
||||
|
||||
---
|
||||
## Current Scope
|
||||
|
||||
## Purpose
|
||||
This repo now emits:
|
||||
|
||||
Validate RTMP streaming interoperability with ZLMediaKit, specifically for:
|
||||
- RTMP H.264 publishing and playback
|
||||
- Enhanced RTMP HEVC (H.265) support
|
||||
- Low-latency streaming configurations
|
||||
- HTTP-FLV, HTTP-TS, and WebRTC protocols
|
||||
- RTP
|
||||
- Enhanced RTMP through `libavformat` or `ffmpeg_process`
|
||||
- MCAP recording
|
||||
|
||||
---
|
||||
It does not contain:
|
||||
|
||||
## Prerequisites
|
||||
- a custom RTMP packetizer
|
||||
- RTMP domestic mode
|
||||
- direct in-repo RTSP publishing
|
||||
- direct in-repo WebRTC publishing
|
||||
- audio support
|
||||
|
||||
- Docker (recommended) or ZLMediaKit built from source
|
||||
- FFmpeg or the project streaming binary
|
||||
- Optional: ffplay, VLC for playback verification
|
||||
## Quick Start
|
||||
|
||||
---
|
||||
|
||||
## Quick Start (Docker)
|
||||
Run ZLMediaKit in Docker:
|
||||
|
||||
```bash
|
||||
# Run ZLMediaKit with default configuration
|
||||
docker run --rm -it -p 1935:1935 -p 8080:80 -p 8554:554 \
|
||||
-p 10000:10000 -p 30000-30500:30000-30500/udp \
|
||||
zlmediakit/zlmediakit:master
|
||||
|
||||
# With custom config (mount your config.ini)
|
||||
docker run --rm -it -p 1935:1935 -p 8080:80 \
|
||||
-v $(pwd)/config.ini:/opt/media/conf/config.ini \
|
||||
docker run --rm -it \
|
||||
-p 1935:1935 \
|
||||
-p 8080:80 \
|
||||
-p 8000:8000/udp \
|
||||
zlmediakit/zlmediakit:master
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Smoke Commands
|
||||
|
||||
### 1. Basic RTMP H.264 Stream Test
|
||||
## Publish From `cvmmap-streamer`
|
||||
|
||||
```bash
|
||||
# Publish test stream to ZLMediaKit
|
||||
ffmpeg -re -f lavfi -i testsrc=duration=60:size=1280x720:rate=30 \
|
||||
-f lavfi -i sine=frequency=1000:duration=60 \
|
||||
-pix_fmt yuv420p -c:v libx264 -preset fast -b:v 3000k \
|
||||
-c:a aac -b:a 128k -f flv rtmp://localhost/live/smoke_test
|
||||
cd ~/Code/cvmmap-streamer
|
||||
./build/cvmmap_streamer \
|
||||
--run-mode pipeline \
|
||||
--input-uri 'cvmmap://zed@/tmp/cvmmap' \
|
||||
--codec h264 \
|
||||
--encoder-backend ffmpeg \
|
||||
--encoder-device nvidia \
|
||||
--rtmp \
|
||||
--rtmp-url 'rtmp://127.0.0.1/live/zlm_smoke' \
|
||||
--rtmp-transport libavformat
|
||||
```
|
||||
|
||||
For an external fallback/oracle path:
|
||||
|
||||
```bash
|
||||
# Playback via RTMP
|
||||
ffplay rtmp://localhost/live/smoke_test
|
||||
|
||||
# Playback via HTTP-FLV
|
||||
ffplay http://localhost:8080/live/smoke_test.live.flv
|
||||
|
||||
# Playback via HTTP-TS
|
||||
ffplay http://localhost:8080/live/smoke_test.live.ts
|
||||
./build/cvmmap_streamer \
|
||||
--run-mode pipeline \
|
||||
--input-uri 'cvmmap://zed@/tmp/cvmmap' \
|
||||
--codec h265 \
|
||||
--encoder-backend ffmpeg \
|
||||
--encoder-device software \
|
||||
--rtmp \
|
||||
--rtmp-url 'rtmp://127.0.0.1/live/zlm_smoke_h265' \
|
||||
--rtmp-transport ffmpeg_process
|
||||
```
|
||||
|
||||
### 2. Enhanced RTMP HEVC (H.265) Test
|
||||
|
||||
**Prerequisites:**
|
||||
- ZLMediaKit with HEVC support enabled in config
|
||||
- FFmpeg 6.0+ with libx265 and enhanced RTMP support
|
||||
|
||||
**Configuration in config.ini:**
|
||||
```ini
|
||||
[rtmp]
|
||||
port=1935
|
||||
# h265 rtmp packing: 1 = Enhanced RTMP (standard), 0 = Domestic extension
|
||||
enhanced=1
|
||||
|
||||
[protocol]
|
||||
enable_rtmp=1
|
||||
```
|
||||
## Playback Checks
|
||||
|
||||
```bash
|
||||
# Publish HEVC stream (Enhanced RTMP)
|
||||
ffmpeg -re -f lavfi -i testsrc=duration=60:size=1280x720:rate=30 \
|
||||
-f lavfi -i sine=frequency=1000:duration=60 \
|
||||
-pix_fmt yuv420p -c:v libx265 -preset fast -b:v 2000k \
|
||||
-c:a aac -b:a 128k -f flv rtmp://localhost/live/smoke_hevc
|
||||
|
||||
# Alternative using project binary (if HEVC enabled)
|
||||
# ./cvmmap-streamer --output rtmp://localhost/live/smoke_hevc --codec hevc
|
||||
ffplay rtmp://127.0.0.1/live/zlm_smoke
|
||||
ffplay http://127.0.0.1:8080/live/zlm_smoke.live.flv
|
||||
ffplay http://127.0.0.1:8080/live/zlm_smoke.live.ts
|
||||
```
|
||||
|
||||
```bash
|
||||
# Playback HEVC stream via various protocols
|
||||
ffplay rtmp://localhost/live/smoke_hevc
|
||||
ffplay http://localhost:8080/live/smoke_hevc.live.flv
|
||||
ffplay http://localhost:8080/live/smoke_hevc.live.ts
|
||||
```
|
||||
## Notes
|
||||
|
||||
### 3. Low-Latency Configuration
|
||||
|
||||
For minimal latency with ZLMediaKit, modify config.ini:
|
||||
|
||||
```ini
|
||||
[general]
|
||||
# Disable merge write (0 = immediate write)
|
||||
mergeWriteMS=0
|
||||
|
||||
[protocol]
|
||||
# Frame timestamp override: 0=source, 1=system, 2=relative
|
||||
modify_stamp=0
|
||||
|
||||
# Protocol demand mode (1 = generate on demand, reduces latency)
|
||||
rtmp_demand=1
|
||||
flv_demand=1
|
||||
ts_demand=1
|
||||
|
||||
[rtmp]
|
||||
handshakeSecond=5
|
||||
keepAliveSecond=5
|
||||
|
||||
[rtp]
|
||||
# Low latency mode (WARNING: may cause artifacts with H.264 multi-slice)
|
||||
lowLatency=1
|
||||
```
|
||||
|
||||
**Caveats for low-latency mode:**
|
||||
- mergeWriteMS=0 disables write buffering (higher CPU, more syscalls)
|
||||
- modify_stamp=0 uses source timestamps (requires stable encoder timing)
|
||||
- *_demand=1 causes first viewer to wait for next GOP
|
||||
- lowLatency=1 in RTP may cause artifacts with certain H.264 streams
|
||||
|
||||
### 4. Stream Proxy Test (Optional)
|
||||
|
||||
ZLMediaKit can proxy streams from other sources:
|
||||
|
||||
```bash
|
||||
# Add stream proxy via HTTP API
|
||||
curl -X POST "http://localhost:8080/index/api/addStreamProxy" \
|
||||
-H "Content-Type: application/x-www-form-urlencoded" \
|
||||
-d "secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc" \
|
||||
-d "vhost=__defaultVhost__" \
|
||||
-d "app=proxy" \
|
||||
-d "stream=test" \
|
||||
-d "url=rtmp://localhost/live/smoke_test"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## HEVC Compatibility Notes
|
||||
|
||||
### Enhanced RTMP vs Domestic Extension
|
||||
|
||||
ZLMediaKit supports both HEVC packing formats via the enhanced config option:
|
||||
|
||||
**Enhanced RTMP (enhanced=1, RECOMMENDED):**
|
||||
- Uses standard FourCC hvc1
|
||||
- Compatible with FFmpeg 6.0+, OBS 29+
|
||||
- SRS 6.0+, ZLMediaKit master
|
||||
|
||||
**Domestic Extension (enhanced=0):**
|
||||
- Uses FLV codec ID 12
|
||||
- Required for some legacy Chinese CDN providers
|
||||
- May need patched FFmpeg for older versions
|
||||
|
||||
### Codec Priority in WebRTC
|
||||
|
||||
When using WebRTC with ZLMediaKit, codec priority can be configured:
|
||||
|
||||
```ini
|
||||
[rtc]
|
||||
# Video codec priority (first = highest)
|
||||
preferredCodecV=H264,H265,AV1,VP9,VP8
|
||||
```
|
||||
|
||||
**Note:** Chrome does not yet support HEVC in WebRTC; Safari does with experimental flags.
|
||||
|
||||
---
|
||||
|
||||
## Health Check
|
||||
|
||||
```bash
|
||||
# Get server statistics
|
||||
curl "http://localhost:8080/index/api/getStatistic?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc"
|
||||
|
||||
# Get MediaServer list
|
||||
curl "http://localhost:8080/index/api/getMediaList?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc"
|
||||
|
||||
# Check if stream exists
|
||||
curl "http://localhost:8080/index/api/isMediaOnline?secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc&vhost=__defaultVhost__&app=live&stream=smoke_test&schema=rtmp"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Missing Server Environment Behavior
|
||||
|
||||
If ZLMediaKit is not available or the Docker container fails to start:
|
||||
|
||||
1. **SKIP** - Do not fail mandatory acceptance
|
||||
2. **Log** - Document the environment issue
|
||||
3. **Continue** - Proceed with other tests
|
||||
|
||||
Example skip condition:
|
||||
```bash
|
||||
if ! docker run --rm -p 1935:1935 zlmediakit/zlmediakit:master true 2>/dev/null; then
|
||||
echo "ZLMediaKit environment unavailable - skipping smoke tests"
|
||||
exit 0
|
||||
fi
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Issue | Solution |
|
||||
|-------|----------|
|
||||
| Connection refused | Check port 1935/8080 not in use; verify server started |
|
||||
| Stream not found | Verify app/stream name; check ZLMediaKit logs |
|
||||
| HEVC playback fails | Ensure player supports HEVC; check enhanced setting |
|
||||
| High latency | Disable mergeWriteMS, use modify_stamp=0 |
|
||||
| Artifacts in stream | Disable rtp.lowLatency if H.264 multi-slice |
|
||||
| API returns 401 | Verify secret parameter matches config.ini |
|
||||
|
||||
---
|
||||
- Use Enhanced RTMP only.
|
||||
- Prefer `h264` when testing browser-facing or WebRTC-facing downstream bridges.
|
||||
- Any WebRTC playback is provided by ZLMediaKit, not by this repo directly.
|
||||
|
||||
## References
|
||||
|
||||
- [ZLMediaKit GitHub](https://github.com/ZLMediaKit/ZLMediaKit)
|
||||
- [ZLMediaKit Wiki](https://github.com/ZLMediaKit/ZLMediaKit/wiki)
|
||||
- [Enhanced RTMP Specification](https://github.com/veovera/enhanced-rtmp)
|
||||
|
||||
Reference in New Issue
Block a user