TSDuck v3.40-4033
MPEG Transport Stream Toolkit
|
An efficient TSDuck-specific TS packets encapsulation in a PID. More...
#include <tsPacketEncapsulation.h>
Public Types | |
enum | PESMode { DISABLED = 0 , FIXED = 1 , VARIABLE = 2 } |
Type of PES encapsulation mode. More... | |
Public Member Functions | |
PacketEncapsulation (PID pidOutput=PID_NULL, const PIDSet &pidInput=NoPID, PID pcrReference=PID_NULL) | |
Constructor. | |
void | addInputPID (PID pid) |
Add one PID to encapsulate. | |
bool | hasError () const |
Check if a previous error is pending. | |
const PIDSet & | inputPIDs () const |
Get the current set of input PID's. | |
const UString & | lastError () const |
Get the last error message. | |
PID | outputPID () const |
Get the output PID. | |
size_t | pidCount () const |
Get the current number of input PID's being encapsulated. | |
bool | processPacket (TSPacket &pkt) |
Process a TS packet from the input stream. | |
PID | referencePCR () const |
Get the reference PID for PCR's. | |
void | removeInputPID (PID pid) |
Remove one PID to encapsulate. | |
void | reset (PID pidOutput=PID_NULL, const PIDSet &pidInput=NoPID, PID pcrReference=PID_NULL) |
Reset the encapsulation. | |
void | resetError () |
Reset the last error. | |
void | setInputPIDs (const PIDSet &pidInput) |
Replace the set of input PID's. | |
void | setMaxBufferedPackets (size_t count) |
Set the maximum number of buffered packets. | |
void | setOutputPID (PID pid) |
Change the output PID. | |
void | setPacking (bool on, size_t limit) |
Set packing mode. | |
void | setPES (PESMode mode) |
Set PES mode. | |
void | setPESOffset (size_t offset) |
Set PES Offset. | |
void | setReferencePCR (PID pid) |
Change the reference PID for PCR's. | |
Static Public Attributes | |
static constexpr size_t | DEFAULT_MAX_BUFFERED_PACKETS = 1024 |
Default maximum number of buffered packets. | |
An efficient TSDuck-specific TS packets encapsulation in a PID.
An instance of this class encapsulates several PID's from the input transport stream into one single output PID. Functionally, this is a subset of the features of T2-MI but much more lightweight and significantly faster to process.
In the output elementary stream (ES), all input TS packets are contiguous, without encapsulation. The initial 0x47 synchronization byte is removed. Only the remaining 187 bytes are encapsulated.
In the output PID, the packetization is similar to sections, with 187-bytes packets instead of sections. The Payload Unit Start Indicator (PUSI) bit is set in the header of TS packets containing the start of an encapsulated packet. When the PUSI bit is set, the first byte of the payload is a "pointer field" to the beginning of the first encapsulated packet.
Due to the overhead of the TS header, the number of output packets is slightly larger than the input packets. The input streams must contain a few null packets to absorb the extra output packets. For this reason, null packets (PID 0x1FFF) are never encapsulated.
When selecting the PES encapsulation the same plain elementary stream is used, but with a PES envelope. This reduces the payload size, but makes the outer encapsulation more transparent. The full overhead is around 14-20% of additional data.
The PES envelope uses a KLVA SMPTE-336M encapsulation to insert the inner payload into one private (testing) key. Each TS packet contains only one key, with a size no larger than the payload of one TS packet. So each PES packet fits into a single TS packet.
The SMPTE-336M encapsulation implemented can be either the asynchronous (without timestamps) or the synchronous (with PTS). The latter consumes more space (+10 bytes), and it's only useful when it's needed to remux the encapsulated stream with an external tool that requires to use PTS marks. No other advantages are provided.
Two variant strategies are implemented. The FIXED mode uses the short (7-bit) BER encoding. This limits the PES payload to a maximum of 127 bytes. And the adaptation field of the outer packet is enlarged with some stuff. However, the advantage is that the PES is sufficient small to include more data in the outer TS packet. This reduces the possibility than some external processing will split the outer packet in two to accommodate the entire PES data.
The VARIABLE mode does not impose this restriction and outer packets are filled to the maximum. The drawback is that sometimes the long form of BER encoding is used with two bytes and others the short form with one byte. Furthermore, this increases the chances that some external processing occupies two outer packets for the same inner PES packet. Still, support for those split PES packets is included. The only requirement is that the 26|27 PES+KLVA header is inserted in the first packet (with PUSI on). The remaining payload can be distributed in the following TS packets.
The PES envelope has an overhead of 26|27|36|37 bytes based on:
To enable the use of the Synchronous encapsulation is required to use PCRs and provide one offset. This value (positive or negative) will be added to the PCR to compute the PTS. Recommended values are between -90000 and +90000 (-1,+1 second). If you use negative values then you can restore in advance the encapsulated stream after remuxing. However, this will be valid only if you use an external tool to remux. If you're unsure, then don't enable it.
A warning about the Synchronous mode: At start the PTS marks can't be in synch with the target pcr-pid. This is because the PCR value isn't readed at start. But the PTS is required to be in all PES packets of the encapsulation. So, it's recommended to discard the outcoming stream until valid PTS values appear in the encapsulated stream.
In order to correctly identify the encapsulated PES stream, it is recommended to include in the PMT table a format identifier descriptor for "KLVA" (0x4B4C5641); and use the associated metadata for the stream type based on the selected Sync/Async mode:
Example (Asynchronous):
where the outer PID is 7777 and the attached service is 100.
Example (Synchronous):
where the outer PID is 7777, the pid 101 carries the PCR of the service, the attached service is 100 and the PTS is advanced around half second.
ts::PacketEncapsulation::PacketEncapsulation | ( | PID | pidOutput = PID_NULL , |
const PIDSet & | pidInput = NoPID , |
||
PID | pcrReference = PID_NULL |
||
) |
Constructor.
[in] | pidOutput | The output PID. When PID_NULL, no encapsulation is done. |
[in] | pidInput | The initial set of PID's to encapsulate. |
[in] | pcrReference | The PID with PCR's to use as reference to add PCR's in the encapsulating PID. When PID_NULL, do not add PCR. |
void ts::PacketEncapsulation::reset | ( | PID | pidOutput = PID_NULL , |
const PIDSet & | pidInput = NoPID , |
||
PID | pcrReference = PID_NULL |
||
) |
Reset the encapsulation.
[in] | pidOutput | The new output PID. When PID_NULL, no encapsulation is done. |
[in] | pidInput | The new set of PID's to encapsulate. |
[in] | pcrReference | The PID with PCR's to use as reference to add PCR's in the encapsulating PID. When PID_NULL, do not add PCR. |
bool ts::PacketEncapsulation::processPacket | ( | TSPacket & | pkt | ) |
Process a TS packet from the input stream.
[in,out] | pkt | A TS packet. If the packet belongs to one of the input PID's, it is replaced by an encapsulating packet in the output PID. Some null packets are also replaced to absorb the encapsulation overhead. |
|
inline |
Get the last error message.
|
inline |
Check if a previous error is pending.
|
inline |
Get the output PID.
void ts::PacketEncapsulation::setOutputPID | ( | PID | pid | ) |
Change the output PID.
[in] | pid | The new output PID. |
|
inline |
Get the current set of input PID's.
|
inline |
Get the current number of input PID's being encapsulated.
void ts::PacketEncapsulation::setInputPIDs | ( | const PIDSet & | pidInput | ) |
Replace the set of input PID's.
[in] | pidInput | The new set of PID's to encapsulate. |
void ts::PacketEncapsulation::addInputPID | ( | PID | pid | ) |
Add one PID to encapsulate.
[in] | pid | The new PID to encapsulate. |
void ts::PacketEncapsulation::removeInputPID | ( | PID | pid | ) |
Remove one PID to encapsulate.
[in] | pid | The PID to no longer encapsulate. |
|
inline |
Get the reference PID for PCR's.
void ts::PacketEncapsulation::setReferencePCR | ( | PID | pid | ) |
Change the reference PID for PCR's.
[in] | pid | The new reference PID for PCR's. PID_NULL if there is none. |
void ts::PacketEncapsulation::setMaxBufferedPackets | ( | size_t | count | ) |
Set the maximum number of buffered packets.
The buffered packets are produced by the encapsulation overhead. An overflow is usually caused by insufficient null packets in the input stream.
[in] | count | The maximum number of buffered packets. |
|
inline |
Set packing mode.
When packing mode is off (the default), encapsulated packets are issued as soon as null packet are available for replacement, potentially leaving unused part in some outer packet. When packing mode if on, outer packets are emitted only when they are full.
[in] | on | Packing mode. |
[in] | limit | Number of packets after which encapsulation is forced, even when packing is off. |
|
inline |
Set PES mode.
Enables the PES mode encapsulation (disabled by default).
[in] | mode | PES mode. |
|
inline |
Set PES Offset.
When using the PES mode it enables the PES Synchronous encapsulation when != 0. The offset value is used to compute the PTS of the encap stream based on the PCR.
[in] | offset | value. Use 0 for Asynchronous PES mode (default). |