/** @page libtutorial TSDuck library tutorial

The TSDuck library contains general-purpose C++ classes and utilities to handle
MPEG transport streams.

Roughly, the TSDuck library provides two categories of features:

- Operating system abstraction layer to make the application code fully portable
  between heterogeneous platforms. This is similar to frameworks such as Qt,
  but much more lightweight.
- Handling of MPEG/DVB transport streams and signalization.

All C++ declarations are located inside the namespace `ts`, either directly within
`ts` or inside inner namespaces. All preprocessor's macros are named with prefix `TS_`.

# C++ features {#cppfeatures}

## Portability issues {#portability}

The file tsPlatform.h contains some very low level definitions such as macros
defining the environment (processor, compiler, operating system, endianness),
byte and bit manipulation, etc.

## C++ strings {#cppstrings}

C and C++ strings are made of 8-bit characters which are notoriously unable
to represent international character sets. The usage of `std::string` with the
TSDuck library is discouraged in favor of @ref unicodestring "Unicode strings".

## Unicode strings {#unicodestring}

The class ts::UString implements Java-like Unicode strings. Each character
uses 16 bits of storage. Formally, ts::UString uses UTF-16 representation.
This means that all characters from all modern languages can be represented
as one single character. Characters from archaic languages may need two
UTF-16 values, called a "surrogate pair".

Technically, ts::UString is a subclass of `std::u16string`. So any operation
on standard C++ strings is also available to ts::UString. But many more operations
have been added to manipulate Unicode strings.

For consistency, the type ts::UChar is a typedef for `char16_t`. The file
tsUChar.h defines some utility functions on ts::UChar. It also defines
constants for most Unicode characters like ts::COLON or
ts::LATIN_CAPITAL_LETTER_A_WITH_ACUTE, among hundredths of others.

Some interesting features in class ts::UString are:
- Explicit and implicit conversions between UTF-8 and UTF-16.
- Including automatic conversion to UTF-8 when writing to text streams.
- Conversions with DVB and ARIB character sets.
- Conversions with HTML encoding.
- Management of "display width", that is to say the amount of space which
  is used when the string is displayed. This can be different from the
  string length in the presence of combining diacritical characters or
  surrogate pairs.
- String padding, trimming, truncation, justification, case conversions.
- Substring, prefix or suffix detection, removal or substitution.
- Splitting and joining strings based on separators or line widths.
- Reading or writing text lines from or to a text file.
- Data formatting using
  @ref ts::UString::Format() "Format()",
  @ref ts::UString::Decimal() "Decimal()",
  @ref ts::UString::Hexa() "Hexa()" or
  @ref ts::UString::Dump() "Dump()".
- Data scanning using
  @ref ts::UString::scan() "scan()".

Unicode strings can be converted to and from DVB or ARIB (Japan) strings.
Most DVB-defined character sets are implemented (see the classes ts::Charset
and ts::DVBCharset) and recognized when a string is read from a descriptor.
When a string is serialized into a binary descriptor, the most appropriate DVB
character set is used. In practice, a few known DVB character sets are used
and when the string cannot be encoded in any of them UTF-8 is used
(UTF-8 is a valid DVB character set).

## Binary data {#bindata}

The class ts::ByteBlock represents a raw block of bytes. It is a subclass
of `std::vector<uint8_t>` and consequently benefits from all standard vector
operations. It also adds useful methods for data serialization or deserialization
in any byte order.

For data serialization or deserialization over arbitrary
memory areas, the header file tsMemory.h provides low-level functions to
access integer values of 8, 16, 24, 32, 40, 48 and 64 bits in any byte order.

The class ts::Buffer provides a higher-level abstraction layer over a memory area
to parse or generate bitstreams. It gives access to data of any bit-size at any bit
position, any endianness, either as a continuous stream or seeking at random bit positions.

The principles of the C++ class ts::Buffer were freely inspired by the Java
class @c java.nio.ByteBuffer. There are differences between the two but the main
principles are similar.

Its subclass ts::PSIBuffer provides primitives to serialize and deserialize
MPEG and DVB structures such as list of descriptors, DVB, ARIB and ATSC strings
or "Modified Julian Dates".

## Memory management {#memmgmt}

The memory management is entirely based on the _smart pointer design pattern_.
This is implemented by the template class ts::SafePtr, using internal reference counters.

All dynamically allocated objected are managed using smart pointers.
Thus, coding in C++ is as simple as in Java: simply allocate objects,
always use smart pointers to reference them and forget about memory management.
When an object is no longer referenced, it is automatically deallocated.
Extensive testing using tools like @e valgrind have proven this to be true.

Be aware, however, that smart pointers are not completely as efficient
as Java garbage collector. There are a few pathological cases where
objects are never deallocated. This is the case when two objects reference
each other but are no longer referenced anywhere else. A true garbage collector
would detect this pair of objects as collectively inaccessible and will reclaim
them. Smart pointers, on the contrary, will never deallocate them since their
reference count is not zero. But such cases are rare and well know.
So, just pay attention to them.

Smart pointers can be made thread-safe through a @e mutex class as template parameter.

The default mutex class is ts::null_mutex which does nothing. So, by default, smart
pointers are not thread-safe. All usages of a given instantiation of ts::SafePtr
shall take place in the same thread (or must be explicitly synchronized). So, using
smart pointers is fast by default, without synchronization overhead.

To make an instantiation of ts::SafePtr thread-safe, use the class std::mutex as
template parameter. Smart pointers from this instantiation can be used from
different threads. Note, however, that the protection does not extend to the
@e pointed object which must be properly synchronized.

A typical application of thread-safe smart pointers is inter-thread communication
using message queues. If the messages are polymorph or too big to be copied in the
message queue, use thread-safe smart pointers to these messages. The message queue
copies smart pointers, not objects. To implement message queues, you may use the
template class ts::MessageQueue.

## Singletons and static data {#singletons}

The _singleton_ design pattern is simple in theory, but not so simple to
implement correctly in practice. The TSDuck library encapsulates the
implementation difficulties using the two macros TS_DECLARE_SINGLETON()
and TS_DEFINE_SINGLETON().

Similarly, using static data can be a nightmare because it is impossible
to manage the initialization order of modules in C++. Again, the TSDuck
library encapsulates these implementation difficulties using the macro
TS_STATIC_INSTANCE().

## Error reporting {#errreport}

All TSDuck classes use a consistent error reporting mechanism through the
ts::Report abstract class.

This interface defines several levels of severity in the type ts::Severity,
ranging from ts::Severity::Debug to ts::Severity::Fatal.
Each instance of ts::Report defines which levels of message are reported to the user.
This is usually triggered by command-line options such as `--verbose` or `--debug`.

Most classes or methods from the TSDuck library use a reference to an
instance of ts::Report to report messages and errors. The actual
reporting object is often built at application level and then propagated
to all layers of code.

Some interesting subclasses of ts::Report are:
- ts::CerrReport, a singleton which reports errors to `std::cerr`.
  The macro @link CERR @endlink can be used as a shortcut to the instance of the singleton.
- ts::NullReport, a singleton which drops all messages.
  The macro @link NULLREP @endlink can be used as a shortcut to the instance of the singleton.
- ts::ReportFile which logs messages in a file. It can be made thread-safe
  using a mutex class as template argument.
- ts::ReportBuffer which logs messages in a memory buffer. It can be made thread-safe
  using a mutex class as template argument.
- ts::Args (see @ref cmdargs "below") which defines the syntax and handling
  of command line arguments. This is the typical instance of ts::Report
  which is used at application-level.
- ts::TSP, a class which is used by tsp plugins to communicate with the
  top-level @e tsp application. Each tsp plugin executes in a separate thread.
  This class is used to asynchronously log messages from plugins without slowing
  down the plugin's thread.

## Exceptions {#except}

As a general rule, TSDuck prefers the usage of error reporting interface
and error status over exceptions. However, for a limited number of
unrecoverable conditions which should never occur in practice, exceptions
are used.

All TSDuck exceptions inherit from the superclass ts::Exception. An instance
of this exception is able to embed an error message and an optional system
error code.

Each specific exception should be a subclass of ts::Exception. Instead of
rewriting the subclass code, applications should use the macro TS_DECLARE_EXCEPTION().

## Pseudo-enumeration data {#enums}

An instance of the class ts::Enumeration associates a list of integer or @e enum values
with strings. It can be used to display meaningful strings
instead of integer values. But it is even more useful to decode command line
arguments. When an option accepts a predefined list of values, the input
string can be either an integer value or a name. When it is a name,
it can even be abbreviated as long as it is not ambiguous in the corresponding
ts::Enumeration. This is transparent for the application which receives the
corresponding integer value.

## Command-line arguments {#cmdargs}

The class ts::Args implements a generic handling of command line arguments.

Each application or plugin typically defines its own subclass of ts::Args.
The subclass defines the command line syntax and the corresponding help text.
The superclass ts::Args automatically parses the command line, reports errors
and common options such as `--help` or `--version`.

The value of command line options can be free strings, integer values or
enumeration values. Integer values are recognized in decimal or hexadecimal
form (prefix `0x`) and thousands separators ('`,`') which are present for
clarity are ignored. Enumeration values are handled through ts::Enumeration.

## XML data {#xml}

The TSDuck library embeds an XML parser and several classes to handle a DOM structure.
See the class ts::xml::Node, the abstract base class of the DOM hierarchy.

## JSON data {#json}

The TSDuck library embeds a JSON parser and several classes to handle JSON values.
See the class ts::json::Value, the abstract base class of the JSON hierarchy.

# Cryptography {#crypto}

The TSDuck library contains a few cryptographic classes. The TSDuck library
is *not* a cryptographic library and will never be. Cryptography is a serious
matter which should be left to cryptographers.

Some transport stream processing operations require some cryptography, essentially
block ciphers and hash functions. To do that, the TSDuck library includes a few
cryptographic functions which were originally copied from the
<a href="http://www.libtom.net/LibTomCrypt/">LibTomCrypt library</a>.

This copy is allowed by the very liberal license of LibTomCrypt.
Copying code from LibTomCrypt inside TSDuck instead of referencing it
has the following advantages:

- Encapsulate the C API of LibTomCrypt into higher-level C++ classes.
- Automatically manage the resources using C++ constructors and destructors.
- Allow a portable usage of the cryptographic functions without rebuilding LibTomCrypt.
- Remove a dependency to an external library.

The abstract class ts::BlockCipher is the root of a hierarchy of symmetric cryptography
classes, including chaining modes. The main block cipher classes are ts::AES,
ts::TDES and ts::DES.

Chaining modes are template classes which inherit from the abstract class ts::CipherChaining.
The template parameter is a block cipher class. The main chaining modes are
ts::ECB, ts::CBC or more exotic modes from the DTV world such as ts::DVS042.

But ts::CipherChaining is also a subclass of ts::BlockCipher because it
remains a symmetric cipher. So, ciphers like ts::AES or <b>ts::CBC<ts::AES></b>
can be used through the same ts::BlockCipher interface.

The class ts::Scrambling implements DVB-CSA-2, the Digital Video Broadcasting
Common Scrambling Algorithm. This implementation is older than the open-source
<a href="https://www.videolan.org/developers/libdvbcsa.html">libdvbcsa library</a>
and is probably less efficient.

The abstract class ts::Hash is the root of a hierarchy of hash functions classes.
The main hash functions are ts::SHA1, ts::SHA256 or ts::SHA512.

The abstract class ts::RandomGenerator if the root of pseudo-random generators.
Currently, only one subclass exists: ts::SystemRandomGenerator which is a portable
interface to the system-provided PRNG. Usually, this is not the best PRNG on earth,
but it is fine for most usages in TSDuck applications. However, you should not use
it for secure applications. If you need security, use a cryptographic library.

# Operating system features {#osfeatures}

## Miscelleaneous system utilities {#sysutils}

The file tsSysUtils.h declares utility functions on top of the operating system.

These functions manipulate:

- File paths.
- File attributes.
- Creating or deleting files and directories.
- Environment variables.
- Process identifiers.
- System error codes.

## Time {#time}

The class ts::Time is a portable implementation of time (both local and UTC time).
Many operations are provided, such as:
- Getting system time in various forms.
- Arithmetic operations on time.
- Analysing and building time values.
- Formatting time values as strings.

The class ts::Monotonic implements a monotonic clock and high-precision timer
(to the best of the capabilities of the operating system). It is typically used
by the plugin @e regulate for precise timing operations.

## Multithreading {#multithread}

TSDuck is heavily multi-threaded. The abstract class ts::Thread manages a thread.
To define an actual thread, derive this class and implement the virtual method @e main().

The class ts::ThreadAttributes contains all mandatory or optional attributes of
a thead. An application typically build a ts::ThreadAttributes object and then
creates threads using these attributes.

In earlier versions of TSDuck, synchronization primitives used to be implemented
through specific classes (@c ts::Mutex, @c ts::Condition). They are now removed and the
new C++11 classes such as @c std::mutex and @c std::condition_variable are used instead.

TSDuck relies on C++ mechanisms to track the usage of resources. The library provides
mechanisms to ensure that no dangling lock is lost through the _guard design pattern_.

## Virtual memory {#virtmem}

The class ts::ResidentBuffer implements a buffer which is locked in physical memory,
preventing paging or swapping on this buffer. This is useful for large data buffers with high
performance constraints.

This is a template class. The template parameter is the type of the elementary data
in the buffer.

The core data of the @e tsp processor is a <b>ts::ResidentBuffer<ts::TSPacket></b>.
The incoming packets are directly written into this buffer by the input plugin.
Each packet processing plugin directly reads and writes the packets here.
And the output plugin reads the packet there, at the very same place they
were written by the input plugin. Given that this global buffer is locked in
physical memory, the best performances are guaranteed.

Note however that most operating systems require that the application has privileges
to lock physical memory.

## Processes {#processes}

To track potential memory leaks and the impact of the application on the system,
the class ts::SystemMonitor creates a background thread which reports the process
metrics of the application at regular intervals.

The class ts::ForkPipe is a portable and convenient way to create a process
running a specific command and creates an outgoing pipe from the calling application
to the standard input of the created process.
The pipe is open in binary mode (when it makes sense for the operating system)
and can be used to pass an entire transport stream when necessary.

## Networking {#networking}

The classes ts::IPv4Address and ts::IPv4SocketAddress define an IPv4 address and
a corresponding socket address (an IPv4 address and a port number). Host
name resolution and multicast are supported.

The classes ts::TCPSocket and ts::UDPSocket implement TCP/IP and UDP/IP endpoints.

The class ts::UDPSocket can be used directly to send and receive datagrams.
Multicast is supported.

The class ts::TCPSocket can be used only through two subclasses.
The subclass ts::TCPConnection is a TCP/IP communication endpoint, either
on client or server side. It is used to send or receive data streams.
The subclass ts::TCPServer is used to implement a TCP server. It accepts
incoming client connections and initiates a ts::TCPConnection for each
new connection. On the client side, the class ts::TCPConnection is directly
used to connect to the server.

Subclasses of ts::TCPConnection are used to implement specific protocols
on top of TCP/IP. Currently, the available subclasses are ts::TelnetConnection
and ts::tlv::Connection. The latter is used in @ref dvbprotocols
"DVB SimulCrypt head-end protocols".

The class ts::WebRequest performs simple Web requests using HTTP, HTTPS or FTP.
Using a URL, the result can be downloaded in memory or in a file. Multiple
redirections and SSL/TLS are automatically handled. This class is built on
top of native system libraries (_libcurl_ on UNIX systems, _Wininet_ on Windows).

## Shared libraries {#sharelibs}

The TSDuck library contains classes to load shared libraries (@c .dll on Windows,
@c .so on Linux, @c .dylib on macOS) and lookup symbols inside them in a portable way.
These classes are typically used to load TSP plugins but can be used in any application.

The class ts::SharedLibrary manipulates any type of shared library.

The subclass ts::ApplicationSharedLibrary searches a shared library using
TSDuck rules: if the file is not found "as it is", an optional prefix and
a list of directories are used. This is how, for instance, searching the
shared library named @e "zap" will end up loading the file @e tsplugin_zap.dll
in the same directory as the application executable file.

## Smart-card interface {#pcscinterface}

Applications which interact with smart-cards shall use the PC/SC interface.
PC/SC is a standard interface which was originally developped for Windows
but which is also available on Linux and macOS.

The TSDuck library does not embed or hide PC/SC but it provides a few utilities
like transmitting an APDU and read the response in one single function or
searching a smart-card with some characteristics in the ATR from all connected
smart-cards.

All these utilities are grouped in the namespace ts::pcsc.

## Windows specificities {#wincom}

The class ts::COM provides a portable and reliable way to make sure
that the Common Object Model (COM) is properly initialized and
terminated on Windows systems. This class is defined on all
platforms but does nothing on non-Windows systems. It is consequently
safe to use it everywhere without tedious conditional compilation
directives.

Other classes manipulate Windows-specific objects and are not available
on non-Windows systems.

The template class ts::ComPtr is the equivalent of a smart pointer
for COM objects. The reference count of a COM object is properly
incremented and decremented when the COM object is manipulated through a ts::ComPtr.
The COM object is automatically released when no more reference exists.

# MPEG/DVB features {#mpegfeatures}

## Transport streams {#tsclasses}

The class ts::TSPacket defines a transport stream packet.
It is in fact a flat structure which occupies exactly 188 bytes
in memory. It is safe to use arrays or vectors of ts::TSPacket.
The packets are guaranteed to be contiguous in memory.

But the class ts::TSPacket also adds many operations on the TS packet
to read or modify properties like the PID (type ts::PID), the
continuity counters or deeper structures like PCR, DTS or PTS.

The class ts::TransportStreamId contains the identification of an
MPEG/DVB transport stream.

The class ts::Service contains all possible properties of a DVB service.
Not all properties need to be set at the same time. Each property can
be individually set, cleared or queried.

Transport stream files are implemented by classes ts::TSFileInput and
ts::TSFileOutput. They respectively read and write transport stream
files with specific features such as repeating the reading of a part
of the file.

The subclass ts::TSFileInputBuffered provides additional, but limited,
capabilities to seek forward and backward on non-seekable files
such as pipes.

The subclass ts::TSFileOutputResync adds resynchronization capabilities
on continuity counters and PID's.

The class ts::TSAnalyzer consumes all TS packets from a transport
stream and analyzes virtually everything from the stream. This is
the class which is used by the command @e tsanalyzer to collect
the vast amount of information it reports.

The class ts::PCRAnalyzer is a useful tool to evaluate the bitrate of a
transport stream. It performs the analysis of the Program Clock Reference
(PCR) which are present in the transport stream in order to evaluate the
bitrate of the stream. If PCR are not found, the class can also use
Decoding Time Stamps (DTS) to evaluate the bitrate. This is less precise
than PCR but can be used as a backup.

## Audio, video and PES packets {#audiovideopes}

The TSDuck library provides classes to manipulate PES packets and
a few audio and video attributes. These features are limited to the
analysis of a transport stream. There is no video or audio decoding
features. Specialized libraries exist for this and are out of scope
for TSDuck.

The class ts::PESPacket implements a PES packet and can manipulate
its attributes, header and payload.

The class ts::PESDemux extracts PES packets from a transport stream.
It can also notify the application of the changes in audio or video
attributes.

The abstract class ts::AbstractAudioVideoAttributes is the root of a
hierarchy of classes which contains attributes for audio or video
streams. Currently, specialized classes exist for MPEG-2 video,
AVC/H.264 video, MPEG-2 audio and AC-3 audio.

The class ts::AVCParser performs the parsing of an AVC/H.264 bitstream.

## Signalization {#siclasses}

The MPEG/DVB signalization is built from sections, tables and descriptors.
All these concepts are implemented in the TSDuck library.

### Binary, specialized and XML formats {#sigformats}

Signalization objects, sections, tables and descriptors, can
be manipulated in several formats: binary objects, specialized
classes and XML.

The classes ts::Section, ts::BinaryTable and ts::Descriptor
implement binary forms of the signalization objects.

A binary table are made of a collection of sections. A binary
table is valid when all binary sections are present. Each section
contains its section number in the table and the total expected
number of sections inside the table.

All sections and descriptors can be represented by the
classes ts::Section and ts::Descriptor. They simply contain the
complete binary content of the object and can manipulate the
various components. An instance of ts::Section stores the _table_id_
and manipulates the various components of the section header.
For long sections, the final CRC32 can be checked for consistency
or recomputed after modification of the section content.

Tables can be stored in binary files. The format of the files is quite
simple. They just contain raw binary sections, without any encapsulation.
Tables can also be stored in XML files (see below).
The class ts::SectionFile reads and writes tables or section from
files, independently of the format, either a binary section file
or an XML file.

Tables and descriptors can also be manipulated using specialized
classes such as ts::PAT or ts::PMT for tables and ts::ContentDescriptor or
ts::ShortEventDescriptor for descriptors.

All specialized classes inherit from a common abstract root named
ts::AbstractSignalization. All descriptors inherit from ts::AbstractDescriptor.
All tables inherit from ts::AbstractTable. Tables with long sections
inherit from ts::AbstractLongTable.

All MPEG-defined and DVB-defined tables are implemented. Most
MPEG-defined and DVB-defined descriptors are implemented but not all of them.
Unimplemented descriptors shall be manipulated in binary form
(or be implemented...)

Binary tables or descriptors are converted from or to specialized
classes using @e serialize() and @e deserialize() methods.
The validity of a binary or specialized object can be checked using
the @e isValid() method.

Sample deserialization:
~~~~
void someFunction(ts::DuckContext& duck, const ts::BinaryTable& table)
{
    ts::PMT pmt;
    if (table.isValid() && table.tableId() == ts::TID_PMT) {
        pmt.deserialize(duck, table);
        if (pmt.isValid()) {
            processPMT(pmt);
        }
    }
}
~~~~

The deserialization can also be done in the constructor.
And the validity and _table_id_ checking is done anyway in the deserialization.
So, the previous code can be simplified as:
~~~~
void someFunction(ts::DuckContext& duck, const ts::BinaryTable& table)
{
    ts::PMT pmt(duck, table);
    if (pmt.isValid()) {
        processPMT(pmt);
    }
}
~~~~

Sample serialization:
~~~~
ts::DuckContext duck;

ts::PMT pmt;
pmt.version = 12;
pmt.service_id = 0x1234;
// Declare one component, PID 0x345, carrying H.264/AVC video.
pmt.streams[0x345].stream_type = ts::ST_AVC_AUDIO;

ts::BinaryTable table;
pmt.serialize(duck, table);
~~~~

Note that an instance of the class ts::DuckContext can store various information
about the way to interpret incorrect signalization or preferences. Its default
value is appropriate for a standard PSI/SI processing.

Finally, specialized classes for tables and descriptors can be converted
to and from XML using the methods @e toXML() and @e fromXML().

These methods are typically used by the class ts::SectionFile which represents
a file containing sections and tables in binary or XML format. The class
can be used to load a set of tables in XML format or to store table objects
in XML format.

The class ts::SectionFile is the core of the _tstabcomp_ utility, the
tables compiler (or decompiler).

### Demux and packetization {#demux}

Signalization objects can be extracted from transport streams using
the class ts::SectionDemux and inserted back into transport streams
using the class ts::Packetizer. These two classes also have specialized
subclasses.

An instance of ts::SectionDemux can extract sections or complete tables
in binary form. Tables with long sections are usually cycled. A given
table with a given version number and a given "TID extension" is
reported only once, after collecting all its sections. The same table
will be reported again only when its version number changes.

On the contrary, short tables are all reported since they do not implement
versioning.

It is also possible to use a ts::SectionDemux to be notified of all
individual sections.

## Application preferences contexts

The class ts::DuckContext carries various preferences about the standards
or localizations. Each application has a given context. Using @c tsp, each
plugin has it own context.

The preferences which are carried by a context include the default standard
(DVB, ATSC, ISDB), the default character sets in PSI/SI, the default private
data specifier (for DVB private descriptors), the HF region (for terrestrial
or satellite frequency mapping)

The ts::DuckContext class can automatically define command-line arguments
to explicitly specity preferences (options @c -\-atsc or @c -\-default-charset
for instance). Thus, the preferences are setup from the beginning.

But preferences are also accumulated all along the execution. For instance,
as soon as an ATSC table is demuxed, the fact that the transport stream
contains ATSC data is stored in the context. Later, when an MPEG table (a PMT
for instance) contains an ambiguous descriptor tag which is used by DVB and
ATSC, then the ATSC alternative will be used.

## DVB SimulCrypt protocols {#dvbprotocols}

The communications inside a DVB SimulCrypt head-end is defined by the
standard ETSI TS 103 197, "Head-end implementation of DVB SimulCrypt".

Most of these protocols use the same principles. They use binary TLV
(Tag/Length/Value) messages, asynchronous communications, concepts
of _channels_, _streams_, status and error messages.

The generic handling of these messages is implemented by classes in the
namespace ts::tlv. All TLV messages inherit from ts::tlv::Message.
channel-level messages inherit from ts::tlv::ChannelMessage and
stream-level messages inherit from ts::tlv::StreamMessage.

The syntax of a given protocol is defined by subclassing ts::tlv::Protocol.

Currently, the TSDuck library implements the following protocols:
- ECMG <=> SCS in namespace ts::ecmgscs.
- EMMG/PDG <=> MUX in namespace ts::emmgmux.

## Conditional access systems {#cassupport}

The class ts::CASMapper analyzes the signalization of a transport stream,
locates ECM and EMM stream and associates each of them with a _CA_System_Id_.
An instance of ts::CASMapper can be queried for ECM, EMM streams or CAS
vendors.

## Other forms of demux {#otherdemux}

We have already mentioned the classes ts::SectionDemux and ts::PESDemux.
Other specialized forms of demux can be implemented. The class ts::T2MIDemux
demuxes T2-MI (DVB-T2 Modulator Interface) packets and extracts encapsulated
transport streams. Similarly, the class ts::TeletextDemux extracts Teletext
subtitles from TS packets.

Since all forms of demux share a number of properties, they all inherit from
a root abstract class named ts::AbstractDemux.

## DVB tuners {#dvbtuners}

The class ts::Tuner interfaces DVB tuner devices in a portable ways.
This is quite a challenge since Linux and Windows use very different
DVB frameworks. Some very-specific features are available either
only on Linux or Windows.

The abstract class ts::TunerParameters is the root of a hierarchy
of classes containing tuning parameters. Subclasses exist for
DVB-S, DVB-T, DVB-C and ATSC. ISDB-S and ISDB-T are currently unsupported.

The class ts::TSScanner reads a TS from a ts::Tuner until all scanning
information is found, typically until the PAT, NIT and SDT are received.
This is the basis for scanning a DVB network.

Note that DVB tuner devices are supported on Linux and Windows only. On macOS,
the above classes are defined but return "unimplemented" errors when used.

## Interface to Dektec devices {#dektecops}

TSDuck can manipulate ASI and modulator boards from Dektec. The TSDuck
library includes the DTAPI library, a proprietary C++ interface which
is provided by Dektec. The DTAPI is not available in source form and
not part of the TSDuck source repository. However, when TSDuck is built,
the DTAPI is downloaded in binary from Dektec and included in the TSDuck
library. Such a packaging is authorized by the DTAPI license (see the
file @e LICENSE.txt in the TSDuck source repository or installation tree).

An application should not directly call the DTAPI. In practice,
this works on Linux but not on Windows. So if you want portability, do
not do this. The reason is that the structure of Windows DLL's is such
that exported code from a DLL must be compiled using specific attributes.
But the DTAPI, as provided by Dektec, was not compiled with these
attributes. So, when the DTAPI is included in @e tsduck.dll, the DTAPI
can be called from inside @e tsduck.dll but is not accessible from the
application.

This is why accessing the DTAPI from the application must be done through
some TSDuck proxy class. The classes ts::DektecControl, ts::DektecInputPlugin
and ts::DektecOutputPlugin provide the features which are required by the
utility @e tsdektec and the plugin @e dektec and can be used by third-party
applications.

Note that Dektec devices are supported on Linux and Windows only. On macOS,
the above classes are defined but return "unimplemented" errors when used.

*/
