|
MythTV
0.26-pre
|
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
1.7.6.1