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