MythTV master
mpegtables.cpp
Go to the documentation of this file.
1// -*- Mode: c++ -*-
2// Copyright (c) 2003-2004, Daniel Thor Kristjansson
3
4#include <QChar>
5#include <QMap>
6#include <QString>
7#include <QTime>
8#include <algorithm>
9
12
13#include "atscdescriptors.h"
14#include "mpegtables.h"
15#include "splicedescriptors.h"
16
17const std::array<const uint8_t,8> DEFAULT_PAT_HEADER
18{
19 0x00, // TableID::PAT
20 0xb0, // Syntax indicator
21 0x00, // Length (set separately)
22 0x00, // Transport stream ID top bits
23
24 0x00, // Transport stream ID bottom bits
25 0xc1, // current | reserved
26 0x00, // Current Section
27 0x00, // Last Section
28};
29
30const std::array<const uint8_t,12> DEFAULT_PMT_HEADER
31{
32 0x02, // TableID::PMT
33 0xb0, // Syntax indicator
34 0x00, // Length (set separately)
35 0x00, // MPEG Program number top bits (set separately)
36
37 0x00, // MPEG Program number bottom bits (set separately)
38 0xc1, // Version + Current/Next
39 0x00, // Current Section
40 0x00, // Last Section
41 0xff, 0xff, // PCR pid
42 0x00, 0x00, // Program Info Length
43};
44
45static const std::array<const uint,4> len_for_alloc
46{
48 - 1 /* for start of field pointer */
49 - 3 /* for data before data last byte of pes length */,
50 4000,
51};
52
54 const QString &sistandard)
55{
56 if ((sistandard != "dvb") && (OpenCableVideo == stream_id))
57 return MPEG2Video;
58
59 /* normalize DVB style signalling to ATSC style signalling to make
60 * IsAudio work with either, see A/52:2010 A4 vs A5 */
62 return AC3Audio;
63
64 /* normalize DVB style signalling to ATSC style signalling to make
65 * IsAudio work with either */
67 return EAC3Audio;
68
69 QString reg;
70 const unsigned char *d = MPEGDescriptor::Find(
72 if (d)
73 {
75 if (rd.IsValid())
76 reg = rd.FormatIdentifierString();
77 }
78
79 /* normalize all three DTS frame sizes, via http://www.smpte-ra.org/mpegreg/mpegreg.html */
80 if ((reg == "DTS1") || (reg == "DTS2") || (reg == "DTS3"))
81 return DTSAudio;
82
83 /* normalize AC-3 signalling according to A/52:2010 A4 */
84 if (reg == "AC-3")
85 return AC3Audio;
86
87 /* normalize E-AC-3 signalling with guesswork via http://www.smpte-ra.org/mpegreg/mpegreg.html */
88 if (reg == "EAC3")
89 return EAC3Audio;
90
91#if 0
92 // not needed while there is no specific stream id for these
95 return stream_id;
96#endif
97
98 return stream_id;
99}
100
101bool PSIPTable::HasCRC(void) const
102{
103 // default is false, but gets set to true for 0x80-0xfe at the end!
104 bool has_crc = false;
105
106 switch (TableID())
107 {
108 // MPEG
109 case TableID::PAT: // NOLINT(bugprone-branch-clone)
110 case TableID::CAT:
111 case TableID::PMT:
112 has_crc = true;
113 break;
114// case TableID::TSDT
115
116 // DVB mandatory
117 case TableID::NIT:
118 case TableID::SDT:
119 case TableID::PF_EIT:
120 has_crc = true;
121 break;
122 case TableID::TDT:
123 has_crc = false;
124 break;
125
126 // DVB optional
127 case TableID::NITo:
128 case TableID::SDTo:
129 case TableID::BAT:
130 case TableID::PF_EITo:
131 has_crc = true;
132 break;
133 case TableID::RST:
134 case TableID::ST:
135 has_crc = false;
136 break;
137 case TableID::TOT:
138 has_crc = true;
139 break;
140// case TableID::RNT:
141// case TableID::CT:
142// case TableID::RCT:
143// case TableID::CIT:
144// case TableID::MPEFEC:
145 case TableID::DIT:
146 has_crc = false;
147 break;
148 case TableID::SIT: // NOLINT(bugprone-branch-clone)
149 has_crc = true;
150 break;
151
152 // SCTE
153 case TableID::NITscte:
154 case TableID::NTT:
156 case TableID::STTscte:
157 case TableID::SITscte:
158 has_crc = true;
159 break;
160 case TableID::ADET:
161 has_crc = false;
162 break;
163
164 // ATSC
165 case TableID::MGT:
166 case TableID::TVCT:
167 case TableID::CVCT:
168 case TableID::RRT:
169 case TableID::EIT:
170 case TableID::ETT:
171 case TableID::STT:
172 case TableID::DET:
173 case TableID::DST:
174
175 //case TableID::PIT:
176 case TableID::NRT:
177 case TableID::LTST:
178 case TableID::DCCT:
179 case TableID::DCCSCT:
180 //case TableID::SITatsc:
181 case TableID::AEIT:
182 case TableID::AETT:
183 case TableID::SVCT:
184 has_crc = true;
185 break;
186
187 default:
188 {
189 // DVB Longterm EIT data
190 if (TableID::SC_EITbeg <= TableID() &&
192 {
193 has_crc = true;
194 }
195
196 // FIXME Dishnet Longterm EIT data, only on PID 0x300! Forces
197 // table_id 0x80-0xfe to true, unless handled before or after!
198 if (TableID::DN_EITbego <= TableID() &&
200 {
201 has_crc = true;
202 }
203
204 // ATSC/DVB conditional access ECM/EMM, reset to false after Dishnet
205 if (TableID::ECM0 <= TableID() &&
207 {
208 has_crc = false;
209 }
210 }
211 break;
212 }
213
214 return has_crc;
215}
216
218{
219 bool has_sn = false;
220 switch (TableID())
221 {
222 // MPEG
223 case TableID::PAT:
224 case TableID::CAT:
225 case TableID::PMT:
226 // ATSC
227 case TableID::MGT:
228 case TableID::TVCT:
229 case TableID::CVCT:
230 case TableID::RRT:
231 case TableID::EIT:
232 case TableID::ETT:
233 case TableID::STT:
234 case TableID::DET:
235 case TableID::DST:
236 has_sn = true;
237 break;
238 }
239
240 return has_sn;
241}
242
243bool PSIPTable::VerifyPSIP(bool verify_crc) const
244{
245 if (verify_crc && (CalcCRC() != CRC()))
246 {
247 LOG(VB_SIPARSER, LOG_ERR,
248 QString("PSIPTable: Failed CRC check 0x%1 != 0x%2 "
249 "for TableID = 0x%3")
250 .arg(CRC(),0,16).arg(CalcCRC(),0,16).arg(TableID(),0,16));
251 return false;
252 }
253
254 unsigned char *bufend = m_fullBuffer + m_allocSize;
255
256 if ((m_pesData + 2) >= bufend)
257 return false; // can't query length
258
259 if (psipdata() >= bufend)
260 return false; // data outside buffer
261
262 if (TableID::PAT == TableID())
263 {
264 uint pcnt = (SectionLength() - kPsipOffset - 2) >> 2;
265 bool ok = (psipdata() + (pcnt << 2) + 3 < bufend);
266 if (!ok)
267 {
268 LOG(VB_SIPARSER, LOG_ERR,
269 "PSIPTable: PAT: program list extends past end of buffer");
270 return false;
271 }
272
273 if ((Length() == 0xfff) && (TableIDExtension() == 0xffff) &&
274 (Section() == 0xff) && (LastSection() == 0xff))
275 {
276 LOG(VB_SIPARSER, LOG_ERR, "PSIPTable: PAT: All values at maximums");
277 return false;
278 }
279
280 return true;
281 }
282
283 if (TableID::PMT == TableID())
284 {
285 if (psipdata() + 3 >= bufend)
286 {
287 LOG(VB_SIPARSER, LOG_ERR,
288 "PSIPTable: PMT: can't query program info length");
289 return false;
290 }
291
292 if (psipdata() + Length() - 9 > bufend)
293 {
294 LOG(VB_SIPARSER, LOG_ERR,
295 "PSIPTable: PMT: reported length too large");
296 return false;
297 }
298
299 uint proginfolen = ((psipdata()[2]<<8) | psipdata()[3]) & 0x0fff;
300 const unsigned char *proginfo = psipdata() + 4;
301 const unsigned char *cpos = proginfo + proginfolen;
302 if (cpos > bufend)
303 {
304 LOG(VB_SIPARSER, LOG_ERR,
305 "PSIPTable: PMT: program info extends past end of buffer");
306 return false;
307 }
308
309 const unsigned char *pos = cpos;
310 uint i = 0;
311 for (; pos < psipdata() + Length() - 9; i++)
312 {
313 const unsigned char *ptr = pos;
314 if (pos + 4 > bufend)
315 {
316 LOG(VB_SIPARSER, LOG_ERR,
317 QString("PSIPTable: PMT: stream info %1 extends "
318 "past end of buffer").arg(i));
319 return false;
320 }
321 pos += 5 + (((ptr[3] << 8) | ptr[4]) & 0x0fff);
322 }
323 if (pos > bufend)
324 {
325 LOG(VB_SIPARSER, LOG_ERR,
326 QString("PSIPTable: PMT: last stream info %1 extends "
327 "past end of buffer").arg(i));
328 return false;
329 }
330
331 return true;
332 }
333
334 return true;
335}
336
338{
340 auto *dst = tspacket->data() + sizeof(TSHeader) + 1; /* start of field pointer */
342 PSIPTable psip = PSIPTable::View(*tspacket);
344 - 1 /* for start of field pointer */
345 - 3 /* for data before data last byte of pes length */);
346 auto *pat = new ProgramAssociationTable(psip);
347 pat->SetTotalLength(DEFAULT_PAT_HEADER.size());
348 delete tspacket;
349 return pat;
350}
351
353 uint tsid, uint version,
354 const std::vector<uint>& pnum, const std::vector<uint>& pid)
355{
356 const uint count = std::min(pnum.size(), pid.size());
359 pat->SetTranportStreamID(tsid);
360 pat->SetTotalLength(kPsipOffset + (count * 4));
361
362 // create PAT data
363 if ((count * 4) >= (184 - (kPsipOffset+1)))
364 { // old PAT must be in single TS for this create function
365 LOG(VB_GENERAL, LOG_ERR,
366 "PAT::Create: Error, old PAT size exceeds maximum PAT size.");
367 delete pat;
368 return nullptr;
369 }
370
371 uint offset = kPsipOffset;
372 for (uint i = 0; i < count; i++)
373 {
374 // pnum
375 pat->pesdata()[offset++] = pnum[i]>>8;
376 pat->pesdata()[offset++] = pnum[i] & 0xff;
377 // pid
378 pat->pesdata()[offset++] = ((pid[i]>>8) & 0x1f) | 0xe0;
379 pat->pesdata()[offset++] = pid[i] & 0xff;
380 }
381
382 pat->Finalize();
383
384 return pat;
385}
386
388{
389 ProgramMapTable *pmt = nullptr;
391 auto *dst = tspacket->data() + sizeof(TSHeader) + 1; /* start of field pointer */
393
394 if (smallPacket)
395 {
396 PSIPTable psip = PSIPTable::View(*tspacket);
397 psip.SetLength(len_for_alloc[0]);
398 pmt = new ProgramMapTable(psip);
399 }
400 else
401 {
402 PSIPTable psip(*tspacket);
403 psip.SetLength(len_for_alloc[1]);
404 pmt = new ProgramMapTable(psip);
405 }
406
408 delete tspacket;
409 return pmt;
410}
411
413 uint programNumber, uint basepid, uint pcrpid, uint version,
414 std::vector<uint> pids, std::vector<uint> types)
415{
416 const uint count = std::min(pids.size(), types.size());
417 ProgramMapTable* pmt = CreateBlank(false);
418 pmt->tsheader()->SetPID(basepid);
419
420 pmt->RemoveAllStreams();
421 pmt->SetProgramNumber(programNumber);
422 pmt->SetPCRPID(pcrpid);
424
425 for (uint i=0; i<count; i++)
426 pmt->AppendStream(pids[i], types[i]);
427 pmt->Finalize();
428
429 return pmt;
430}
431
433 uint programNumber, uint basepid, uint pcrpid, uint version,
434 const desc_list_t &global_desc,
435 const std::vector<uint> &pids,
436 const std::vector<uint> &types,
437 const std::vector<desc_list_t> &prog_desc)
438{
439 const uint count = std::min(pids.size(), types.size());
440 ProgramMapTable* pmt = CreateBlank(false);
441 pmt->tsheader()->SetPID(basepid);
442
443 pmt->RemoveAllStreams();
444 pmt->SetProgramNumber(programNumber);
445 pmt->SetPCRPID(pcrpid);
447
448 std::vector<unsigned char> gdesc;
449 for (const auto *gd : global_desc)
450 {
451 uint len = gd[1] + 2;
452 gdesc.insert(gdesc.end(), gd, gd + len);
453 }
454 pmt->SetProgramInfo(gdesc.data(), gdesc.size());
455
456 for (uint i = 0; i < count; i++)
457 {
458 std::vector<unsigned char> pdesc;
459 for (const auto *pd : prog_desc[i])
460 {
461 uint len = pd[1] + 2;
462 pdesc.insert(pdesc.end(), pd, pd + len);
463 }
464
465 pmt->AppendStream(pids[i], types[i], pdesc.data(), pdesc.size());
466 }
467 pmt->Finalize();
468
469 LOG(VB_SIPARSER, LOG_INFO, "Created PMT \n" + pmt->toString());
470
471 return pmt;
472}
473
475{
476 m_ptrs.clear();
477 const unsigned char *cpos = psipdata() + kPmtHeaderMinOffset + ProgramInfoLength();
478 auto *pos = const_cast<unsigned char*>(cpos);
479 for (uint i = 0; pos < psipdata() + Length() - 9; i++)
480 {
481 m_ptrs.push_back(pos);
482 pos += 5 + StreamInfoLength(i);
483#if 0
484 LOG(VB_SIPARSER, LOG_DEBUG, QString("Parsing PMT(0x%1) i(%2) len(%3)")
485 .arg((uint64_t)this, 0, 16) .arg(i) .arg(StreamInfoLength(i)));
486#endif
487 }
488 m_ptrs.push_back(pos);
489#if 0
490 LOG(VB_SIPARSER, LOG_DEBUG, QString("Parsed PMT(0x%1)\n%2")
491 .arg((uint64_t)this, 0, 16) .arg(toString()));
492#endif
493}
494
496 uint pid, uint type,
497 unsigned char* streamInfo, uint infoLength)
498{
499 if (!StreamCount())
501 memset(m_ptrs[StreamCount()], 0xff, 5);
504 SetStreamProgramInfo(StreamCount(), streamInfo, infoLength);
507}
508
519bool ProgramMapTable::IsVideo(uint i, const QString& sistandard) const
520{
522 return true;
523
526 uint stream_id = StreamID::Normalize(StreamType(i), list, sistandard);
527
528 return StreamID::IsVideo(stream_id);
529}
530
541bool ProgramMapTable::IsAudio(uint i, const QString& sistandard) const
542{
544 return true;
545
548 uint stream_id = StreamID::Normalize(StreamType(i), list, sistandard);
549
550 return StreamID::IsAudio(stream_id);
551}
552
557bool ProgramMapTable::IsEncrypted(const QString& sistandard) const
558{
559 bool encrypted = IsProgramEncrypted();
560
561 for (uint i = 0; !encrypted && i < StreamCount(); i++) {
562 /* Only check audio/video streams */
563 if (IsAudio(i,sistandard) || IsVideo(i,sistandard))
564 encrypted |= IsStreamEncrypted(i);
565 }
566
567 return encrypted;
568}
569
574{
577
578 uint encrypted = 0;
579 QMap<uint,uint> encryption_system;
580 for (auto & desc : descs)
581 {
583 if (!cad.IsValid())
584 continue;
585 encryption_system[cad.PID()] = cad.SystemID();
586 encrypted |= cad.SystemID();
587
588#if 0
589 LOG(VB_GENERAL, LOG_INFO, "DTVsm: " + cad.toString());
590#endif
591 }
592
593 return encrypted != 0;
594}
595
602{
605
606 uint encrypted = 0;
607 QMap<uint,uint> encryption_system;
608 for (auto & desc : descs)
609 {
611 if (!cad.IsValid())
612 continue;
613 encryption_system[cad.PID()] = cad.SystemID();
614 encrypted |= cad.SystemID();
615#if 0
616 LOG(VB_GENERAL, LOG_INFO, "DTVsm: " + cad.toString());
617#endif
618 }
619
620 return encrypted != 0;
621}
622
623bool ProgramMapTable::IsStillPicture(const QString& sistandard) const
624{
625 static constexpr unsigned char kStillPictureFlag = 0x01;
626
627 for (uint i = 0; i < StreamCount(); i++)
628 {
629 if (IsVideo(i, sistandard))
630 {
631 return StreamInfoLength(i) > 2 &&
633 ((StreamInfo(i)[2] & kStillPictureFlag) != 0);
634 }
635 }
636 return false;
637}
638
639
649 std::vector<uint> &pids,
650 const QString &sistandard) const
651{
653 {
654 for (uint i=0; i < StreamCount(); i++)
655 if (type == StreamType(i))
656 pids.push_back(StreamPID(i));
657 }
658 else if (StreamID::AnyVideo == type)
659 {
660 for (uint i=0; i < StreamCount(); i++)
661 if (IsVideo(i, sistandard))
662 pids.push_back(StreamPID(i));
663 }
664 else if (StreamID::AnyAudio == type)
665 {
666 for (uint i=0; i < StreamCount(); i++)
667 if (IsAudio(i, sistandard))
668 pids.push_back(StreamPID(i));
669 }
670
671 return pids.size();
672}
673
685 std::vector<uint> &pids,
686 std::vector<uint> &types,
687 const QString &sistandard,
688 bool normalize) const
689{
690 uint pids_start = pids.size();
691
693 {
694 for (uint i=0; i < StreamCount(); i++)
695 {
696 if (type == StreamType(i))
697 {
698 pids.push_back(StreamPID(i));
699 types.push_back(StreamType(i));
700 }
701 }
702 }
703 else if (StreamID::AnyVideo == type)
704 {
705 for (uint i=0; i < StreamCount(); i++)
706 {
707 if (IsVideo(i, sistandard))
708 {
709 pids.push_back(StreamPID(i));
710 types.push_back(StreamType(i));
711 }
712 }
713 }
714 else if (StreamID::AnyAudio == type)
715 {
716 for (uint i=0; i < StreamCount(); i++)
717 {
718 if (IsAudio(i, sistandard))
719 {
720 pids.push_back(StreamPID(i));
721 types.push_back(StreamType(i));
722 }
723 }
724 }
725
726 if (!normalize)
727 return pids.size();
728
729 for (size_t i = pids_start; i < pids.size(); i++)
730 {
731 int index = FindPID(pids[i]);
732 if (index >= 0)
733 {
736 types[i] = StreamID::Normalize(types[i], desc, sistandard);
737 }
738 }
739
740 return pids.size();
741}
742
744{
745 uint pid = desired_pid;
746 if (pid >= PID::MPEG_NULL_PID)
747 pid = 0x20;
748
749 while (FindPID(pid) != -1)
750 pid += 0x10;
751
752 if (pid < PID::MPEG_NULL_PID)
753 return pid;
754
755 pid = desired_pid;
756 while (FindPID(pid) != -1)
757 pid += 1;
758
759 if (pid < PID::MPEG_NULL_PID)
760 return pid;
761
762 pid = 0x20;
763 while (FindPID(pid) != -1)
764 pid += 1;
765
766 return pid & 0x1fff;
767}
768
770{
771 if (tspacket.PayloadStart())
772 {
773 m_psiOffset = tspacket.AFCOffset() + tspacket.StartOfFieldPointer();
774 }
775 else
776 {
777 LOG(VB_GENERAL, LOG_ERR, "Started PESPacket, but !payloadStart()");
778 m_psiOffset = tspacket.AFCOffset();
779 }
780 m_pesData = tspacket.data() + m_psiOffset + 1;
781
782 m_badPacket = true;
783 // first check if Length() will return something useful and
784 // then check if the packet ends in the first TSPacket
785 if ((m_pesData - tspacket.data()) <= (188-3) &&
786 (m_pesData + Length() - tspacket.data()) <= (188-3))
787 {
789 }
790}
791
792QString PSIPTable::toString(void) const
793{
794 QString str;
795 str.append(QString(" PSIP tableID(0x%1) length(%2) extension(0x%3)\n")
796 .arg(TableID(), 0, 16).arg(Length())
797 .arg(TableIDExtension(), 0, 16));
798 str.append(QString(" version(%1) current(%2) "
799 "section(%3) last_section(%4)\n")
800 .arg(Version()).arg(static_cast<int>(IsCurrent()))
801 .arg(Section()).arg(LastSection()));
802 if ((TableID() >= TableID::MGT) && (TableID() <= TableID::SRM))
803 {
804 str.append(QString(" atsc_protocol_version(%1)\n")
805 .arg(ATSCProtocolVersion()));
806 }
807 return str;
808}
809
810QString PSIPTable::toStringXML(uint indent_level) const
811{
812 QString indent = StringUtil::indentSpaces(indent_level);
813 return indent + "<PSIPSection " + XMLValues(indent_level + 1) + " />";
814}
815
816QString PSIPTable::XMLValues(uint indent_level) const
817{
818 QString indent = StringUtil::indentSpaces(indent_level);
819
820 QString str = QString(
821 R"(table_id="0x%1" length="%2")")
822 .arg(TableID(), 2, 16, QChar('0'))
823 .arg(Length());
824
825 if (HasSectionNumber())
826 {
827 str += QString(R"( section="%4" last_section="%5")")
828 .arg(Section()).arg(LastSection());
829 }
830
831 if ((TableID() >= TableID::MGT) && (TableID() <= TableID::SRM))
832 {
833 str += QString("\n%1version=\"%2\" current=\"%3\" "
834 "protocol_version=\"%4\" extension=\"0x%5\"")
835 .arg(indent)
837 .arg(ATSCProtocolVersion())
838 .arg(TableIDExtension(), 0, 16);
839 }
840
841 return str;
842}
843
845{
846 QString str;
847 str.append(QString("Program Association Section\n"));
848 str.append(PSIPTable::toString());
849 str.append(QString(" tsid(%1) ").arg(TransportStreamID()));
850 str.append(QString("programCount(%1)\n").arg(ProgramCount()));
851
852 uint cnt0 = 0;
853 uint cnt1fff = 0;
854 for (uint i = 0; i < ProgramCount(); i++)
855 {
856 if (0x1fff == ProgramPID(i))
857 {
858 cnt1fff++;
859 continue;
860 }
861
862 if (0x0 == ProgramPID(i))
863 {
864 cnt0++;
865 continue;
866 }
867
868 str += QString(" program number %1 has PID 0x%2\n")
869 .arg(ProgramNumber(i),5)
870 .arg(ProgramPID(i),4,16,QChar('0'));
871 }
872
873 if (cnt0 || cnt1fff)
874 {
875 str.append(QString(" also contains %1 dummy programs\n")
876 .arg(cnt0 + cnt1fff));
877 }
878
879 return str;
880}
881
883{
884 QString indent_0 = StringUtil::indentSpaces(indent_level);
885 QString indent_1 = StringUtil::indentSpaces(indent_level + 1);
886
887 QString str = QString(
888 "%1<ProgramAssociationSection tsid=\"0x%2\" program_count=\"%3\""
889 "\n%4%5>\n")
890 .arg(indent_0)
891 .arg(TransportStreamID(),4,16,QChar('0'))
892 .arg(ProgramCount())
893 .arg(indent_1,
894 PSIPTable::XMLValues(indent_level + 1));
895
896 for (uint i = 0; i < ProgramCount(); i++)
897 {
898 bool dummy = (0x1fff == ProgramPID(i)) || (0x0 == ProgramPID(i));
899 str += QString("%1<Program number=\"%2\" pid=\"0x%3\" %4/>\n")
900 .arg(indent_1)
901 .arg(ProgramNumber(i))
902 .arg(ProgramPID(i),4,16,QChar('0'))
903 .arg(dummy ? "comment=\"Dummy Program\" " : "");
904 }
905
906 return str + indent_0 + "</ProgramAssociationSection>";
907}
908
909QString ProgramMapTable::toString(void) const
910{
911 QString str =
912 QString("Program Map Section"
913 "\n%1"
914 " pnum(%2) pid(0x%3) pcrpid(0x%4)")
915 .arg(PSIPTable::toString())
916 .arg(ProgramNumber())
917 .arg(tsheader()->PID(),0,16)
918 .arg(PCRPID(),0,16);
919
920 std::vector<const unsigned char*> desc =
922 for (auto & d : desc)
923 {
924 str.append(QString("\n %1")
925 .arg(MPEGDescriptor(d, 300).toString()));
926 }
927
928 for (uint i = 0; i < StreamCount(); i++)
929 {
930 str.append(QString("\n Stream #%1 pid(0x%2) type(0x%3 %4)")
931 .arg(i).arg(StreamPID(i), 0, 16)
932 .arg(StreamType(i), 2, 16, QChar('0'))
933 .arg(StreamTypeString(i)));
935 for (auto & d : desc)
936 {
937 str.append(QString("\n %1")
938 .arg(MPEGDescriptor(d, 300).toString()));
939 }
940 }
941 return str;
942}
943
944QString ProgramMapTable::toStringXML(uint indent_level) const
945{
946 QString indent_0 = StringUtil::indentSpaces(indent_level);
947 QString indent_1 = StringUtil::indentSpaces(indent_level + 1);
948
949 QString str = QString(
950 "%1<ProgramMapSection pcr_pid=\"0x%2\" program_number=\"%3\"\n"
951 "%4program_info_length=\"%5\" stream_count=\"%7\"%8>\n")
952 .arg(indent_0)
953 .arg(PCRPID(),0,16)
954 .arg(ProgramNumber())
955 .arg(indent_1)
956 .arg(ProgramInfoLength())
957 .arg(StreamCount())
958 .arg(PSIPTable::XMLValues(indent_level + 1));
959
960 std::vector<const unsigned char*> gdesc =
962 for (auto & gd : gdesc)
963 {
964 str += MPEGDescriptor(gd, 300)
965 .toStringXML(indent_level + 1) + "\n";
966 }
967
968 for (uint i = 0; i < StreamCount(); i++)
969 {
970 str += QString("%1<Stream pid=\"0x%2\" type=\"0x%3\" "
971 "type_desc=\"%4\" stream_info_length=\"%5\"")
972 .arg(indent_1)
973 .arg(StreamPID(i),2,16,QChar('0'))
974 .arg(StreamType(i),2,16,QChar('0'))
975 .arg(StreamTypeString(i))
976 .arg(StreamInfoLength(i));
977 std::vector<const unsigned char*> ldesc =
979 str += (ldesc.empty()) ? " />\n" : ">\n";
980 for (auto & ld : ldesc)
981 {
982 str += MPEGDescriptor(ld, 300)
983 .toStringXML(indent_level + 2) + "\n";
984 }
985 if (!ldesc.empty())
986 str += indent_1 + "</Stream>\n";
987 }
988
989 return str + indent_0 + "</ProgramMapSection>";
990}
991
992const char *StreamID::toString(uint streamID)
993{
994 // valid for some ATSC/DVB stuff too
995 switch (streamID)
996 {
998 return "video-mpeg2";
1000 return "video-mpeg1";
1002 return "video-mpeg4";
1004 return "video-h264";
1006 return "video-h265";
1008 return "video-opencable";
1009
1010 // audio
1011 case StreamID::AC3Audio:
1012 return "audio-ac3"; // EIT, PMT
1014 return "audio-eac3"; // EIT, PMT
1016 return "audio-mp2-layer[1,2,3]"; // EIT, PMT
1018 return "audio-mp1-layer[1,2,3]"; // EIT, PMT
1020 return "audio-aac-latm"; // EIT, PMT
1022 return "audio-aac"; // EIT, PMT
1023 case StreamID::DTSAudio:
1024 return "audio-dts"; // EIT, PMT
1025
1026 // other
1027 case StreamID::PrivSec:
1028 return "private-sec";
1029 case StreamID::PrivData:
1030 return "private-data";
1031
1032 // DSMCC Object Carousel
1033 case StreamID::DSMCC_A:
1034 return "dsmcc-a encap";
1035 case StreamID::DSMCC_B:
1036 return "dsmcc-b std data";
1037 case StreamID::DSMCC_C:
1038 return "dsmcc-c NPD data";
1039 case StreamID::DSMCC_D:
1040 return "dsmcc-d data";
1041
1042 // Can be in any MPEG stream ATSC, DVB, or ARIB ; but defined in SCTE 35
1043 case StreamID::Splice:
1044 return "splice"; // PMT
1045
1046 //case TableID::STUFFING: XXX: Duplicate?
1047 // return "stuffing"; // optionally in any
1048 //case TableID::CENSOR: FIXME collides with StreamID::EAC3Audio
1049 // return "censor"; // EIT, optionally in PMT
1050 case TableID::ECN:
1051 return "extended channel name";
1052 case TableID::SRVLOC:
1053 return "service location"; // required in VCT
1054 case TableID::TSS: // other channels with same stuff
1055 return "time-shifted service";
1056 case TableID::CMPNAME:
1057 return "component name"; //??? PMT
1058 }
1059 return "unknown";
1060}
1061
1063{
1064 // valid for some ATSC/DVB stuff too
1065 switch (stream_id)
1066 {
1067 // video
1069 return "11172-2 MPEG-1 Video";
1071 return "13818-2 MPEG-2 Video";
1073 return "14492-2 MPEG-4 Video";
1075 return "H.264 Video";
1077 return "H.265 Video";
1079 return "OpenCable Video";
1080 case StreamID::VC1Video:
1081 return "VC-1 Video";
1082
1083 // audio
1085 return "11172-2 MPEG-1 Audio";
1087 return "13818-3 MPEG-2 Audio";
1089 return "13818-7 AAC MPEG-2 Audio";
1091 return "13818-3 AAC LATM MPEG-2 Audio";
1092 case StreamID::AC3Audio:
1093 return "AC3 Audio";
1095 return "E-AC3 Audio";
1096 case StreamID::DTSAudio:
1097 return "DTS Audio";
1098
1099 // DSMCC Object Carousel
1100 case StreamID::DSMCC:
1101 return "13818-1 DSM-CC";
1102 case StreamID::DSMCC_A:
1103 return "13818-6 DSM-CC Type A";
1104 case StreamID::DSMCC_B:
1105 return "13818-6 DSM-CC Type B";
1106 case StreamID::DSMCC_C:
1107 return "13818-6 DSM-CC Type C";
1108 case StreamID::DSMCC_D:
1109 return "13818-6 DSM-CC Type D";
1110 case StreamID::DSMCC_DL:
1111 return "13818-6 Download";
1113 return "13818-6 Metadata in PES";
1115 return "13818-6 Metadata in Sections";
1117 return "13818-6 Metadata in Data Carousel";
1119 return "13818-6 Metadata in Obj Carousel";
1121 return "13818-6 Metadata in Download";
1122
1123 // other
1124 case StreamID::PrivSec:
1125 return "13818-1 Private Sections";
1126 case StreamID::PrivData:
1127 return "13818-3 Private Data";
1128 case StreamID::MHEG:
1129 return "13522 MHEG";
1130 case StreamID::H222_1:
1131 return "ITU H.222.1";
1132 case StreamID::MPEG2Aux:
1133 return "13818-1 Aux & ITU H.222.0";
1135 return "14496-1 SL/FlexMux in PES";
1137 return "14496-1 SL/FlexMux in Sections";
1139 return "13818-10 IPMP";
1141 return "13818-10 IPMP2";
1142
1143 case AnyMask: return {};
1144 case AnyVideo: return "video";
1145 case AnyAudio: return "audio";
1146 }
1147
1148 return {};
1149}
1150
1152{
1155 const unsigned char *lang_desc = MPEGDescriptor::Find(
1157
1158 if (!lang_desc)
1159 return {};
1160
1161 ISO639LanguageDescriptor iso_lang(lang_desc);
1162 if (!iso_lang.IsValid())
1163 return "";
1164 return iso_lang.CanonicalLanguageString();
1165}
1166
1168{
1171 const unsigned char *lang_desc = MPEGDescriptor::Find(
1173
1174 if (!lang_desc)
1175 return 0;
1176
1177 ISO639LanguageDescriptor iso_lang(lang_desc);
1178 if (!iso_lang.IsValid())
1179 return 0;
1180
1181 // Hack for non-standard AD labelling on UK Satellite and Irish DTTV
1182 // Language string of 'nar' for narrative indicates an AD track
1183 if (iso_lang.AudioType() == 0x0 &&
1184 iso_lang.LanguageString() == "nar")
1185 return 0x03;
1186
1187 return iso_lang.AudioType();
1188}
1189
1190QString ProgramMapTable::StreamDescription(uint i, const QString& sistandard) const
1191{
1192 desc_list_t list;
1193
1195 uint type = StreamID::Normalize(StreamType(i), list, sistandard);
1196 QString desc = StreamID::toString(type);
1197 QString lang = GetLanguage(i);
1198
1199 if (!lang.isEmpty())
1200 desc += QString(" (%1)").arg(lang);
1201
1202 return desc;
1203}
1204
1206{
1207 QString str =
1208 QString("Conditional Access Section %1")
1209 .arg(PSIPTable::toString());
1210
1211 std::vector<const unsigned char*> gdesc =
1213 for (auto & gd : gdesc)
1214 str += " " + MPEGDescriptor(gd, 300).toString() + "\n";
1215
1216 return str;
1217}
1218
1220{
1221 QString indent_0 = StringUtil::indentSpaces(indent_level);
1222
1223 QString str =
1224 QString("%1<ConditionalAccessSection %3")
1225 .arg(indent_0,
1226 PSIPTable::XMLValues(indent_level + 1));
1227
1228 std::vector<const unsigned char*> gdesc =
1230 str += (gdesc.empty()) ? " />\n" : ">\n";
1231 for (auto & gd : gdesc)
1232 {
1233 str += MPEGDescriptor(gd, 300)
1234 .toStringXML(indent_level + 1) + "\n";
1235 }
1236 if (!gdesc.empty())
1237 str += indent_0 + "</ConditionalAccessSection>\n";
1238
1239 return str;
1240}
1241
1242QString SpliceTimeView::toString(int64_t first, int64_t last) const
1243{
1244 if (!IsTimeSpecified())
1245 return {"splice_time(N/A)"};
1246
1247 int64_t abs_pts_time = PTSTime();
1248 if ((first > 0) && (last > 0))
1249 {
1250 int64_t elapsed = abs_pts_time - first;
1251 elapsed = (elapsed < 0) ? elapsed + 0x1000000000LL : elapsed;
1252 QTime abs = QTime(0,0,0,0).addMSecs(elapsed/90);
1253
1254 elapsed = abs_pts_time - last; /* rel_pts_time */
1255 elapsed = (elapsed < 0) ? elapsed + 0x1000000000LL : elapsed;
1256 QTime rel = QTime(0,0,0,0).addMSecs(elapsed/90);
1257
1258 return QString("splice_time(pts: %1 abs: %2, rel: +%3)")
1259 .arg(QString::number(abs_pts_time),
1260 abs.toString("hh:mm:ss.zzz"),
1261 rel.toString("hh:mm:ss.zzz"));
1262 }
1263
1264 return QString("splice_time(pts: %1)").arg(abs_pts_time);
1265}
1266
1268 uint indent_level, int64_t first, int64_t last) const
1269{
1270 QString indent = StringUtil::indentSpaces(indent_level);
1271
1272 if (!IsTimeSpecified())
1273 return indent + "<SpliceTime />";
1274
1275 int64_t abs_pts_time = PTSTime();
1276
1277 QString abs_str;
1278 if (first > 0)
1279 {
1280 int64_t elapsed = abs_pts_time - first;
1281 elapsed = (elapsed < 0) ? elapsed + 0x1000000000LL : elapsed;
1282 QTime abs = QTime(0,0,0,0).addMSecs(elapsed/90);
1283 abs_str = QString("absolute=\"%1\" ")
1284 .arg(abs.toString("hh:mm:ss.zzz"));
1285 }
1286
1287 QString rel_str;
1288 if (last > 0)
1289 {
1290 int64_t elapsed = abs_pts_time - last; /* rel_pts_time */
1291 elapsed = (elapsed < 0) ? elapsed + 0x1000000000LL : elapsed;
1292 QTime rel = QTime(0,0,0,0).addMSecs(elapsed/90);
1293 rel_str = QString("relative=\"+%1\" ")
1294 .arg(rel.toString("hh:mm:ss.zzz"));
1295 }
1296
1297 return QString("%1<SpliceTime pts=\"%2\" %3%4/>")
1298 .arg(indent,QString::number(abs_pts_time),abs_str,rel_str);
1299}
1300
1303 const QString &/*codeWord*/)
1304{
1305 // TODO
1306 return nullptr;
1307}
1308
1310{
1311 m_epilog = nullptr;
1312 m_ptrs0.clear();
1313 m_ptrs1.clear();
1314
1315 if (TableID::SITscte != TableID())
1316 return false;
1317
1318 if (SpliceProtocolVersion() != 0)
1319 return false;
1320
1321 if (IsEncryptedPacket())
1322 return true; // it's "parsed" but you can't read encrypted portion
1323
1326 {
1327 m_epilog = pesdata() + 14;
1328 }
1329 else if (kSCTTimeSignal == type)
1330 {
1331 m_epilog = pesdata() + 14 + TimeSignal().size();
1332 }
1333 else if (kSCTSpliceSchedule == type)
1334 {
1335 uint splice_count = pesdata()[14];
1336 const unsigned char *cur = pesdata() + 15;
1337 for (uint i = 0; i < splice_count; i++)
1338 {
1339 m_ptrs0.push_back(cur);
1340 bool event_cancel = (cur[4] & 0x80) != 0;
1341 if (event_cancel)
1342 {
1343 m_ptrs1.push_back(nullptr);
1344 cur += 5;
1345 continue;
1346 }
1347 bool program_slice = (cur[5] & 0x40) != 0;
1348 uint component_count = cur[6];
1349 m_ptrs1.push_back(cur + (program_slice ? 10 : 7 * component_count));
1350 }
1351 if (splice_count)
1352 {
1353 bool duration = (m_ptrs0.back()[5] & 0x2) != 0;
1354 m_epilog = m_ptrs1.back() + (duration ? 9 : 4);
1355 }
1356 else
1357 {
1358 m_epilog = cur;
1359 }
1360 }
1361 else if (kSCTSpliceInsert == type)
1362 {
1363 m_ptrs1.push_back(pesdata() + 14);
1364 bool splice_cancel = (pesdata()[18] & 0x80) != 0;
1365 if (splice_cancel)
1366 {
1367 m_epilog = pesdata() + 19;
1368 }
1369 else
1370 {
1371 bool program_splice = (pesdata()[19] & 0x40) != 0;
1372 bool duration = (pesdata()[19] & 0x20) != 0;
1373 bool splice_immediate = (pesdata()[19] & 0x10) != 0;
1374 const unsigned char *cur = pesdata() + 20;
1375 if (program_splice && !splice_immediate)
1376 {
1377 cur += SpliceTimeView(cur).size();
1378 }
1379 else if (!program_splice)
1380 {
1381 uint component_count = pesdata()[20];
1382 cur = pesdata() + 21;
1383 for (uint i = 0; i < component_count; i++)
1384 {
1385 m_ptrs0.push_back(cur);
1386 cur += splice_immediate ?
1387 1 : 1 + SpliceTimeView(cur).size();
1388 }
1389 }
1390 m_ptrs1.push_back(cur);
1391 m_ptrs1.push_back(cur + (duration ? 5 : 0));
1392 }
1393 }
1394 else
1395 {
1396 m_epilog = nullptr;
1397 }
1398
1399 return m_epilog != nullptr;
1400}
1401
1403{
1404 uint alg = EncryptionAlgorithm();
1405 switch (alg)
1406 {
1407 case kNoEncryption: return "None";
1408 case kECB: return "DES-ECB";
1409 case kCBC: return "DES-CBC";
1410 case k3DES: return "3DES";
1411 default:
1412 return QString((alg<32) ? "Reserved(%1)" : "Private(%1)").arg(alg);
1413 }
1414}
1415
1417{
1419 switch (type)
1420 {
1421 case kSCTNull:
1422 return "Null";
1423 case kSCTSpliceSchedule:
1424 return "SpliceSchedule";
1425 case kSCTSpliceInsert:
1426 return "SpliceInsert";
1427 case kSCTTimeSignal:
1428 return "TimeSignal";
1430 return "BandwidthReservation";
1431 case kSCTPrivateCommand:
1432 return "Private";
1433 default:
1434 return QString("Reserved(%1)").arg(type);
1435 };
1436}
1437
1438QString SpliceInformationTable::toString(int64_t first, int64_t last) const
1439{
1440 QString str =
1441 QString("SpliceInformationSection enc_alg(%1) pts_adj(%2)")
1443 .arg(PTSAdjustment());
1444 str += IsEncryptedPacket() ? QString(" cw_index(%1)") : QString("");
1445 str += QString(" command_len(%1) command_type(%2) scte_pid(0x%3)")
1446 .arg(SpliceCommandLength())
1448 .arg(getSCTEPID(), 0, 16));
1449
1450 if (IsEncryptedPacket())
1451 return str;
1452
1453 switch (SpliceCommandType())
1454 {
1455 case kSCTSpliceSchedule:
1456 break;
1457 case kSCTSpliceInsert:
1458 {
1459 str += "\n " + SpliceInsert().toString(first, last);
1460 break;
1461 }
1462 case kSCTTimeSignal:
1463 break;
1464 }
1465
1466 return str;
1467}
1468
1469QString SpliceInsertView::toString(int64_t first, int64_t last) const
1470{
1471 QString str =
1472 QString("eventid(0x%1) cancel(%2) "
1473 "out_of_network(%3) program_splice(%4) "
1474 "duration(%5) immediate(%6)\n ")
1475 .arg(SpliceEventID(),0,16)
1476 .arg(IsSpliceEventCancel()?"yes":"no",
1477 IsOutOfNetwork()?"yes":"no",
1478 IsProgramSplice()?"yes":"no",
1479 IsDuration()?"yes":"no",
1480 IsSpliceImmediate()?"yes":"no");
1481
1483 str += SpliceTime().toString(first, last);
1484
1485 str += QString(" unique_program_id(%1)")
1486 .arg(UniqueProgramID());
1487
1488 str += QString(" avail(%1/%2)")
1489 .arg(AvailNum()).arg(AvailsExpected());
1490
1491 return str;
1492}
1493
1495 uint indent_level, int64_t first, int64_t last) const
1496{
1497 QString indent = StringUtil::indentSpaces(indent_level);
1498
1499 QString cap_time = "";
1500 if (first >= 0)
1501 {
1502 cap_time = QString("pts=\"%1\" ").arg(first);
1503 if (last >= 0)
1504 {
1505 QTime abs = QTime(0,0,0,0).addMSecs((last - first)/90);
1506 cap_time += QString("capture_time=\"%1\" ")
1507 .arg(abs.toString("hh:mm:ss.zzz"));
1508 }
1509 }
1510
1511 QString str = QString(
1512 "%1<SpliceInformationSection %2 encryption_algorithm=\"%3\" "
1513 "pts_adjustment=\"%4\" code_word_index=\"%5\" command_type=\"%6\" scte_pid=\"0x%7\" >\n")
1514 .arg(indent,
1515 cap_time,
1517 .arg(PTSAdjustment())
1518 .arg(CodeWordIndex())
1520 .arg(getSCTEPID(), 0 ,16);
1521
1522 if (IsEncryptedPacket())
1523 return str + indent + "</SpliceInformationSection>";
1524
1525 switch (SpliceCommandType())
1526 {
1527 case kSCTSpliceSchedule:
1528 break;
1529 case kSCTSpliceInsert:
1530 {
1531 str += SpliceInsert().toStringXML(indent_level + 1, first, last);
1532 str += "\n";
1533 break;
1534 }
1535 case kSCTTimeSignal:
1536 break;
1537 }
1538
1539 str += indent + "</SpliceInformationSection>";
1540 return str;
1541}
1542
1544 uint indent_level, int64_t first, int64_t last) const
1545{
1546 QString indent_0 = StringUtil::indentSpaces(indent_level);
1547 QString indent_1 = StringUtil::indentSpaces(indent_level + 1);
1548 QString str = QString(
1549 "%1<SpliceInsert eventid=\"0x%2\" cancel=\"%3\"\n")
1550 .arg(indent_0)
1551 .arg(SpliceEventID(),0,16)
1553
1554 str += QString(
1555 "%1out_of_network=\"%2\" program_splice=\"%3\" duration=\"%4\"\n")
1556 .arg(indent_1,
1560
1561 str += QString(
1562 "%1immediate=\"%2\" unique_program_id=\"%3\"\n"
1563 "%4avail_num=\"%5\" avails_expected=\"%6\">\n")
1564 .arg(indent_1,
1566 .arg(UniqueProgramID())
1567 .arg(indent_1)
1568 .arg(AvailNum())
1569 .arg(AvailsExpected());
1570
1572 {
1573 str += SpliceTime().toStringXML(indent_level + 1, first, last) + "\n";
1574 }
1575
1576 str += indent_0 + "</SpliceInsert>";
1577 return str;
1578}
QString toString() const override
uint DescriptorsLength(void) const
Definition: mpegtables.h:861
QString toStringXML(uint indent_level) const override
const unsigned char * Descriptors(void) const
Definition: mpegtables.h:863
QString toString(void) const override
QString LanguageString(void) const
QString CanonicalLanguageString(void) const
static desc_list_t Parse(const unsigned char *data, uint len)
bool IsValid(void) const
static desc_list_t ParseOnlyInclude(const unsigned char *data, uint len, int excluded_descid)
static const unsigned char * Find(const desc_list_t &parsed, uint desc_tag)
virtual QString toStringXML(uint indent_level) const
Returns XML representation of string the TS Reader XML format.
virtual QString toString(void) const
bool VerifyCRC(void) const
Definition: pespacket.cpp:181
void Finalize()
Definition: pespacket.h:217
void SetTotalLength(uint len)
Definition: pespacket.h:176
unsigned char * m_pesData
Pointer to PES data in full buffer.
Definition: pespacket.h:219
uint CalcCRC(void) const
Definition: pespacket.cpp:173
uint m_psiOffset
AFCOffset + StartOfFieldPointer.
Definition: pespacket.h:222
const TSHeader * tsheader() const
Definition: pespacket.h:90
uint m_allocSize
Total number of bytes we allocated.
Definition: pespacket.h:225
bool m_badPacket
true if a CRC is not good yet
Definition: pespacket.h:226
const unsigned char * pesdata() const
Definition: pespacket.h:164
unsigned char * m_fullBuffer
Pointer to allocated data.
Definition: pespacket.h:220
void SetLength(uint len)
Definition: pespacket.h:171
uint CRC(void) const
Definition: pespacket.h:189
uint Length() const
Definition: pespacket.h:99
Contains Packet Identifier numeric values.
Definition: mpegtables.h:207
@ MPEG_NULL_PID
The all-ones PID value 0x1FFF indicates a Null TS Packet introduced to maintain a constant bit rate o...
Definition: mpegtables.h:246
A PSIP table is a variant of a PES packet containing an MPEG, ATSC or DVB table.
Definition: mpegtables.h:410
uint LastSection(void) const
Definition: mpegtables.h:534
uint Version(void) const
Definition: mpegtables.h:522
bool HasCRC(void) const override
1 bit Cyclic Redundancy Check present
Definition: mpegtables.cpp:101
static PSIPTable View(const TSPacket &tspacket)
Definition: mpegtables.h:487
uint ATSCProtocolVersion(void) const
Definition: mpegtables.h:538
bool HasSectionNumber(void) const
Definition: mpegtables.cpp:217
static const uint kPsipOffset
Definition: mpegtables.h:574
const unsigned char * psipdata(void) const
Definition: mpegtables.h:541
QString XMLValues(uint indent_level) const
Definition: mpegtables.cpp:816
bool IsCurrent(void) const
Definition: mpegtables.h:528
void InitPESPacket(TSPacket &tspacket)
Only handles single TS packet PES packets, for PMT/PAT tables basically.
Definition: mpegtables.cpp:769
virtual QString toStringXML(uint indent_level) const
Definition: mpegtables.cpp:810
bool VerifyPSIP(bool verify_crc) const
Definition: mpegtables.cpp:243
uint TableID(void) const
Definition: mpegtables.h:496
virtual QString toString(void) const
Definition: mpegtables.cpp:792
uint Section(void) const
Definition: mpegtables.h:531
uint TableIDExtension(void) const
Definition: mpegtables.h:515
uint SectionLength(void) const
Definition: mpegtables.h:507
void SetVersionNumber(uint ver)
Definition: mpegtables.h:556
The Program Association Table lists all the programs in a stream, and is always found on PID 0.
Definition: mpegtables.h:599
void SetTranportStreamID(uint gtsid)
Definition: mpegtables.h:635
QString toString(void) const override
Definition: mpegtables.cpp:844
static ProgramAssociationTable * CreateBlank(bool smallPacket=true)
Definition: mpegtables.cpp:337
uint ProgramCount(void) const
Definition: mpegtables.h:619
uint TransportStreamID(void) const
Definition: mpegtables.h:617
QString toStringXML(uint indent_level) const override
Definition: mpegtables.cpp:882
ProgramAssociationTable(const ProgramAssociationTable &table)
Definition: mpegtables.h:601
static ProgramAssociationTable * Create(uint tsid, uint version, const std::vector< uint > &pnum, const std::vector< uint > &pid)
Definition: mpegtables.cpp:352
uint ProgramNumber(uint i) const
Definition: mpegtables.h:626
uint ProgramPID(uint i) const
Definition: mpegtables.h:629
A PMT table maps a program described in the ProgramAssociationTable to various PID's which describe t...
Definition: mpegtables.h:676
bool IsEncrypted(const QString &sistandard) const
Returns true iff PMT contains CA descriptor for a vid/aud stream.
Definition: mpegtables.cpp:557
void SetPCRPID(uint pid)
Definition: mpegtables.h:737
uint FindPIDs(uint type, std::vector< uint > &pids, const QString &sistandard) const
Finds all pids matching type.
Definition: mpegtables.cpp:648
uint FindUnusedPID(uint desired_pid=0x20) const
Definition: mpegtables.cpp:743
QString GetLanguage(uint i) const
Returns the canonical language if we find the iso639 descriptor.
void RemoveAllStreams(void)
Definition: mpegtables.h:789
uint GetAudioType(uint i) const
Returns the audio type from the iso 639 descriptor.
void SetStreamPID(uint i, uint pid)
Definition: mpegtables.h:745
bool IsProgramEncrypted(void) const
Returns true iff PMT's ProgramInfo contains CA descriptor.
Definition: mpegtables.cpp:573
QString toStringXML(uint indent_level) const override
Definition: mpegtables.cpp:944
uint StreamCount(void) const
Definition: mpegtables.h:733
bool IsStillPicture(const QString &sistandard) const
Returns true iff PMT contains a still-picture video stream.
Definition: mpegtables.cpp:623
void SetStreamType(uint i, uint type)
Definition: mpegtables.h:751
uint PCRPID(void) const
stream that contains program clock reference.
Definition: mpegtables.h:709
uint StreamPID(uint i) const
Definition: mpegtables.h:724
void SetStreamProgramInfo(uint i, unsigned char *streamInfo, uint infoLength)
Definition: mpegtables.h:808
std::vector< unsigned char * > m_ptrs
Definition: mpegtables.h:831
void SetProgramNumber(uint num)
Definition: mpegtables.h:743
QString toString(void) const override
Definition: mpegtables.cpp:909
uint StreamType(uint i) const
Definition: mpegtables.h:721
int FindPID(uint pid) const
Locates stream index of pid.
Definition: mpegtables.h:780
const unsigned char * ProgramInfo(void) const
Definition: mpegtables.h:718
const unsigned char * StreamInfo(uint i) const
Definition: mpegtables.h:730
uint ProgramNumber(void) const
Definition: mpegtables.h:712
QString StreamTypeString(uint i) const
Returns a string representation of type at stream index i.
Definition: mpegtables.h:763
void AppendStream(uint pid, uint type, unsigned char *streamInfo=nullptr, uint infoLength=0)
Definition: mpegtables.cpp:495
uint ProgramInfoLength(void) const
Definition: mpegtables.h:715
bool IsAudio(uint i, const QString &sistandard) const
Returns true iff the stream at index i is an audio stream.
Definition: mpegtables.cpp:541
bool IsVideo(uint i, const QString &sistandard) const
Returns true iff the stream at index i is a video stream.
Definition: mpegtables.cpp:519
uint StreamInfoLength(uint i) const
Definition: mpegtables.h:727
static ProgramMapTable * CreateBlank(bool smallPacket=true)
Definition: mpegtables.cpp:387
bool IsStreamEncrypted(uint pid) const
Returns true iff PMT contains CA descriptor.
Definition: mpegtables.cpp:601
ProgramMapTable(const ProgramMapTable &table)
Definition: mpegtables.h:679
void SetProgramInfo(unsigned char *streamInfo, uint infoLength)
Definition: mpegtables.h:822
void Parse(void) const
Definition: mpegtables.cpp:474
static ProgramMapTable * Create(uint programNumber, uint basepid, uint pcrpid, uint version, std::vector< uint > pids, std::vector< uint > types)
Definition: mpegtables.cpp:412
QString StreamDescription(uint i, const QString &sistandard) const
Returns a better (and more expensive) string representation of type at stream index i than StreamType...
static const uint kPmtHeaderMinOffset
Definition: mpegtables.h:830
QString FormatIdentifierString(void) const
uint SpliceCommandType(void) const
Definition: mpegtables.h:1110
std::vector< const unsigned char * > m_ptrs1
Definition: mpegtables.h:1185
uint64_t PTSAdjustment(void) const
Definition: mpegtables.h:1065
uint SpliceCommandLength(void) const
Definition: mpegtables.h:1087
std::vector< const unsigned char * > m_ptrs0
Definition: mpegtables.h:1184
uint EncryptionAlgorithm(void) const
Definition: mpegtables.h:1057
uint SpliceProtocolVersion(void) const
Definition: mpegtables.h:1039
SpliceTimeView TimeSignal(void) const
Definition: mpegtables.h:1135
QString toString(void) const override
Definition: mpegtables.h:1175
int getSCTEPID(void) const
Definition: mpegtables.h:1028
static SpliceInformationTable * GetDecrypted(const QString &codeWord)
Returns decrypted version of this packet.
QString toStringXML(uint indent_level) const override
Definition: mpegtables.h:1177
uint CodeWordIndex(void) const
Definition: mpegtables.h:1083
QString EncryptionAlgorithmString(void) const
QString SpliceCommandTypeString(void) const
bool IsEncryptedPacket(void) const
Definition: mpegtables.h:1042
SpliceInsertView SpliceInsert(void) const
Definition: mpegtables.h:1129
const unsigned char * m_epilog
Definition: mpegtables.h:1186
SpliceTimeView SpliceTime(void) const
Definition: mpegtables.h:978
bool IsSpliceImmediate(void) const
Definition: mpegtables.h:974
bool IsSpliceEventCancel(void) const
Definition: mpegtables.h:964
virtual QString toString(int64_t first, int64_t last) const
bool IsProgramSplice(void) const
Definition: mpegtables.h:970
uint AvailsExpected(void) const
Definition: mpegtables.h:998
uint SpliceEventID(void) const
Definition: mpegtables.h:958
virtual QString toStringXML(uint indent_level, int64_t first, int64_t last) const
bool IsOutOfNetwork(void) const
Definition: mpegtables.h:968
bool IsDuration(void) const
Definition: mpegtables.h:972
uint UniqueProgramID(void) const
Definition: mpegtables.h:993
uint AvailNum(void) const
Definition: mpegtables.h:996
virtual QString toStringXML(uint indent_level, int64_t first, int64_t last) const
bool IsTimeSpecified(void) const
Definition: mpegtables.h:876
virtual QString toString(int64_t first, int64_t last) const
uint64_t PTSTime(void) const
Definition: mpegtables.h:880
uint size(void) const
Definition: mpegtables.h:895
static uint Normalize(uint stream_id, const desc_list_t &desc, const QString &sistandard)
Definition: mpegtables.cpp:53
@ MetaDataOC
ISO 13818-6 Metadata in Object Carousel.
Definition: mpegtables.h:142
@ MPEG2Video
ISO 13818-2 & ITU H.262 (aka MPEG-2)
Definition: mpegtables.h:116
@ MetaDataDC
ISO 13818-6 Metadata in Data Carousel.
Definition: mpegtables.h:141
@ EAC3Audio
A/53 Part 3:2009 6.7.3.
Definition: mpegtables.h:129
@ PrivData
ISO 13818-1 PES private data & ITU H.222.0.
Definition: mpegtables.h:147
@ DSMCC_D
ISO 13818-6 type D Any DSMCC Data.
Definition: mpegtables.h:137
@ DSMCC_A
ISO 13818-6 type A Multi-protocol Encap.
Definition: mpegtables.h:134
@ DSMCC_B
ISO 13818-6 type B Std DSMCC Data.
Definition: mpegtables.h:135
@ FlexMuxSec
ISO 14496-1 SL/FlexMux in 14496_sections.
Definition: mpegtables.h:155
@ MetaDataDL
ISO 13818-6 Metadata in Download Protocol.
Definition: mpegtables.h:143
@ MPEG2AACAudio
ISO 13818-7 Audio w/ADTS syntax.
Definition: mpegtables.h:126
@ DSMCC_DL
ISO 13818-6 Download Protocol.
Definition: mpegtables.h:138
@ AC3Audio
A/53 Part 3:2009 6.7.1.
Definition: mpegtables.h:128
@ DSMCC
ISO 13818-1 Annex A DSM-CC & ITU H.222.0.
Definition: mpegtables.h:133
@ FlexMuxPES
ISO 14496-1 SL/FlexMux in PES packets.
Definition: mpegtables.h:154
@ MPEG2IPMP2
ISO 13818-10 Digital Restrictions Mangment.
Definition: mpegtables.h:158
@ MPEG2Aux
ISO 13818-1 auxiliary & ITU H.222.0.
Definition: mpegtables.h:152
@ DSMCC_C
ISO 13818-6 type C NPT DSMCC Data.
Definition: mpegtables.h:136
@ H265Video
ISO 23008-2 & ITU H.265 (aka HEVC, Ultra HD)
Definition: mpegtables.h:119
@ MetaDataSec
Meta data in metadata_section's.
Definition: mpegtables.h:140
@ MPEG2Audio
ISO 13818-3.
Definition: mpegtables.h:125
@ H222_1
ITU H.222.1.
Definition: mpegtables.h:150
@ VC1Video
SMPTE 421M video codec (aka VC1) in Blu-Ray.
Definition: mpegtables.h:121
@ MPEG4Video
ISO 14492-2 (aka MPEG-4)
Definition: mpegtables.h:117
@ PrivSec
ISO 13818-1 private tables & ITU H.222.0.
Definition: mpegtables.h:146
@ MPEG2IPMP
ISO 13818-10 Digital Restrictions Mangment.
Definition: mpegtables.h:157
@ Splice
ANSI/SCTE 35 2007.
Definition: mpegtables.h:160
@ MPEG2AudioAmd1
ISO 13818-3/AMD-1 Audio using LATM syntax.
Definition: mpegtables.h:127
@ MPEG1Audio
ISO 11172-3.
Definition: mpegtables.h:124
@ MPEG1Video
ISO 11172-2 (aka MPEG-1)
Definition: mpegtables.h:115
@ MetaDataPES
Meta data in PES packets.
Definition: mpegtables.h:139
@ OpenCableVideo
Always MPEG-2??
Definition: mpegtables.h:120
@ MHEG
ISO 13522 MHEG.
Definition: mpegtables.h:149
@ H264Video
ISO 14492-10 & ITU H.264 (aka MPEG-4-AVC)
Definition: mpegtables.h:118
static const char * toString(uint streamID)
Definition: mpegtables.cpp:992
static QString GetDescription(uint stream_id)
static bool IsAudio(uint type)
Returns true iff audio is MPEG1/2, AAC, AC3 or DTS audio stream.
Definition: mpegtables.h:179
static bool IsVideo(uint type)
Returns true iff video is an MPEG1/2/3, H264 or open cable video stream.
Definition: mpegtables.h:168
Used to access header of a TSPacket.
Definition: tspacket.h:47
bool PayloadStart(void) const
Definition: tspacket.h:89
void SetPID(unsigned int pid)
Definition: tspacket.h:160
const unsigned char * data(void) const
Definition: tspacket.h:174
Used to access the data of a Transport Stream packet.
Definition: tspacket.h:208
static constexpr unsigned int kPayloadSize
Definition: tspacket.h:262
unsigned int AFCOffset(void) const
Definition: tspacket.h:249
static TSPacket * CreatePayloadOnlyPacket(void)
Definition: tspacket.h:215
unsigned int StartOfFieldPointer(void) const
Definition: tspacket.h:254
@ DN_EITbego
Definition: mpegtables.h:314
@ SC_EITbeg
Definition: mpegtables.h:280
@ SVCTscte
Definition: mpegtables.h:342
@ DN_EITendo
Definition: mpegtables.h:315
@ SC_EITendo
Definition: mpegtables.h:283
unsigned int uint
Definition: compat.h:60
static const struct wl_interface * types[]
static const iso6937table * d
std::vector< const unsigned char * > desc_list_t
const std::array< const uint8_t, 8 > DEFAULT_PAT_HEADER
Definition: mpegtables.cpp:18
static const std::array< const uint, 4 > len_for_alloc
Definition: mpegtables.cpp:46
const std::array< const uint8_t, 12 > DEFAULT_PMT_HEADER
Definition: mpegtables.cpp:31
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
static QString indent(uint level)
MBASE_PUBLIC long long copy(QFile &dst, QFile &src, uint block_size=0)
Copies src file to dst file.
QString bool_to_string(bool val)
This is equivalent to QVariant(bool).toString()
Definition: stringutil.h:48
QString indentSpaces(unsigned int level, unsigned int size=4)
Definition: stringutil.h:40
string version
Definition: giantbomb.py:185