PID Filter - Demultiplexer: Difference between revisions

From LinuxTVWiki
Jump to navigation Jump to search
No edit summary
m (fixed links)
 
(4 intermediate revisions by 2 users not shown)
Line 1: Line 1:
== Introduction ==
== Introduction ==


A raw [[MPEG2 Transport Stream]] consists data of all the services transmitted on a particular transponder. The task on the receiver side is to filter out the interesting packets and schedule them to their target decoders: Audio packets to the audio-decoder, video packets to the video decoder, subtitle packets to the subtitle decoder etc...
A raw [[MPEG-2 Transport Stream]] consists data of all the services transmitted on a particular transponder. The task on the receiver side is to filter out the interesting packets and schedule them to their target decoders: Audio packets to the audio-decoder, video packets to the video decoder, subtitle packets to the subtitle decoder etc...


MPEG2 TS packets are identified by the Packet ID, the PID. This is a 13-bit number located in the 2nd and 3rd byte of a TS packet.
MPEG-2 TS packets are identified by the Packet ID, the PID. This is a 13-bit number located in the 2nd and 3rd byte of a TS packet.


== PID Filter Algorithm ==
== PID Filter Algorithm ==
Line 10: Line 10:


== PID Filter Sample Code (the easy way) ==
== PID Filter Sample Code (the easy way) ==

This implementation uses a trivial PID table of 2^13 (=8192) bits where every bit is set to '1' if this particular PID is enabled and cleared to '0' if the PID is disabled. The entire table has a size of 8kbit (1kByte). <tt>pid_is_enabled()</tt> simply tests if the bit on position '<pid>' is set.

You can also organize you filters in a linked list and traverse this every time, but you don't need to do it that complicated unless you really want...

Here the code:


<tt>
<tt>
static unsigned char pid_table [1024] = { 0 };
static inline
void enable_pid (unsigned short pid)
{
unsigned int index = pid / 8;
unsigned int bit = pid % 8;
pid_table[index] |= 1 << bit;
}
static inline
void disable_pid (unsigned short pid)
{
unsigned int index = pid / 8;
unsigned int bit = pid % 8;
pid_table[index] &= ~(1 << bit);
}
static inline
int pid_is_enabled (unsigned short pid)
{
unsigned int index = pid / 8;
unsigned int bit = pid % 8;
return (pid_table[index] & (1 << bit)) ? 1 : 0;
}
static inline
static inline
unsigned short ts_pid (const unsigned char *ts_packet)
unsigned short ts_pid (const unsigned char *ts_packet)
Line 34: Line 70:


<tt>
<tt>
static inline
unsigned short ts_pid (const unsigned char *ts_packet)
{
return ((ts_packet[1] & 0x1f) << 8) + ts_packet[2];
}
static
static
void pidfilter_process_ts_packet (const unsigned char ts_packet[188])
void pidfilter_process_ts_packet (const unsigned char ts_packet[188])
Line 66: Line 95:
if (scrambling_control != 0)
if (scrambling_control != 0)
return 0;
return;
if (pid_is_enabled(pid))
if (pid_is_enabled(pid))
Line 80: Line 109:


The MPEG table decoder receives now all tables of an enabled PID, these are usually related anyways.
The MPEG table decoder receives now all tables of an enabled PID, these are usually related anyways.

[[Category:Technology]]

Latest revision as of 22:11, 6 January 2008

Introduction

A raw MPEG-2 Transport Stream consists data of all the services transmitted on a particular transponder. The task on the receiver side is to filter out the interesting packets and schedule them to their target decoders: Audio packets to the audio-decoder, video packets to the video decoder, subtitle packets to the subtitle decoder etc...

MPEG-2 TS packets are identified by the Packet ID, the PID. This is a 13-bit number located in the 2nd and 3rd byte of a TS packet.

PID Filter Algorithm

The algorithm is easy: we simply check the 13 PID bits and look whether this PID is enabled in our PID filter list.

PID Filter Sample Code (the easy way)

This implementation uses a trivial PID table of 2^13 (=8192) bits where every bit is set to '1' if this particular PID is enabled and cleared to '0' if the PID is disabled. The entire table has a size of 8kbit (1kByte). pid_is_enabled() simply tests if the bit on position '<pid>' is set.

You can also organize you filters in a linked list and traverse this every time, but you don't need to do it that complicated unless you really want...

Here the code:

static unsigned char pid_table [1024] = { 0 };


static inline
void enable_pid (unsigned short pid)
{
        unsigned int index = pid / 8;
        unsigned int bit = pid % 8;
        pid_table[index] |= 1 << bit;
}


static inline
void disable_pid (unsigned short pid)
{
        unsigned int index = pid / 8;
        unsigned int bit = pid % 8;
        pid_table[index] &= ~(1 << bit);
}


static inline
int pid_is_enabled (unsigned short pid)
{
        unsigned int index = pid / 8;
        unsigned int bit = pid % 8;
        return (pid_table[index] & (1 << bit)) ? 1 : 0;
}


static inline
unsigned short ts_pid (const unsigned char *ts_packet)
{
        return ((ts_packet[1] & 0x1f) << 8) + ts_packet[2];
}


static
void pidfilter_process_ts_packet (const unsigned char ts_packet[188])
{
        unsigned short pid = ts_pid(ts_packet);

        if (pid_is_enabled(pid))
               pass_packet_to_decoder(ts_packet);
}

PID Filter Sample Code (with sanity checks)

This slightly extended version of the above code contains additional sanity checks that have been useful in the past:

static
void pidfilter_process_ts_packet (const unsigned char ts_packet[188])
{
        unsigned short pid = ts_pid(ts_packet);
        unsigned char scrambling_control;

        /**
         *  check TS error indicator bit and discard broken packets...
         */
        if (ts_packet[1] & 0x80) {
                bad_packet_counter++;
                return;
        }

        /**
         *  this makes no sense - however, some transponders like to send
         *  packets with scrambling bits set which contain gaga data (??).
         *
         *  In any case no scrambled packets should arrive in the demux,
         *  CSA descramblers are located before this stage of the pipeline,
         *  so simply discard this garbage...
         */
        scrambling_control = (ts_packet[3] >> 6) & 0x03;

        if (scrambling_control != 0)
                return;

        if (pid_is_enabled(pid))
               pass_packet_to_decoder(ts_packet);
}

Section Filtering

Most DVB Hardware decoders provide so called Section Filters, these allow to specify which MPEG and DVB section tables we want to receive in a particular queue.

But in practice these tables are organized in a way that we want to update our clock, EPG state and DSM-CC caroussels continously and enable all section filters on a particular PID in most cases. So it's questionable whether it makes sense to implement a similiar solution in future designs, simple PID filtering is usually sufficient.

The MPEG table decoder receives now all tables of an enabled PID, these are usually related anyways.