Muxer — Statistical Multiplex

TSDuck-based MPEG Transport Stream multiplexer with full PSI/SI support

MPTS-multiplexare & Adaptiv Hybrid Statmux

Stream Manager mux:sammanställer flera SPTS-strömmar till en CBR MPTS-utgång (DVB/IPTV). Adaptive Hybrid Statmux kombinerar en CBR-kärnfyllnad med VBR-balanserade kodare för konstant mux-utgång.

1. Kodare layer (FFmpeg per stream)

När den överordnade muxen har statmux aktiverad, kör varje FFmpeg-kodare begränsad VBR: -b:v <avg> -minrate <min> -maxrate <max> -bufsize <max×2>. VBV-buffer = 2× max ger ~2 s toppreserv. Statmux-strömmar får också ett deterministiskt GOP-avstånd (-force_key_frames) per stream_id så att I-frame-toppar inte sammanfaller över kanaler.

2. Mux-lager (TSDuck tsp-pipeline)

tsp -I null (∞ NULL-paket @ linjehastighet) → -P merge tsp -I ip <stream> (överlagrar riktiga paket) → -P continuity (dropplarm) → -P pcradjust --bitrate X (omskriver PCRs) → -P pcrverify --jitter-max 500µs → -P bitrate_monitor (hastighetslarm ±5%) → -P regulate --bitrate X --packet-burst 32 → -O ip <out> --packet-burst 7 --enforce-burst.

3. Utmatning layer (UDP)

regulate-pluginen avger exakt mux.bitrate bps på ledningen. Inmatningar som ligger efter → NULL-paket fyller gapet. Inmatningar som toppar → intern FIFO-buffer (4096 paket ≈ 0,3 s @ 19 Mbps) absorberar. --enforce-burst tvingar 7 TS-paket per UDP-datagram (1316 B, IPTV-standard).

Rekommenderad sizing (Σ min / avg / max vs mux.bitrate)

Muxens övre fält visar 3 summor med färgstatus. Regler:

Σ avg ≤ 85 % mux.bitrate — genomsnittlig målsumma över alla kanaler plus ljud. Det är muxens 'budget'. 15 % statistisk reserv skyddar mot toppsammanträffande. Grön ≤ 85 %, amber ≤ 100 %, röd > 100 %.

Σ max ≤ 160 % mux.bitrate — taksumm för toppar. Tillåtet att överskrida kapaciteten (det är poängen med statmux — toppar sammanfaller sällan). Grön ≤ 160 %, amber ≤ 200 %, röd > 200 % (droppar vid ihållande topp).

Σ min ≤ 50 % mux.bitrate — kodarens golvsumma. Ett säkert golv säkerställer att kodaren inte sjunker till onödigt låg kvalitet vid stillasittande scener. Grön ≤ 50 %, amber ≤ 90 %, röd > 90 %.

Exempel: 4 HD-kanaler i en 19 Mbps DVB-T-mux

Tillgänglig budget efter PSI/SI/EIT: ~18,5 Mbps. Σ avg = 4 × 4,0 = 16 Mbps (86 % — ambergräns, sänk ytterligare). Σ max = 4 × 6,0 = 24 Mbps (130 % — grön, OK). Σ min = 4 × 3,0 = 12 Mbps (65 % — amber, OK). Mål: avg ~85 % av budget, max ≤ 160 %.

Diagnostics & larm

Vid ≥ 10 larm på 60 s visas en blinkande avisering i Mux-gränssnittet som rekommenderar en hastighetsreduktion. Auto-back-off är INTE aktivt — operatören bestämmer.

-P bitrate_monitor --periodic 60 --min/max ±5% — larm om faktisk hastighet avviker bortom ±5 % av målet. Betyder att regulate är utsvält (inmatningen dog).

-P continuity — spårar TS-continuity-räknare. Loggar en varning vid varje drop (översubskription, FFmpeg-krasch, NIC-jitter).

-P pcrverify --jitter-max 500000 — DVB tillåter PCR-jitter ≤ 500 µs. Larm = pcradjust hinner inte eller källan har trasiga PCRs.

Glitches & deras orsaker

GOP-sammanträffande — alla kodare avger I-frames samtidigt, toppsammanträffande. Fix: GOP-avstånd (redan aktiverat för statmux, hash(stream_id) mod gop_size).

Inmatning loss-of-signal — single channel goes black, mux continues (thanks to -I null base). Varaktighet ~3-8 s for FFmpeg restart.

Översubskription (ihållande toppar > kapacitet) — blockerar/ljudhakar ~50-200 ms. Fix: sänk streamens avg med 5-10 % eller ta bort en kanal.

PCR-drift — STB-hakar varannan sekund. Fix: pcradjust i pipeline (redan där), övervaka pcrverify-larm.

STB VBV-underrun — STB förlorar synkronisering och återfår (~2-3 s). Fix: kodare bufsize = 2 × maxrate (redan), sänk maxrate.

tsp-pipelineparametrar (mux_worker.ex)

--max-input-packets 4096 / --max-flushed-packets 4096 (intern FIFO ≈ 0,3 s @ 19 Mbps). --receive-buffer-size 16777216 (16 MB UDP-mottagningsbuffer per inmatning). --packet-burst 32 (regulate) / 7 (utgång, IPTV-standard). --enforce-burst (varje UDP-datagram är exakt 7 paket).

Empirisk kapacitetsberäkning (CLT)

Topp-bar badge `📐 rec X.XM` shows the recommended mux capacity derived from the central limit theorem. The sum of independent VBR streams approaches a normal distribution, so Mux = μ_total + z·σ_total + margin. σ_i is estimated from each input's VBR range as (max−min)/4 (assuming the range covers ±2σ). The margin = 10% of μ_total compensates for PSI/SI overhead, encoder rate-control jitter, and stream correlation that pure CLT under-estimates.

Märkfärg: 🟢 grön = cap ≥ 99,7 % rec (konservativ) · 🟡 amber = mellan 99 % och 99,7 % · 🔴 röd = cap < 99 % (underdimensionerad, risk för droppar) · 🔵 blå = cap inställd.

z-score per täckningsmål: 90 % z=1,28 · 95 % z=1,65 · 99 % z=2,33 · 99,7 % z=3,00 (standard) · 99,99 % z=3,72 (sändningsklass). Märktyptipsen listar alla nivåer; klick applicerar 99,7 %-rekommendationen på mux.bitrate (mux-omstart krävs).

σ_eff = σ_total × statmux_factor (statmux_factor = 0,7 när Statmux är PÅ, annars 1,0)

Rekommenderad values per channel (HD H.264)

1080p25 HD-kanal: genomsnitt = 4000–5000 kbps, min = genomsnitt × 0,75 (~3000–3750), max = genomsnitt × 1,5 (~6000–7500). Gränssnittet fyller automatiskt i min/max baserat på genomsnittet. Statmux-gränssnittet fyller automatiskt i genomsnittet från strömmens transcoder-profil. SD-kanal: genomsnitt = 2000–2500 kbps. UHD: genomsnitt = 12000–18000 kbps.

Adaptiv Hybrid Statmux

Adaptiv Hybrid Statmux är en körtidsmekanism som flyttar oanvänd kapacitet från kärnströmmar (skyddade, full VBR) till balanserade strömmar (offrade). "Hybrid" eftersom två distinkta hastighetskontrollregimer körs sida vid sida (CBR-kärnfyllnad + VBR-balanserad); "adaptiv" eftersom routern omvärderar en gång per sekund baserat på en HLS-förhandsvisningsprognos. Operatören markerar strömmar som balanserade via kryssrutan till höger; systemet förkodar dem i tre nivåer (HÖG/MED/LÅG) och routern byter atomiskt symboliken baserat på återstående marginal efter att ha förutsagt kärntoppar.

Kapacitet — hur bitraten fördelas

Mux-kapacitet 38 Mbps
  ┌──────────────────────────────────────────────────────────────────┐
  │█████████████████████████████████████████████████████░░░░░░░░░░░░│
  └──────────────────────────────────────────────────────────────────┘
   ◀────── core_max (förutsagd från 6 HLS-segment) ─▶◀── balanserad ──▶
                                                       per_balanced
                                                       = (kap − core_max
                                                          − SI-överhead
                                                          − ljud) / N

  Exempel: kap=38000  core_max=29000  SI=200  ljud_totalt=1280  N_balanserad=2
           återstående = 38000 − 29000 − 200 − 1280 = 7520 kbps
           per_balanserad_max = 7520 / 2 = 3760 kbps
           clamp(3760, 500, 3000) = 3000 kbps  ← tak för balanserad VBR

Praktisk vinst (10 strömmar × 3 Mbps genomsnitt, 4 Mbps max)

Utan Adaptiv Hybrid Statmux måste du dimensionera muxen för det värsta fallet Σ max. Med Adaptiv Hybrid Statmux dimensionerar du runt Σ genomsnitt + en statistisk buffert (korrelation för sändning ρ=0,15). Verklig vinst ~5 Mbps på en 38 Mbps-mux, eller +1 ström vid samma kapacitet.

Ren CBR (kodare fast)

VBR utan Statmux

Adaptiv Hybrid Statmux PÅ

URL ↔ Statmux-exklusivitet

Anpassad URL input override and Statmux are mutually exclusive. With Statmux on, the balanced transcoder relies on the local encoder HLS to control bitrate. An external URL would bypass that control loop. The UI enforces this both ways — the checkbox locks when there is a conflicting combination, and the tooltip shows which stream is blocking.

Pipeline (kodare → balanserad transkodare → mux ffmpeg → tsp)

┌─────────────────────────┐
          │  Kodare (NVDEC→NVENC)  │ ← UDP satellite
   STREAM │  /dev/shm/stream_X/h264/│
          │  → muxed.m3u8 + segments│
          └────────────┬────────────┘
                       │
              ┌────────┴────────┐
              │                 │
        role="core"        role="balanced"
        (protected)        (sacrificial)
              │                 │
              │                 ▼
              │     ┌───────────────────────────┐
              │     │  BalancedTranscoder       │
              │     │  ffmpeg p1 NVENC VBR      │
              │     │  -maxrate dynamic         │ ← Adaptive Hybrid router
              │     │  /dev/shm/stream_X_       │   1 s tick (predicts from
              │     │   balanced/h264/...m3u8   │   6 HLS segments, atomic
              │     └───────────┬───────────────┘   symlink swap HIGH/MED/MIN)
              │                 │
              ▼                 ▼
          ┌─────────────────────────┐
          │  ffmpeg-as-mux          │ ← /dev/shm/mux_X/pipe.sh
          │  -f mpegts pipe:1       │
          │  -muxrate <cap>         │
          └────────────┬────────────┘
                       │ shell pipe
                       ▼
          ┌─────────────────────────┐
          │  tsp -I file -          │
          │  continuity → regulate  │
          │  → pcradjust → bitrate_ │
          │     monitor             │
          │  -P nit -P sdt -P inject│
          │     (DVB SI tables)     │
          └────────────┬────────────┘
                       │
                       ▼ UDP multicast
                  239.x.x.x:1234

Dimensionering av kärn-VBR min/genomsnitt/max för statmux

Statistisk vinst inträffar endast när kodare har ett brett VBR-område — när max ≈ genomsnitt är kodaren effektivt CBR och routern har inget att omfördela. Konfigurera `min/genomsnitt/max` per ström så att Σmax är bekvämt över mux-kapaciteten (översubskription = marginal för statistisk vinst) medan Σgenomsnitt ligger bekvämt under den.

Worked example — 38 Mbps mux, 10 HD core + 2 balanced:

  Old (CBR-locked):       min=2000  avg=3000  max=4000
     Σmax = 10×4000 + 2×7600 = 55200 kbps  (1.45× cap — small gain)
     σ_per_stream = (4000−2000)/4 = 500 kbps  (trivial — flat)
     Σ statistical headroom ≈ 1.5 Mbps

  Rekommenderad (wide VBR): min=1500  avg=3000  max=6000
     Σmax = 10×6000 + 2×7600 = 75200 kbps  (1.98× cap — healthy gain)
     Σavg = 10×3000 + 2×3000 =  36000 kbps  (95% cap — comfortable)
     Σmin = 10×1500 + 2×500  =  16000 kbps  (42% cap — comfortable floor)
     σ_per_stream = (6000−1500)/4 = 1125 kbps  (significant)
     Σ statistical headroom ≈ 4 Mbps

  Real benefit: on action scenes core peaks at 5−6 Mbps (HD detail), the
  router sheds balanced to MIN tier, total wire stays at 38 Mbps.
Rekommenderad range per core stream:

  • min  ≈ avg × 0.5  (encoder may drop on still scenes)
  • avg  = nominal target by resolution (HD ≈ 3 Mbps, FullHD ≈ 5 Mbps, UHD ≈ 12 Mbps)
  • max  ≈ avg × 2.0  (encoder may peak on action — sport, action film)

Mux capacity guards (must hold):

  • Σ avg core + Σ avg balanced  ≤  mux.bitrate × 0.85   (comfortable target)
  • Σ max core + Σ max balanced  ≤  mux.bitrate × 2.0    (over-subscription gain)
  • Σ min core + Σ min balanced  ≤  mux.bitrate × 0.6    (worst-case floor)

σ_per_stream = (max − min) / 4  (assumes ±2σ range)
σ_total = √((1−ρ) · Σσ²ᵢ + ρ · (Σσᵢ)²)   ρ = 0.15 broadcast typical
σ_eff = σ_total × 0.7                     (statmux factor when ON)
Mux_99.7% = μ_total + 3 · σ_eff           (shown in top-bar 📐 rec)

Tips & felsökning

Minst 1 balanserad ström — utan en sådan har den Adaptiva Hybrid-routern inget att dämpa under toppar, så vinst = 0

Musik- och informationskanaler är de bästa kandidaterna — 90 %+ tolerans mot hastighetsbortfall

Spåra via `[balance-router]`-loggningsposter — visar `core_max`, `remaining`, nivåövergångar för varje 1 s-tick

Om `core_max > kapacitet` (VARNING CORE OVERPEAK i loggen), minska antalet kärnströmmar eller sänk kodarens maxhastighet

Operatörsarbetsflöde

Lägg till streams to the mux (channel assignment stays manual)

Växla Statmux på mux-huvudet (gul chip). När det är aktiverat växlar alla kodare till VBR och startar om

Markera offerströmmar via den orange kryssrutan till höger — vanligtvis musik/informationskanaler där hastighetsbortfall är osynligt

Klart. Den Adaptiva Hybrid-routern läser en 6-segments HLS-prognos från kärnströmmar varje 1 s och byter atomiskt den balanserade symboliken mellan HÖG/MED/LÅG-nivåer

StatMux — inbyggd statistisk multiplex

The mux runs on a native C NIF (single-host, replaced the old gst_mux.py). Each channel has its own CBR encoder; the NIF demultiplexes them, statistically allocates bitrate by scene complexity, pads with NULL packets to a fixed wire cap, and emits one MPTS UDP multicast. This help describes the current UI: chart, headroom slider, diff gauge, channel cards.

Klass: sluten återkoppling statmux med C1-framförhållning (framkoppling) över VBR-encoders — broadcast statmux-princip, driven från källkomplexitet.

Arkitektur och dataflöde

Architecture diagram

UDP multicast SSM, per kanal

Encoder

källkomplexitet

Loopback — kodar Mux-utmatning för återkoppling.

egen linje / stream

allokator (Σ ≤ pool)

buffert

null-utfyllnad → CBR

CBR-tråd vid cap

förutse komplex scen innan dippen

uppmätt tråd — kalibrering

målbithastighet

Varje kanal körs på sin egen linje upp till muxen (separat encoder + loopback-anslutning), där alla sammanfogas i en MPTS multicast-linje med exakt fast bithastighet. Allokatorn är den centrala hjärnan (1 GenServer per mux), tick ~0,85 s.

Hjärnan: återkoppling + C1-framförhållning

Allokatorn kombinerar två signaler — en prediktion från källkomplexitet (framåt) och den uppmätta tråden (bakåt). Detta liknar broadcast-statmuxar som känner till en frames kostnad innan kodning.

C1 mäter innehållets komplexitet vid avkodaren — vilket leder encoder-output med pipelineslatensen. Den relativa komplexitetsändringen (korrelation r≈0,92 med bitar) tillämpas på målbithastigheten i BÅDA riktningarna INNAN encodern producerar det.

Uppmätt tråd (återkoppling)

Exakta per-stream bitar emitterade av muxen (sändarsidans räknare) kalibrerar komplexitet→bithastighet-mappningen och håller summan exakt vid poolen. Grundsanningsankare — C1-prediktionen är inte perfekt (r 0,92), den efterföljande tråden korrigerar den.

Leveransbarhet

En streams anspråk backas upp av vad encodern faktiskt producerar (× topprumsreservation). En enkel kanal kan inte hamsra bandbredd den inte kan använda — den frigör det till de hungriga.

Utjämnad kvalitet

Målet är inte lika bithastighet utan lika kvalitet — kontinuerligt tryck flyttar bitar från högkvalitetskanaler (låg QP) mot lågkvalitetskanaler (hög QP).

Prediktiv omfördelning

När C1 signalerar att en kanal minskar, överlämnas dess bandbredd till de andra i samma tick — de rampar upp innan minskningen faktiskt når tråden.

Per-channel weight = complexity_q12 × max_bps (action scene + higher max ⇒ more bits).

Per-stream budget = global budget × weight / Σweights, clamp [min_bps, max_bps], recomputed every 10 ms.

×headroom % (slider) on the encoder target → Σ real encoder < wire cap ⇒ rings drain empty ⇒ clean video.

Stale-exclusion: a dead input (no receive > 2 s) is dropped from the splitter — its share goes to live channels, not wasted; re-included automatically on recovery.

NULL pad fills the difference to the wire cap (strictly CBR). Kodare feedback: ZMQ complexity → BalanceRouter → set_bitrate.

CBR-tråd: buffer + null-utfyllnad + pacing

Utdatan är en exakt CBR-ström vid det konfigurerade cap:et. Tre lager garanterar det:

Stående buffer ~1 s

Sändkön håller en stående nivå på ~1 s av tråd som absorberar sub-sekund GOP-dippar (mellan I-frames). Verifierat från inspelningen: 0,5–1 s absorberar 88–91% av dipparna.

Null-utfyllnad

När innehållet är under cap fylls skillnaden med MPEG-TS null-paket (PID 0x1FFF). Tråden träffar ALLTID cap:et — DVB-kompatibel.

Exakt pacing

Utgång pacas till exakt cap (busy-spin ABSTIME); ett 12 ms skuldklämma förhindrar catch-up-burstar efter ett kort stopp → ingen PCR-jitter, inga över-cap-toppar.

Bithastighet chart (main)

Stacked area — each channel has its colour (matching its card below). Σ of all + NULL pad = wire cap. Switch the time window 10m / 1h / 24h; pills next to it = event counts (CC / PCR / BR / OVF) for the selected window.

Färgade band

Varje kanal har en stabil färg; tjocklek = dess ögonblickliga bithastighet. Overhead (PSI/EIT) är grå längst ned, null-utfyllnad är texturerad vit längst upp.

Cap / Max-linje

Den streckade linjen längst upp = konfigurerat cap (trådtak). Innehåll + null-utfyllnad sitter alltid under det.

Null-band

Det prickade vita bandet längst upp = null-utfyllnad (ledig kapacitet). Ju tunnare det är, desto fullare är tråden; det försvinner vid krävande innehåll.

Drop-markeringar

Röda markeringar på tidslinjen = sändköspill (drop). Noll i stabilt läge; burstar bara vid boot/flood.

Intervall (30s–30m)

Knappar byter tidsfönster omedelbart (klientside), den aktiva har grå bakgrund. Grafen ackumulerar 30 min i webbläsaren.

Verktygstips

Hovring visar per-kanal bithastighet, QP och kvalitetsindex vid det momentet (historiskt värde, inte live).

Max bitfrekvens (kbps) — hård gräns för strömmen.

Aktuell poolregleringsnivå (pool/(pool−trim)). >100% = övertryck (fyller buffern), <100% = trimning.

Reserv (skjutreglage)

Toleransband ovanför cap — hur mycket som ska hållas som null-reserv. 0 = fyll exakt N; positivt = större reserv (säkrare); negativt = lätt överfyllnad.

Buffert (drop)

Rubriken visar sändkö-utnyttjande % och kumulativa drops. Knappen rensa drops nollställer räknaren.

GOP-storlek (frames) — nyckelbildsintervall.

Gemensam GOP-längd för alla kanaler i muxen (låst i videoprofiler vid start). Väggförsprångning sprider I-frames i tid så de inte kolliderar.

VBV-bufferstorlek (ms) — Video Buffer Verifier.

Encoder VBV-buffertstorlek (ms). Mindre jämnar ut I-frames (bra för rörelsekhanaler), större ger mer detaljerade I-frames. Standard 850; per-stream-override möjlig.

Kanal cards (Programs)

The section header has a 'Collapse / Expand all' toggle. Expand a card by clicking it or clicking its colour band in the chart. The left coloured strip with checkbox = channel membership in the mux.

dark = körs OK

orange = starting / restarting

grey + dimmed = down/error and checkbox OFF (intentionally disabled — no alarm)

red + BLINKING = FAULT — channel is in the mux (checkbox ON) but the stream is down/error

PSI/SI-tabeller (komplett DVB-uppsättning)

StatMux genererar den fullständiga uppsättningen obligatoriska MPEG-TS / DVB-tabeller direkt i NIF-muxen — ingen extern SI-inserter. Tabeller är jämnt tidsinriktade i strömmen så att en STB alltid hämtar PSI/SI snabbt efter omsökning.

Tabell

PID-allokering för PSI/SI-deskriptorer.

Intervall

Syfte / källa

EIT ↔ EPG: full integration

EIT (Event Information Table, PID 0x12) är inte statisk — den är fullt kopplad till applikationens EPG-system. Operatören tilldelar varje kanal i muxen en EPG-tjänst (eit_epg_service_id), och muxen genererar live EIT från dess schemalagda händelser.

Sizing / recommendations

mux.bitrate = wire CBR cap (typ. 37 Mbps for 12 SD/HD channels).

Σ avg ≲ cap (comfortable target) · Σ max oversubscribed 1.5–2× cap (that is the point of statmux — peaks rarely coincide) · Σ min = worst-case floor.

Set per-stream min/avg/max in Stream → Transcoder profile (auto-syncs to mux_input). Action/sport 8–10 M, news/talking head 1–2 M, min never < 800 k.

The headroom slider is a quick live lever of reserve vs. tightness — no restart.

Relation till broadcast-statmuxar

Vi gör riktig statistisk multiplexning — dynamisk bitomfördelning över VBR-kanaler som delar en fast tråd, med kvalitetsutjämning. Mekaniskt är vi nära professionella headend-statmuxar (cap-justering, 1 s-buffer, null-utfyllnad, GOP/B-frames, golvöverstyrning).

Vad vi har

CBR-tråd vid cap · 1 s buffer · per-stream proportionell allokering · C1-framkoppling · kvalitetsutjämning · prediktiv omfördelning · null-utfyllnad · exakt pacing.

Var vi skiljer oss

En broadcast-statmux använder encoderns hastighets-distortionsuppskattning (exakt framekostnad, encodern är en slav till allokatorn). Vi använder C1-källkomplexitet (r≈0,92) + en VBR-encoder som väljer sin egen QP — en hårdvarugräns, inte en designgräns.

Felsökning

Symtom

Orsak / lösning

Kanal red and blinking

In the mux (checkbox ON) but stream down/error → check the source/encoder of that stream. Self-recovers once restored.

Lots of NULL / large grey area

Calm content or low headroom — normal (statmux gain). For tighter utilization raise the headroom slider or per-stream max_bps.

Picture freezes / glitches

Headroom too high (rings not draining) → lower the slider to 80–82 %. Watch the diff gauge / NULL.

After restart streams=0 / all NULL

Mux started before the encoders — self-heal automatically reaches 12 within ~30 s (1 s tick retry). Nej manual action.

Diff gauge stuck at 0 / chart empty

Nej live samples (mux stopped or encoders not körs) — check both the mux and stream status.

Arkitektur (änd-till-änd)

SAT UDP SSM ─┐
             ├─ gst_encoder.py(K1)  CBR ─ TCP127 ─┐        ZMK-komplexitet
   (per      ├─ gst_encoder.py(K2)  CBR ─ TCP127 ─┤            ▲   │
   kanal)     └─ gst_encoder.py(Kn)  CBR ─ TCP127 ─┤            │   ▼
                                                  ▼     BalanceRouter
                                   ┌─────── NIF StatMux ───────┐  │ set_bitrate
                                   │ per-ingångs ring (drop-old) │◄─┘
                                   │ 2-pass drain (A prio, V)  │
                                   │ allokatör: w=cmplx×max    │
                                   │ ×headroom% (reglage 78-90) │
                                   │ stale-exclusion (>2s)     │
                                   │ NULL pad -> wire cap CBR  │
                                   │ PCR pass-through          │
                                   └────────────┬──────────────┘
                                                ▼
                                   MPTS  UDP multicast (CBR cap)

gst_encoder.py per stream: SAT UDP SSM input → nvh264enc rc-mode=cbr. Bithastighet is driven by BalanceRouter via set_bitrate. Scene complexity (SAD/px) reported over ZMQ to the allocator.

Per-ingångs ring (TCP-loopback från encoder), 2-pass drain (ljudprioritet, video fullständig), proportionell allokatör, NULL-pad exakt till ledningskapacitet (CBR), PCR-pass-through från encoder.

En MPTS (PAT/PMT/SDT genereras av NIF) → UDP-multicast på utgångs-VLAN. Ledningen är strikt CBR vid mux.bitrate (NULL-fyllnad).

Rad 1: ⚠ (valideringsproblem) · PNR · namn i en ram (färg = tillstånd).

Rad 2+: min·genom·max kbps · förutsedd komplexitet Δ låg/medel/hög/topp · INPUT FÖRLORAD · ⚙URL · encoder Mbps · SID · service_type.

Namn colour = stream state:

Mbps
 37 ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌  <= cap 37.0 Mbit (röd, tråd CBR tak)
    · · · · · · · · · · · · · · · · ·     <= ledigt utrymme = NULL-paddning
    ·· grå · svarta prickar · reserv ··       (outnyttjad kapacitet)
 31 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━  <= headroom 85% · 31.5 Mbit (orange,
    ▓▓▓▓ JOJ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓     encoder-målen siktar hit)
    ▒▒▒▒ Markíza ▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒▒
    ░░░░ TA3 ░░░░░░░░░░░░░░░░░░░░░░░░░░  <= klicka på band -> expandera kort
  0 └──────────────────────────────────
        tid ->           10m │ 1h │ 24h     CC0 PCR0 BR0 OVF0

Röd 'cap'-linje: tråd CBR-tak (mux.bitrate) — NULL fyller upp hit.

Orange 'headroom N%' line: = cap × headroom slider / 100. Kodare set_bitrate targets aim here. Moves with the slider.

Grey area with black dots between content and cap = NULL padding (unused reserve). Mer dots = more reserve.

Klicka på en kanals färgband → expanderar automatiskt den kanalens kort nedanför.

Schema

MuxEitAdapter läser händelser från EPG-systemet per tjänst, bygger DVB EIT-sektioner (namn, tid, varaktighet, beskrivning, genre) och paketerar dem på PID 0x12. Sektionsversioner ökas vid EPG-ändring — STB:n hämtar uppdateringen.

EIT injiceras direkt i NIF-muxen, jämnt IN i null-utrymmet (1 paket / N output + p/f periodiskt) — ersätter den bursty externa tsp-kaskaden. Topp/genomsnitt ≈ 1,1, ingen innehållsavlägsnande, cap håller.

Tabell 0x4E — den aktuellt körande + nästa händelse. Injiceras var ≤2 s för omedelbar nu/nästa-aktualitet på STB:n.

Muxen regenererar periodiskt EIT .bin från EPG (~15 s) — en EPG-schemaändring når tråden utan omstart. Muxrubriken visar EIT ✓ när aktiv.

Tabeller 0x50/0x51 — hela schemat timmar/dagar framöver (segment). Spridda jämnt i strömmen.

Diff-mätare (ovanför diagrammet)

Indicator of real flow vs cap. Centrum = cap (0). Marker left (green) = reserve (Σ content under cap); right (red) = overflow. Live, moves every tick.

-5 Mbps CAP 37000 kbps +5 Mbps

[#### grön = reserv ####│::: röd = över cap :::]

^ -3200k

(Σ innehåll ~3.2 Mbps under cap = hälsosam reserv)

Headroom-reglage (78–90 %, standard 85)

Lägre (→78): mer NULL-reserv, säkrare, mindre tight cap-utnyttjande.

Högre (→90): tightare cap-utnyttjande, mindre NULL.

⚠ ≥88 %: slider turns yellow — close to the ring-overflow freeze ceiling. Svår-clamp 78–90 (cannot reach 100 — guard against frozen video).

Asymmetri: att sänka lägger till reserv pålitligt; att höja är begränsat av per-ström max_bps clamp (allocatören trycker inte en kanal över dess max → säkert).

Styr hur stor del av cap:en encoder-målen siktar på: encoder-mål = budget × headroom% / 100 (orange linje i diagrammet). Ändras i realtid (effekt från nästa 10 ms tick), sparas i SystemConfig.

Signalförlust / kanalfel (isolering)

One channel fails (encoder crash / signal loss) ⇒ the mux keeps körs, other channels unaffected, wire holds the cap (NULL absorbs the outage), CC=0 on survivors. Per-input ring threads are independent. The failed channel shows a red blinking name + INPUT LOST badge; the encoder is supervised-restarted and the channel self-recovers.

PCR / timing

PCR and PES PTS/DTS are pass-through from the encoder (single clock domain ⇒ coherent, no drift). Residual PCR jitter ~tens of ms is inherent (10 ms output tick + UDP) — STB/VLC PLL tolerates it, CC=0. Svår DVB-S2 modulator compliance is out of scope for the current IPTV use case.

CAT — conditional access (endast vid scrambling / ECM).

EIT — händelseinformation (EPG) — från EPG-systemet, se nedan.

NIT — nätverksinformation (nätverks-ID, namn, transportström).

PAT — programlista (mappar PNR → PMT PID).

PMT — per program: video/ljud/PCR PID, codecs, descriptors.

SDT — tjänstenamn och leverantörer (vad STB:n visar i listan).

TDT/TOT — tid och datum + lokal offset (STB-klocka).

TSDuck Plugins Used

merge
regulate
pat
pmt
sdt
nit
eitinject
timeref
bitrate_monitor
continuity
psimerge
count