---
title: TS Analyze Perfect Streamer Toolkit v2.3 — TR 101 290
url: https://doc2.pstreamer.tv/en/manual/toolkit/ts_analyze.html
lang: en
product: Perfect Streamer
version: 2.0.2.362
---

# TS Analyze Perfect Streamer Toolkit v2.3 — TR 101 290

Part of the **Perfect Streamer Toolkit** — [https://pstreamer.tv](https://pstreamer.tv)

Command-line **MPEG-TS transport stream analyzer** with **ETSI TR 101 290 V1.4.1** conformance checking and **ISO/IEC 13818-1** T-STD buffer model validation.

Reads **UDP multicast/unicast** or **TS files**, automatically discovers the PCR PIDs via PAT/PMT and prints a full or short report to stdout.

The tool is part of the **pstreamer** package and, once installed, resides at `/opt/pss/tools/ts_analyze` — no separate installation is required.

## What it checks

The analyzer walks every TS packet and reports violations:

- **Priority 1** (TS decodability): TS sync, sync loss, PAT/PMT presence and CRC, continuity counter, PID presence
- **Priority 2** (recommended monitoring): transport error indicator, CRC errors, PCR repetition / accuracy / discontinuities, PTS interval, CAT presence
- **Priority 3** (extended monitoring): NIT/SDT/EIT/TDT intervals, unreferenced PIDs, T-STD buffer overflow / underflow

It additionally reports:

- **PCR accuracy** down to ±500 ns — regression over byte positions
- **PCR drift** in ppm (live mode only)
- **T-STD buffer model** for every elementary stream (live mode)
- Validation of **SI section sizes** against the ISO/EN limits, with EIT-on-STB compatibility warnings (>1024 B)
- **UDP IAT** (inter-arrival time) — datagram-level jitter statistics (live mode only)

## Usage

```
ts_analyze [options] <input>
```

### Inputs

| Form | Description |
| --- | --- |
| `udp://239.1.1.1:1234` | UDP multicast |
| `udp://eth0@239.1.1.1:1234` | UDP multicast on the specified interface |
| `udp://192.168.1.100:1234` | UDP unicast |
| `udp://lo@127.0.0.1:12655` | UDP unicast on loopback (test source) |
| `/path/to/file.ts` | Local TS file |

RTP encapsulation of UDP is detected and unwrapped automatically.

### Options

| Option | Description | Default |
| --- | --- | --- |
| `-t, --time <sec>` | Analysis duration in seconds | `30` |
| `-s, --short` | Short summary report | – |
| `-f, --full` | Full detailed report | yes |
| `-b, --bitrate <Mbps>` | TS bitrate hint for file mode | `38.8` |
| `-p, --pcr-pid <pid>` | Analyze only the specified PCR PID (decimal or `0xHHHH`) | auto |
| `-l, --pcr-limit <ms>` | PCR repetition error limit in ms | `40` |
| `--no-eit` | Skip EIT analysis — P3.7..P3.10 are reported as `N/A`, the EIT contribution to P2.2 / to the section size totals is excluded | EIT enabled |
| `--no-nit` | Skip NIT analysis — P3.1, P3.2 are reported as `N/A`, the NIT contribution to P2.2 / to the section size totals is excluded | NIT enabled |
| `--no-color` | Disable ANSI colours in the output | colours enabled |
| `--xml` | Structured XML on stdout (no stderr) | text |
| `-h, --help` | Show help | – |

### Examples

```bash
# 30-second TR 101 290 check on a multicast stream
ts_analyze -t 30 udp://239.10.10.1:1234

# short summary, save to log (no color)
ts_analyze -s --no-color -t 60 udp://239.10.10.1:1234 > report.txt

# analyze a TS file
ts_analyze -t 30 recording.ts

# analyze only a single PCR PID
ts_analyze -p 0x0100 -t 30 udp://239.10.10.1:1234

# machine-readable XML for CI / monitoring
ts_analyze --xml -t 30 udp://239.10.10.1:1234 > result.xml

# skip EIT/NIT analysis (e.g. for streams where they are intentionally absent)
ts_analyze --no-eit --no-nit -t 30 udp://239.10.10.1:1234
```

### Disabling EIT or NIT analysis

In some streams EIT or NIT are intentionally absent (closed networks, laboratory sources, OTT-only delivery and so on). The corresponding TR 101 290 P3 checks then always FAIL the OVERALL gate — which is pure noise.

Use `--no-eit` and/or `--no-nit` to exclude these checks:

| Flag | Skipped checks | Side effects |
| --- | --- | --- |
| `--no-eit` | P3.7 (EIT actual P/F), P3.8 (EIT other P/F), P3.9 (EIT actual schedule), P3.10 (EIT other schedule) | EIT sections are not collected, so their contribution to P2.2 (CRC) and to the SI section size summary is zero. The EIT-on-STB compatibility warning is suppressed. |
| `--no-nit` | P3.1 (NIT actual), P3.2 (NIT other) | NIT sections are not collected, so their contribution to P2.2 (CRC) and to the SI section size summary is zero. |

Skipped checks appear in the report as `N/A` marked `disabled (--no-eit)` / `disabled (--no-nit)`, and in XML as `applicable="false" result="N/A"`. In the short report `NIT=off` / `EIT=off` is shown instead of the error counter.

The flags affect only EIT (PID `0x0012`) and NIT (PID `0x0010`) processing — all other TR 101 290 checks (P1.x, P2.x, SDT, TDT, CAT, T-STD, PCR drift, IAT) are performed as usual.

### XML output mode (`--xml`)

`--xml` makes the analyzer emit a single self-contained UTF-8 XML document on **stdout**. All ancillary output (the banner, `Stream locked`, `PCR PIDs discovered`, the per-second progress line, the capture summary, short-duration warnings) is suppressed; **stderr stays empty** unless a genuine failure occurs (the input could not be opened, no PCR data, the stream is too short, interruption by a signal). ANSI colours are forcibly disabled.

The exit code is the same as in text mode: `0` for OVERALL=PASS, `65` for OVERALL=FAIL, plus the standard error / signal codes (1, 2, 3, 130, 143).

Top-level XML structure:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<ts_analyze version="2.3">
  <source>udp://239.1.1.1:5000</source>
  <timestamp>2026-04-30T12:00:00+0300</timestamp>
  <duration_s>30.00</duration_s>
  <packets total="..." null="..."/>
  <ts_bitrate_mbps>20.012</ts_bitrate_mbps>

  <programs>
    <program number="1" pmt_pid="0x0100" pcr_pid="0x0101">
      <es pid="0x0101" stream_type="0x1b" name="H.264/AVC"/>
      <es pid="0x0102" stream_type="0x03" name="MPEG-2 Audio"/>
    </program>
  </programs>

  <tr101290>
    <check id="1.1" name="TS Sync Byte Error" applicable="true" errors="0" result="PASS"/>
    ...
    <check id="2.3" name="PCR Repetition Error"
           applicable="true" errors="0" result="PASS" soft_violations="3"/>
    ...
    <check id="3.4" name="Unreferenced PIDs" applicable="true" count="2" result="INFO"/>
    ...
  </tr101290>

  <si_section_size oversize_total="0" eit_stb_warn_total="12">
    <table name="EIT_actual_pf" max_bytes="1380" std_limit="4096"
           oversize="0" eit_stb_warn="12" result="WARN_STB"/>
    ...
  </si_section_size>

  <iat datagrams="33252" intervals="33251" min_ms="0.002" max_ms="5.009"
       avg_ms="0.150" stddev_ms="0.295" p95_ms="0.872" p99_ms="1.076"
       max_jitter_ms="4.272" gap_threshold_ms="100.0" gaps_over_threshold="0"/>

  <pcr_pids>
    <pcr_pid value="0x0101" sid="1" pcr_count="1500" discontinuities="0"
             estimated_bitrate_mbps="18.750">
      <interval samples="1499" min_ms="19.812" max_ms="20.195"
                avg_ms="20.001" p95_ms="20.102"
                iso_hard_violations="0" tr_soft_violations="0"
                rec_violations="0" result="PASS"/>
      <accuracy samples="1499" min_ns="-148.3" max_ns="201.7" abs_max_ns="201.7"
                avg_ns="2.1" stddev_ns="45.6" p95_ns="102.3"
                violations="0" result="PASS"/>
      <drift measured="true" ppm="0.618" limit_ppm="30"
             verdict_mode="informational" result="PASS"/>
      <tstd overflows="0" underflows="0" max_fill_bytes="34218" result="PASS">
        <es_buffer es_pid="0x0101" stream_type="0x1b"
                   capacity_bytes="3000000" measuring="true"
                   es_bitrate_mbps="15.200" max_fill_bytes="34218"
                   overflows="0" underflows="0"/>
      </tstd>
    </pcr_pid>
  </pcr_pids>

  <unreferenced_pids count="2">
    <pid value="0x01ff"/>
    <pid value="0x0200"/>
  </unreferenced_pids>

  <overall result="PASS"/>
</ts_analyze>
```

Key conventions:

- All PIDs are formatted as `0xHHHH` (4-digit hex with the `0x` prefix).
- The `result` attribute takes the values `PASS` / `FAIL` / `WARN` / `N/A` / `INFO` / `SKIP` / `ok` / `WARN_STB`.
- For checks that are not applicable (file mode, absence of scrambling and so on) the element is still present, with `applicable="false"` and `result="N/A"`, so that schema consumers see a stable shape.
- `<drift>` carries `verdict_mode="informational"` for `30 s ≤ T < 300 s` and `verdict_mode="hard"` for `T ≥ 300 s`; `result="SKIP"` for runs shorter than 30 s.
- `<iat>` is absent for file-mode runs.
- `<overall>` reflects the same gate as the OVERALL line of the text report and matches the process exit code.

The output is well-formed XML (it validates with `xmllint --noout`); feed it directly to XSLT, Python `lxml` and the like without any parsing workarounds.

## Reading the report

### Status colours

| Status | Colour | Meaning |
| --- | --- | --- |
| `PASS` / `ok` | green | The check conforms to the standard |
| `WARN` / `WARNING` / `WARN(STB)` | yellow | Soft violation, does not affect OVERALL |
| `FAIL` / `ERROR` | red | Standard violation, affects OVERALL |
| `INFO` / `NOTE` / `N/A` | default | Informational only |

Use `--no-color` when redirecting to log files or to non-ANSI terminals.

### Minimum analysis duration

| Duration | Coverage | Exit code |
| --- | --- | --- |
| **< 2 s** | Insufficient — the analysis is rejected | **3** (error) |
| **2–10 s** | P1 + P2 are reliable; some P3 checks may lack data | 0 + WARN |
| **10–30 s** | P1 + P2 + most of P3; TDT (30 s) may not complete in time | 0 + NOTE |
| **≥ 30 s** | Full coverage of all TR 101 290 checks | 0 |

The default duration is **30 seconds**, which is sufficient for full TR 101 290 coverage. Use `-t <sec>` to increase it (for example, for PCR drift acceptance testing) or to shorten it (quick smoke checks).

While running, the analyzer updates a single-line progress indicator on stderr once per second:

```
Progress: 47.3%  (14.2s / 30.0s, 330614 packets)
```

The line uses a carriage return (`\r`) to stay on a single line in the terminal; redirect stderr (`2>/dev/null`) to suppress it.

### PCR drift verdict — two-tier window

The PCR clock tolerance per **ISO/IEC 13818-1 §2.4.2.1** and **ETSI TR 101 290** is **±30 ppm**. The drift value in the report is obtained by linear regression of cumulative PCR seconds against the arrival time measured by the test bench clock; the statistical error decreases as 1 / T^(3/2), so the analysis window must be long enough for the measurement noise to fall below the ±30 ppm limit.

The analyzer therefore makes the drift verdict dependent on the analysis duration:

| Window | Verdict when the drift exceeds the tolerance | Effect on OVERALL |
| --- | --- | --- |
| `T < 30 s` | **skipped** (noise dominates relative to the ±30 ppm limit) | none |
| `30 s ≤ T < 300 s` | **WARN** — informational only | none |
| `T ≥ 300 s` | **FAIL** | OVERALL = FAIL, exit 65 |

`300 s` is the acceptance window (a product value; the **ETSI TR 101 290** standard does not specify measurement intervals) — long enough for even a bursty/loopback delivery path to average out below 1 ppm of measurement noise, so that an out-of-tolerance result reflects the encoder clock rather than the network. The full report shows the current tier in the `Verdict mode` line of the PCR DRIFT block.

To obtain a hard PASS/FAIL verdict on drift, run with `-t 300` or longer.

Source quality recommendations (informational; they do not change the verdict tiers):

| Source | Minimum window for ±5 ppm | For ±2 ppm | Acceptance |
| --- | --- | --- | --- |
| Broadcast multicast (CBR network, jitter < 100 µs) | **30 s** | 60 s | 5 min |
| Stable IP network (jitter < 200 µs) | **30 s** | 2 min | 5–10 min |
| Loopback / bursty sender (UDP unicast on `lo`) | **5 min** | 15 min | 30 min |
| Calibration / laboratory measurement | — | 30 min | 1+ hour |

Examples:

```bash
# Quick PCR drift check on a real broadcast multicast (30 s)
ts_analyze -t 30 -s udp://239.1.1.1:5000

# Reliable check on a loopback source (5 min)
ts_analyze -t 300 -s udp://lo@127.0.0.1:12655

# Lab acceptance (30 min, full report to file)
ts_analyze -t 1800 -f --no-color udp://239.1.1.1:5000 > acceptance.txt
```

If the same stream is analyzed over several short windows and the drift value fluctuates by more than a few ppm between windows, the bottleneck is delivery jitter (sender pacing or the network) rather than the encoder clock — increase the window.

### Exit codes

| Code | Meaning |
| --- | --- |
| `0` | Analysis completed, **OVERALL = PASS** |
| `1` | Argument or input error |
| `2` | No PCR data in the stream |
| `3` | The stream duration is below the 2 s minimum, or no data was received at all (the source is not transmitting, wrong address, multicast join not performed, firewall or wrong interface — the analyzer prints a hint) |
| `65` | Analysis completed, **OVERALL = FAIL** — TR 101 290 / ISO 13818-1 violation |
| `130` | Interrupted by **SIGINT** (Ctrl+C) — the analysis is cancelled, no report is produced |
| `143` | Interrupted by **SIGTERM** — the analysis is cancelled, no report is produced |

`65` is `EX_DATAERR` from POSIX `<sysexits.h>`: “the input data was incorrect”. Use it in CI / monitoring to gate on stream conformance:

```bash
ts_analyze -s -t 60 udp://239.1.1.1:5000 || {
    case $? in
        65)  echo "stream does not conform — see report" >&2 ;;
        130) echo "interrupted by user" >&2 ;;
        *)   echo "tool error" >&2 ;;
    esac
}
```

Codes 130/143 follow the POSIX shell convention `128 + signal_number`, so `$?` after `Ctrl+C` matches what bash returns for any process killed by SIGINT/SIGTERM. On interruption the analyzer prints a single line on stderr (`Analysis interrupted by signal N — no report produced.`) and skips report generation entirely.

## Sample output

### Full report (excerpt)

```
========================================================================
  MPEG-TS ANALYZER v2.3 — TR 101 290 FULL REPORT
  Perfect Streamer Toolkit https://pstreamer.tv
========================================================================
  Source     : udp://239.1.1.1:5000
  Timestamp  : 2026-04-30 12:00:00
  Duration   : 30.00 s
  Packets    : 398936 total, 12045 null
  TS bitrate : 20.012 Mbit/s
------------------------------------------------------------------------

========================================================================
  TR 101 290 — PRIORITY 1 (TS decodability)
========================================================================
  |  1.1   TS Sync Byte                  :        0           PASS
  |  1.4   Continuity Count              :        0           PASS
  |  1.6   PID Absence (5s)              :        0           PASS
  ...

========================================================================
  TR 101 290 — PRIORITY 2 (recommended monitoring)
========================================================================
  |  2.3   PCR Repetition                :        0           PASS
  |  2.5   PCR Accuracy                  :        0           PASS
  ...

========================================================================
  OVERALL COMPLIANCE: PASS  — stream is TR 101 290 compliant
========================================================================
```

### Short report

```
MPEG-TS Analyzer v2.3 | Perfect Streamer Toolkit https://pstreamer.tv
TR 101 290 Summary | udp://239.1.1.1:5000 | 30.0s | 2026-04-30 12:00:00
----------------------------------------------------------------------------------------------------
  P1: sync=0 CC=0 PAT=0 PMT=0 PID=0  P2: TEI=0 CRC=0 PTS=0  P3: NIT=0 SDT=0 EIT=0 TDT=0 unref=2
  IAT: dgrams=33252 avg=0.150 ms max=5.009 ms stddev=0.295 ms p99=1.076 ms gaps>100.000 ms=0
----------------------------------------------------------------------------------------------------
PCR PID       SID     Count     Intv max      Jitter max    Drift     Interval  Accuracy  T-STD
----------------------------------------------------------------------------------------------------
0x0101        1       1500      20.195 ms     76.4 ns       0ppm      PASS      PASS      PASS
----------------------------------------------------------------------------------------------------
OVERALL: PASS
```

## Notes

- **File mode**: PCR drift, the T-STD buffer model and UDP IAT are not measured — they require a real-time reference. All other checks work in both modes.
- **Single transport stream**: one MPTS or SPTS is analyzed at a time.
