You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
345 lines
10 KiB
345 lines
10 KiB
# Adaptive Jitter Buffer Configuration Guide
|
|
|
|
## Overview
|
|
|
|
The FNE (Fixed Network Equipment) includes an adaptive jitter buffer system that can automatically reorder out-of-sequence RTP packets from peers experiencing network issues such as:
|
|
|
|
- **Satellite links** with high latency and variable jitter
|
|
- **Cellular connections** with packet reordering
|
|
- **Congested network paths** causing sporadic delays
|
|
- **Multi-path routing** leading to out-of-order delivery
|
|
|
|
The jitter buffer operates with **zero latency for perfect networks** - if packets arrive in order, they pass through immediately without buffering. Only out-of-order packets trigger the adaptive buffering mechanism.
|
|
|
|
## How It Works
|
|
|
|
### Zero-Latency Fast Path
|
|
When packets arrive in perfect sequence order, they are processed immediately with **no additional latency**. The jitter buffer is effectively transparent.
|
|
|
|
### Adaptive Reordering
|
|
When an out-of-order packet is detected:
|
|
1. The jitter buffer holds the packet temporarily
|
|
2. Waits for missing packets to arrive
|
|
3. Delivers frames in correct sequence order
|
|
4. Times out after a configurable period if gaps persist
|
|
|
|
### Per-Peer, Per-Stream Isolation
|
|
- Each peer connection can have independent jitter buffer settings
|
|
- Within each peer, each call/stream has its own isolated buffer
|
|
- This prevents one problematic stream from affecting others
|
|
|
|
## Configuration
|
|
|
|
### Location
|
|
|
|
Jitter buffer configuration is defined in the FNE configuration file (typically `fne-config.yml`) under the `master` section:
|
|
|
|
```yaml
|
|
master:
|
|
# ... other master configuration ...
|
|
|
|
jitterBuffer:
|
|
enabled: false
|
|
defaultMaxSize: 4
|
|
defaultMaxWait: 40000
|
|
peerOverrides:
|
|
- peerId: 31003
|
|
enabled: true
|
|
maxSize: 6
|
|
maxWait: 80000
|
|
```
|
|
|
|
### Parameters
|
|
|
|
#### Global Settings
|
|
|
|
- **enabled** (boolean, default: `false`)
|
|
- Master enable/disable switch for jitter buffering
|
|
- When `false`, all peers operate with zero-latency pass-through
|
|
- When `true`, peers use jitter buffering with default parameters
|
|
|
|
- **defaultMaxSize** (integer, range: 2-8, default: `4`)
|
|
- Maximum number of frames to buffer per stream
|
|
- Larger values provide more reordering capability but add latency
|
|
- **Recommended values:**
|
|
- `4` - Standard networks (LAN, stable WAN)
|
|
- `6` - High-jitter networks (cellular, congested paths)
|
|
- `8` - Extreme conditions (satellite, very poor links)
|
|
|
|
- **defaultMaxWait** (integer, range: 10000-200000 microseconds, default: `40000`)
|
|
- Maximum time to wait for missing packets
|
|
- Frames older than this are delivered even with gaps
|
|
- **Recommended values:**
|
|
- `40000` (40ms) - Terrestrial networks
|
|
- `60000` (60ms) - Cellular networks
|
|
- `80000` (80ms) - Satellite links
|
|
|
|
#### Per-Peer Overrides
|
|
|
|
The `peerOverrides` array allows you to customize jitter buffer behavior for specific peers:
|
|
|
|
```yaml
|
|
peerOverrides:
|
|
# Satellite link - high latency, requires larger buffer
|
|
- peerId: 31003
|
|
enabled: true
|
|
maxSize: 6
|
|
maxWait: 80000
|
|
|
|
# Cellular peer - variable jitter
|
|
- peerId: 31004
|
|
enabled: true
|
|
maxSize: 5
|
|
maxWait: 60000
|
|
|
|
# Local fiber peer - disable jitter buffer for minimal latency
|
|
- peerId: 31005
|
|
enabled: false
|
|
```
|
|
|
|
Each override entry supports:
|
|
- **peerId** (integer) - The peer ID to configure
|
|
- **enabled** (boolean) - Enable/disable for this specific peer
|
|
- **maxSize** (integer, range: 2-8) - Buffer size override
|
|
- **maxWait** (integer, range: 10000-200000) - Timeout override
|
|
|
|
## Configuration Examples
|
|
|
|
### Example 1: Disabled (Default)
|
|
|
|
For networks with reliable connectivity:
|
|
|
|
```yaml
|
|
master:
|
|
jitterBuffer:
|
|
enabled: false
|
|
defaultMaxSize: 4
|
|
defaultMaxWait: 40000
|
|
```
|
|
|
|
All peers operate with zero-latency pass-through. Best for:
|
|
- Local area networks
|
|
- Stable dedicated connections
|
|
- Networks with minimal packet loss/reordering
|
|
|
|
### Example 2: Global Enable with Defaults
|
|
|
|
Enable jitter buffering for all peers with conservative settings:
|
|
|
|
```yaml
|
|
master:
|
|
jitterBuffer:
|
|
enabled: true
|
|
defaultMaxSize: 4
|
|
defaultMaxWait: 40000
|
|
```
|
|
|
|
Good starting point for:
|
|
- Mixed network environments
|
|
- Networks with occasional jitter
|
|
- General purpose deployments
|
|
|
|
### Example 3: Selective Peer Configuration
|
|
|
|
Enable only for problematic peers:
|
|
|
|
```yaml
|
|
master:
|
|
jitterBuffer:
|
|
enabled: false # Disabled by default
|
|
defaultMaxSize: 4
|
|
defaultMaxWait: 40000
|
|
peerOverrides:
|
|
# Enable only for satellite peer
|
|
- peerId: 31003
|
|
enabled: true
|
|
maxSize: 8
|
|
maxWait: 80000
|
|
|
|
# Enable for cellular peer
|
|
- peerId: 31004
|
|
enabled: true
|
|
maxSize: 6
|
|
maxWait: 60000
|
|
```
|
|
|
|
Recommended approach for:
|
|
- Mostly stable networks with a few problem peers
|
|
- Minimizing overall system latency
|
|
- Targeted optimization
|
|
|
|
### Example 4: High-Jitter Network
|
|
|
|
For challenging network environments:
|
|
|
|
```yaml
|
|
master:
|
|
jitterBuffer:
|
|
enabled: true
|
|
defaultMaxSize: 6
|
|
defaultMaxWait: 60000
|
|
peerOverrides:
|
|
# Satellite link needs even more buffering
|
|
- peerId: 31003
|
|
enabled: true
|
|
maxSize: 8
|
|
maxWait: 100000
|
|
```
|
|
|
|
Suitable for:
|
|
- Wide area networks with variable quality
|
|
- Networks with frequent reordering
|
|
- Deployments with multiple satellite/cellular links
|
|
|
|
## Monitoring and Tuning
|
|
|
|
### Startup Logging
|
|
|
|
When the FNE starts, jitter buffer configuration is displayed in the logs:
|
|
|
|
```
|
|
I: 2025-12-03 22:07:11.374 Jitter Buffer Enabled: yes
|
|
I: 2025-12-03 22:07:11.374 Jitter Buffer Default Max Size: 6 frames
|
|
I: 2025-12-03 22:07:11.374 Jitter Buffer Default Max Wait: 50000 microseconds
|
|
I: 2025-12-03 22:07:11.374 Jitter Buffer Peer Overrides: 3 peer(s) configured
|
|
```
|
|
|
|
### Per-Peer Configuration Logging
|
|
|
|
When a peer connects and jitter buffering is enabled, you'll see (with verbose logging):
|
|
|
|
```
|
|
I: 2025-12-03 22:10:15.234 PEER 31003 jitter buffer configured (override): enabled=yes, maxSize=8, maxWait=80000
|
|
I: 2025-12-03 22:10:16.456 PEER 31004 jitter buffer configured (default): enabled=yes, maxSize=4, maxWait=40000
|
|
```
|
|
|
|
### Future Monitoring (To Be Implemented)
|
|
|
|
Planned monitoring capabilities:
|
|
- Per-peer jitter buffer statistics (reordered frames, dropped frames, timeouts)
|
|
- InfluxDB metrics for trend analysis
|
|
- REST API endpoints for runtime statistics
|
|
- Automatic tuning recommendations based on observed behavior
|
|
|
|
## Performance Characteristics
|
|
|
|
### CPU Impact
|
|
|
|
- **Zero-latency path:** Negligible overhead (~1 comparison per packet)
|
|
- **Buffering path:** Minimal overhead (~map lookup + timestamp check)
|
|
- **Memory:** ~500 bytes per active stream buffer
|
|
|
|
### Latency Impact
|
|
|
|
- **In-order packets:** 0ms additional latency
|
|
- **Out-of-order packets:** Buffered until:
|
|
- Missing packets arrive, OR
|
|
- `maxWait` timeout expires
|
|
- **Typical latency:** 10-40ms for reordered packets on terrestrial networks
|
|
|
|
### Effectiveness
|
|
|
|
Based on the adaptive jitter buffer design:
|
|
- **100% pass-through** for perfect networks (zero latency)
|
|
- **~95-99% recovery** of out-of-order packets within timeout window
|
|
- **Automatic timeout delivery** prevents indefinite stalling
|
|
|
|
## Troubleshooting
|
|
|
|
### Symptom: Audio/Data Gaps Despite Jitter Buffer
|
|
|
|
**Possible Causes:**
|
|
1. `maxWait` timeout too short for network conditions
|
|
2. `maxSize` buffer too small for reordering depth
|
|
3. Actual packet loss (not just reordering)
|
|
|
|
**Solutions:**
|
|
- Increase `maxWait` by 20-40ms increments
|
|
- Increase `maxSize` by 1-2 frames
|
|
- Verify network packet loss with diagnostics
|
|
|
|
### Symptom: Excessive Latency
|
|
|
|
**Possible Causes:**
|
|
1. Jitter buffer enabled on stable connections
|
|
2. `maxWait` set too high
|
|
3. `maxSize` set too large
|
|
|
|
**Solutions:**
|
|
- Disable jitter buffer for known-good peers using overrides
|
|
- Reduce `maxWait` in 10-20ms decrements
|
|
- Reduce `maxSize` to minimum (2-4 frames)
|
|
|
|
### Symptom: No Improvement
|
|
|
|
**Possible Causes:**
|
|
1. Jitter buffer not actually enabled for the problematic peer
|
|
2. Issues beyond reordering (e.g., corruption, auth failures)
|
|
3. Problems at application layer, not transport layer
|
|
|
|
**Solutions:**
|
|
- Verify peer override configuration is correct
|
|
- Check FNE logs for peer-specific configuration messages
|
|
- Enable verbose and debug logging to trace packet flow
|
|
|
|
## Technical Details
|
|
|
|
### RTP Sequence Number Handling
|
|
|
|
The jitter buffer correctly handles RTP sequence number wraparound (RFC 3550):
|
|
- Sequence numbers are 16-bit unsigned integers (0-65535)
|
|
- After 65535, sequence resets to 0
|
|
- Buffer correctly calculates sequence differences across wraparound
|
|
- No special configuration needed
|
|
|
|
### Thread Safety
|
|
|
|
- Each peer's jitter buffer map is protected by a mutex
|
|
- Per-stream buffers operate independently
|
|
- Safe for concurrent access from multiple worker threads
|
|
|
|
### Memory Management
|
|
|
|
- Buffered frames use RAII for automatic cleanup
|
|
- Timed-out frames are automatically freed
|
|
- Stream buffers cleaned up when streams end
|
|
- No memory leaks under normal operation
|
|
|
|
## Best Practices
|
|
|
|
1. **Start Disabled**: Begin with jitter buffering disabled and enable only as needed
|
|
2. **Target Specific Peers**: Use per-peer overrides rather than global enable when possible
|
|
3. **Conservative Tuning**: Start with default parameters and adjust incrementally
|
|
4. **Monitor Performance**: Watch for signs of latency or audio quality issues
|
|
5. **Document Changes**: Keep records of which peers need special configuration
|
|
6. **Test Thoroughly**: Validate changes don't introduce unintended latency
|
|
|
|
## Reference
|
|
|
|
### Related Documentation
|
|
- `ADAPTIVE_JITTER_BUFFER.md` - Technical implementation details
|
|
- `AdaptiveJitterBuffer.example.cpp` - Code examples
|
|
- `fne-config.example.yml` - Full configuration example
|
|
|
|
### Configuration Schema
|
|
|
|
```yaml
|
|
jitterBuffer:
|
|
enabled: <boolean> # false
|
|
defaultMaxSize: <2-8> # 4
|
|
defaultMaxWait: <10000-200000> # 40000
|
|
peerOverrides:
|
|
- peerId: <integer> # Required
|
|
enabled: <boolean> # Optional, defaults to global enabled
|
|
maxSize: <2-8> # Optional, defaults to defaultMaxSize
|
|
maxWait: <10000-200000> # Optional, defaults to defaultMaxWait
|
|
```
|
|
|
|
## Version History
|
|
|
|
- **December 2025** - Initial implementation
|
|
- Zero-latency fast path
|
|
- Per-peer, per-stream adaptive buffering
|
|
- Configuration parsing and validation
|
|
- Sequence wraparound support
|