Repository navigation
Releases: prof-abdo/tsdec
Release list
v2.5.0
Reads the program tables, so a capture of a whole transponder is usable
-a now says what is in a recording rather than listing pids: every program, its
pmt and pcr pid, whether it uses a control word, and each of its streams with
a type and a name. -n then works on one of them, looking the pids up in the
pat and the pmt.
This is the limitation that has been in the readme since the first release. A
transponder normally carries several services with their own elementary streams
and their own control words, so a capture of one is the ordinary case rather
than a special one. Without reading the tables there is no way to know which
pids belong to which programme, the control words of the two services are
interleaved through the file, and picking the wrong one gives output that
decrypts cleanly and is not the programme that was asked for. -p sidestepped it
by making a person read the pids off a hex dump first.
The tables are control information and are not scrambled even when the
elementary streams beside them are, so this works on a recording that has not
been decrypted. Sections are assembled across packets, the pointer field is
honoured, and the mpeg crc is checked: a control structure is the one place in
a transport stream where a corrupt byte changes the meaning of everything after
it, and acting on a bad pat means picking the wrong pids silently.
-n used to be accepted and ignored, documented as a count of expected pids. It
now selects a program.
--json -a emits the tables as data, so a front end can offer a service to pick
rather than making a person read pids off a hex dump. tsdec-gui 0.3.0 does
exactly that.
The test fixtures had been building recordings nobody could read: the pat and
pmt were malformed in three separate ways and the pmt pid the pat pointed at
was never sent on. None of it mattered because nothing read the tables, which
is worth noting on its own. tools/mk_multi_ts.py now builds a recording with two
interleaved services and psi_test checks what comes back, including that
decrypting one leaves the other alone.
Verified on Linux, macOS and Windows.
v2.3.0
A stop that a caller with no console can deliver
Ctrl+C is a console control event, and a front end that has no console of its
own has nowhere to deliver one from. A GUI application on Windows is exactly
that: the windowed build has no console at all, so a stop sent that way either
does nothing or arrives as a kill, and a kill discards every packet already
decrypted.
That is not a hypothetical. It is what the packaged tsdec-gui did: every test
against the Python modules passed, and the frozen executable quietly could not
stop a decode, because only the frozen build reproduces a process with no
console to signal through.
-S <file> asks for the same clean stop by creating a file, and
tsdec_set_stop_file() does the same for a caller that links the library. A
file works the same on every platform and does not care whether anybody is
attached to a terminal, which is exactly what a signal needs.
The flag is kept in a small fixed buffer and polled alongside the in-process
one, so the two mechanisms compose: a process that gets both, as a console
application does, is stopped by whichever arrives first. Nothing that already
used Ctrl+C changes.
The cancellation test now runs both paths. It had to clear the flag between
them, because it did not, and the second run was reporting as stopping
immediately with an empty output. A test that passes for the wrong reason is
worse than no test, and this one had been passing for the wrong reason since
the flag was introduced.
Also percent on the progress event and total on the result were part of
2.2.0; this release only adds the stop file.
Verified on Linux, macOS and Windows.
v2.2.0
Machine readable output, and the fixes needed to actually consume it
tsdec --json writes one JSON object per line on stdout: progress events
while it works, then a single result event. The human log stays on stderr
where it does not interfere. A front end should read this rather than scraping
log text, and tsdec-gui is built on
it.
tsdec --json -f log.cwl -i recording.ts -o clear.tsBuilding the front end on top of it is what turned up the four bugs below.
Every one of them made the JSON unusable from a real consumer, and none of them
was visible from the command line.
Log lines ran together. tsdec_log() never terminated the line, so every
message about an analysis, a pid survey or a summary came out as one long run
of text. Invisible on a terminal, where the eye reconnects the pieces, but a
pipe received a single unparsable line, which is exactly how a front end reads
it, so a pid survey matched nothing at all.
Ctrl+C did nothing under Windows when the process was started in its own
process group, which is how a parent sends a control event to a child alone.
Windows also switches Ctrl+C off for such a child, so the signal arrived as
nothing and the run could only be ended by killing it, losing every packet
already decrypted.
Throughput and ETA were wrong on multi core runs. Both were measured with
clock(), which counts processor time rather than elapsed time. On every unix
a run on eight threads was timed as if it had taken eight times longer than it
did, understating the rate by the same factor. The Windows CRT happens to
return elapsed time, which is why this was never noticed. Both platforms now
use a real monotonic clock, and macOS uses the mach clock, because defining a
feature test macro for clock_gettime also hides _SC_NPROCESSORS_ONLN and
breaks the CPU count.
make test never ran the cancellation test. It was built and then never
executed, so the stop path had no coverage in the test target at all. It now
runs, and it generates its own recording rather than expecting one to be lying
around, large enough that the stop lands mid run on a fast machine.
Also in this release:
tsdec_status_text(), so the command line and--jsondescribe a return
code with the same words instead of a front end inventing its own.percenton every progress event.totalon the result event, the packet count of the input. A client needs
it to show how far a stopped run actually got, rather than claiming it
finished.
The stop path itself is unchanged from 2.1.0: a stop is still noticed between
blocks, the workers still drain what is in flight, and the partial output is
still packet aligned and playable.
Verified on Linux, macOS and Windows.
v2.1.0
TSDEC 2.1.0
Offline decrypter for recorded DVB transport streams.
Small release: it adds the two things a graphical front end needs before it can
be built honestly.
Downloads
| platform | binary | archive |
|---|---|---|
| Linux x86-64 | tsdec-linux-x86_64 |
tsdec-linux-x86_64.tar.gz |
| macOS arm64 (Apple Silicon) | tsdec-macos-arm64 |
tsdec-macos-arm64.tar.gz |
| Windows x86-64 | tsdec-windows-x86_64.exe |
tsdec-windows-x86_64.tar.gz |
The binaries are plain executables: no runtime, no shared library, no install
step. The archives are the same file plus the README and the licence.
Quick start
chmod +x tsdec-linux-x86_64
./tsdec-linux-x86_64 -f control-words.cwl -i recording.ts -o clear.ts -POn Windows, just run tsdec-windows-x86_64.exe.
What is new
You can stop it. Ctrl+C asks the job to stop instead of killing it.
tsdec -f log.cwl -i big-recording.ts -o clear.ts -P
# ... press Ctrl+C partway through
# clear.ts now holds everything processed before the stopWhatever was decrypted up to that point is kept. The partial output stays a
whole number of packets and stays playable, so stopping a long recording never
throws away work already done. The stop is noticed between blocks, a block
being about a megabyte, so it takes effect within a fraction of a second.
The exit status distinguishes stopped on request from could not sync from
input was not encrypted, so a front end can say what actually happened rather
than just "error".
Progress is reported as data. tsdec_run() takes a callback that fires a
few times a second with packets processed and the size of the input, which is
what a real progress bar with a throughput figure and an estimate is built
from. tsdec_job_t replaces the long argument list; the old entry point stays
as a wrapper.
A front end is on the way
The Win32 GUI of 0.4.1 exposed almost none of what the command line can do, so
it was not carried over. A replacement is being built separately in
tsdec-gui. It drives this binary
through its command line rather than duplicating any of this code, which is why
the stop path had to exist first.
Tests
make test checks the bitsliced engine against the scalar one bit for bit,
against the published DVB test vectors, and drives the stop path at one and at
eight threads, checking that the output stays packet aligned and that what was
written before the stop is byte identical to the plaintext.
tools/run_tests.sh builds synthetic transport streams, encrypts them through
tsdec's own constant control word path so the generated log genuinely matches
the data, decrypts them again and compares packet by packet. 17 checks, run on
Linux, macOS and Windows in CI, and the full suite is what produced these
binaries.
Full changelog
https://github.com/prof-abdo/tsdec/blob/main/CHANGELOG.md
Attribution
Based on TSDEC V0.4.1 by ganymede. The CSA engine and the FFdecsa bitslice
implementation come from libdvbcsa by Alexandre Becoulet. GPL v3.
v2.0.0
TSDEC 2.0.0
Offline decrypter for recorded DVB transport streams.
Decrypts a recorded .ts file using control words logged elsewhere, with the
common scrambling algorithm. Works for any DVB crypt system because the system
only governs what happens inside the smartcard; what the CAM does with a control
word is always the same.
Downloads
| platform | binary | archive |
|---|---|---|
| Linux x86-64 | tsdec-linux-x86_64 |
tsdec-linux-x86_64.tar.gz |
| macOS arm64 (Apple Silicon) | tsdec-macos-arm64 |
tsdec-macos-arm64.tar.gz |
| Windows x86-64 | tsdec-windows-x86_64.exe |
tsdec-windows-x86_64.tar.gz |
The binaries are plain executables: no runtime, no shared library, no install
step. The archives are the same file plus the README and the licence.
Quick start
chmod +x tsdec-linux-x86_64
./tsdec-linux-x86_64 -f control-words.cwl -i recording.ts -o clear.ts -POn Windows, just run tsdec-windows-x86_64.exe. tsdec -h lists every
option; the README explains the control word log format and how the sync
works.
What is different from the 0.4.1 line
The CSA cipher is bitsliced. libdvbcsa already carried the FFdecsa
implementation but nothing called it, so every packet went through the scalar
table-lookup cipher alone. It now batches 128 packets into SSE2 registers:
7.6x on the cipher itself, 18.5 to 141 MiB/s.
Decryption is threaded. One scout thread decides which logged control word
applies to each packet; N workers run the batch cipher on planned blocks and
write to disjoint output offsets. On 16 cores that takes a 215 MiB recording
from 11.99s down to 0.22s, roughly 55x end to end, with byte identical output
at every thread count. -t sets the count.
Several bugs fixed. Most visibly, the control word cursor ran past the end
of the log and then reported it as too short even when it had just matched a
key, so a log with many control words failed part way through.
New options. -t threads, -p pid filter for recordings carrying several
services, -o - to write to stdout, -P progress, -r to resync a damaged
stream, -k to refuse damaged control word checksums instead of repairing
them.
If you are coming from the 1.0 build
Nothing you already scripted breaks. -f, -i, -o, -e, -d, -a, -b,
-v and -h keep their meaning.
Two output differences are worth knowing:
- A log that runs out is no longer fatal. tsdec reports the packet where it
stopped and carries on with what it has. - Decrypted packets now carry correct adaptation field control and continuity
counter bits. The old code cleared the scrambling bits with a mask that also
wiped those two, so a byte comparison against 1.0 output differs on byte 4 of
every scrambled packet while the payload is byte identical.
Tests
make test checks the bitsliced engine against the scalar one bit for bit,
against the published DVB test vectors. tools/run_tests.sh builds synthetic
transport streams, encrypts them through tsdec's own constant control word
path so the generated log genuinely matches the data, decrypts them again and
compares packet by packet. Both run on Linux, macOS and Windows in CI, and the
full suite is what produced these binaries.
Full changelog
The complete list of changes, with the reasoning behind each fix, is in
CHANGELOG.md.
Attribution
Based on TSDEC V0.4.1 by ganymede. The CSA engine and the FFdecsa bitslice
implementation come from libdvbcsa by Alexandre Becoulet. GPL v3.