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);
205 p[ 9] = ((Pts >> 29) & 0x0E) | (p[9] & 0xF1);
207 p[11] = ((Pts >> 14) & 0xFE) | 0x01;
209 p[13] = ((Pts << 1) & 0xFE) | 0x01;
214 p[14] = ((Dts >> 29) & 0x0E) | (p[14] & 0xF1);
216 p[16] = ((Dts >> 14) & 0xFE) | 0x01;
218 p[18] = ((Dts << 1) & 0xFE) | 0x01;
223 int64_t d = Pts2 - Pts1;
243 Setup(Data, Length, Pid);
263 pid = Pid >= 0 ? Pid :
TsPid(Data);
273 uchar *p = data + index;
274 if (
TsPid(p) == pid) {
293 return data[index++];
317 if (Index >= 0 && Index < length)
323 int OldIndex = index;
324 int OldNumPacketsPid = numPacketsPid;
325 int OldNumPacketsOther = numPacketsOther;
328 Scanner = (Scanner << 8) | GetByte();
333 numPacketsPid = OldNumPacketsPid;
334 numPacketsOther = OldNumPacketsOther;
341 dsyslog(
"WARNING: required (%d+%d) TS packets to determine frame type", numPacketsOther, numPacketsPid);
343 dsyslog(
"WARNING: required %d video TS packets to determine frame type", numPacketsPid);
374 if (Offset == 4 && Offset < NewPayload)
376 if (Offset == 5 && Offset < NewPayload)
377 Packet[Offset++] = 0;
378 while (Offset < NewPayload)
379 Packet[Offset++] = 0xff;
387 patCounter = pmtCounter = 0;
388 patVersion = pmtVersion = 0;
396 TsPacket[3] = (TsPacket[3] & 0xF0) | Counter;
397 if (++Counter > 0x0F)
403 if (++Version > 0x1F)
410 Length += ((*esInfoLength & 0x0F) << 8) | *(esInfoLength + 1);
411 *esInfoLength = 0xF0 | (Length >> 8);
412 *(esInfoLength + 1) = Length;
420 Target[i++] = 0xE0 | (Pid >> 8);
422 esInfoLength = &Target[i];
443 Target[i++] = *Language++;
444 Target[i++] = *Language++;
445 Target[i++] = *Language++;
446 Target[i++] = SubtitlingType;
447 Target[i++] = CompositionPageId >> 8;
448 Target[i++] = CompositionPageId & 0xFF;
449 Target[i++] = AncillaryPageId >> 8;
450 Target[i++] = AncillaryPageId & 0xFF;
461 for (
int n = 0; n < pageCount; n++) {
463 Target[i++] = *Language++;
464 Target[i++] = *Language++;
465 Target[i++] = *Language++;
466 Target[i++] = (pages[n].
ttxtType << 3) + pages[n].ttxtMagazine;
483 Target[Length] = 0x00;
484 for (
const char *End = Language + strlen(Language); Language < End; ) {
485 Target[i++] = *Language++;
486 Target[i++] = *Language++;
487 Target[i++] = *Language++;
489 Target[Length] += 0x04;
490 if (*Language ==
'+')
501 Target[i++] = crc >> 24;
502 Target[i++] = crc >> 16;
503 Target[i++] = crc >> 8;
508 #define P_TSID 0x8008 // pseudo TS ID 509 #define P_PMT_PID 0x0084 // pseudo PMT pid 510 #define MAXPID 0x2000 // the maximum possible number of pids 514 bool Used[
MAXPID] = {
false };
515 #define SETPID(p) { if ((p) >= 0 && (p) < MAXPID) Used[p] = true; } 516 #define SETPIDS(l) { const int *p = l; while (*p) { SETPID(*p); p++; } } 523 for (pmtPid =
P_PMT_PID; Used[pmtPid]; pmtPid++)
529 memset(pat, 0xFF,
sizeof(pat));
537 int PayloadStart = i;
540 int SectionLength = i;
544 p[i++] = 0xC1 | (patVersion << 1);
547 p[i++] = pmtPid >> 8;
548 p[i++] = pmtPid & 0xFF;
549 p[i++] = 0xE0 | (pmtPid >> 8);
550 p[i++] = pmtPid & 0xFF;
551 pat[SectionLength] = i - SectionLength - 1 + 4;
552 MakeCRC(pat + i, pat + PayloadStart, i - PayloadStart);
553 IncVersion(patVersion);
560 memset(buf, 0xFF,
sizeof(buf));
563 int Vpid = Channel->
Vpid();
564 int Ppid = Channel->
Ppid();
565 int Tpid = Channel->
Tpid();
569 int SectionLength = i;
572 p[i++] = pmtPid >> 8;
573 p[i++] = pmtPid & 0xFF;
574 p[i++] = 0xC1 | (pmtVersion << 1);
577 p[i++] = 0xE0 | (Ppid >> 8);
583 i += MakeStream(buf + i, Channel->
Vtype(), Vpid);
584 for (
int n = 0; Channel->
Apid(n); n++) {
585 i += MakeStream(buf + i, Channel->
Atype(n), Channel->
Apid(n));
586 const char *Alang = Channel->
Alang(n);
587 i += MakeLanguageDescriptor(buf + i, Alang);
589 for (
int n = 0; Channel->
Dpid(n); n++) {
590 i += MakeStream(buf + i, 0x06, Channel->
Dpid(n));
591 i += MakeAC3Descriptor(buf + i, Channel->
Dtype(n));
592 i += MakeLanguageDescriptor(buf + i, Channel->
Dlang(n));
594 for (
int n = 0; Channel->
Spid(n); n++) {
595 i += MakeStream(buf + i, 0x06, Channel->
Spid(n));
599 i += MakeStream(buf + i, 0x06, Tpid);
603 int sl = i - SectionLength - 2 + 4;
604 buf[SectionLength] |= (sl >> 8) & 0x0F;
605 buf[SectionLength + 1] = sl;
606 MakeCRC(buf + i, buf, i);
611 uchar *p = pmt[numPmtPackets++];
615 p[j++] = pmtPid & 0xFF;
626 IncVersion(pmtVersion);
632 patVersion = PatVersion & 0x1F;
633 pmtVersion = PmtVersion & 0x1F;
639 GeneratePmtPid(Channel);
641 GeneratePmt(Channel);
647 IncCounter(patCounter, pat);
653 if (Index < numPmtPackets) {
654 IncCounter(pmtCounter, pmt[Index]);
664 updatePrimaryDevice = UpdatePrimaryDevice;
671 patVersion = pmtVersion = -1;
682 Data += PayloadOffset;
683 Length -= PayloadOffset;
685 if ((Length -= Data[0] + 1) <= 0)
699 pmtPids[NumPmtPids++] = assoc.
getPid();
703 pmtPids[NumPmtPids] = 0;
707 esyslog(
"ERROR: can't parse PAT");
715 Data += PayloadOffset;
716 Length -= PayloadOffset;
720 if ((Length -= Data[0] + 1) <= 0)
723 if (SectionLength(Data, Length) > Length) {
724 if (Length <=
int(
sizeof(pmt))) {
725 memcpy(pmt, Data, Length);
729 esyslog(
"ERROR: PMT packet length too big (%d byte)!", Length);
734 else if (pmtSize > 0) {
736 if (Length <=
int(
sizeof(pmt)) - pmtSize) {
737 memcpy(pmt + pmtSize, Data, Length);
741 esyslog(
"ERROR: PMT section length too big (%d byte)!", pmtSize + Length);
744 if (SectionLength(pmt, pmtSize) > pmtSize)
757 if (updatePrimaryDevice)
770 totalTtxtSubtitlePages = 0;
788 apids[NumApids] = stream.
getPid();
790 *alangs[NumApids] = 0;
797 char *s = alangs[NumApids];
816 if (updatePrimaryDevice)
840 spids[NumSpids] = stream.
getPid();
841 *slangs[NumSpids] = 0;
842 subtitlingTypes[NumSpids] = 0;
843 compositionPageIds[NumSpids] = 0;
844 ancillaryPageIds[NumSpids] = 0;
847 char *s = slangs[NumSpids];
863 if (updatePrimaryDevice)
882 teletextSubtitlePages[totalTtxtSubtitlePages].ttxtType = ttxt.
getTeletextType();
883 totalTtxtSubtitlePages++;
903 dpids[NumDpids] = dpid;
904 dtypes[NumDpids] = dtype;
905 strn0cpy(dlangs[NumDpids], lang,
sizeof(dlangs[NumDpids]));
935 dpids[NumDpids] = stream.
getPid();
937 strn0cpy(dlangs[NumDpids], lang,
sizeof(dlangs[NumDpids]));
957 spids[NumSpids] = stream.
getPid();
958 *slangs[NumSpids] = 0;
959 subtitlingTypes[NumSpids] = 0;
960 compositionPageIds[NumSpids] = 0;
961 ancillaryPageIds[NumSpids] = 0;
962 if (updatePrimaryDevice)
978 if (updatePrimaryDevice) {
986 esyslog(
"ERROR: can't parse PMT");
995 int Pid =
TsPid(Data);
998 else if (IsPmtPid(Pid)) {
1000 if (patVersion >= 0 && pmtVersion >= 0)
1011 PatVersion = patVersion;
1012 PmtVersion = pmtVersion;
1013 return patVersion >= 0 && pmtVersion >= 0;
1041 if (length + Length > size) {
1043 if (
uchar *NewData = (
uchar *)realloc(data, NewSize)) {
1048 esyslog(
"ERROR: out of memory");
1053 memcpy(data + length, Data, Length);
1057 #define MAXPESLENGTH 0xFFF0 1063 Length = lastLength;
1070 uchar *p = data + offset - 6;
1077 memmove(p, data, 4);
1090 lastLength = Length;
1096 if (Length <= length) {
1098 lastLength = Length;
1114 length = offset = 0;
1124 printf(
"--- %s\n", Name);
1125 for (
int i = 0; i < Length; i++) {
1126 if (i && (i % 16) == 0)
1128 printf(
" %02X", Data[i]);
1135 printf(
"%s: %04X", Name, Length);
1136 int n =
min(Length, 20);
1137 for (
int i = 0; i < n; i++)
1138 printf(
" %02X", Data[i]);
1141 n =
max(n, Length - 10);
1142 for (n =
max(n, Length - 10); n < Length; n++)
1143 printf(
" %02X", Data[n]);
1150 TsDump(Name, Data, Length);
1164 virtual int Parse(
const uchar *Data,
int Length,
int Pid) = 0;
1181 independentFrame =
false;
1182 iFrameTemporalReferenceOffset = 0;
1190 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1200 newFrame = independentFrame =
true;
1205 newFrame = independentFrame =
false;
1218 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1224 seenIndependentFrame =
false;
1225 lastIFrameTemporalReference = -1;
1230 newFrame = independentFrame =
false;
1231 bool SeenPayloadStart =
false;
1232 cTsPayload tsPayload(const_cast<uchar *>(Data), Length, Pid);
1234 SeenPayloadStart =
true;
1237 if (debug && seenIndependentFrame)
1240 uint32_t OldScanner = scanner;
1242 if (!SeenPayloadStart && tsPayload.
AtTsStart())
1243 OldScanner = scanner;
1244 scanner = (scanner << 8) | tsPayload.
GetByte();
1245 if (scanner == 0x00000100) {
1247 scanner = OldScanner;
1252 int TemporalReference = (b1 << 2 ) + ((b2 & 0xC0) >> 6);
1253 uchar FrameType = (b2 >> 3) & 0x07;
1254 if (tsPayload.
Find(0x000001B5)) {
1255 if (((tsPayload.
GetByte() & 0xF0) >> 4) == 0x08) {
1258 if (PictureStructure == 0x02)
1263 independentFrame = FrameType == 1;
1264 if (independentFrame) {
1265 if (lastIFrameTemporalReference >= 0)
1266 iFrameTemporalReferenceOffset = TemporalReference - lastIFrameTemporalReference;
1267 lastIFrameTemporalReference = TemporalReference;
1270 seenIndependentFrame |= independentFrame;
1271 if (seenIndependentFrame) {
1272 static const char FrameTypes[] =
"?IPBD???";
1283 return tsPayload.
Used();
1291 nutCodedSliceNonIdr = 1,
1292 nutCodedSliceIdr = 5,
1293 nutSequenceParameterSet = 7,
1294 nutAccessUnitDelimiter = 9,
1308 uchar GetByte(
bool Raw =
false);
1313 uint32_t GetBits(
int Bits);
1314 uint32_t GetGolombUe(
void);
1315 int32_t GetGolombSe(
void);
1316 void ParseAccessUnitDelimiter(
void);
1317 void ParseSequenceParameterSet(
void);
1318 void ParseSliceHeader(
void);
1324 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1333 separate_colour_plane_flag =
false;
1334 log2_max_frame_num = 0;
1335 frame_mbs_only_flag =
false;
1336 gotAccessUnitDelimiter =
false;
1337 gotSequenceParameterSet =
false;
1342 uchar b = tsPayload.GetByte();
1348 if (b == 0x03 && zeroBytes >= 2)
1349 b = tsPayload.GetByte();
1365 return (byte & (1 << bit--)) ? 1 : 0;
1372 b |= GetBit() << Bits;
1379 for (
int b = 0; !b && z < 32; z++)
1381 return (1 << z) - 1 + GetBits(z);
1386 uint32_t v = GetGolombUe();
1388 if ((v & 0x01) != 0)
1391 return -int32_t(v / 2);
1398 newFrame = independentFrame =
false;
1399 tsPayload.Setup(const_cast<uchar *>(Data), Length, Pid);
1401 tsPayload.SkipPesHeader();
1403 if (debug && gotSequenceParameterSet) {
1408 scanner = (scanner << 8) | GetByte(
true);
1409 if ((scanner & 0xFFFFFF00) == 0x00000100) {
1410 uchar NalUnitType = scanner & 0x1F;
1411 switch (NalUnitType) {
1412 case nutAccessUnitDelimiter: ParseAccessUnitDelimiter();
1413 gotAccessUnitDelimiter =
true;
1415 case nutSequenceParameterSet:
if (gotAccessUnitDelimiter) {
1416 ParseSequenceParameterSet();
1417 gotSequenceParameterSet =
true;
1420 case nutCodedSliceNonIdr:
1421 case nutCodedSliceIdr:
if (gotAccessUnitDelimiter && gotSequenceParameterSet) {
1423 gotAccessUnitDelimiter =
false;
1425 tsPayload.Statistics();
1426 return tsPayload.Used();
1432 if (tsPayload.AtPayloadStart()
1436 return tsPayload.Used();
1441 if (debug && gotSequenceParameterSet)
1448 uchar profile_idc = GetByte();
1452 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) {
1453 int chroma_format_idc = GetGolombUe();
1454 if (chroma_format_idc == 3)
1455 separate_colour_plane_flag = GetBit();
1460 for (
int i = 0; i < ((chroma_format_idc != 3) ? 8 : 12); i++) {
1462 int SizeOfScalingList = (i < 6) ? 16 : 64;
1465 for (
int j = 0; j < SizeOfScalingList; j++) {
1467 NextScale = (LastScale + GetGolombSe() + 256) % 256;
1469 LastScale = NextScale;
1475 log2_max_frame_num = GetGolombUe() + 4;
1476 int pic_order_cnt_type = GetGolombUe();
1477 if (pic_order_cnt_type == 0)
1479 else if (pic_order_cnt_type == 1) {
1483 for (
int i = GetGolombUe(); i--; )
1490 frame_mbs_only_flag = GetBit();
1492 if (gotAccessUnitDelimiter && !gotSequenceParameterSet)
1494 dbgframes(frame_mbs_only_flag ?
"S" :
"s");
1502 int slice_type = GetGolombUe();
1503 independentFrame = (slice_type % 5) == 2;
1505 static const char SliceTypes[] =
"PBIpi";
1506 dbgframes(
"%c", SliceTypes[slice_type % 5]);
1508 if (frame_mbs_only_flag)
1511 if (separate_colour_plane_flag)
1513 GetBits(log2_max_frame_num);
1514 if (!frame_mbs_only_flag) {
1516 newFrame = !GetBit();
1529 newFrame = independentFrame =
false;
1532 framesPerSecond = 0;
1533 framesInPayloadUnit = framesPerPayloadUnit = 0;
1539 if (*(uint32_t *)p1 < *(uint32_t *)p2)
return -1;
1540 if (*(uint32_t *)p1 > *(uint32_t *)p2)
return 1;
1548 isVideo = type == 0x01 || type == 0x02 || type == 0x1B;
1551 if (type == 0x01 || type == 0x02)
1553 else if (type == 0x1B)
1555 else if (type == 0x04 || type == 0x06)
1558 esyslog(
"ERROR: unknown stream type %d (PID %d) in frame detector", type, pid);
1566 newFrame = independentFrame =
false;
1571 while (Skipped < Length && (Data[Skipped] !=
TS_SYNC_BYTE || Length - Skipped > TS_SIZE && Data[Skipped + TS_SIZE] !=
TS_SYNC_BYTE))
1573 esyslog(
"ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
1574 return Processed + Skipped;
1579 int Pid =
TsPid(Data);
1588 if (!framesPerPayloadUnit)
1589 framesPerPayloadUnit = framesInPayloadUnit;
1591 int n = parser->Parse(Data, Length, pid);
1593 if (parser->NewFrame()) {
1595 independentFrame = parser->IndependentFrame();
1597 if (framesPerPayloadUnit <= 1)
1601 framesInPayloadUnit++;
1602 if (independentFrame)
1611 if (framesPerSecond <= 0.0) {
1613 if (numPtsValues < 2 || numPtsValues < MaxPtsValues && numIFrames < 2) {
1617 ptsValues[numPtsValues] =
PesGetPts(Pes);
1619 if (numPtsValues && ptsValues[numPtsValues - 1] > 0xF0000000 && ptsValues[numPtsValues] < 0x10000000) {
1629 if (numPtsValues >= 2 && numIFrames >= 2) {
1631 qsort(ptsValues, numPtsValues,
sizeof(uint32_t),
CmpUint32);
1633 for (
int i = 0; i < numPtsValues; i++)
1634 ptsValues[i] = ptsValues[i + 1] - ptsValues[i];
1635 qsort(ptsValues, numPtsValues,
sizeof(uint32_t),
CmpUint32);
1636 int Div = framesPerPayloadUnit;
1637 if (framesPerPayloadUnit > 1)
1638 Div += parser->IFrameTemporalReferenceOffset();
1641 uint32_t Delta = ptsValues[0] / Div;
1644 if (abs(Delta - 3600) <= 1)
1645 framesPerSecond = 25.0;
1646 else if (Delta % 3003 == 0)
1647 framesPerSecond = 30.0 / 1.001;
1648 else if (abs(Delta - 1800) <= 1)
1649 framesPerSecond = 50.0;
1650 else if (Delta == 1501)
1651 framesPerSecond = 60.0 / 1.001;
1658 framesPerSecond = double(
PTSTICKS) / Delta;
1659 dbgframes(
"\nDelta = %d FPS = %5.2f FPPU = %d NF = %d TRO = %d\n", Delta, framesPerSecond, framesPerPayloadUnit, numPtsValues + 1, parser->IFrameTemporalReferenceOffset());
1661 parser->SetDebug(
false);
1666 else if (Pid ==
PATPID && synced && Processed)
1671 Processed += Handled;
1682 LastContinuityOutput = -1;
1688 LastContinuityInput = -1;
1689 ContinuityOffset = 0;
1692 NaluFillState = NALU_NONE;
1694 History = 0xffffffff;
1695 DropAllPayload =
false;
1702 int LastKeepByte = -1;
1706 History = 0xffffffff;
1708 NaluFillState = NALU_NONE;
1711 for (
int i=0; i<size; i++) {
1712 History = (History << 8) | Payload[i];
1717 bool DropByte =
false;
1719 if (History >= 0x00000180 && History <= 0x000001FF)
1722 PesId = History & 0xff;
1724 NaluFillState = NALU_NONE;
1726 else if (PesId >= 0xe0 && PesId <= 0xef
1727 && History >= 0x00000100 && History <= 0x0000017F)
1729 int NaluId = History & 0xff;
1731 NaluFillState = ((NaluId & 0x1f) == 0x0c) ? NALU_FILL : NALU_NONE;
1734 if (PesId >= 0xe0 && PesId <= 0xef
1735 && PesOffset >= 1 && PesOffset <= 2)
1740 if (NaluFillState == NALU_FILL && NaluOffset > 0)
1744 if (Payload[i] == 0xFF)
1748 else if (Payload[i] == 0x80)
1750 NaluFillState = NALU_TERM;
1755 dsyslog(
"cNaluDumper: Unexpected NALU fill data: %02x", Payload[i]);
1756 NaluFillState = NALU_END;
1757 if (LastKeepByte == -1)
1765 else if (NaluFillState == NALU_TERM)
1768 NaluFillState = NALU_END;
1769 if (LastKeepByte == -1)
1792 if (LastContinuityInput >= 0)
1794 int NewContinuityInput = HasPayload ? (LastContinuityInput + 1) &
TS_CONT_CNT_MASK : LastContinuityInput;
1797 dsyslog(
"cNaluDumper: TS continuity offset %i", Offset);
1798 if (Offset > ContinuityOffset)
1799 ContinuityOffset = Offset;
1801 LastContinuityInput = ContinuityInput;
1811 DropAllPayload =
false;
1826 bool DropThisPayload = DropAllPayload;
1833 DropAllPayload =
true;
1841 if (DropThisPayload && HasAdaption)
1845 DropThisPayload =
false;
1848 if (DropThisPayload)
1856 NewContinuityOutput = (NewContinuityOutput + ContinuityOffset) &
TS_CONT_CNT_MASK;
1858 LastContinuityOutput = NewContinuityOutput;
1859 ContinuityOffset = 0;
1868 pPatPmtParser = NULL;
1873 tempLengthAtEnd =
false;
1881 esyslog(
"cNaluStreamProcessor::PutBuffer: New data before old data was processed!");
1897 if (tempLengthAtEnd)
1900 for (
int i=0; i<tempLength; i++)
1901 tempBuffer[i] = tempBuffer[
TS_SIZE-tempLength+i];
1904 if (tempLength < TS_SIZE && length > 0)
1907 memcpy(tempBuffer+tempLength, data, Size);
1915 tempLengthAtEnd =
false;
1926 esyslog(
"ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
1928 tempLengthAtEnd =
true;
1929 tempLength =
TS_SIZE - Skipped;
1930 OutLength = Skipped;
1934 int Pid =
TsPid(tempBuffer);
1938 pPatPmtParser->ParsePat(tempBuffer,
TS_SIZE);
1939 else if (pPatPmtParser->IsPmtPid(Pid))
1940 pPatPmtParser->ParsePmt(tempBuffer,
TS_SIZE);
1945 if (Pid == vpid || (pPatPmtParser && Pid == pPatPmtParser->Vpid() && pPatPmtParser->Vtype() == 0x1B))
1946 Drop = NaluDumper.ProcessTSPacket(tempBuffer);
1962 uchar *OutEnd = Out;
1970 esyslog(
"ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
1974 memcpy(OutEnd, data, Skipped);
1980 int Pid =
TsPid(data);
1984 pPatPmtParser->ParsePat(data,
TS_SIZE);
1985 else if (pPatPmtParser->IsPmtPid(Pid))
1986 pPatPmtParser->ParsePmt(data,
TS_SIZE);
1991 if (Pid == vpid || (pPatPmtParser && Pid == pPatPmtParser->Vpid() && pPatPmtParser->Vtype() == 0x1B))
1992 Drop = NaluDumper.ProcessTSPacket(data);
1996 memcpy(OutEnd, data,
TS_SIZE);
2010 memcpy(tempBuffer, data, length);
2011 tempLength = length;
2012 tempLengthAtEnd =
false;
2015 OutLength = (OutEnd - Out);
2016 return OutLength > 0 ? Out : NULL;
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)
int TotalTeletextSubtitlePages() const
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.
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.
int MakeTeletextDescriptor(uchar *Target, const tTeletextSubtitlePage *pages, int pageCount)
#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...
StructureLoop< Teletext > teletextLoop
const char * Dlang(int i) const
StructureLoop< Subtitling > subtitlingLoop
void ParseSequenceParameterSet(void)
int64_t TsGetDts(const uchar *p, int l)
void TsExtendAdaptionField(unsigned char *Packet, int ToLength)
int MakeAC3Descriptor(uchar *Target, uchar Type)
int getTeletextPageNumber() const
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
int TsContinuityCounter(const uchar *p)
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)
const tTeletextSubtitlePage * TeletextSubtitlePages() const
cPatPmtParser(bool UpdatePrimaryDevice=false)
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.
void TsSetContinuityCounter(uchar *p, uchar Counter)
void ProcessPayload(unsigned char *Payload, int size, bool PayloadStart, sPayloadInfo &Info)
int getSubtitlingType() const
StructureLoop< Language > languageLoop
#define WRN_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION
int TsGetPayload(const uchar **p)
int getTeletextType() const
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)
uint32_t GetBits(int Bits)
static void SetBrokenLink(uchar *Data, int Length)
char ttxtLanguage[MAXLANGCODE1]
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
bool ProcessTSPacket(unsigned char *Packet)
#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)
int64_t TsGetPts(const uchar *p, int l)
uint16_t CompositionPageId(int i) const
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
int DropPayloadStartBytes
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)
int getTeletextMagazineNumber() const
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 PutBuffer(uchar *Data, int Length)
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.
uchar * GetBuffer(int &OutLength)
bool SkipPesHeader(void)
Skips all bytes belonging to the PES header of the payload.