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.
dvmhost/docs/FNE Jitter Buffer Configura...

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:

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:

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:

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:

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:

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:

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

  • ADAPTIVE_JITTER_BUFFER.md - Technical implementation details
  • AdaptiveJitterBuffer.example.cpp - Code examples
  • fne-config.example.yml - Full configuration example

Configuration Schema

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

Powered by TurnKey Linux.