00001
00002
00003 #ifndef _MPEG_TABLES_H_
00004 #define _MPEG_TABLES_H_
00005
00006 #include <cassert>
00007 #include "pespacket.h"
00008 #include "mpegdescriptors.h"
00009
00026 class PESStreamID
00027 {
00028 public:
00029 enum
00030 {
00031 PictureStartCode = 0x00,
00032 SliceStartCodeBegin = 0x01,
00033 SliceStartCodeEnd = 0xaf,
00034 DVBECMData = 0xb0,
00035 DVBEMMData = 0xb1,
00036 UserData = 0xb2,
00038 SequenceStartCode = 0xb3,
00039 SequenceError = 0xb4,
00041 MPEG2ExtensionStartCode = 0xb5,
00042 MPEGReservedB6 = 0xb6,
00043 SEQEndCode = 0xb7,
00047 GOPStartCode = 0xb8,
00048 ProgramEndCode = 0xb9,
00049 PackHeader = 0xba,
00050 SystemHeader = 0xbb,
00051 ProgramStreamMap = 0xbc,
00053 NonMPEGAudioVideo = 0xbd,
00054 PaddingStream = 0xbe,
00056 DVDNavigation = 0xbf,
00058 MPEGAudioStreamBegin = 0xc0,
00060 MPEGAudioStreamEnd = 0xdf,
00062 MPEGVideoStreamBegin = 0xe0,
00064 MPEGVideoStreamEnd = 0xef,
00065 ECMData = 0xf0,
00066 EMMData = 0xf1,
00067 DSMCCData = 0xf2,
00069 Data13522 = 0xf3,
00071 DataH2221Begin = 0xf4,
00073 DataH2221End = 0xf8,
00074 AncillaryData = 0xf9,
00075 MPEGReservedFA = 0xfa,
00076 MPEGReservedFB = 0xfb,
00077 MPEGReservedFC = 0xfc,
00078 MPEGReservedFD = 0xfd,
00079 MPEGReservedFE = 0xfe,
00080 MPEGReservedFF = 0xff,
00081 };
00082 };
00083
00084
00091 class StreamID
00092 {
00093 public:
00094 enum
00095 {
00096
00097 MPEG1Video = 0x01,
00098 MPEG2Video = 0x02,
00099 MPEG4Video = 0x10,
00100 H264Video = 0x1b,
00101 OpenCableVideo = 0x80,
00102
00103
00104 MPEG1Audio = 0x03,
00105 MPEG2Audio = 0x04,
00106 MPEG2AudioAmd1 = 0x11,
00107 AACAudio = 0x0f,
00108 AC3Audio = 0x81,
00109 DTSAudio = 0x8a,
00110
00111
00112 DSMCC = 0x08,
00113 DSMCC_A = 0x0a,
00114 DSMCC_B = 0x0b,
00115 DSMCC_C = 0x0c,
00116 DSMCC_D = 0x0d,
00117 DSMCC_DL = 0x14,
00118 MetaDataPES = 0x15,
00119 MetaDataSec = 0x16,
00120 MetaDataDC = 0x17,
00121 MetaDataOC = 0x18,
00122 MetaDataDL = 0x19,
00123
00124
00125 PrivSec = 0x05,
00126 PrivData = 0x06,
00127
00128 MHEG = 0x07,
00129 H222_1 = 0x09,
00130
00131 MPEG2Aux = 0x0e,
00132
00133 FlexMuxPES = 0x12,
00134 FlexMuxSec = 0x13,
00135
00136 MPEG2IPMP = 0x1a,
00137 MPEG2IPMP2 = 0x7f,
00138
00139
00140 AnyMask = 0xFFFF0000,
00141 AnyVideo = 0xFFFF0001,
00142 AnyAudio = 0xFFFF0002,
00143 };
00145 static bool IsVideo(uint type)
00146 {
00147 return ((StreamID::MPEG1Video == type) ||
00148 (StreamID::MPEG2Video == type) ||
00149 (StreamID::MPEG4Video == type) ||
00150 (StreamID::H264Video == type) ||
00151 (StreamID::OpenCableVideo == type));
00152 }
00154 static bool IsAudio(uint type)
00155 {
00156 return ((StreamID::MPEG1Audio == type) ||
00157 (StreamID::MPEG2Audio == type) ||
00158 (StreamID::AACAudio == type) ||
00159 (StreamID::AC3Audio == type) ||
00160 (StreamID::DTSAudio == type));
00161 }
00163 static bool IsObjectCarousel(uint type)
00164 {
00165 return ((StreamID::DSMCC_A == type) ||
00166 (StreamID::DSMCC_B == type) ||
00167 (StreamID::DSMCC_C == type) ||
00168 (StreamID::DSMCC_D == type));
00169 }
00170 static uint Normalize(uint stream_id, const desc_list_t &desc,
00171 const QString &sistandard);
00172 static const char* toString(uint streamID);
00173 };
00174
00175 enum
00176 {
00177 MPEG_PAT_PID = 0x0000,
00178 MPEG_CAT_PID = 0x0001,
00179 MPEG_TSDT_PID = 0x0002,
00180
00181 DVB_NIT_PID = 0x0010,
00182 DVB_SDT_PID = 0x0011,
00183 DVB_EIT_PID = 0x0012,
00184 DVB_RST_PID = 0x0013,
00185 DVB_TDT_PID = 0x0014,
00186
00187
00188 DVB_DNLONG_EIT_PID = 0x0300,
00189
00190
00191 PREMIERE_EIT_DIREKT_PID = 0x0b11,
00192 PREMIERE_EIT_SPORT_PID = 0x0b12,
00193
00194 ATSC_PSIP_PID = 0x1ffb,
00195 };
00196
00200 class TableID
00201 {
00202 public:
00203 enum
00204 {
00205 PAT = 0x00,
00206 CAT = 0x01,
00207 PMT = 0x02,
00208 TSDT = 0x03,
00209
00210
00211 NIT = 0x40,
00212 SDT = 0x42,
00213 PF_EIT = 0x4e,
00214 TDT = 0x70,
00215
00216
00217 NITo = 0x41,
00218 SDTo = 0x46,
00219 BAT = 0x4a,
00220 PF_EITo = 0x4f,
00221 SC_EITbeg = 0x50,
00222 SC_EITend = 0x5f,
00223 SC_EITbego = 0x60,
00224 SC_EITendo = 0x6f,
00225 RST = 0x71,
00226 ST = 0x72,
00227 TOT = 0x73,
00228 RNT = 0x74,
00229 CT = 0x75,
00230 RCT = 0x76,
00231 CIT = 0x77,
00232 MPEFEC = 0x78,
00233 DIT = 0x7e,
00234 SIT = 0x7f,
00235
00236
00237 DVBCAbeg = 0x80,
00238 DVBCAend = 0x8f,
00239
00240
00241 DN_EITbego = 0x80,
00242 DN_EITendo = 0xfe,
00243
00244
00245 ARIBbeg = 0x80,
00246 ARIBend = 0x8f,
00247
00248
00249 PIM = 0xC0,
00250 PNM = 0xC1,
00251 NIM = 0xC2,
00252
00253 NITscte = 0xC2,
00254 NTM = 0xC3,
00255
00256
00257 NTT = 0xC3,
00258 VCM = 0xC4,
00259
00260 SVCTscte = 0xC4,
00261 STM = 0xC5,
00262
00263 STTscte = 0xC5,
00264 SM = 0xC6,
00265 MGTscte = 0xC7,
00266 LVCT = 0xC9,
00267 RRTscte = 0xCA,
00268
00269 CEA = 0xD8,
00270 ADET = 0xD9,
00271
00272
00273 ECM0 = 0x80,
00274 ECM1 = 0x81,
00275 ECMbeg = 0x82,
00276 ECMend = 0x8f,
00277
00278
00279 MGT = 0xC7,
00280 TVCT = 0xC8,
00281 CVCT = 0xC9,
00282 RRT = 0xCA,
00283 EIT = 0xCB,
00284 ETT = 0xCC,
00285 STT = 0xCD,
00286 DET = 0xCE,
00287 DST = 0xCF,
00288
00289 PIT = 0xD0,
00290 NRT = 0xD1,
00291 LTST = 0xD2,
00292 DCCT = 0xD3,
00293 DCCSCT = 0xD4,
00294 SITatsc = 0xD5,
00295 AEIT = 0xD6,
00296 AETT = 0xD7,
00297 SVCT = 0xDA,
00298
00299 SRM = 0xE0,
00300
00301
00302 STUFFING = 0x80,
00303 CAPTION = 0x86,
00304 CENSOR = 0x87,
00305
00306
00307 PREMIERE_CIT = 0xA0,
00308 PREMIERE_CPT = 0xA1,
00309
00310 ECN = 0xA0,
00311 SRVLOC = 0xA1,
00312 TSS = 0xA2,
00313 CMPNAME = 0xA3,
00314 };
00315 };
00316
00321 class PSIPTable : public PESPacket
00322 {
00323 private:
00324
00325 PSIPTable(const PESPacket& pkt, bool)
00326 : PESPacket(reinterpret_cast<const TSPacket*>(pkt.tsheader()), false)
00327 { ; }
00328 public:
00329 PSIPTable(const PSIPTable& table) : PESPacket(table)
00330 {
00331
00332
00333 }
00334 PSIPTable(const PESPacket& table) : PESPacket(table)
00335 {
00336
00337
00338 }
00339 PSIPTable(const TSPacket& table) : PESPacket(table)
00340 {
00341
00342
00343 }
00344
00345
00346 static const PSIPTable View(const TSPacket& tspacket)
00347 { return PSIPTable(PESPacket::View(tspacket), false); }
00348
00349 static PSIPTable View(TSPacket& tspacket)
00350 { return PSIPTable(PESPacket::View(tspacket), false); }
00351
00352
00353
00354
00355 uint TableID(void) const { return StreamID(); }
00356
00357
00358 bool SectionSyntaxIndicator(void) const { return pesdata()[1] & 0x80; }
00359
00360 bool PrivateIndicator(void) const { return pesdata()[1] & 0x40; }
00361
00362
00363
00364
00365
00366 uint SectionLength(void) const { return Length() + 3; }
00367
00368
00369 uint TableIDExtension(void) const
00370 { return (pesdata()[3]<<8) | pesdata()[4]; }
00371
00372
00373
00374
00375
00376 uint Version(void) const { return (pesdata()[5]>>1) & 0x1f; }
00377
00378
00379
00380
00381
00382 bool IsCurrent(void) const { return bool(pesdata()[5]&1); }
00383
00384
00385 uint Section(void) const { return pesdata()[6]; }
00386
00387
00388 uint LastSection(void) const { return pesdata()[7]; }
00389
00390
00391
00392 uint ProtocolVersion(void) const { return pesdata()[8]; }
00393
00394
00395 const unsigned char* psipdata(void) const
00396 { return pesdata() + PSIP_OFFSET; }
00397 unsigned char* psipdata(void)
00398 { return pesdata() + PSIP_OFFSET; }
00399
00400
00401 void SetTableID(uint id) { SetStreamID(id); }
00402
00403
00404 void SetSectionLength(uint length) { SetLength(length-3); }
00405 void SetTableIDExtension(uint len)
00406 {
00407 pesdata()[3] = (len>>8) & 0xff;
00408 pesdata()[4] = len & 0xff;
00409 }
00410 void SetVersionNumber(uint ver)
00411 { pesdata()[5] = (pesdata()[5] & 0xc1) | ((ver & 0x1f)<<1); }
00412 void SetCurrent(bool cur)
00413 { pesdata()[5] = (pesdata()[5] & 0xfe) | (cur ? 1 : 0); }
00414 void SetSection(uint num) { pesdata()[6] = num; }
00415 void SetLastSection(uint num) { pesdata()[7] = num; }
00416
00417
00418 void SetProtocolVersion(int ver) { pesdata()[8] = ver; }
00419
00420 bool HasCRC(void) const;
00421
00422 bool VerifyPSIP(bool verify_crc) const;
00423
00424 const QString toString(void) const;
00425
00426 static const uint PSIP_OFFSET = 8;
00427 };
00428
00447 class ProgramAssociationTable : public PSIPTable
00448 {
00449 public:
00450 ProgramAssociationTable(const ProgramAssociationTable& table)
00451 : PSIPTable(table)
00452 {
00453 assert(TableID::PAT == TableID());
00454 }
00455
00456 ProgramAssociationTable(const PSIPTable &table) : PSIPTable(table)
00457 {
00458 assert(TableID::PAT == TableID());
00459 }
00460
00461
00462 static ProgramAssociationTable* Create(uint tsid, uint version,
00463 const vector<uint>& pnum,
00464 const vector<uint>& pid);
00465
00466 uint TransportStreamID(void) const { return TableIDExtension(); }
00467
00468 uint ProgramCount(void) const
00469 {
00470 if (SectionLength() > (PSIP_OFFSET+2))
00471 return (SectionLength()-PSIP_OFFSET-2)>>2;
00472 return 0;
00473 }
00474
00475 uint ProgramNumber(uint i) const
00476 { return (psipdata()[(i<<2)] << 8) | psipdata()[(i<<2) + 1]; }
00477
00478 uint ProgramPID(uint i) const
00479 {
00480 return (((psipdata()[(i<<2) + 2] & 0x1f) << 8) |
00481 psipdata()[(i<<2) + 3]);
00482 }
00483
00484 void SetTranportStreamID(uint gtsid) { SetTableIDExtension(gtsid); }
00485
00486
00487 uint FindPID(uint progNum) const
00488 {
00489 for (uint i = 0; i < ProgramCount(); i++)
00490 if (progNum==ProgramNumber(i))
00491 return ProgramPID(i);
00492 return 0;
00493 }
00494 uint FindAnyPID(void) const
00495 {
00496 for (uint i = 0; i < ProgramCount(); i++)
00497 if (0!=ProgramNumber(i))
00498 return ProgramPID(i);
00499 return 0;
00500 }
00501 uint FindProgram(uint pid) const
00502 {
00503 for (uint i = 0; i < ProgramCount(); i++)
00504 if (pid==ProgramPID(i))
00505 return ProgramNumber(i);
00506 return 0;
00507 }
00508
00509 const QString toString(void) const;
00510
00511 private:
00512 static ProgramAssociationTable* CreateBlank(bool smallPacket = true);
00513 };
00514
00520 class ProgramMapTable : public PSIPTable
00521 {
00522 public:
00523
00524 ProgramMapTable(const ProgramMapTable& table) : PSIPTable(table)
00525 {
00526 assert(TableID::PMT == TableID());
00527 Parse();
00528 }
00529
00530 ProgramMapTable(const PSIPTable& table) : PSIPTable(table)
00531 {
00532 assert(TableID::PMT == TableID());
00533 Parse();
00534 }
00535
00536 static ProgramMapTable* Create(uint programNumber, uint basepid,
00537 uint pcrpid, uint version,
00538 vector<uint> pids, vector<uint> types);
00539
00540 static ProgramMapTable* Create(uint programNumber, uint basepid,
00541 uint pcrpid, uint version,
00542 const desc_list_t &global_desc,
00543 const vector<uint> &pids,
00544 const vector<uint> &types,
00545 const vector<desc_list_t> &prog_desc);
00546
00548 uint PCRPID(void) const
00549 { return ((psipdata()[0] << 8) | psipdata()[1]) & 0x1fff; }
00550
00551 uint ProgramNumber(void) const
00552 { return TableIDExtension(); }
00553
00554 uint ProgramInfoLength(void) const
00555 { return ((psipdata()[2]<<8) | psipdata()[3]) & 0x0fff; }
00556
00557 const unsigned char* ProgramInfo(void) const
00558 { return psipdata() + 4; }
00559
00560 uint StreamType(uint i) const
00561 { return _ptrs[i][0]; }
00562
00563 uint StreamPID(uint i) const
00564 { return ((_ptrs[i][1] << 8) | _ptrs[i][2]) & 0x1fff; }
00565
00566 uint StreamInfoLength(uint i) const
00567 { return ((_ptrs[i][3] << 8) | _ptrs[i][4]) & 0x0fff; }
00568
00569 const unsigned char* StreamInfo(uint i) const
00570 { return _ptrs[i] + 5; }
00571
00572 uint StreamCount(void) const
00573 { return (_ptrs.size()) ? _ptrs.size()-1 : 0; }
00574
00575
00576 void SetPCRPID(uint pid)
00577 {
00578 psipdata()[0] = ((pid >> 8) & 0x1F) | (psipdata()[0] & 0xE0);
00579 psipdata()[1] = (pid & 0xFF);
00580 }
00581
00582 void SetProgramNumber(uint num) { SetTableIDExtension(num); }
00583
00584 void SetStreamPID(uint i, uint pid)
00585 {
00586 _ptrs[i][1] = ((pid>>8) & 0x1f) | (_ptrs[i][1] & 0xe0);
00587 _ptrs[i][2] = pid & 0xff;
00588 }
00589
00590 void SetStreamType(uint i, uint type)
00591 { _ptrs[i][0] = type; }
00592
00593
00594 bool IsVideo(uint i, QString sistandard) const;
00595 bool IsAudio(uint i, QString sistandard) const;
00596 bool IsEncrypted(void) const;
00597 bool IsProgramEncrypted(void) const;
00598 bool IsStreamEncrypted(uint pid) const;
00600 bool IsStillPicture(QString sistandard) const;
00602 QString StreamTypeString(uint i) const
00603 { return StreamID::toString(StreamType(i)); }
00606 QString StreamDescription(uint i, QString sistandard) const;
00608 QString GetLanguage(uint i) const;
00609
00610 uint FindPIDs(uint type, vector<uint> &pids,
00611 const QString &sistandard) const;
00612 uint FindPIDs(uint type, vector<uint> &pids, vector<uint> &types,
00613 const QString &sistandard, bool normalize) const;
00614
00617 int FindPID(uint pid) const
00618 {
00619 for (uint i = 0; i < StreamCount(); i++)
00620 if (pid == StreamPID(i))
00621 return i;
00622 return -1;
00623 }
00624 uint FindUnusedPID(uint desired_pid = 0x20);
00625
00626 void RemoveAllStreams(void)
00627 {
00628 memset(psipdata(), 0xff, pmt_header);
00629 SetProgramInfoLength(0);
00630 _ptrs.clear();
00631 }
00632 void AppendStream(uint pid, uint type, unsigned char* si = 0, uint il = 0);
00633
00634 void Parse(void) const;
00635 const QString toString(void) const;
00636
00637 private:
00638 void SetStreamInfoLength(uint i, uint length)
00639 {
00640 _ptrs[i][3] = ((length>>8) & 0x0f) | (_ptrs[i][3] & 0xf0);
00641 _ptrs[i][4] = length & 0xff;
00642 }
00643
00644 void SetStreamProgramInfo(uint i, unsigned char* streamInfo,
00645 uint infoLength)
00646 {
00647 SetStreamInfoLength(i, infoLength);
00648 memcpy(_ptrs[i] + 5, streamInfo, infoLength);
00649 }
00650
00651 void SetProgramInfoLength(uint length)
00652 {
00653 psipdata()[2] = ((length<<8) & 0x0f) | (psipdata()[2] & 0xf0);
00654 psipdata()[3] = length & 0xff;
00655 }
00656
00657 void SetProgramInfo(unsigned char *streamInfo, uint infoLength)
00658 {
00659 SetProgramInfoLength(infoLength);
00660 memcpy(psipdata() + 4, streamInfo, infoLength);
00661 }
00662
00663 static ProgramMapTable* CreateBlank(bool smallPacket = true);
00664
00665 static const uint pmt_header = 4;
00666 mutable vector<unsigned char*> _ptrs;
00667 };
00668
00673 class ConditionalAccessTable : public PSIPTable
00674 {
00675 public:
00676 ConditionalAccessTable(const PSIPTable &table) : PSIPTable(table)
00677 {
00678
00679
00680
00681 assert(TableID::CAT == TableID());
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 }
00693
00694
00695
00696 uint DescriptorsLength(void) const
00697 { return SectionLength() - PSIP_OFFSET; }
00698 const unsigned char *Descriptors(void) const { return psipdata(); }
00699
00700
00701 };
00702
00712 class AdaptationFieldControl
00713 {
00714 public:
00715 AdaptationFieldControl(const unsigned char* packet) : _data(packet) { ; }
00716
00720 uint Length(void) const { return _data[0]; }
00721
00725 bool Discontinuity(void) const { return _data[1] & 0x80; }
00726
00727 bool RandomAccess(void) const { return bool(_data[1] & 0x40); }
00728
00729 bool Priority(void) const { return bool(_data[1] & 0x20); }
00730
00731
00732
00736 bool PCR(void) const { return bool(_data[1] & 0x10); }
00740 bool OPCR(void) const { return bool(_data[1] & 0x08); }
00748 bool SplicingPoint(void) const { return bool(_data[1] & 0x04); }
00749
00750
00751 bool PrivateTransportData(void) const { return bool(_data[1] & 0x02); }
00752
00753 bool FieldExtension(void) const { return bool(_data[1] & 0x1); }
00754
00755 uint ExtensionLength(void) const { return _data[2]; }
00756
00757
00758 bool LTW(void) const { return bool(_data[3] & 0x80); }
00759
00760 bool PiecewiseRate(void) const { return bool(_data[3] & 0x40); }
00761
00762 bool SeamlessSplice(void) const { return bool(_data[3] & 0x20); }
00763
00764
00765 private:
00766 const unsigned char* _data;
00767 };
00768
00769 #endif