Repository navigation
G729 Decoding
sipnab decodes G.729 audio (Annex A, with Annex B comfort noise) into the same outputs as G.711, G.722 and Opus:
- WAV exports;
- the recording in a vCon;
- the live audio route;
- the dead-air and clipping measurement.
It also decodes the core layer of G.729.1 streams: see The core layer of G.729.1.
It needs one file per host first: the decoder's codebook tables. sipnab builds that file from the ITU-T G.729 software package on your host. This page says how to install it, and why sipnab does not ship it.
Run this once on each host that decodes G.729:
sipnab g729 installBefore it does anything, the command prints what it downloads, the sha256 it checks, where it writes the file, and why sipnab does not ship the tables, then asks:
sipnab g729 install builds the G.729 decoder's codebook tables.
Source: https://www.itu.int/rec/dologin_pub.asp?lang=e&id=T-REC-G.729-201206-I!!SOFT-ZST-E&type=items. sipnab downloads the ITU-T G.729 (06/2012) Release 3 package (18476968 bytes), checks that its sha256 is 979680ff3b52b13a5701453178efd32b53e340114638fd330fdb6669eec86620, keeps only the numeric codebook values, writes them to /home/you/.config/sipnab/g729-tables.bin, and deletes the download.
The trained codebook values of G.729 are published in the reference C code of the ITU-T G.729 software package, and that code's notice keeps its authors' rights. So sipnab reads them from your own copy of the package instead of shipping them. Everything sipnab ships is MIT OR Apache-2.0. Details: https://github.com/NormB/sipnab/blob/main/crates/g729/PROVENANCE.md
Install the G.729 tables? [y/N]
Answer y or yes (any case) to install. Any other answer installs
nothing, prints Not installed: the answer was not yes. and exits 1.
After a yes, the command:
- downloads the ITU-T G.729 (06/2012) software package, Release 3, from itu.int (18,476,968 bytes);
- checks the package's sha256 against the pinned value
979680ff3b52b13a5701453178efd32b53e340114638fd330fdb6669eec86620; - reads the numeric codebook values out of it in memory, and checks their sha256 against a second pinned value;
- writes them to
g729-tables.bin, mode 0644, by an atomic rename; - deletes the download;
- prints
Installed the G.729 tables:with the file's path, andValues sha256:with the hash of the values.
sipnab refuses a package whose sha256 differs: it prints the expected and the
actual hash and Nothing was installed., and exits 1. A file that is not the
package, given with --from, reads:
Refused fake.zip: its sha256 is 5040121d75ccd1afe14dd9d30f016bb9cce741a3276212993c0b315552145af8, expected 979680ff3b52b13a5701453178efd32b53e340114638fd330fdb6669eec86620 (the ITU-T G.729 (06/2012) Release 3 package). Nothing was installed.
Check that the file is the ITU-T G.729 (06/2012) Release 3 package zip, and download it again if its hash differs.
--yes answers the question, for scripts and Dockerfiles:
sipnab g729 install --yesThe file goes in the directory of the user config file:
$XDG_CONFIG_HOME/sipnab/g729-tables.bin, else
~/.config/sipnab/g729-tables.bin. To put it elsewhere, give the path with
--g729-tables, and give the same path to the runs that decode, or set it
once in the config file:
[g729]
tables = "/srv/sipnab/g729-tables.bin"A service account usually has no home directory, so a server install names the path:
sudo sipnab g729 install --yes --g729-tables /srv/sipnab/g729-tables.binsipnab g729 statusOn a host without the tables it prints:
G.729 tables: not installed
Table file: /home/you/.config/sipnab/g729-tables.bin
G.729 not decoded: codebook tables not installed; run sipnab g729 install
With the tables in place it prints G.729 tables: installed, the file it
read, and Values sha256: with the hash of the values. It exits 0 when the
file holds the tables and 1 when it does not. --g729-tables, -f and --no-config work as they do for a
run, so the command reports on the file a run with the same options reads.
It checks that file as a run does: it names each key it does not know on
stderr, and refuses a file a run refuses, with the run's message and exit
status, without reporting on it. An empty [g729] tables is one such file:
invalid config value: [g729] tables is empty; give a path, or remove the key for the default
--from installs from a copy and opens no connection. It takes any of:
- the package zip, downloaded elsewhere. The same sha256 check applies:
sipnab g729 install --from 'T-REC-G.729-201206-I!!SOFT-ZST-E.zip' - a directory extracted from the package;
- the
g729-tables.binof another host. sipnab checks its values against the same pinned hash:sipnab g729 install --yes --from /mnt/usb/g729-tables.bin
With --from, the notice the command prints before it asks starts
Source: <path>. Nothing is downloaded. and ends The source is not changed. After the install it prints what it read, for example
Read the table file <path> (sha256 <hash>), then the path it wrote and
Values sha256:.
Copying g729-tables.bin to the path a run reads works as well. --from
adds the check.
Every release binary that decodes G.729, the static musl tarballs and the
-noaudio packages included, can download the package. --from is the
offline method in each of them.
sipnab leaves a G.729 stream out of the audio, never puts silence in its place, and says why and what to run:
G.729 not decoded: codebook tables not installed; run sipnab g729 install
A WAV export, the REST and MCP audio exports and a vCon's capture caveat all carry that sentence. sipnab exports the audio of the call's other streams as usual.
The command line, the REST API, MCP and vCon export never download the tables on their own: a capture tool on a server does not open a network connection nobody asked for. The terminal UI asks once, the first time it shows a G.729 stream:
This call uses G.729. Download the decoder tables from itu.int now? [y/N]
With [g729] auto_install = true, the terminal UI downloads without asking.
Nothing else reads that key.
A run reads tables installed while it is going when it next decodes a G.729
stream. sipnab keeps G.729 payload whenever the build has the g729
feature, so --retain-audio audio held before the install decodes too.
sipnab places each G.729 packet by its RTP timestamp and fills time in which no packet arrived with the decoder's own output:
- A missing RTP sequence number marks a packet the sender sent and the capture did not see. sipnab hands the decoder its frames as lost frames, and the decoder conceals them.
- In the rest of the time the sender sent nothing (Annex B discontinuous transmission). sipnab hands the decoder those frames as frames the sender did not transmit, and the decoder carries the comfort noise on.
- sipnab sizes a lost packet by the stream's usual speech packet: the most frequent number of 10 ms frames among the speech packets received.
- After speech, if the lost packets at that size fill the gap or more, sipnab decodes the whole gap as lost frames. If they fill less of it, a pause began inside the gap. sipnab then decodes the lost frames first, counts the last lost packet as the one-frame SID that starts a pause, and decodes the rest of the gap as pause.
- After a SID frame, sipnab decodes the pause first and the lost frames last, right before the packet that resumed.
- With no sequence number missing, sipnab decodes the whole gap as pause.
When a loss sits next to a pause, the timestamps and sequence numbers can fit two layouts of the same call, and sipnab decodes the layout the rules above give. Two examples, each four or three frames long:
- In a stream of two-frame speech packets, the capture misses both the SID before a pause and the first speech packet after it, in a four-frame gap. Two lost packets of two frames fill the gap, so sipnab decodes four lost frames. The call had one lost frame, two frames of pause, and one lost frame.
- In a stream of three-frame speech packets, the capture misses the SID after speech, in a three-frame gap. One lost packet of three frames fills the gap, so sipnab decodes three lost frames. The call had one lost frame and two frames of pause.
In both, two lost speech packets (the first example) or one lost three-frame speech packet (the second) fit the same timestamps and sequence numbers, and for those calls the frames sipnab decodes are the call's. Where the call had the other layout, the decoded audio differs only in the frames of that gap.
An export decodes packets that arrived out of order in timestamp order, and decodes a packet that repeats a timestamp once. The live audio route sends each packet as it reads it, so it skips a packet that arrives after it has sent later audio.
G.729.1 (RFC 4749) is a wideband codec built on G.729. Each 20 ms frame starts with an 8 kbit/s core layer, which holds two G.729 frames. Higher layers add narrowband quality at 12 kbit/s and wideband audio from 14 to 32 kbit/s. sipnab decodes the core layer and nothing above it.
What sipnab does with a G.729.1 stream:
- It recognizes the stream from the SDP: sipnab names a payload type that
a=rtpmap:<pt> G7291/16000bindsG7291, and runs it on the 16 kHz RTP clock, 320 timestamp units per 20 ms frame. sipnab cannot name a G.729.1 stream whose SDP the capture does not hold, and does not decode it. - It decodes the first 20 octets of every frame, at every bit rate the call used, as two G.729 frames, into 160 samples at 8 kHz. The audio is narrowband. It is not the audio a G.729.1 decoder plays.
- A SID (RFC 5459: frame type 14 alone, or 2, 3 or 6 octets after the frames) drives the G.729 Annex B comfort noise from its first 15 bits. sipnab does not read the rest of the SID.
- A packet of frame type 15 (no data) decodes nothing and is not a loss. sipnab ignores a packet of frame type 12 or 13 (reserved), counts it as a frame that failed to decode, and conceals its 20 ms as a lost packet. It ignores octets that are neither a whole frame nor a SID.
- sipnab fills lost packets and pauses by the rules in Lost, late and repeated packets, and counts each 20 ms frame as two 10 ms G.729 frames.
- It uses the same tables, installed the same way. Without them, sipnab leaves a G.729.1 stream out with the same sentence and command as G.729.
Every output that carries the decoded audio says what it is and names the
bit rates of the frames decoded: the note inside the WAV file, the export
summary, the vCon's capture caveat, the decoded_as field of a live RTP
leg object (in the stop message, every frame sent), and the decoded_as
field of the audio socket's stream message (the frames sipnab decoded
before it announced the stream). For example, a one-way call of 250 packets at
32 kbit/s:
# Run all of these, in order.
sipnab -N -q --no-cli-print -I g7291-call.pcap --retain-audio \
--export-vcon g7291-call@192.0.2.10 > call.vcon.json
jq -r '.analysis[0].body.capture_completeness.media_note' call.vcon.jsonProduced by sipnab 0.5.222 via mechanism sipnab-capture. Audio decoded from
RTP payload this run retained; it is bounded by where the capture point sat
and by what retention kept, and is not a recording made by the endpoints.
INCOMPLETE. — G.729.1: this audio is the G.729.1 core layer (8 kbit/s)
decoded as G.729 at 8 kHz; the stream's frames were sent at 32 kbit/s; the
layers above 8 kbit/s (narrowband enhancement and wideband) are not
decoded, so this is not the audio a G.729.1 decoder produces. — PARTIAL:
media in only ONE direction reached this capture; no stream going the other
way was observed. That may be a one-way call, or a capture point that only
sees one leg -- this file cannot tell you which.
The output is one line, wrapped here to fit the page.
The trained codebook values of G.729 are published in the reference C code
of the ITU-T G.729 software package, and that code's notice keeps its
authors' rights. So sipnab reads them from your own copy of the package
instead of shipping them. Everything sipnab ships is MIT OR Apache-2.0.
Details:
crates/g729/PROVENANCE.md.
- No file in the sipnab repository, crate, binary or package holds an ITU-T table value. Each release scans the built binaries and packages for any run of six or more integers that matches the tables.
- The tables that the Recommendation defines by a formula, sipnab's own code generates.
-
sipnab g729 installtakes the values from the ITU-T package on your host. sipnab never hosts or mirrors that package.
The decoder is the sipnab-g729 crate in this repository, written in Rust from the
text of ITU-T G.729 and its Annexes A and B by a clean-room process: the
author of the Rust never read the ITU-T C code. It decodes all 16 ITU-T
decoder test vectors bit-exactly.
crates/g729/PROVENANCE.md
records who read what, the hashes of every file involved, and the package's
copyright statements in full.
Website · Repository · Issues · Generated from docs/ — edit there, not here.
Getting started
- Installation
- First CLI Triage
- Glossary
- Cookbook
- Runnable Examples
- Real World Captures
- Troubleshooting
- Tuning Capture
- Encapsulations
- Rtpengine Relays
- Backers
Using the TUI
CLI & automation
- CLI Reference
- Error Messages
- Filter DSL
- Output Formats
- SIP Response Codes
- SIP Methods
- SIP Header Fields
- SIP Parameters
- SIP Lint Rules
- MOS and Codecs
Configuration
Integrations (API & MCP)
- REST API
- Prometheus Metrics
- Authentication
- MCP
- MCP Deployment
- MCP Across an Estate
- MCP Tools
- MCP Tools Core
- MCP Tools Signaling
- MCP Tools Captures
- MCP Tools Security
- MCP Tools Media
- MCP Tools Relay
- MCP Tools TFPS
- MCP Tools Server
- MCP Tools vCon
- MCP Tools TLS
- MCP Protocol
- Uprobe Walkthrough
- Capture SIP over TLS
- WASM Plugins
- vCon Export
- vCon Capture Stack
- G729 Decoding
Your SIP server
- Use OpenSIPS as the SIP Server
- Run sipnab beside OpenSIPS
- Use Kamailio as the SIP Server
- Run sipnab beside Kamailio
- Use Asterisk as the PBX
- Run sipnab beside Asterisk
- Use FreeSWITCH in the Voice Stack
- Run sipnab beside FreeSWITCH
Add to your voice stack
- Add a vCon Server
- Send vCons to a vCon Server
- Send vCons to vcon store
- Add TFPS
- Control TFPS from sipnab
- Ban SIP Scanners with fail2ban
- Feed fail2ban from sipnab
- Add rtpengine
- Name rtpengine Media with sipnab
- Add rtpproxy
- Name rtpproxy Media with sipnab
- Add Homer
- Connect sipnab to Homer
- Add Prometheus and Grafana
- Add sipnab Metrics to Prometheus
Development & internals
- Internals Index
- Internals Subsystem Guide
- Internals Invariants
- Internals Testing
- Internals Walkthroughs
- Internals Build CI Release
- Internals Profiling
- Internals Domain Primer
- Library API
- Benchmarks
- Fault Model
- Threat Model
- Assurance Case
- Architecture
- Internals Threading
- Internals TUI Testing
- Internals Zero Copy Payloads
- Internals Uprobe Capture
- Internals Rtpengine Control Plane
- Internals Relay Control Decoding
- Internals vCon Exporter
- Internals Operator Guide Notes
- Internals Postmortems
- Internals Code Map
- Internals Lint Rules
- Internals Encapsulation Decoding
- Internals MCP Design Notes
- Internals Metrics And Output Notes