23 #define dbgpatpmt(a...) if (DebugPatPmt) fprintf(stderr, a) 24 #define dbgframes(a...) if (DebugFrames) fprintf(stderr, a) 26 #define MAX_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION 6 27 #define WRN_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION (MAX_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION / 2) 28 #define WRN_TS_PACKETS_FOR_FRAME_DETECTOR (MIN_TS_PACKETS_FOR_FRAME_DETECTOR / 2) 30 #define EMPTY_SCANNER (0xFFFFFFFF) 37 if ((Data[6] & 0xC0) == 0x80) {
41 PesPayloadOffset = 6 + 3 + Data[8];
42 if (Count < PesPayloadOffset)
45 if (ContinuationHeader)
46 *ContinuationHeader = ((Data[6] == 0x80) && !Data[7] && !Data[8]);
55 for (
int i = 0; i < 16; i++) {
56 if (Data[PesPayloadOffset] != 0xFF)
59 if (Count <= ++PesPayloadOffset)
64 if ((Data[PesPayloadOffset] & 0xC0) == 0x40) {
65 PesPayloadOffset += 2;
67 if (Count <= PesPayloadOffset)
71 if (ContinuationHeader)
72 *ContinuationHeader =
false;
74 if ((Data[PesPayloadOffset] & 0xF0) == 0x20) {
76 PesPayloadOffset += 5;
78 else if ((Data[PesPayloadOffset] & 0xF0) == 0x30) {
80 PesPayloadOffset += 10;
82 else if (Data[PesPayloadOffset] == 0x0F) {
86 if (ContinuationHeader)
87 *ContinuationHeader =
true;
92 if (Count < PesPayloadOffset)
98 #define VIDEO_STREAM_S 0xE0 106 for (
int i = PesPayloadOffset; i < Length - 7; i++) {
107 if (Data[i] == 0 && Data[i + 1] == 0 && Data[i + 2] == 1 && Data[i + 3] == 0xB8) {
108 if (!(Data[i + 7] & 0x40))
113 dsyslog(
"SetBrokenLink: no GOP header found in video packet");
116 dsyslog(
"SetBrokenLink: no video packet in frame");
128 memset(p + 6, 0xFF,
TS_SIZE - 6);
141 p[10] = (b << 7) | (p[10] & 0x7E) | ((e >> 8) & 0x01);
147 int TsSync(
const uchar *Data,
int Length,
const char *File,
const char *Function,
int Line)
155 if (Skipped && File && Function && Line)
156 esyslog(
"ERROR: skipped %d bytes to sync on start of TS packet at %s/%s(%d)", Skipped, File, Function, Line);
218 p[ 9] = ((Pts >> 29) & 0x0E) | (p[9] & 0xF1);
220 p[11] = ((Pts >> 14) & 0xFE) | 0x01;
222 p[13] = ((Pts << 1) & 0xFE) | 0x01;
227 p[14] = ((Dts >> 29) & 0x0E) | (p[14] & 0xF1);
229 p[16] = ((Dts >> 14) & 0xFE) | 0x01;
231 p[18] = ((Dts << 1) & 0xFE) | 0x01;
236 int64_t d = Pts2 - Pts1;
256 Setup(Data, Length, Pid);
276 pid = Pid >= 0 ? Pid :
TsPid(Data);
286 uchar *p = data + index;
287 if (
TsPid(p) == pid) {
306 return data[index++];
330 if (Index >= 0 && Index < length)
336 int OldIndex = index;
337 int OldNumPacketsPid = numPacketsPid;
338 int OldNumPacketsOther = numPacketsOther;
341 Scanner = (Scanner << 8) | GetByte();
346 numPacketsPid = OldNumPacketsPid;
347 numPacketsOther = OldNumPacketsOther;
354 dsyslog(
"WARNING: required (%d+%d) TS packets to determine frame type", numPacketsOther, numPacketsPid);
356 dsyslog(
"WARNING: required %d video TS packets to determine frame type", numPacketsPid);
364 patCounter = pmtCounter = 0;
365 patVersion = pmtVersion = 0;
373 TsPacket[3] = (TsPacket[3] & 0xF0) | Counter;
374 if (++Counter > 0x0F)
380 if (++Version > 0x1F)
387 Length += ((*esInfoLength & 0x0F) << 8) | *(esInfoLength + 1);
388 *esInfoLength = 0xF0 | (Length >> 8);
389 *(esInfoLength + 1) = Length;
397 Target[i++] = 0xE0 | (Pid >> 8);
399 esInfoLength = &Target[i];
420 Target[i++] = *Language++;
421 Target[i++] = *Language++;
422 Target[i++] = *Language++;
423 Target[i++] = SubtitlingType;
424 Target[i++] = CompositionPageId >> 8;
425 Target[i++] = CompositionPageId & 0xFF;
426 Target[i++] = AncillaryPageId >> 8;
427 Target[i++] = AncillaryPageId & 0xFF;
437 Target[Length] = 0x00;
438 for (
const char *End = Language + strlen(Language); Language < End; ) {
439 Target[i++] = *Language++;
440 Target[i++] = *Language++;
441 Target[i++] = *Language++;
443 Target[Length] += 0x04;
444 if (*Language ==
'+')
455 Target[i++] = crc >> 24;
456 Target[i++] = crc >> 16;
457 Target[i++] = crc >> 8;
462 #define P_TSID 0x8008 // pseudo TS ID 463 #define P_PMT_PID 0x0084 // pseudo PMT pid 464 #define MAXPID 0x2000 // the maximum possible number of pids 468 bool Used[
MAXPID] = {
false };
469 #define SETPID(p) { if ((p) >= 0 && (p) < MAXPID) Used[p] = true; } 470 #define SETPIDS(l) { const int *p = l; while (*p) { SETPID(*p); p++; } } 477 for (pmtPid =
P_PMT_PID; Used[pmtPid]; pmtPid++)
483 memset(pat, 0xFF,
sizeof(pat));
491 int PayloadStart = i;
494 int SectionLength = i;
498 p[i++] = 0xC1 | (patVersion << 1);
501 p[i++] = pmtPid >> 8;
502 p[i++] = pmtPid & 0xFF;
503 p[i++] = 0xE0 | (pmtPid >> 8);
504 p[i++] = pmtPid & 0xFF;
505 pat[SectionLength] = i - SectionLength - 1 + 4;
506 MakeCRC(pat + i, pat + PayloadStart, i - PayloadStart);
507 IncVersion(patVersion);
514 memset(buf, 0xFF,
sizeof(buf));
517 int Vpid = Channel->
Vpid();
518 int Ppid = Channel->
Ppid();
522 int SectionLength = i;
525 p[i++] = pmtPid >> 8;
526 p[i++] = pmtPid & 0xFF;
527 p[i++] = 0xC1 | (pmtVersion << 1);
530 p[i++] = 0xE0 | (Ppid >> 8);
536 i += MakeStream(buf + i, Channel->
Vtype(), Vpid);
537 for (
int n = 0; Channel->
Apid(n); n++) {
538 i += MakeStream(buf + i, Channel->
Atype(n), Channel->
Apid(n));
539 const char *Alang = Channel->
Alang(n);
540 i += MakeLanguageDescriptor(buf + i, Alang);
542 for (
int n = 0; Channel->
Dpid(n); n++) {
543 i += MakeStream(buf + i, 0x06, Channel->
Dpid(n));
544 i += MakeAC3Descriptor(buf + i, Channel->
Dtype(n));
545 i += MakeLanguageDescriptor(buf + i, Channel->
Dlang(n));
547 for (
int n = 0; Channel->
Spid(n); n++) {
548 i += MakeStream(buf + i, 0x06, Channel->
Spid(n));
552 int sl = i - SectionLength - 2 + 4;
553 buf[SectionLength] |= (sl >> 8) & 0x0F;
554 buf[SectionLength + 1] = sl;
555 MakeCRC(buf + i, buf, i);
560 uchar *p = pmt[numPmtPackets++];
564 p[j++] = pmtPid & 0xFF;
575 IncVersion(pmtVersion);
581 patVersion = PatVersion & 0x1F;
582 pmtVersion = PmtVersion & 0x1F;
588 GeneratePmtPid(Channel);
590 GeneratePmt(Channel);
596 IncCounter(patCounter, pat);
602 if (Index < numPmtPackets) {
603 IncCounter(pmtCounter, pmt[Index]);
613 updatePrimaryDevice = UpdatePrimaryDevice;
621 patVersion = pmtVersion = -1;
631 Data += PayloadOffset;
632 Length -= PayloadOffset;
634 if ((Length -= Data[0] + 1) <= 0)
648 pmtPids[NumPmtPids++] = assoc.
getPid();
652 pmtPids[NumPmtPids] = 0;
656 esyslog(
"ERROR: can't parse PAT");
664 Data += PayloadOffset;
665 Length -= PayloadOffset;
669 if ((Length -= Data[0] + 1) <= 0)
672 if (SectionLength(Data, Length) > Length) {
673 if (Length <=
int(
sizeof(pmt))) {
674 memcpy(pmt, Data, Length);
678 esyslog(
"ERROR: PMT packet length too big (%d byte)!", Length);
683 else if (pmtSize > 0) {
685 if (Length <=
int(
sizeof(pmt)) - pmtSize) {
686 memcpy(pmt + pmtSize, Data, Length);
690 esyslog(
"ERROR: PMT section length too big (%d byte)!", pmtSize + Length);
693 if (SectionLength(pmt, pmtSize) > pmtSize)
706 if (updatePrimaryDevice)
736 apids[NumApids] = stream.
getPid();
738 *alangs[NumApids] = 0;
745 char *s = alangs[NumApids];
764 if (updatePrimaryDevice)
788 spids[NumSpids] = stream.
getPid();
789 *slangs[NumSpids] = 0;
790 subtitlingTypes[NumSpids] = 0;
791 compositionPageIds[NumSpids] = 0;
792 ancillaryPageIds[NumSpids] = 0;
795 char *s = slangs[NumSpids];
811 if (updatePrimaryDevice)
829 dpids[NumDpids] = dpid;
830 dtypes[NumDpids] = dtype;
831 strn0cpy(dlangs[NumDpids], lang,
sizeof(dlangs[NumDpids]));
861 dpids[NumDpids] = stream.
getPid();
863 strn0cpy(dlangs[NumDpids], lang,
sizeof(dlangs[NumDpids]));
883 spids[NumSpids] = stream.
getPid();
884 *slangs[NumSpids] = 0;
885 subtitlingTypes[NumSpids] = 0;
886 compositionPageIds[NumSpids] = 0;
887 ancillaryPageIds[NumSpids] = 0;
888 if (updatePrimaryDevice)
904 if (updatePrimaryDevice) {
913 esyslog(
"ERROR: can't parse PMT");
922 int Pid =
TsPid(Data);
925 else if (IsPmtPid(Pid)) {
927 if (patVersion >= 0 && pmtVersion >= 0)
938 PatVersion = patVersion;
939 PmtVersion = pmtVersion;
940 return patVersion >= 0 && pmtVersion >= 0;
955 int L = (M < 3) ? 1 : 0;
956 return 14956 + D + int((Y - L) * 365.25) + int((M + 1 + L * 12) * 30.6001);
966 *p++ = ParentalRating;
974 uchar *DescriptorsStart;
975 memset(eit, 0xFF,
sizeof(eit));
977 time_t t = time(NULL) - 3600;
978 tm *tm = localtime_r(&t, &tm_r);
979 uint16_t MJD = YMDtoMJD(tm->tm_year, tm->tm_mon + 1, tm->tm_mday);
985 *p++ = 0x10 | (counter++ & 0x0F);
995 *p++ = 0xC1 | (version << 1);
1016 DescriptorsStart = p;
1017 p = AddParentalRatingDescriptor(p);
1019 *(SectionStart - 1) = p - SectionStart + 4;
1020 *(DescriptorsStart - 1) = p - DescriptorsStart;
1022 int crc =
SI::CRC32::crc32((
char *)PayloadStart, p - PayloadStart, 0xFFFFFFFF);
1055 if (length + Length > size) {
1057 if (
uchar *NewData = (
uchar *)realloc(data, NewSize)) {
1062 esyslog(
"ERROR: out of memory");
1067 memcpy(data + length, Data, Length);
1071 #define MAXPESLENGTH 0xFFF0 1077 Length = lastLength;
1084 uchar *p = data + offset - 6;
1091 memmove(p, data, 4);
1104 lastLength = Length;
1110 if (Length <= length) {
1112 lastLength = Length;
1128 length = offset = 0;
1138 printf(
"--- %s\n", Name);
1139 for (
int i = 0; i < Length; i++) {
1140 if (i && (i % 16) == 0)
1142 printf(
" %02X", Data[i]);
1149 printf(
"%s: %04X", Name, Length);
1150 int n =
min(Length, 20);
1151 for (
int i = 0; i < n; i++)
1152 printf(
" %02X", Data[i]);
1155 n =
max(n, Length - 10);
1156 for (n =
max(n, Length - 10); n < Length; n++)
1157 printf(
" %02X", Data[n]);
1164 TsDump(Name, Data, Length);
1178 virtual int Parse(
const uchar *Data,
int Length,
int Pid) = 0;
1195 independentFrame =
false;
1196 iFrameTemporalReferenceOffset = 0;
1204 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1214 newFrame = independentFrame =
true;
1219 newFrame = independentFrame =
false;
1232 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1238 seenIndependentFrame =
false;
1239 lastIFrameTemporalReference = -1;
1244 newFrame = independentFrame =
false;
1245 bool SeenPayloadStart =
false;
1246 cTsPayload tsPayload(const_cast<uchar *>(Data), Length, Pid);
1248 SeenPayloadStart =
true;
1251 if (debug && seenIndependentFrame)
1254 uint32_t OldScanner = scanner;
1256 if (!SeenPayloadStart && tsPayload.
AtTsStart())
1257 OldScanner = scanner;
1258 scanner = (scanner << 8) | tsPayload.
GetByte();
1259 if (scanner == 0x00000100) {
1261 scanner = OldScanner;
1266 int TemporalReference = (b1 << 2 ) + ((b2 & 0xC0) >> 6);
1267 uchar FrameType = (b2 >> 3) & 0x07;
1268 if (tsPayload.
Find(0x000001B5)) {
1269 if (((tsPayload.
GetByte() & 0xF0) >> 4) == 0x08) {
1272 if (PictureStructure == 0x02)
1277 independentFrame = FrameType == 1;
1278 if (independentFrame) {
1279 if (lastIFrameTemporalReference >= 0)
1280 iFrameTemporalReferenceOffset = TemporalReference - lastIFrameTemporalReference;
1281 lastIFrameTemporalReference = TemporalReference;
1284 seenIndependentFrame |= independentFrame;
1285 if (seenIndependentFrame) {
1286 static const char FrameTypes[] =
"?IPBD???";
1297 return tsPayload.
Used();
1305 nutCodedSliceNonIdr = 1,
1306 nutCodedSliceIdr = 5,
1307 nutSequenceParameterSet = 7,
1308 nutAccessUnitDelimiter = 9,
1322 uchar GetByte(
bool Raw =
false);
1327 uint32_t GetBits(
int Bits);
1328 uint32_t GetGolombUe(
void);
1329 int32_t GetGolombSe(
void);
1330 void ParseAccessUnitDelimiter(
void);
1331 void ParseSequenceParameterSet(
void);
1332 void ParseSliceHeader(
void);
1338 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1347 separate_colour_plane_flag =
false;
1348 log2_max_frame_num = 0;
1349 frame_mbs_only_flag =
false;
1350 gotAccessUnitDelimiter =
false;
1351 gotSequenceParameterSet =
false;
1356 uchar b = tsPayload.GetByte();
1362 if (b == 0x03 && zeroBytes >= 2)
1363 b = tsPayload.GetByte();
1379 return (byte & (1 << bit--)) ? 1 : 0;
1386 b |= GetBit() << Bits;
1393 for (
int b = 0; !b && z < 32; z++)
1395 return (1 << z) - 1 + GetBits(z);
1400 uint32_t v = GetGolombUe();
1402 if ((v & 0x01) != 0)
1405 return -int32_t(v / 2);
1412 newFrame = independentFrame =
false;
1413 tsPayload.Setup(const_cast<uchar *>(Data), Length, Pid);
1415 tsPayload.SkipPesHeader();
1417 if (debug && gotSequenceParameterSet) {
1422 scanner = (scanner << 8) | GetByte(
true);
1423 if ((scanner & 0xFFFFFF00) == 0x00000100) {
1424 uchar NalUnitType = scanner & 0x1F;
1425 switch (NalUnitType) {
1426 case nutAccessUnitDelimiter: ParseAccessUnitDelimiter();
1427 gotAccessUnitDelimiter =
true;
1429 case nutSequenceParameterSet:
if (gotAccessUnitDelimiter) {
1430 ParseSequenceParameterSet();
1431 gotSequenceParameterSet =
true;
1434 case nutCodedSliceNonIdr:
1435 case nutCodedSliceIdr:
if (gotAccessUnitDelimiter && gotSequenceParameterSet) {
1437 gotAccessUnitDelimiter =
false;
1439 tsPayload.Statistics();
1440 return tsPayload.Used();
1446 if (tsPayload.AtPayloadStart()
1450 return tsPayload.Used();
1455 if (debug && gotSequenceParameterSet)
1462 uchar profile_idc = GetByte();
1466 if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 244 || profile_idc == 44 || profile_idc == 83 || profile_idc == 86 || profile_idc ==118 || profile_idc == 128) {
1467 int chroma_format_idc = GetGolombUe();
1468 if (chroma_format_idc == 3)
1469 separate_colour_plane_flag = GetBit();
1474 for (
int i = 0; i < ((chroma_format_idc != 3) ? 8 : 12); i++) {
1476 int SizeOfScalingList = (i < 6) ? 16 : 64;
1479 for (
int j = 0; j < SizeOfScalingList; j++) {
1481 NextScale = (LastScale + GetGolombSe() + 256) % 256;
1483 LastScale = NextScale;
1489 log2_max_frame_num = GetGolombUe() + 4;
1490 int pic_order_cnt_type = GetGolombUe();
1491 if (pic_order_cnt_type == 0)
1493 else if (pic_order_cnt_type == 1) {
1497 for (
int i = GetGolombUe(); i--; )
1504 frame_mbs_only_flag = GetBit();
1506 if (gotAccessUnitDelimiter && !gotSequenceParameterSet)
1508 dbgframes(frame_mbs_only_flag ?
"S" :
"s");
1516 int slice_type = GetGolombUe();
1517 independentFrame = (slice_type % 5) == 2;
1519 static const char SliceTypes[] =
"PBIpi";
1520 dbgframes(
"%c", SliceTypes[slice_type % 5]);
1522 if (frame_mbs_only_flag)
1525 if (separate_colour_plane_flag)
1527 GetBits(log2_max_frame_num);
1528 if (!frame_mbs_only_flag) {
1530 newFrame = !GetBit();
1541 nutSliceSegmentTrailingN = 0,
1542 nutSliceSegmentTrailingR = 1,
1543 nutSliceSegmentTSAN = 2,
1544 nutSliceSegmentTSAR = 3,
1545 nutSliceSegmentSTSAN = 4,
1546 nutSliceSegmentSTSAR = 5,
1547 nutSliceSegmentRADLN = 6,
1548 nutSliceSegmentRADLR = 7,
1549 nutSliceSegmentRASLN = 8,
1550 nutSliceSegmentRASLR = 9,
1551 nutSliceSegmentBLAWLP = 16,
1552 nutSliceSegmentBLAWRADL = 17,
1553 nutSliceSegmentBLANLP = 18,
1554 nutSliceSegmentIDRWRADL = 19,
1555 nutSliceSegmentIDRNLP = 20,
1556 nutSliceSegmentCRANUT = 21,
1557 nutVideoParameterSet = 32,
1558 nutSequenceParameterSet = 33,
1559 nutPictureParameterSet = 34,
1560 nutAccessUnitDelimiter = 35,
1561 nutEndOfSequence = 36,
1562 nutEndOfBitstream = 37,
1568 nutUnspecified0 = 48,
1569 nutUnspecified7 = 55,
1573 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1591 if ((
scanner & 0xFFFFFF00) == 0x00000100) {
1621 framesPerSecond = 0;
1622 framesInPayloadUnit = framesPerPayloadUnit = 0;
1628 if (*(uint32_t *)p1 < *(uint32_t *)p2)
return -1;
1629 if (*(uint32_t *)p1 > *(uint32_t *)p2)
return 1;
1637 isVideo = type == 0x01 || type == 0x02 || type == 0x1B || type == 0x24;
1640 if (type == 0x01 || type == 0x02)
1642 else if (type == 0x1B)
1644 else if (type == 0x24)
1646 else if (type == 0x03 || type == 0x04 || type == 0x06)
1649 esyslog(
"ERROR: unknown stream type %d (PID %d) in frame detector", type, pid);
1660 if (
int Skipped =
TS_SYNC(Data, Length))
1661 return Processed + Skipped;
1665 int Pid =
TsPid(Data);
1674 if (!framesPerPayloadUnit)
1675 framesPerPayloadUnit = framesInPayloadUnit;
1677 int n = parser->Parse(Data, Length, pid);
1679 if (parser->NewFrame()) {
1683 if (framesPerPayloadUnit <= 1)
1687 framesInPayloadUnit++;
1697 if (framesPerSecond <= 0.0) {
1699 if (numPtsValues < 2 || numPtsValues < MaxPtsValues && numIFrames < 2) {
1703 ptsValues[numPtsValues] =
PesGetPts(Pes);
1705 if (numPtsValues && ptsValues[numPtsValues - 1] > 0xF0000000 && ptsValues[numPtsValues] < 0x10000000) {
1715 if (numPtsValues >= 2 && numIFrames >= 2) {
1717 qsort(ptsValues, numPtsValues,
sizeof(uint32_t),
CmpUint32);
1719 for (
int i = 0; i < numPtsValues; i++)
1720 ptsValues[i] = ptsValues[i + 1] - ptsValues[i];
1721 qsort(ptsValues, numPtsValues,
sizeof(uint32_t),
CmpUint32);
1722 int Div = framesPerPayloadUnit;
1723 if (framesPerPayloadUnit > 1)
1724 Div += parser->IFrameTemporalReferenceOffset();
1727 int Delta = ptsValues[0] / Div;
1731 framesPerSecond = 24.0 / 1.001;
1732 else if (abs((int32_t)Delta - 3600) <= 1)
1733 framesPerSecond = 25.0;
1734 else if (Delta % 3003 == 0)
1735 framesPerSecond = 30.0 / 1.001;
1736 else if (abs((int32_t)Delta - 1800) <= 1)
1737 framesPerSecond = 50.0;
1738 else if (Delta == 1501)
1739 framesPerSecond = 60.0 / 1.001;
1746 framesPerSecond = double(
PTSTICKS) / Delta;
1747 dbgframes(
"\nDelta = %d FPS = %5.2f FPPU = %d NF = %d TRO = %d\n", Delta, framesPerSecond, framesPerPayloadUnit, numPtsValues + 1, parser->IFrameTemporalReferenceOffset());
1749 parser->SetDebug(
false);
1754 else if (Pid ==
PATPID && synced && Processed)
1759 Processed += Handled;
uint16_t AncillaryPageId(int i) const
bool ParsePatPmt(const uchar *Data, int Length)
Parses the given Data (which may consist of several TS packets, typically an entire frame) and extrac...
void ParsePat(const uchar *Data, int Length)
Parses the PAT data from the single TS packet in Data.
int Used(void)
Returns the number of raw bytes that have already been used (e.g.
bool separate_colour_plane_flag
uchar GetByte(void)
Gets the next byte of the TS payload, skipping any intermediate TS header data.
const int * Dpids(void) const
void SetVersions(int PatVersion, int PmtVersion)
Sets the version numbers for the generated PAT and PMT, in case this generator is used to...
bool TsError(const uchar *p)
void SetPid(int Pid, int Type)
Sets the Pid and stream Type to detect frames for.
#define MAX_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION
#define DEFAULTFRAMESPERSECOND
int PesPayloadOffset(const uchar *p)
void IncCounter(int &Counter, uchar *TsPacket)
bool SkipBytes(int Bytes)
Skips the given number of bytes in the payload and returns true if there is still data left to read...
bool TsHasAdaptationField(const uchar *p)
bool getCurrentNextIndicator() const
void ParsePmt(const uchar *Data, int Length)
Parses the PMT data from the single TS packet in Data.
virtual int Parse(const uchar *Data, int Length, int Pid)
Parses the given Data, which is a sequence of Length bytes of TS packets.
uchar SubtitlingType(int i) const
bool IndependentFrame(void)
bool TsPayloadStart(const uchar *p)
bool gotAccessUnitDelimiter
int MakeLanguageDescriptor(uchar *Target, const char *Language)
void GeneratePmtPid(const cChannel *Channel)
Generates a PMT pid that doesn't collide with any of the actual pids of the Channel.
int64_t PesGetPts(const uchar *p)
int Analyze(const uchar *Data, int Length)
Analyzes the TS packets pointed to by Data.
uint16_t YMDtoMJD(int Y, int M, int D)
int getCompositionPageId() const
bool TsHasPayload(const uchar *p)
StructureLoop< Association > associationLoop
StructureLoop< Stream > streamLoop
#define TS_ADAPT_FIELD_EXISTS
static u_int32_t crc32(const char *d, int len, u_int32_t CRCvalue)
void IncEsInfoLength(int Length)
int MakeCRC(uchar *Target, const uchar *Data, int Length)
bool SetAvailableTrack(eTrackType Type, int Index, uint16_t Id, const char *Language=NULL, const char *Description=NULL)
Sets the track of the given Type and Index to the given values.
#define WRN_TS_PACKETS_FOR_FRAME_DETECTOR
void SetChannel(const cChannel *Channel)
Sets the Channel for which the PAT/PMT shall be generated.
bool AtPayloadStart(void)
Returns true if this payload handler is currently pointing to the first byte of a TS packet that star...
bool PesHasPts(const uchar *p)
cPatPmtGenerator(const cChannel *Channel=NULL)
int MakeSubtitlingDescriptor(uchar *Target, const char *Language, uchar SubtitlingType, uint16_t CompositionPageId, uint16_t AncillaryPageId)
DescriptorTag getDescriptorTag() const
void Setup(uchar *Data, int Length, int Pid=-1)
Sets up this TS payload handler with the given Data, which points to a sequence of Length bytes of co...
const char * Dlang(int i) const
StructureLoop< Subtitling > subtitlingLoop
void ParseSequenceParameterSet(void)
int64_t TsGetDts(const uchar *p, int l)
int MakeAC3Descriptor(uchar *Target, uchar Type)
void GeneratePat(void)
Generates a PAT section for later use with GetPat().
bool Find(uint32_t Code)
Searches for the four byte sequence given in Code and returns true if it was found within the payload...
int MakeStream(uchar *Target, uchar Type, int Pid)
uchar GetByte(bool Raw=false)
Gets the next data byte.
int iFrameTemporalReferenceOffset
bool Eof(void) const
Returns true if all available bytes of the TS payload have been processed.
const char * Alang(int i) const
bool PesLongEnough(int Length)
void TsSetPcr(uchar *p, int64_t Pcr)
int TsPid(const uchar *p)
virtual int Parse(const uchar *Data, int Length, int Pid)
Parses the given Data, which is a sequence of Length bytes of TS packets.
cFrameDetector(int Pid=0, int Type=0)
Sets up a frame detector for the given Pid and stream Type.
void ParseSliceHeader(void)
void EnsureSubtitleTrack(void)
Makes sure one of the preferred language subtitle tracks is selected.
#define TS_PAYLOAD_EXISTS
int getSectionNumber() const
int PesLength(const uchar *p)
void PesSetPts(uchar *p, int64_t Pts)
void ParseAccessUnitDelimiter(void)
int lastIFrameTemporalReference
cH264Parser(void)
Sets up a new H.264 parser.
void Reset(void)
Resets the converter.
bool PesHasDts(const uchar *p)
void PesSetDts(uchar *p, int64_t Dts)
void BlockDump(const char *Name, const u_char *Data, int Length)
void TsSetDts(uchar *p, int l, int64_t Dts)
cPatPmtParser(bool UpdatePrimaryDevice=false)
int TsSync(const uchar *Data, int Length, const char *File, const char *Function, int Line)
int GetLastIndex(void)
Returns the index into the TS data of the payload byte that has most recently been read...
void TsDump(const char *Name, const u_char *Data, int Length)
virtual int Parse(const uchar *Data, int Length, int Pid)
Parses the given Data, which is a sequence of Length bytes of TS packets.
int64_t PtsDiff(int64_t Pts1, int64_t Pts2)
Returns the difference between two PTS values.
void PutTs(const uchar *Data, int Length)
Puts the payload data of the single TS packet at Data into the converter.
void ClrAvailableTracks(bool DescriptionsOnly=false, bool IdsOnly=false)
Clears the list of currently available tracks.
ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader)
int IFrameTemporalReferenceOffset(void)
uchar * GetPmt(int &Index)
Returns a pointer to the Index'th TS packet of the PMT section.
uchar * Generate(int Sid)
int getSubtitlingType() const
StructureLoop< Language > languageLoop
#define WRN_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION
int TsGetPayload(const uchar **p)
void GeneratePmt(const cChannel *Channel)
Generates a PMT section for the given Channel, for later use with GetPmt().
int32_t GetGolombSe(void)
void TsHidePayload(uchar *p)
int getStreamType() const
void PesDump(const char *Name, const u_char *Data, int Length)
virtual int Parse(const uchar *Data, int Length, int Pid)
Parses the given Data, which is a sequence of Length bytes of TS packets.
uint32_t GetBits(int Bits)
static void SetBrokenLink(uchar *Data, int Length)
void Statistics(void) const
May be called after a new frame has been detected, and will log a warning if the number of TS packets...
bool seenIndependentFrame
const int * Apids(void) const
#define MIN_TS_PACKETS_FOR_FRAME_DETECTOR
void EnsureAudioTrack(bool Force=false)
Makes sure an audio track is selected that is actually available.
static cDevice * PrimaryDevice(void)
Returns the primary device.
int getVersionNumber() const
bool PesHasLength(const uchar *p)
#define TS_SYNC(Data, Length)
int64_t TsGetPts(const uchar *p, int l)
uint16_t CompositionPageId(int i) const
uchar * AddParentalRatingDescriptor(uchar *p, uchar ParentalRating=0)
int getLastSectionNumber() const
bool TsIsScrambled(const uchar *p)
bool GetVersions(int &PatVersion, int &PmtVersion) const
Returns true if a valid PAT/PMT has been parsed and stores the current version numbers in the given v...
int64_t PesGetDts(const uchar *p)
void SetByte(uchar Byte, int Index)
Sets the TS data byte at the given Index to the value Byte.
int getTransportStreamId() const
DescriptorLoop streamDescriptors
bool gotSequenceParameterSet
const char * Slang(int i) const
void IncVersion(int &Version)
const int * Spids(void) const
const uchar * GetPes(int &Length)
Gets a pointer to the complete PES packet, or NULL if the packet is not complete yet.
uint32_t GetGolombUe(void)
int getAncillaryPageId() const
void SetDebug(bool Debug)
int TsPayloadOffset(const uchar *p)
void SetRepeatLast(void)
Makes the next call to GetPes() return exactly the same data as the last one (provided there was no c...
bool AtTsStart(void)
Returns true if this payload handler is currently pointing to first byte of a TS packet.
void TsSetPts(uchar *p, int l, int64_t Pts)
const char * I18nNormalizeLanguageCode(const char *Code)
Returns a 3 letter language code that may not be zero terminated.
static int CmpUint32(const void *p1, const void *p2)
void Reset(void)
Resets the parser.
Descriptor * getNext(Iterator &it)
uchar * GetPat(void)
Returns a pointer to the PAT section, which consists of exactly one TS packet.
bool SkipPesHeader(void)
Skips all bytes belonging to the PES header of the payload.