MythTV  0.26-pre
mpegtables.h
Go to the documentation of this file.
00001 // -*- Mode: c++ -*-
00002 // Copyright (c) 2003-2004, Daniel Thor Kristjansson
00003 #ifndef _MPEG_TABLES_H_
00004 #define _MPEG_TABLES_H_
00005 
00006 #include <cassert>
00007 #include "mpegdescriptors.h"
00008 #include "pespacket.h"
00009 #include "mythtvexp.h"
00010 #include "mythmiscutil.h" // for xml_indent
00011 
00028 #define GPS_EPOCH 315964800
00029 
00031 #define GPS_LEAP_SECONDS 14
00032 
00033 
00037 class MTV_PUBLIC PESStreamID
00038 {
00039   public:
00040     enum
00041     {
00042         PictureStartCode        = 0x00,
00043         SliceStartCodeBegin     = 0x01,
00044         SliceStartCodeEnd       = 0xaf,
00045         DVBECMData              = 0xb0,
00046         DVBEMMData              = 0xb1,
00047         UserData                = 0xb2,
00049         SequenceStartCode       = 0xb3,
00050         SequenceError           = 0xb4,
00052         MPEG2ExtensionStartCode = 0xb5,
00053         MPEGReservedB6          = 0xb6,
00054         SEQEndCode              = 0xb7,
00058         GOPStartCode            = 0xb8,
00059         ProgramEndCode          = 0xb9,
00060         PackHeader              = 0xba,
00061         SystemHeader            = 0xbb,
00062         ProgramStreamMap        = 0xbc,
00064         NonMPEGAudioVideo       = 0xbd,
00065         PaddingStream           = 0xbe,
00067         DVDNavigation           = 0xbf,
00069         MPEGAudioStreamBegin    = 0xc0,
00071         MPEGAudioStreamEnd      = 0xdf,
00073         MPEGVideoStreamBegin    = 0xe0,
00075         MPEGVideoStreamEnd      = 0xef,
00076         ECMData                 = 0xf0,
00077         EMMData                 = 0xf1,
00078         DSMCCData               = 0xf2,
00080         Data13522               = 0xf3,
00082         DataH2221Begin          = 0xf4,
00084         DataH2221End            = 0xf8,
00085         AncillaryData           = 0xf9,
00086         MPEGReservedFA          = 0xfa,
00087         FlexMux                 = 0xfb, // MPEG-2 13818-1
00088         MPEGReservedFC          = 0xfc,
00089         MPEGReservedFD          = 0xfd,
00090         MPEGReservedFE          = 0xfe,
00091         ProgramStreamDirectory  = 0xff, // MPEG-2 13818-1
00092     };
00093 };
00094 
00095 
00102 class MTV_PUBLIC StreamID
00103 {
00104   public:
00105     enum
00106     {
00107         // video
00108         MPEG1Video     = 0x01, 
00109         MPEG2Video     = 0x02, 
00110         MPEG4Video     = 0x10, 
00111         H264Video      = 0x1b, 
00112         OpenCableVideo = 0x80,
00113         VC1Video       = 0xea, 
00114 
00115         // audio
00116         MPEG1Audio     = 0x03, 
00117         MPEG2Audio     = 0x04, 
00118         MPEG2AACAudio  = 0x0f, 
00119         MPEG2AudioAmd1 = 0x11, 
00120         AC3Audio       = 0x81,
00121         DTSAudio       = 0x8a,
00122 
00123         // DSM-CC Object Carousel
00124         DSMCC          = 0x08, 
00125         DSMCC_A        = 0x0a, 
00126         DSMCC_B        = 0x0b, 
00127         DSMCC_C        = 0x0c, 
00128         DSMCC_D        = 0x0d, 
00129         DSMCC_DL       = 0x14, 
00130         MetaDataPES    = 0x15, 
00131         MetaDataSec    = 0x16, 
00132         MetaDataDC     = 0x17, 
00133         MetaDataOC     = 0x18, 
00134         MetaDataDL     = 0x19, 
00135 
00136         // other
00137         PrivSec        = 0x05, 
00138         PrivData       = 0x06, 
00139 
00140         MHEG           = 0x07, 
00141         H222_1         = 0x09, 
00142 
00143         MPEG2Aux       = 0x0e, 
00144 
00145         FlexMuxPES     = 0x12, 
00146         FlexMuxSec     = 0x13, 
00147 
00148         MPEG2IPMP      = 0x1a, 
00149         MPEG2IPMP2     = 0x7f, 
00150 
00151         Splice         = 0x86, 
00152 
00153         // special id's, not actually ID's but can be used in FindPIDs
00154         AnyMask        = 0xFFFF0000,
00155         AnyVideo       = 0xFFFF0001,
00156         AnyAudio       = 0xFFFF0002,
00157     };
00159     static bool IsVideo(uint type)
00160     {
00161         return ((StreamID::MPEG1Video == type) ||
00162                 (StreamID::MPEG2Video == type) ||
00163                 (StreamID::MPEG4Video == type) ||
00164                 (StreamID::H264Video  == type) ||
00165                 (StreamID::VC1Video   == type) ||
00166                 (StreamID::OpenCableVideo == type));
00167     }
00169     static bool IsAudio(uint type)
00170     {
00171         return ((StreamID::MPEG1Audio     == type) ||
00172                 (StreamID::MPEG2Audio     == type) ||
00173                 (StreamID::MPEG2AudioAmd1 == type) ||
00174                 (StreamID::MPEG2AACAudio  == type) ||
00175                 (StreamID::AC3Audio       == type) ||
00176                 (StreamID::DTSAudio       == type));
00177     }
00179     static bool IsObjectCarousel(uint type)
00180     {
00181         return ((StreamID::DSMCC_A == type) ||
00182                 (StreamID::DSMCC_B == type) ||
00183                 (StreamID::DSMCC_C == type) ||
00184                 (StreamID::DSMCC_D == type));
00185     }
00186     static uint Normalize(uint stream_id, const desc_list_t &desc,
00187                           const QString &sistandard);
00188     static const char* toString(uint streamID);
00189     static QString GetDescription(uint streamID);
00190 };
00191 
00192 enum
00193 {
00194     MPEG_PAT_PID  = 0x0000,
00195     MPEG_CAT_PID  = 0x0001,
00196     MPEG_TSDT_PID = 0x0002,
00197 
00198     DVB_NIT_PID   = 0x0010,
00199     DVB_SDT_PID   = 0x0011,
00200     DVB_EIT_PID   = 0x0012,
00201     DVB_RST_PID   = 0x0013,
00202     DVB_TDT_PID   = 0x0014,
00203 
00204     // Dishnet longterm EIT is on pid 0x300
00205     DVB_DNLONG_EIT_PID = 0x0300,
00206 
00207     // Bell longterm EIT is on pid 0x441
00208     DVB_BVLONG_EIT_PID = 0x0441,
00209 
00210     // Premiere EIT for Direkt/Sport PPV
00211     PREMIERE_EIT_DIREKT_PID = 0x0b11,
00212     PREMIERE_EIT_SPORT_PID  = 0x0b12,
00213 
00214     ATSC_PSIP_PID = 0x1ffb,
00215 
00216     SCTE_PSIP_PID = 0x1ffc,
00217 
00218     // UK Freesat PIDs: SDTo/BAT, longterm EIT, shortterm EIT
00219     FREESAT_SI_PID     = 0x0f01,
00220     FREESAT_EIT_PID    = 0x0f02,
00221     FREESAT_ST_EIT_PID = 0x0f03,
00222 };
00223 
00227 class MTV_PUBLIC TableID
00228 {
00229   public:
00230     enum
00231     {
00232         PAT      = 0x00, // always on pid 0x00
00233         CAT      = 0x01, // always on pid 0x01
00234         PMT      = 0x02,
00235         TSDT     = 0x03, // always on pid 0x02
00236 
00237         // DVB manditory
00238         NIT      = 0x40, // always on pid 0x10
00239         SDT      = 0x42, // always on pid 0x11
00240         PF_EIT   = 0x4e, // always on pid 0x12
00241         TDT      = 0x70, // always on pid 0x14
00242 
00243         // DVB optional
00244         NITo     = 0x41, // always on pid 0x10
00245         SDTo     = 0x46, // always on pid 0x11
00246         BAT      = 0x4a, // always on pid 0x11
00247         PF_EITo  = 0x4f, // always on pid 0x12
00248         SC_EITbeg  = 0x50, // always on pid 0x12
00249         SC_EITend  = 0x5f, // always on pid 0x12
00250         SC_EITbego = 0x60, // always on pid 0x12
00251         SC_EITendo = 0x6f, // always on pid 0x12
00252         RST      = 0x71, // always on pid 0x13
00253         ST       = 0x72, // any pid 0x10-0x14
00254         TOT      = 0x73, // always on pid 0x14
00255         RNT      = 0x74, // always on pid 0x16
00256         CT       = 0x75,
00257         RCT      = 0x76,
00258         CIT      = 0x77, // always on pid 0x12
00259         MPEFEC   = 0x78,
00260         DIT      = 0x7e, // always on pid 0x1e
00261         SIT      = 0x7f, // always on pid 0x1f
00262 
00263         // DVB Conditional Access
00264         DVBCAbeg = 0x80,
00265         DVBCAend = 0x8f,
00266 
00267         // Dishnet Longterm EIT data
00268         DN_EITbego = 0x80, // always on pid 0x300
00269         DN_EITendo = 0xfe, // always on pid 0x300
00270 
00271         // ARIB
00272         ARIBbeg  = 0x80,
00273         ARIBend  = 0x8f,
00274 
00275         // SCTE 57 -- old depreciated standard
00276         PIM      = 0xC0, // Program Information Message (57 2003) PMT PID
00277         PNM      = 0xC1, // Program Name Message (57 2003) PMT PID
00278         // The PIM and PNM do not have SCTE 65 equivalents.
00279 
00280         // Under SCTE 57 -- NIM, NTM, VCM, and STM were carried on the
00281         // network PID (Table ID 0x0) as defined in the PAT, but under
00282         // SCTE 65 the equivalent tables are carried on 0x1FFC
00283 
00284         NIM      = 0xC2, // Network Information Message (57 2003)
00285         NTM      = 0xC3, // Network Text Message (57 2003)
00286         // The NTM is like the SCTE 65 NTT table, except that it
00287         // carries more subtable types and the id for the source name
00288         // subtable they both share is type 5 rather than 6 which can
00289         // cause calimity if not dealt with properly.
00290         VCM      = 0xC4, // Virtual Channel Message (57 2003)
00291         STM      = 0xC5, // System Time Message (57 2003)
00292 
00293         // SCTE 65 -- Current US Cable TV standard
00294         NITscte  = 0xC2, // Network Information Table (NIT) (65 2002) on 0x1FFC
00295         NTT      = 0xC3, // Network Text Table (NTT) (65 2002) on 0x1FFC
00296         SVCTscte = 0xC4, // Short Virtual Channel Table (65 2002) on 0x1FFC
00297         STTscte  = 0xC5, // System Time Table (STT) (65 2002) on 0x1FFC
00298 
00299         // Other SCTE
00300         SM       = 0xC6, // subtitle_message (27 2003)
00301         CEA      = 0xD8, // Cable Emergency Alert (18 2002)
00302         ADET     = 0xD9, // Aggregate Data Event Table (80 2002)
00303 
00304         // SCTE 35
00305         SITscte  = 0xFC, // SCTE 35 Splice Info Table (Cueing messages)
00306 
00307         // ATSC Conditional Access (A/70)
00308         ECM0     = 0x80,
00309         ECM1     = 0x81,
00310         ECMbeg   = 0x82, // ECM begin private data
00311         ECMend   = 0x8f, // ECM end private data
00312 
00313         // ATSC main
00314         MGT      = 0xC7, // Master Guide Table A/65 on 0x1ffb
00315         TVCT     = 0xC8, // Terrestrial Virtual Channel Table A/65 on 0x1ffb
00316         CVCT     = 0xC9, // Cable Virtual Channel Table A/65 on 0x1ffb
00317         RRT      = 0xCA, // Region Rating Table A/65 on 0x1ffb
00318         EIT      = 0xCB, // Event Information Table A/65 (per MGT)
00319         ETT      = 0xCC, // Extended Text Table A/65 (per MGT)
00320         STT      = 0xCD, // System Time Table A/65
00321         DET      = 0xCE, // Data Event Table A/90 (per MGT)
00322         DST      = 0xCF, // Data Service Table A/90
00323 
00324         PIT      = 0xD0, // Program ID Table ???
00325         NRT      = 0xD1, // Network Resources Table A/90
00326         LTST     = 0xD2, // Long Term Service Table A/90
00327         DCCT     = 0xD3, // Directed Channel Change Table A/57 on 0x1ffb
00328         DCCSCT   = 0xD4, // DCC Selection Code Table A/57 on 0x1ffb
00329         SITatsc  = 0xD5, // Selection Information Table (EIA-775.2 2000)
00330         AEIT     = 0xD6, // Aggregate Event Information Table A/81, SCTE 65
00331         AETT     = 0xD7, // Aggregate Extended Text Table A/81, SCTE 65
00332         SVCT     = 0xDA, // Satellite VCT A/81
00333 
00334         SRM      = 0xE0, // System Renewability Message (ATSC TSG-717r0)
00335 
00336         // Unknown
00337         STUFFING = 0x80,
00338         CAPTION  = 0x86,
00339         CENSOR   = 0x87,
00340 
00341         // Private premiere.de
00342         PREMIERE_CIT = 0xA0,
00343         PREMIERE_CPT = 0xA1,
00344 
00345         ECN      = 0xA0,
00346         SRVLOC   = 0xA1,
00347         TSS      = 0xA2,
00348         CMPNAME  = 0xA3,
00349     };
00350 };
00351 
00356 class MTV_PUBLIC PSIPTable : public PESPacket
00357 {
00358   private:
00359     // creates non-clone version, for View
00360     PSIPTable(const PESPacket& pkt, bool)
00361         : PESPacket(reinterpret_cast<const TSPacket*>(pkt.tsheader()), false)
00362         { ; }
00363   public:
00364     PSIPTable(const PSIPTable& table) : PESPacket(table)
00365     {
00366         // section_syntax_ind   1       1.0       8   should always be 1
00367         // private_indicator    1       1.1       9   should always be 1
00368     }
00369     PSIPTable(const PESPacket& table) : PESPacket(table)
00370     {
00371         // section_syntax_ind   1       1.0       8   should always be 1
00372         // private_indicator    1       1.1       9   should always be 1
00373     }
00374     PSIPTable(const TSPacket& table) : PESPacket(table)
00375     {
00376         // section_syntax_ind   1       1.0       8   should always be 1
00377         // private_indicator    1       1.1       9   should always be 1
00378     }
00379 
00380 
00381     static const PSIPTable View(const TSPacket& tspacket)
00382         { return PSIPTable(PESPacket::View(tspacket), false); }
00383 
00384     static PSIPTable View(TSPacket& tspacket)
00385         { return PSIPTable(PESPacket::View(tspacket), false); }
00386 
00387     // Section            Bits   Start Byte sbit
00388     // -----------------------------------------
00389     // table_id             8       0.0       0
00390     uint TableID(void) const { return StreamID(); }
00391 
00392     // section_syntax_ind   1       1.0       8   ATSC -- should always be 1
00393     bool SectionSyntaxIndicator(void) const { return pesdata()[1] & 0x80; }
00394     // private_indicator    1       1.1       9
00395     bool PrivateIndicator(void) const { return pesdata()[1] & 0x40; }
00396     // reserved             2       1.2      10
00397 
00398     // section_length      12       1.4      12   always less than 0x3fd
00399     // adds 3 to the total section length to account for 3 bytes
00400     // before the end of the section length field.
00401     uint SectionLength(void) const { return Length() + 3; }
00402 
00404     // Things below this line may not apply to SCTE/DVB tables.
00405 
00406     // table_id_extension  16       3.0      24   table dependent
00407     uint TableIDExtension(void) const
00408         { return (pesdata()[3]<<8) | pesdata()[4]; }
00409 
00410     // reserved             2       5.0      40
00411 
00412     // version_number       5       5.2      42
00413     // incremented modulo 32 when table info changes
00414     uint Version(void) const { return (pesdata()[5]>>1) & 0x1f; }
00415 
00416     // current_next_ind     1       5.7      47
00417     // if 0 this table is not yet valid, but will be the next psip
00418     // table with the same sectionNumber(), tableIDExtension() and
00419     // tableID() to become valid.
00420     bool IsCurrent(void) const { return bool(pesdata()[5]&1); }
00421 
00422     // section_number       8       6.0      48
00423     uint Section(void) const { return pesdata()[6]; }
00424 
00425     // last_section_number  8       7.0      56
00426     uint LastSection(void) const { return pesdata()[7]; }
00427 
00428     // Protocol Version for ATSC PSIP tables
00429     // protocol_version     8       8.0      64   should always be 0 for now
00430     uint ATSCProtocolVersion(void) const { return pesdata()[8]; }
00431 
00432     // PSIP_table_data      x       8.0      72 (incl. protocolVersion)
00433     const unsigned char* psipdata(void) const
00434         { return pesdata() + PSIP_OFFSET; }
00435     unsigned char* psipdata(void)
00436         { return pesdata() + PSIP_OFFSET; }
00437 
00438     // sets
00439     void SetTableID(uint id) { SetStreamID(id); }
00440     // subtracts 3 from total section length to account for 3 bytes
00441     // before the end of the section length field.
00442     void SetSectionLength(uint length) { SetLength(length-3); }
00443     void SetTableIDExtension(uint len)
00444     {
00445         pesdata()[3] = (len>>8) & 0xff;
00446         pesdata()[4] = len & 0xff;
00447     }
00448     void SetVersionNumber(uint ver)
00449         { pesdata()[5] = (pesdata()[5] & 0xc1) | ((ver & 0x1f)<<1); }
00450     void SetCurrent(bool cur)
00451         { pesdata()[5] = (pesdata()[5] & 0xfe) | (cur ? 1 : 0); }
00452     void SetSection(uint num) { pesdata()[6] = num; }
00453     void SetLastSection(uint num) { pesdata()[7] = num; }
00454 
00455     // Only for real ATSC PSIP tables.
00456     void SetATSCProtocolVersion(int ver) { pesdata()[8] = ver; }
00457 
00458     bool HasCRC(void) const;
00459     bool HasSectionNumber(void) const;
00460 
00461     bool VerifyPSIP(bool verify_crc) const;
00462 
00463     virtual QString toString(void) const;
00464     virtual QString toStringXML(uint indent_level) const;
00465 
00466     static const uint PSIP_OFFSET = 8; // general PSIP header offset
00467 
00468   protected:
00469     QString XMLValues(uint indent_level) const;
00470 };
00471 
00490 class MTV_PUBLIC ProgramAssociationTable : public PSIPTable
00491 {
00492   public:
00493     ProgramAssociationTable(const ProgramAssociationTable& table)
00494         : PSIPTable(table)
00495     {
00496         assert(TableID::PAT == TableID());
00497     }
00498 
00499     ProgramAssociationTable(const PSIPTable &table) : PSIPTable(table)
00500     {
00501         assert(TableID::PAT == TableID());
00502     }
00503 
00504     // transport stream ID, program ID, count
00505     static ProgramAssociationTable* Create(uint tsid, uint version,
00506                                            const vector<uint>& pnum,
00507                                            const vector<uint>& pid);
00508 
00509     uint TransportStreamID(void) const { return TableIDExtension(); }
00510 
00511     uint ProgramCount(void) const
00512     {
00513         if (SectionLength() > (PSIP_OFFSET+2))
00514             return (SectionLength()-PSIP_OFFSET-2)>>2;
00515         return 0;
00516     }
00517 
00518     uint ProgramNumber(uint i) const
00519         { return (psipdata()[(i<<2)] << 8) | psipdata()[(i<<2) + 1]; }
00520 
00521     uint ProgramPID(uint i) const
00522     {
00523         return (((psipdata()[(i<<2) + 2] & 0x1f) << 8) |
00524                 psipdata()[(i<<2) + 3]);
00525     }
00526 
00527     void SetTranportStreamID(uint gtsid) { SetTableIDExtension(gtsid); }
00528 
00529     // helper function
00530     uint FindPID(uint progNum) const
00531     {
00532         for (uint i = 0; i < ProgramCount(); i++)
00533             if (progNum==ProgramNumber(i))
00534                 return ProgramPID(i);
00535         return 0;
00536     }
00537     uint FindAnyPID(void) const
00538     {
00539         for (uint i = 0; i < ProgramCount(); i++)
00540             if (0!=ProgramNumber(i))
00541                 return ProgramPID(i);
00542         return 0;
00543     }
00544     uint FindProgram(uint pid) const
00545     {
00546         for (uint i = 0; i < ProgramCount(); i++)
00547             if (pid==ProgramPID(i))
00548                 return ProgramNumber(i);
00549         return 0;
00550     }
00551 
00552     virtual QString toString(void) const;
00553     virtual QString toStringXML(uint indent_level) const;
00554 
00555   private:
00556     static ProgramAssociationTable* CreateBlank(bool smallPacket = true);
00557 };
00558 
00564 class MTV_PUBLIC ProgramMapTable : public PSIPTable
00565 {
00566   public:
00567 
00568     ProgramMapTable(const ProgramMapTable& table) : PSIPTable(table)
00569     {
00570         assert(TableID::PMT == TableID());
00571         Parse();
00572     }
00573 
00574     ProgramMapTable(const PSIPTable& table) : PSIPTable(table)
00575     {
00576         assert(TableID::PMT == TableID());
00577         Parse();
00578     }
00579 
00580     static ProgramMapTable* Create(uint programNumber, uint basepid,
00581                                    uint pcrpid, uint version,
00582                                    vector<uint> pids, vector<uint> types);
00583 
00584     static ProgramMapTable* Create(uint programNumber, uint basepid,
00585                                    uint pcrpid, uint version,
00586                                    const desc_list_t         &global_desc,
00587                                    const vector<uint>        &pids,
00588                                    const vector<uint>        &types,
00589                                    const vector<desc_list_t> &prog_desc);
00590 
00592     uint PCRPID(void) const
00593         { return ((psipdata()[0] << 8) | psipdata()[1]) & 0x1fff; }
00594 
00595     uint ProgramNumber(void) const
00596         { return TableIDExtension(); }
00597 
00598     uint ProgramInfoLength(void) const
00599         { return ((psipdata()[2]<<8) | psipdata()[3]) & 0x0fff; }
00600 
00601     const unsigned char* ProgramInfo(void) const
00602         { return psipdata() + 4; }
00603 
00604     uint StreamType(uint i) const
00605         { return _ptrs[i][0]; }
00606 
00607     uint StreamPID(uint i) const
00608         { return ((_ptrs[i][1] << 8) | _ptrs[i][2]) & 0x1fff; }
00609 
00610     uint StreamInfoLength(uint i) const
00611         { return ((_ptrs[i][3] << 8) | _ptrs[i][4]) & 0x0fff; }
00612 
00613     const unsigned char* StreamInfo(uint i) const
00614         { return _ptrs[i] + 5; }
00615 
00616     uint StreamCount(void) const
00617         { return (_ptrs.size()) ? _ptrs.size()-1 : 0; }
00618 
00619     // sets
00620     void SetPCRPID(uint pid)
00621     {
00622         psipdata()[0] = ((pid >> 8) & 0x1F) | (psipdata()[0] & 0xE0);
00623         psipdata()[1] = (pid & 0xFF);
00624     }
00625 
00626     void SetProgramNumber(uint num) { SetTableIDExtension(num); }
00627 
00628     void SetStreamPID(uint i, uint pid)
00629     {
00630         _ptrs[i][1] = ((pid>>8) & 0x1f) | (_ptrs[i][1] & 0xe0);
00631         _ptrs[i][2] = pid & 0xff;
00632     }
00633 
00634     void SetStreamType(uint i, uint type)
00635         { _ptrs[i][0] = type; }
00636 
00637     // helper methods
00638     bool IsVideo(uint i, QString sistandard) const;
00639     bool IsAudio(uint i, QString sistandard) const;
00640     bool IsEncrypted(QString sistandard) const;
00641     bool IsProgramEncrypted(void) const;
00642     bool IsStreamEncrypted(uint pid) const;
00644     bool IsStillPicture(QString sistandard) const;
00646     QString StreamTypeString(uint i) const
00647         { return StreamID::toString(StreamType(i)); }
00650     QString StreamDescription(uint i, QString sistandard) const;
00652     QString GetLanguage(uint i) const;
00653 
00654     uint FindPIDs(uint type, vector<uint> &pids,
00655                   const QString &sistandard) const;
00656     uint FindPIDs(uint type, vector<uint> &pids, vector<uint> &types,
00657                   const QString &sistandard, bool normalize) const;
00658 
00661     int FindPID(uint pid) const
00662     {
00663         for (uint i = 0; i < StreamCount(); i++)
00664             if (pid == StreamPID(i))
00665                 return i;
00666         return -1;
00667     }
00668     uint FindUnusedPID(uint desired_pid = 0x20);
00669 
00670     void RemoveAllStreams(void)
00671     {
00672         memset(psipdata(), 0xff, pmt_header);
00673         SetProgramInfoLength(0);
00674         _ptrs.clear();
00675     }
00676     void AppendStream(uint pid, uint type, unsigned char* si = 0, uint il = 0);
00677 
00678     void Parse(void) const;
00679     virtual QString toString(void) const;
00680     virtual QString toStringXML(uint indent_level) const;
00681     // unsafe sets
00682   private:
00683     void SetStreamInfoLength(uint i, uint length)
00684     {
00685         _ptrs[i][3] = ((length>>8) & 0x0f) | (_ptrs[i][3] & 0xf0);
00686         _ptrs[i][4] = length & 0xff;
00687     }
00688 
00689     void SetStreamProgramInfo(uint i, unsigned char* streamInfo,
00690                               uint infoLength)
00691     {
00692         SetStreamInfoLength(i, infoLength);
00693         memcpy(_ptrs[i] + 5, streamInfo, infoLength);
00694     }
00695 
00696     void SetProgramInfoLength(uint length)
00697     {
00698         psipdata()[2] = ((length>>8) & 0x0f) | (psipdata()[2] & 0xf0);
00699         psipdata()[3] = length & 0xff;
00700     }
00701 
00702     void SetProgramInfo(unsigned char *streamInfo, uint infoLength)
00703     {
00704         SetProgramInfoLength(infoLength);
00705         memcpy(psipdata() + 4, streamInfo, infoLength);
00706     }
00707 
00708     static ProgramMapTable* CreateBlank(bool smallPacket = true);
00709 
00710     static const uint pmt_header = 4; // minimum PMT header offset
00711     mutable vector<unsigned char*> _ptrs; // used to parse
00712 };
00713 
00718 class MTV_PUBLIC ConditionalAccessTable : public PSIPTable
00719 {
00720   public:
00721     ConditionalAccessTable(const PSIPTable &table) : PSIPTable(table)
00722     {
00723     // Section            Bits   Start Byte sbit
00724     // -----------------------------------------
00725     // table_id             8       0.0       0
00726         assert(TableID::CAT == TableID());
00727     // section_syntax_ind   1       1.0       8   should always be 1
00728     // private_indicator    1       1.1       9   should always be 0
00729     // reserved             2       1.2      10
00730     // section_length      12       1.4      12   always less than 0x3fd
00731     // table_id_extension  16       3.0      24   unused
00732     // reserved             2       5.0      40
00733     // version_number       5       5.2      42
00734     // current_next_ind     1       5.3      47
00735     // section_numben       8       6.0      48
00736     // last_section_number  8       7.0      56
00737     }
00738 
00739     // for (i = 0; i < N; i++)      8.0      64
00740     //   { descriptor() }
00741     uint DescriptorsLength(void) const
00742         { return SectionLength() - PSIP_OFFSET; }
00743     const unsigned char *Descriptors(void) const { return psipdata(); }
00744 
00745     virtual QString toString(void) const;
00746     virtual QString toStringXML(uint indent_level) const;
00747 
00748     // CRC_32 32 rpchof
00749 };
00750 
00751 class MTV_PUBLIC SpliceTimeView
00752 {
00753   public:
00754     SpliceTimeView(const unsigned char *data) : _data(data) { }
00755     //   time_specified_flag    1  0.0
00756     bool IsTimeSpecified(void) const { return _data[0] & 0x80; }
00757     //   if (time_specified_flag == 1)
00758     //     reserved             6  0.1
00759     //     pts_time            33  0.6
00760     uint64_t PTSTime(void) const
00761     {
00762         return ((uint64_t(_data[0] & 0x1) << 32) |
00763                 (uint64_t(_data[1])       << 24) |
00764                 (uint64_t(_data[2])       << 16) |
00765                 (uint64_t(_data[3])       <<  8) |
00766                 (uint64_t(_data[4])));
00767     }
00768     //   else
00769     //     reserved             7  0.1
00770     // }
00771     virtual QString toString(int64_t first, int64_t last) const;
00772     virtual QString toStringXML(
00773         uint indent_level, int64_t first, int64_t last) const;
00774 
00775     uint size(void) const { return IsTimeSpecified() ? 1 : 5; }
00776   private:
00777     const unsigned char *_data;
00778 };
00779 
00780 class MTV_PUBLIC SpliceScheduleView
00781 {
00782   public:
00783     SpliceScheduleView(const vector<const unsigned char*> &ptrs0,
00784                        const vector<const unsigned char*> &ptrs1) :
00785         _ptrs0(ptrs0), _ptrs1(ptrs1)
00786     {
00787     }
00788     //   splice_count           8  14.0
00789     uint SpliceCount(void) const { return min(_ptrs0.size(), _ptrs1.size()); }
00790 
00791     //   splice_event_id       32  0.0 + _ptrs0[i]
00792     uint SpliceEventID(uint i) const
00793     {
00794         return ((_ptrs0[i][0] << 24) | (_ptrs0[i][1] << 16) |
00795                 (_ptrs0[i][2] <<  8) | (_ptrs0[i][3]));
00796     }
00797     //   splice_event_cancel_indicator 1 4.0 + _ptrs0[i]
00798     //   reserved               7   4.1 + _ptrs0[i]
00799     //   if (splice_event_cancel_indicator == ‘0’) {
00800     //     out_of_network_indicator 1 5.0 + _ptrs0[i]
00801     //     program_splice_flag  1 5.1 + _ptrs0[i]
00802     //     duration_flag        1 5.2 + _ptrs0[i]
00803     //     reserved             5 5.3 + _ptrs0[i]
00804     //     if (program_splice_flag == ‘1’) 
00805     //       utc_splice_time   32 6.0 + _ptrs0[i]
00806     //     else {
00807     //       component_count    8 6.0 + _ptrs0[i]
00808     //       for(j = 0; j < component_count; j++) {
00809     //         component_tag    8 7.0 + _ptrs0[i]+j*5
00810     //         utc_splice_time 32 8.0 + _ptrs0[i]+j*5
00811     //       }
00812     //     }
00813     //     if (duration_flag) {
00814     //       auto_return        1 0.0 + _ptrs1[i]
00815     //       reserved           6 0.1 + _ptrs1[i]
00816     //       duration          33 0.7 + _ptrs1[i]
00817     //     }
00818     //     unique_program_id   16 0.0 + _ptrs1[i] + (duration_flag)?5:0
00819     //     avail_num            8 2.0 + _ptrs1[i] + (duration_flag)?5:0
00820     //     avails_expected      8 3.0 + _ptrs1[i] + (duration_flag)?5:0
00821     //   }
00822 
00823   private:
00824     vector<const unsigned char*> _ptrs0;
00825     vector<const unsigned char*> _ptrs1;    
00826 };
00827 
00828 class MTV_PUBLIC SpliceInsertView
00829 {
00830   public:
00831     SpliceInsertView(const vector<const unsigned char*> &ptrs0,
00832                      const vector<const unsigned char*> &ptrs1) :
00833         _ptrs0(ptrs0), _ptrs1(ptrs1)
00834     {
00835     }
00836 
00837     //   splice_event_id       32   0.0 + _ptrs1[0]
00838     uint SpliceEventID(void) const
00839     {
00840         return ((_ptrs1[0][0] << 24) | (_ptrs1[0][1] << 16) |
00841                 (_ptrs1[0][2] <<  8) | (_ptrs1[0][3]));
00842     }
00843     //   splice_event_cancel    1    4.0 + _ptrs1[0]
00844     bool IsSpliceEventCancel(void) const { return _ptrs1[0][4] & 0x80; }
00845     //   reserved               7    4.1 + _ptrs1[0]
00846     //   if (splice_event_cancel_indicator == 0) {
00847     //     out_of_network_flag  1    5.0 + _ptrs1[0]
00848     bool IsOutOfNetwork(void) const { return _ptrs1[0][5] & 0x80; }
00849     //     program_splice_flag  1    5.1 + _ptrs1[0]
00850     bool IsProgramSplice(void) const { return _ptrs1[0][5] & 0x40; }
00851     //     duration_flag        1    5.2 + _ptrs1[0]
00852     bool IsDuration(void) const { return _ptrs1[0][5] & 0x20; }
00853     //     splice_immediate_flag 1   5.3 + _ptrs1[0]
00854     bool IsSpliceImmediate(void) const { return _ptrs1[0][5] & 0x20; }
00855     //     reserved             4    5.4 + _ptrs1[0]
00856     //     if ((program_splice_flag == 1) && (splice_immediate_flag == ‘0’))
00857     //       splice_time()   8-38    6.0 + _ptrs1[0]
00858     SpliceTimeView SpliceTime(void) const
00859         { return SpliceTimeView(_ptrs1[0]+6); }
00860     //     if (program_splice_flag == 0) {
00861     //       component_count    8    6.0 + _ptrs1[0]
00862     //       for (i = 0; i < component_count; i++) {
00863     //         component_tag    8    0.0 + _ptrs0[i]
00864     //         if (splice_immediate_flag == ‘0’)
00865     //           splice_time() 8-38  1.0 + _ptrs0[i]
00866     //       }
00867     //     }
00868     //     if (duration_flag == ‘1’)
00869     //       auto_return        1    0.0 + _ptrs1[1]
00870     //       reserved           6    0.1 + _ptrs1[1]
00871     //       duration          33    0.7 + _ptrs1[1]
00872     //     unique_program_id   16    0.0 + _ptrs1[2]
00873     uint UniqueProgramID(void) const
00874         { return (_ptrs1[2][0]<<8) | _ptrs1[2][1]; }
00875     //     avail_num            8    2.0 + _ptrs1[2]
00876     uint AvailNum(void) const { return _ptrs1[2][2]; }
00877     //     avails_expected      8    3.0 + _ptrs1[2]
00878     uint AvailsExpected(void) const { return _ptrs1[2][3]; }
00879     //   }
00880 
00881     virtual QString toString(int64_t first, int64_t last) const;
00882     virtual QString toStringXML(
00883         uint indent_level, int64_t first, int64_t last) const;
00884 
00885   private:
00886     vector<const unsigned char*> _ptrs0;
00887     vector<const unsigned char*> _ptrs1;
00888 };
00889 
00890 class MTV_PUBLIC SpliceInformationTable : public PSIPTable
00891 {
00892   public:
00893     SpliceInformationTable(const SpliceInformationTable &table) :
00894         PSIPTable(table), _epilog(NULL)
00895     {
00896         assert(TableID::SITscte == TableID());
00897         Parse();
00898     }
00899     SpliceInformationTable(const PSIPTable &table) :
00900         PSIPTable(table), _epilog(NULL)
00901     {
00902         assert(TableID::SITscte == TableID());
00903         Parse();
00904     }
00905     ~SpliceInformationTable() { ; }
00906 
00907     // ANCE/SCTE 35 2007
00908     //       Name             bits  loc  expected value
00909     // table_id                 8   0.0       0xFC
00910     // section_syntax_indicator 1   1.0          1
00911     // private_indicator        1   1.1          0
00912     // reserved                 2   1.2          3
00913     // section_length          12   1.4
00914     // ^^^ All above this line provided by PSIPTable
00915     // protocol_version         8   3.0          0
00916     uint SpliceProtocolVersion(void) const { return pesdata()[3]; }
00917     void SetSpliceProtocolVersion(uint ver) { pesdata()[3] = ver; }
00918     // encrypted_packet         1   4.0
00919     bool IsEncryptedPacket(void) const { return pesdata()[4] & 0x80; }
00920     void SetEncryptedPacket(bool val)
00921     {
00922         pesdata()[4] = (pesdata()[4] & ~0x80) | ((val) ? 0x80 : 0);
00923     }
00924     // encryption_algorithm     6   4.1
00925     enum
00926     {
00927         kNoEncryption = 0,
00928         kECB          = 1, // DES - ECB mode, FIPS PUB 81 (8 byte blocks)
00929         kCBC          = 2, // DES - CBC mode, FIPS PUB 81 (8 byte blocks)
00930         k3DES         = 3, // 3 DES - TDEA, FIPS PUB 46-3 (8 byte blocks)
00931         // values 4-31 are reserved for future extension
00932         // values 32-63 are user private
00933     };
00934     uint EncryptionAlgorithm(void) const { return (pesdata()[4] >> 1) & 0x3f; }
00935     QString EncryptionAlgorithmString(void) const;
00936     void SetEncryptionAlgorithm(uint val)
00937     {
00938         pesdata()[4] &= 0x81;
00939         pesdata()[4] |= ((val&0x3f) << 1);
00940     }
00941     // pts_adjustment          33   4.7
00942     uint64_t PTSAdjustment(void) const
00943     {
00944         return ((uint64_t(pesdata()[4] & 0x1) << 32) |
00945                 (uint64_t(pesdata()[5])       << 24) |
00946                 (uint64_t(pesdata()[6])       << 16) |
00947                 (uint64_t(pesdata()[7])       <<  8) |
00948                 (uint64_t(pesdata()[8])));
00949     }
00950     void SetPTSAdjustment(uint64_t val)
00951     {
00952         pesdata()[4] &= ~0x1;
00953         pesdata()[4] |= (val>>32) & 0x1;
00954         pesdata()[5] = ((val>>24) & 0xff);
00955         pesdata()[6] = ((val>>16) & 0xff);
00956         pesdata()[7] = ((val>>8 ) & 0xff);
00957         pesdata()[8] = ((val    ) & 0xff);
00958     }
00959     // cw_index (enc key)       8   9.0
00960     uint CodeWordIndex(void) const { return pesdata()[9]; }
00961     void SetCodeWordIndex(uint val) { pesdata()[9] = val; }
00962     // reserved                12  10.0
00963     // splice_command_length   12  11.4
00964     uint SpliceCommandLength(void) const
00965     {
00966         return ((pesdata()[11] & 0xf) << 8) | pesdata()[12];
00967     }
00968     void SetSpliceCommandLength(uint len)
00969     {
00970         pesdata()[11] &= ~0xf;
00971         pesdata()[11] |= (len >> 8) & 0xf;
00972         pesdata()[12] = len & 0xff;
00973     }
00974     // splice_command_type      8  13.0
00975     enum {
00976         kSCTNull                 = 0x00,
00977         kSCTReserved0            = 0x01,
00978         kSCTReserved1            = 0x02,
00979         kSCTReserved2            = 0x03,
00980         kSCTSpliceSchedule       = 0x04,
00981         kSCTSpliceInsert         = 0x05,
00982         kSCTTimeSignal           = 0x06,
00983         kSCTBandwidthReservation = 0x07,
00984         // 0x08-0xfe reserved
00985         kSCTPrivateCommand       = 0xff,
00986     };
00987     uint SpliceCommandType(void) const { return pesdata()[13]; }
00988     QString SpliceCommandTypeString(void) const;
00989     void SetSpliceCommandType(uint type) { pesdata()[13] = type & 0xff; }
00990 
00991     // ALL BELOW THIS LINE OTHER THAN CRC_32 ARE ENCRYPTED IF FLAG SET
00992 
00994 
00995     // nothing here, info in descriptors
00996 
00998 
00999     // if (splice_command_type == 0x04) splice_schedule()
01000     SpliceScheduleView SpliceSchedule(void) const
01001         { return SpliceScheduleView(_ptrs0, _ptrs1); }
01002 
01004 
01005     // if (splice_command_type == 0x05) splice_insert()
01006     SpliceInsertView SpliceInsert(void) const
01007         { return SpliceInsertView(_ptrs0, _ptrs1); }
01008 
01010 
01011     // if (splice_command_type == 0x06) splice_time()
01012     SpliceTimeView TimeSignal(void) const
01013         { return SpliceTimeView(pesdata()+14); }
01014 
01016 
01017     // nothing here, info in descriptors
01018 
01020 
01021     // if (splice_command_type == 0xff) private_command()
01022     //   identifier            32  14.0
01023     //   for (i = 0; i < N; i++)
01024     //     private_byte         8  ??.0
01025     //
01026 
01028     // NOTE: Aside from CRC's we can not interpret things below
01029     // this comment with private or reserved commands.
01030 
01031     // descriptor_loop_length  16   0.0 + _epilog
01032     uint SpliceDescriptorsLength(uint i) const
01033     {
01034         return (_epilog[0] << 8) | _epilog[1];
01035     }
01036 
01037     // for (i = 0; i < ? ; i++)
01038     //   splice_descriptor()   ??   ??.?
01039     const unsigned char *SpliceDescriptors(void) const
01040     {
01041         return (_epilog) ? _epilog + 2 : NULL;
01042     }
01043     // for (i = 0; i < ?; i++)
01044     //   alignment_stuffing     8   ??.0
01045     // if (encrypted_packet())
01046     //    E_CRC_32             32   ??.0
01047     // CRC_32                  32   ??.0
01048 
01049     SpliceInformationTable *GetDecrypted(const QString &codeWord) const;
01050     bool Parse(void);
01051 
01052     virtual QString toString(void) const { return toString(-1LL, -1LL); }
01053     virtual QString toStringXML(uint indent_level) const
01054         { return toStringXML(indent_level, -1LL, -1LL); }
01055 
01056     QString toString(int64_t first, int64_t last) const;
01057     QString toStringXML(uint indent_level, int64_t first, int64_t last) const;
01058 
01059   private:
01060     vector<const unsigned char*> _ptrs0;
01061     vector<const unsigned char*> _ptrs1;
01062     const unsigned char *_epilog;
01063 };
01064 
01074 class MTV_PUBLIC AdaptationFieldControl
01075 {
01076   public:
01077     AdaptationFieldControl(const unsigned char* packet) : _data(packet) { ; }
01078 
01082     uint Length(void) const             { return _data[0]; }
01083 
01087     bool Discontinuity(void) const      { return _data[1] & 0x80; }
01088     // random_access_indicator (?)           1   1.1
01089     bool RandomAccess(void) const       { return bool(_data[1] & 0x40); }
01090     // elementary_stream_priority_indicator  1   1.2
01091     bool Priority(void) const           { return bool(_data[1] & 0x20); }
01092 
01093 // Each of the following extends the adaptation header.  In order:
01094 
01098     bool PCR(void) const                { return bool(_data[1] & 0x10); }
01102     bool OPCR(void) const               { return bool(_data[1] & 0x08); }
01110     bool SplicingPoint(void) const      { return bool(_data[1] & 0x04); }
01111     //  transport_private_data_flag          1   1.6
01112     // (adds 1 byte)
01113     bool PrivateTransportData(void) const { return bool(_data[1] & 0x02); }
01114     // adaptation_field_extension_flag       1   1.7
01115     bool FieldExtension(void) const     { return bool(_data[1] & 0x1); }
01116     // extension length                      8   2.0
01117     uint ExtensionLength(void) const    { return _data[2]; }
01118     // ltw flag                              1   3.0
01119     // (adds 2 bytes)
01120     bool LTW(void) const                { return bool(_data[3] & 0x80); }
01121     // piecewise_rate_flag (adds 3 bytes)    1   3.1
01122     bool PiecewiseRate(void) const      { return bool(_data[3] & 0x40); }
01123     // seamless_splice_flag (adds 5 bytes)   1   3.2
01124     bool SeamlessSplice(void) const     { return bool(_data[3] & 0x20); }
01125     // unused flags                          5   3.3
01126 
01127   private:
01128     const unsigned char* _data;
01129 };
01130 
01131 #endif
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends