MPEG-2 Frame Aligner

From LinuxTVWiki
Revision as of 20:38, 1 November 2004 by Holger (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.

Introduction

Most hardware does not provides aligned MPEG2 data streams, also the linux-dvb API's DVR device can get out of sync if the MPEG2 TS data stream is interrupted, e.g. due to DMA buffer overflows or if the demod delivers partial packets in case of uncorrectable block errors.

MPEG2 TS packets can be 188 (without FEC data) or 204 bytes long (including 16 FEC bytes).

Algorithm

The MPEG2 Frame Aligner can get implemented as simple state machine, whenever we are in an "out-of-sync"-state we check all followig bytes until we encounter a MPEG2 TS Sync Byte (0x47). From then on we check every 188 or 204 bytes if the next 0x47-sync-byte is present. If so the packet is passed to the PID filter

Sample Code

The following sample code works for 188-byte packets. This code is taken from the LinuxDVB kernel driver (originally written by Florian Schirmer) and thus GPL'd.

A more generic and robust version based on a state machine should not be too hard to implement and would be able to synchronize both 188- and 204-byte-packets. Please let us know when you feel in the mood to implement+test this, we'll be happy to help whereever possible.

struct framealigner {
        char tsbuf[188];
        int tsbufp;
};


void framealigner_process_ts_data (struct framealigner *fa,
                                   const char *buf,
                                   unsigned int count)
{
        unsigned int p = 0, i, j;

        if ((i = fa->tsbufp)) {
                if (count < (j=188-i)) {
                        memcpy(&fa->tsbuf[i], buf, count);
                        fa->tsbufp += count;
                        return;
                }
                memcpy(&fa->tsbuf[i], buf, j);
                pidfilter_ts_packet(fa->tsbuf);
                fa->tsbufp = 0;
                p += j;
        }

        while (p < count) {
                if (buf[p] == 0x47) {
                        if (count-p >= 188) {
                                pidfilter_process_ts_packet(buf+p);
                                p += 188;
                        } else {
                                i = count - p;
                                memcpy(fa->tsbuf, buf+p, i);
                                fa->tsbufp = i;
                                return;
                        }
                } else
                        p++;
        }
}