vdr  1.7.27
remux.h
Go to the documentation of this file.
00001 /*
00002  * remux.h: Tools for detecting frames and handling PAT/PMT
00003  *
00004  * See the main source file 'vdr.c' for copyright information and
00005  * how to reach the author.
00006  *
00007  * $Id: remux.h 2.32 2011/09/04 12:48:26 kls Exp $
00008  */
00009 
00010 #ifndef __REMUX_H
00011 #define __REMUX_H
00012 
00013 #include "channels.h"
00014 #include "tools.h"
00015 
00016 enum ePesHeader {
00017   phNeedMoreData = -1,
00018   phInvalid = 0,
00019   phMPEG1 = 1,
00020   phMPEG2 = 2
00021   };
00022 
00023 ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader = NULL);
00024 
00025 class cRemux {
00026 public:
00027   static void SetBrokenLink(uchar *Data, int Length);
00028   };
00029 
00030 // Some TS handling tools.
00031 // The following functions all take a pointer to one complete TS packet.
00032 
00033 #define TS_SYNC_BYTE          0x47
00034 #define TS_SIZE               188
00035 #define TS_ERROR              0x80
00036 #define TS_PAYLOAD_START      0x40
00037 #define TS_TRANSPORT_PRIORITY 0x20
00038 #define TS_PID_MASK_HI        0x1F
00039 #define TS_SCRAMBLING_CONTROL 0xC0
00040 #define TS_ADAPT_FIELD_EXISTS 0x20
00041 #define TS_PAYLOAD_EXISTS     0x10
00042 #define TS_CONT_CNT_MASK      0x0F
00043 #define TS_ADAPT_DISCONT      0x80
00044 #define TS_ADAPT_RANDOM_ACC   0x40 // would be perfect for detecting independent frames, but unfortunately not used by all broadcasters
00045 #define TS_ADAPT_ELEM_PRIO    0x20
00046 #define TS_ADAPT_PCR          0x10
00047 #define TS_ADAPT_OPCR         0x08
00048 #define TS_ADAPT_SPLICING     0x04
00049 #define TS_ADAPT_TP_PRIVATE   0x02
00050 #define TS_ADAPT_EXTENSION    0x01
00051 
00052 #define PATPID 0x0000 // PAT PID (constant 0)
00053 #define MAXPID 0x2000 // for arrays that use a PID as the index
00054 
00055 inline bool TsHasPayload(const uchar *p)
00056 {
00057   return p[3] & TS_PAYLOAD_EXISTS;
00058 }
00059 
00060 inline bool TsHasAdaptationField(const uchar *p)
00061 {
00062   return p[3] & TS_ADAPT_FIELD_EXISTS;
00063 }
00064 
00065 inline bool TsPayloadStart(const uchar *p)
00066 {
00067   return p[1] & TS_PAYLOAD_START;
00068 }
00069 
00070 inline bool TsError(const uchar *p)
00071 {
00072   return p[1] & TS_ERROR;
00073 }
00074 
00075 inline int TsPid(const uchar *p)
00076 {
00077   return (p[1] & TS_PID_MASK_HI) * 256 + p[2];
00078 }
00079 
00080 inline bool TsIsScrambled(const uchar *p)
00081 {
00082   return p[3] & TS_SCRAMBLING_CONTROL;
00083 }
00084 
00085 inline int TsPayloadOffset(const uchar *p)
00086 {
00087   int o = TsHasAdaptationField(p) ? p[4] + 5 : 4;
00088   return o <= TS_SIZE ? o : TS_SIZE;
00089 }
00090 
00091 inline int TsGetPayload(const uchar **p)
00092 {
00093   if (TsHasPayload(*p)) {
00094      int o = TsPayloadOffset(*p);
00095      *p += o;
00096      return TS_SIZE - o;
00097      }
00098   return 0;
00099 }
00100 
00101 inline int TsContinuityCounter(const uchar *p)
00102 {
00103   return p[3] & TS_CONT_CNT_MASK;
00104 }
00105 
00106 inline int TsGetAdaptationField(const uchar *p)
00107 {
00108   return TsHasAdaptationField(p) ? p[5] : 0x00;
00109 }
00110 
00111 // The following functions all take a pointer to a sequence of complete TS packets.
00112 
00113 int64_t TsGetPts(const uchar *p, int l);
00114 void TsSetTeiOnBrokenPackets(uchar *p, int l);
00115 
00116 // Some PES handling tools:
00117 // The following functions that take a pointer to PES data all assume that
00118 // there is enough data so that PesLongEnough() returns true.
00119 
00120 inline bool PesLongEnough(int Length)
00121 {
00122   return Length >= 6;
00123 }
00124 
00125 inline bool PesHasLength(const uchar *p)
00126 {
00127   return p[4] | p[5];
00128 }
00129 
00130 inline int PesLength(const uchar *p)
00131 {
00132   return 6 + p[4] * 256 + p[5];
00133 }
00134 
00135 inline int PesPayloadOffset(const uchar *p)
00136 {
00137   return 9 + p[8];
00138 }
00139 
00140 inline bool PesHasPts(const uchar *p)
00141 {
00142   return (p[7] & 0x80) && p[8] >= 5;
00143 }
00144 
00145 inline int64_t PesGetPts(const uchar *p)
00146 {
00147   return ((((int64_t)p[ 9]) & 0x0E) << 29) |
00148          (( (int64_t)p[10])         << 22) |
00149          ((((int64_t)p[11]) & 0xFE) << 14) |
00150          (( (int64_t)p[12])         <<  7) |
00151          ((((int64_t)p[13]) & 0xFE) >>  1);
00152 }
00153 
00154 // PAT/PMT Generator:
00155 
00156 #define MAX_SECTION_SIZE 4096 // maximum size of an SI section
00157 #define MAX_PMT_TS  (MAX_SECTION_SIZE / TS_SIZE + 1)
00158 
00159 class cPatPmtGenerator {
00160 private:
00161   uchar pat[TS_SIZE]; // the PAT always fits into a single TS packet
00162   uchar pmt[MAX_PMT_TS][TS_SIZE]; // the PMT may well extend over several TS packets
00163   int numPmtPackets;
00164   int patCounter;
00165   int pmtCounter;
00166   int patVersion;
00167   int pmtVersion;
00168   int pmtPid;
00169   uchar *esInfoLength;
00170   void IncCounter(int &Counter, uchar *TsPacket);
00171   void IncVersion(int &Version);
00172   void IncEsInfoLength(int Length);
00173 protected:
00174   int MakeStream(uchar *Target, uchar Type, int Pid);
00175   int MakeAC3Descriptor(uchar *Target, uchar Type);
00176   int MakeSubtitlingDescriptor(uchar *Target, const char *Language, uchar SubtitlingType, uint16_t CompositionPageId, uint16_t AncillaryPageId);
00177   int MakeTeletextDescriptor(uchar *Target, const tTeletextSubtitlePage *pages, int pageCount);
00178   int MakeLanguageDescriptor(uchar *Target, const char *Language);
00179   int MakeCRC(uchar *Target, const uchar *Data, int Length);
00180   void GeneratePmtPid(const cChannel *Channel);
00183   void GeneratePat(void);
00185   void GeneratePmt(const cChannel *Channel);
00188 public:
00189   cPatPmtGenerator(const cChannel *Channel = NULL);
00190   void SetVersions(int PatVersion, int PmtVersion);
00199   void SetChannel(const cChannel *Channel);
00201   uchar *GetPat(void);
00204   uchar *GetPmt(int &Index);
00209   };
00210 
00211 // PAT/PMT Parser:
00212 
00213 class cPatPmtParser {
00214 private:
00215   uchar pmt[MAX_SECTION_SIZE];
00216   int pmtSize;
00217   int patVersion;
00218   int pmtVersion;
00219   int pmtPid;
00220   int vpid;
00221   int ppid;
00222   int vtype;
00223   int tpid;
00224   int apids[MAXAPIDS + 1]; // list is zero-terminated
00225   int atypes[MAXAPIDS + 1]; // list is zero-terminated
00226   char alangs[MAXAPIDS][MAXLANGCODE2];
00227   int dpids[MAXDPIDS + 1]; // list is zero-terminated
00228   int dtypes[MAXDPIDS + 1]; // list is zero-terminated
00229   char dlangs[MAXDPIDS][MAXLANGCODE2];
00230   int spids[MAXSPIDS + 1]; // list is zero-terminated
00231   char slangs[MAXSPIDS][MAXLANGCODE2];
00232   uchar subtitlingTypes[MAXSPIDS];
00233   uint16_t compositionPageIds[MAXSPIDS];
00234   uint16_t ancillaryPageIds[MAXSPIDS];
00235   bool updatePrimaryDevice;
00236   int totalTtxtSubtitlePages;
00237   tTeletextSubtitlePage teletextSubtitlePages[MAXTXTPAGES];
00238 protected:
00239   int SectionLength(const uchar *Data, int Length) { return (Length >= 3) ? ((int(Data[1]) & 0x0F) << 8)| Data[2] : 0; }
00240 public:
00241   cPatPmtParser(bool UpdatePrimaryDevice = false);
00242   void Reset(void);
00245   void ParsePat(const uchar *Data, int Length);
00248   void ParsePmt(const uchar *Data, int Length);
00255   bool GetVersions(int &PatVersion, int &PmtVersion) const;
00258   int PmtPid(void) const { return pmtPid; }
00261   int Vpid(void) const { return vpid; }
00264   int Ppid(void) const { return ppid; }
00267   int Vtype(void) const { return vtype; }
00270   int Tpid(void) { return tpid; }
00273   const int *Apids(void) const { return apids; }
00274   const int *Dpids(void) const { return dpids; }
00275   const int *Spids(void) const { return spids; }
00276   int Apid(int i) const { return (0 <= i && i < MAXAPIDS) ? apids[i] : 0; }
00277   int Dpid(int i) const { return (0 <= i && i < MAXDPIDS) ? dpids[i] : 0; }
00278   int Spid(int i) const { return (0 <= i && i < MAXSPIDS) ? spids[i] : 0; }
00279   int Atype(int i) const { return (0 <= i && i < MAXAPIDS) ? atypes[i] : 0; }
00280   int Dtype(int i) const { return (0 <= i && i < MAXDPIDS) ? dtypes[i] : 0; }
00281   const char *Alang(int i) const { return (0 <= i && i < MAXAPIDS) ? alangs[i] : ""; }
00282   const char *Dlang(int i) const { return (0 <= i && i < MAXDPIDS) ? dlangs[i] : ""; }
00283   const char *Slang(int i) const { return (0 <= i && i < MAXSPIDS) ? slangs[i] : ""; }
00284   uchar SubtitlingType(int i) const { return (0 <= i && i < MAXSPIDS) ? subtitlingTypes[i] : uchar(0); }
00285   uint16_t CompositionPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? compositionPageIds[i] : uint16_t(0); }
00286   uint16_t AncillaryPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? ancillaryPageIds[i] : uint16_t(0); }
00287   const tTeletextSubtitlePage *TeletextSubtitlePages() const { return teletextSubtitlePages; }
00288   int TotalTeletextSubtitlePages() const { return totalTtxtSubtitlePages; }
00289   };
00290 
00291 // TS to PES converter:
00292 // Puts together the payload of several TS packets that form one PES
00293 // packet.
00294 
00295 class cTsToPes {
00296 private:
00297   uchar *data;
00298   int size;
00299   int length;
00300   int offset;
00301   uchar *lastData;
00302   int lastLength;
00303   bool repeatLast;
00304 public:
00305   cTsToPes(void);
00306   ~cTsToPes();
00307   void PutTs(const uchar *Data, int Length);
00317   const uchar *GetPes(int &Length);
00331   void SetRepeatLast(void);
00334   void Reset(void);
00338   };
00339 
00340 // Some helper functions for debugging:
00341 
00342 void BlockDump(const char *Name, const u_char *Data, int Length);
00343 void TsDump(const char *Name, const u_char *Data, int Length);
00344 void PesDump(const char *Name, const u_char *Data, int Length);
00345 
00346 // Frame detector:
00347 
00348 #define MIN_TS_PACKETS_FOR_FRAME_DETECTOR 5
00349 
00350 class cFrameDetector {
00351 private:
00352   enum { MaxPtsValues = 150 };
00353   int pid;
00354   int type;
00355   bool synced;
00356   bool newFrame;
00357   bool independentFrame;
00358   uint32_t ptsValues[MaxPtsValues]; // 32 bit is enough - we only need the delta
00359   int numPtsValues;
00360   int numFrames;
00361   int numIFrames;
00362   bool isVideo;
00363   double framesPerSecond;
00364   int framesInPayloadUnit;
00365   int framesPerPayloadUnit; // Some broadcasters send one frame per payload unit (== 1),
00366                             // some put an entire GOP into one payload unit (> 1), and
00367                             // some spread a single frame over several payload units (< 0).
00368   int payloadUnitOfFrame;
00369   bool scanning;
00370   uint32_t scanner;
00371   int SkipPackets(const uchar *&Data, int &Length, int &Processed, int &FrameTypeOffset);
00372 public:
00373   cFrameDetector(int Pid = 0, int Type = 0);
00377   void SetPid(int Pid, int Type);
00379   void Reset(void);
00382   int Analyze(const uchar *Data, int Length);
00388   bool Synced(void) { return synced; }
00390   bool NewFrame(void) { return newFrame; }
00393   bool IndependentFrame(void) { return independentFrame; }
00397   double FramesPerSecond(void) { return framesPerSecond; }
00400   };
00401 
00402 #endif // __REMUX_H