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);
351 patCounter = pmtCounter = 0;
352 patVersion = pmtVersion = 0;
360 TsPacket[3] = (TsPacket[3] & 0xF0) | Counter;
361 if (++Counter > 0x0F)
367 if (++Version > 0x1F)
374 Length += ((*esInfoLength & 0x0F) << 8) | *(esInfoLength + 1);
375 *esInfoLength = 0xF0 | (Length >> 8);
376 *(esInfoLength + 1) = Length;
384 Target[i++] = 0xE0 | (Pid >> 8);
386 esInfoLength = &Target[i];
407 Target[i++] = *Language++;
408 Target[i++] = *Language++;
409 Target[i++] = *Language++;
410 Target[i++] = SubtitlingType;
411 Target[i++] = CompositionPageId >> 8;
412 Target[i++] = CompositionPageId & 0xFF;
413 Target[i++] = AncillaryPageId >> 8;
414 Target[i++] = AncillaryPageId & 0xFF;
424 Target[Length] = 0x00;
425 for (
const char *End = Language + strlen(Language); Language < End; ) {
426 Target[i++] = *Language++;
427 Target[i++] = *Language++;
428 Target[i++] = *Language++;
430 Target[Length] += 0x04;
431 if (*Language ==
'+')
442 Target[i++] = crc >> 24;
443 Target[i++] = crc >> 16;
444 Target[i++] = crc >> 8;
449 #define P_TSID 0x8008 // pseudo TS ID 450 #define P_PMT_PID 0x0084 // pseudo PMT pid 451 #define MAXPID 0x2000 // the maximum possible number of pids 455 bool Used[
MAXPID] = {
false };
456 #define SETPID(p) { if ((p) >= 0 && (p) < MAXPID) Used[p] = true; } 457 #define SETPIDS(l) { const int *p = l; while (*p) { SETPID(*p); p++; } } 464 for (pmtPid =
P_PMT_PID; Used[pmtPid]; pmtPid++)
470 memset(pat, 0xFF,
sizeof(pat));
478 int PayloadStart = i;
481 int SectionLength = i;
485 p[i++] = 0xC1 | (patVersion << 1);
488 p[i++] = pmtPid >> 8;
489 p[i++] = pmtPid & 0xFF;
490 p[i++] = 0xE0 | (pmtPid >> 8);
491 p[i++] = pmtPid & 0xFF;
492 pat[SectionLength] = i - SectionLength - 1 + 4;
493 MakeCRC(pat + i, pat + PayloadStart, i - PayloadStart);
494 IncVersion(patVersion);
501 memset(buf, 0xFF,
sizeof(buf));
504 int Vpid = Channel->
Vpid();
505 int Ppid = Channel->
Ppid();
509 int SectionLength = i;
512 p[i++] = pmtPid >> 8;
513 p[i++] = pmtPid & 0xFF;
514 p[i++] = 0xC1 | (pmtVersion << 1);
517 p[i++] = 0xE0 | (Ppid >> 8);
523 i += MakeStream(buf + i, Channel->
Vtype(), Vpid);
524 for (
int n = 0; Channel->
Apid(n); n++) {
525 i += MakeStream(buf + i, Channel->
Atype(n), Channel->
Apid(n));
526 const char *Alang = Channel->
Alang(n);
527 i += MakeLanguageDescriptor(buf + i, Alang);
529 for (
int n = 0; Channel->
Dpid(n); n++) {
530 i += MakeStream(buf + i, 0x06, Channel->
Dpid(n));
531 i += MakeAC3Descriptor(buf + i, Channel->
Dtype(n));
532 i += MakeLanguageDescriptor(buf + i, Channel->
Dlang(n));
534 for (
int n = 0; Channel->
Spid(n); n++) {
535 i += MakeStream(buf + i, 0x06, Channel->
Spid(n));
539 int sl = i - SectionLength - 2 + 4;
540 buf[SectionLength] |= (sl >> 8) & 0x0F;
541 buf[SectionLength + 1] = sl;
542 MakeCRC(buf + i, buf, i);
547 uchar *p = pmt[numPmtPackets++];
551 p[j++] = pmtPid & 0xFF;
562 IncVersion(pmtVersion);
568 patVersion = PatVersion & 0x1F;
569 pmtVersion = PmtVersion & 0x1F;
575 GeneratePmtPid(Channel);
577 GeneratePmt(Channel);
583 IncCounter(patCounter, pat);
589 if (Index < numPmtPackets) {
590 IncCounter(pmtCounter, pmt[Index]);
600 updatePrimaryDevice = UpdatePrimaryDevice;
607 patVersion = pmtVersion = -1;
617 Data += PayloadOffset;
618 Length -= PayloadOffset;
620 if ((Length -= Data[0] + 1) <= 0)
634 pmtPids[NumPmtPids++] = assoc.
getPid();
638 pmtPids[NumPmtPids] = 0;
642 esyslog(
"ERROR: can't parse PAT");
650 Data += PayloadOffset;
651 Length -= PayloadOffset;
655 if ((Length -= Data[0] + 1) <= 0)
658 if (SectionLength(Data, Length) > Length) {
659 if (Length <=
int(
sizeof(pmt))) {
660 memcpy(pmt, Data, Length);
664 esyslog(
"ERROR: PMT packet length too big (%d byte)!", Length);
669 else if (pmtSize > 0) {
671 if (Length <=
int(
sizeof(pmt)) - pmtSize) {
672 memcpy(pmt + pmtSize, Data, Length);
676 esyslog(
"ERROR: PMT section length too big (%d byte)!", pmtSize + Length);
679 if (SectionLength(pmt, pmtSize) > pmtSize)
692 if (updatePrimaryDevice)
721 apids[NumApids] = stream.
getPid();
723 *alangs[NumApids] = 0;
730 char *s = alangs[NumApids];
749 if (updatePrimaryDevice)
773 spids[NumSpids] = stream.
getPid();
774 *slangs[NumSpids] = 0;
775 subtitlingTypes[NumSpids] = 0;
776 compositionPageIds[NumSpids] = 0;
777 ancillaryPageIds[NumSpids] = 0;
780 char *s = slangs[NumSpids];
796 if (updatePrimaryDevice)
814 dpids[NumDpids] = dpid;
815 dtypes[NumDpids] = dtype;
816 strn0cpy(dlangs[NumDpids], lang,
sizeof(dlangs[NumDpids]));
846 dpids[NumDpids] = stream.
getPid();
848 strn0cpy(dlangs[NumDpids], lang,
sizeof(dlangs[NumDpids]));
868 spids[NumSpids] = stream.
getPid();
869 *slangs[NumSpids] = 0;
870 subtitlingTypes[NumSpids] = 0;
871 compositionPageIds[NumSpids] = 0;
872 ancillaryPageIds[NumSpids] = 0;
873 if (updatePrimaryDevice)
889 if (updatePrimaryDevice) {
897 esyslog(
"ERROR: can't parse PMT");
906 int Pid =
TsPid(Data);
909 else if (IsPmtPid(Pid)) {
911 if (patVersion >= 0 && pmtVersion >= 0)
922 PatVersion = patVersion;
923 PmtVersion = pmtVersion;
924 return patVersion >= 0 && pmtVersion >= 0;
952 if (length + Length > size) {
954 if (
uchar *NewData = (
uchar *)realloc(data, NewSize)) {
959 esyslog(
"ERROR: out of memory");
964 memcpy(data + length, Data, Length);
968 #define MAXPESLENGTH 0xFFF0 981 uchar *p = data + offset - 6;
1001 lastLength = Length;
1007 if (Length <= length) {
1009 lastLength = Length;
1025 length = offset = 0;
1035 printf(
"--- %s\n", Name);
1036 for (
int i = 0; i < Length; i++) {
1037 if (i && (i % 16) == 0)
1039 printf(
" %02X", Data[i]);
1046 printf(
"%s: %04X", Name, Length);
1047 int n =
min(Length, 20);
1048 for (
int i = 0; i < n; i++)
1049 printf(
" %02X", Data[i]);
1052 n =
max(n, Length - 10);
1053 for (n =
max(n, Length - 10); n < Length; n++)
1054 printf(
" %02X", Data[n]);
1061 TsDump(Name, Data, Length);
1075 virtual int Parse(
const uchar *Data,
int Length,
int Pid) = 0;
1092 independentFrame =
false;
1093 iFrameTemporalReferenceOffset = 0;
1101 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1111 newFrame = independentFrame =
true;
1116 newFrame = independentFrame =
false;
1129 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1135 seenIndependentFrame =
false;
1136 lastIFrameTemporalReference = -1;
1141 newFrame = independentFrame =
false;
1142 bool SeenPayloadStart =
false;
1143 cTsPayload tsPayload(const_cast<uchar *>(Data), Length, Pid);
1145 SeenPayloadStart =
true;
1148 if (debug && seenIndependentFrame)
1151 uint32_t OldScanner = scanner;
1153 if (!SeenPayloadStart && tsPayload.
AtTsStart())
1154 OldScanner = scanner;
1155 scanner = (scanner << 8) | tsPayload.
GetByte();
1156 if (scanner == 0x00000100) {
1158 scanner = OldScanner;
1163 int TemporalReference = (b1 << 2 ) + ((b2 & 0xC0) >> 6);
1164 uchar FrameType = (b2 >> 3) & 0x07;
1165 if (tsPayload.
Find(0x000001B5)) {
1166 if (((tsPayload.
GetByte() & 0xF0) >> 4) == 0x08) {
1169 if (PictureStructure == 0x02)
1174 independentFrame = FrameType == 1;
1175 if (independentFrame) {
1176 if (lastIFrameTemporalReference >= 0)
1177 iFrameTemporalReferenceOffset = TemporalReference - lastIFrameTemporalReference;
1178 lastIFrameTemporalReference = TemporalReference;
1181 seenIndependentFrame |= independentFrame;
1182 if (seenIndependentFrame) {
1183 static const char FrameTypes[] =
"?IPBD???";
1194 return tsPayload.
Used();
1202 nutCodedSliceNonIdr = 1,
1203 nutCodedSliceIdr = 5,
1204 nutSequenceParameterSet = 7,
1205 nutAccessUnitDelimiter = 9,
1219 uchar GetByte(
bool Raw =
false);
1224 uint32_t GetBits(
int Bits);
1225 uint32_t GetGolombUe(
void);
1226 int32_t GetGolombSe(
void);
1227 void ParseAccessUnitDelimiter(
void);
1228 void ParseSequenceParameterSet(
void);
1229 void ParseSliceHeader(
void);
1235 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1244 separate_colour_plane_flag =
false;
1245 log2_max_frame_num = 0;
1246 frame_mbs_only_flag =
false;
1247 gotAccessUnitDelimiter =
false;
1248 gotSequenceParameterSet =
false;
1253 uchar b = tsPayload.GetByte();
1259 if (b == 0x03 && zeroBytes >= 2)
1260 b = tsPayload.GetByte();
1276 return (byte & (1 << bit--)) ? 1 : 0;
1283 b |= GetBit() << Bits;
1290 for (
int b = 0; !b && z < 32; z++)
1292 return (1 << z) - 1 + GetBits(z);
1297 uint32_t v = GetGolombUe();
1299 if ((v & 0x01) != 0)
1302 return -int32_t(v / 2);
1309 newFrame = independentFrame =
false;
1310 tsPayload.Setup(const_cast<uchar *>(Data), Length, Pid);
1312 tsPayload.SkipPesHeader();
1314 if (debug && gotSequenceParameterSet) {
1319 scanner = (scanner << 8) | GetByte(
true);
1320 if ((scanner & 0xFFFFFF00) == 0x00000100) {
1321 uchar NalUnitType = scanner & 0x1F;
1322 switch (NalUnitType) {
1323 case nutAccessUnitDelimiter: ParseAccessUnitDelimiter();
1324 gotAccessUnitDelimiter =
true;
1326 case nutSequenceParameterSet:
if (gotAccessUnitDelimiter) {
1327 ParseSequenceParameterSet();
1328 gotSequenceParameterSet =
true;
1331 case nutCodedSliceNonIdr:
1332 case nutCodedSliceIdr:
if (gotAccessUnitDelimiter && gotSequenceParameterSet) {
1334 gotAccessUnitDelimiter =
false;
1336 tsPayload.Statistics();
1337 return tsPayload.Used();
1343 if (tsPayload.AtPayloadStart()
1347 return tsPayload.Used();
1352 if (debug && gotSequenceParameterSet)
1359 uchar profile_idc = GetByte();
1363 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) {
1364 int chroma_format_idc = GetGolombUe();
1365 if (chroma_format_idc == 3)
1366 separate_colour_plane_flag = GetBit();
1371 for (
int i = 0; i < ((chroma_format_idc != 3) ? 8 : 12); i++) {
1373 int SizeOfScalingList = (i < 6) ? 16 : 64;
1376 for (
int j = 0; j < SizeOfScalingList; j++) {
1378 NextScale = (LastScale + GetGolombSe() + 256) % 256;
1380 LastScale = NextScale;
1386 log2_max_frame_num = GetGolombUe() + 4;
1387 int pic_order_cnt_type = GetGolombUe();
1388 if (pic_order_cnt_type == 0)
1390 else if (pic_order_cnt_type == 1) {
1394 for (
int i = GetGolombUe(); i--; )
1401 frame_mbs_only_flag = GetBit();
1403 if (gotAccessUnitDelimiter && !gotSequenceParameterSet)
1405 dbgframes(frame_mbs_only_flag ?
"S" :
"s");
1413 int slice_type = GetGolombUe();
1414 independentFrame = (slice_type % 5) == 2;
1416 static const char SliceTypes[] =
"PBIpi";
1417 dbgframes(
"%c", SliceTypes[slice_type % 5]);
1419 if (frame_mbs_only_flag)
1422 if (separate_colour_plane_flag)
1424 GetBits(log2_max_frame_num);
1425 if (!frame_mbs_only_flag) {
1427 newFrame = !GetBit();
1440 newFrame = independentFrame =
false;
1443 framesPerSecond = 0;
1444 framesInPayloadUnit = framesPerPayloadUnit = 0;
1450 if (*(uint32_t *)p1 < *(uint32_t *)p2)
return -1;
1451 if (*(uint32_t *)p1 > *(uint32_t *)p2)
return 1;
1459 isVideo = type == 0x01 || type == 0x02 || type == 0x1B;
1462 if (type == 0x01 || type == 0x02)
1464 else if (type == 0x1B)
1466 else if (type == 0x04 || type == 0x06)
1469 esyslog(
"ERROR: unknown stream type %d (PID %d) in frame detector", type, pid);
1477 newFrame = independentFrame =
false;
1482 while (Skipped < Length && (Data[Skipped] !=
TS_SYNC_BYTE || Length - Skipped > TS_SIZE && Data[Skipped + TS_SIZE] !=
TS_SYNC_BYTE))
1484 esyslog(
"ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
1485 return Processed + Skipped;
1490 int Pid =
TsPid(Data);
1499 if (!framesPerPayloadUnit)
1500 framesPerPayloadUnit = framesInPayloadUnit;
1502 int n = parser->Parse(Data, Length, pid);
1504 if (parser->NewFrame()) {
1506 independentFrame = parser->IndependentFrame();
1508 if (framesPerPayloadUnit <= 1)
1512 framesInPayloadUnit++;
1513 if (independentFrame)
1522 if (framesPerSecond <= 0.0) {
1524 if (numPtsValues < 2 || numPtsValues < MaxPtsValues && numIFrames < 2) {
1528 ptsValues[numPtsValues] =
PesGetPts(Pes);
1530 if (numPtsValues && ptsValues[numPtsValues - 1] > 0xF0000000 && ptsValues[numPtsValues] < 0x10000000) {
1540 if (numPtsValues >= 2 && numIFrames >= 2) {
1542 qsort(ptsValues, numPtsValues,
sizeof(uint32_t),
CmpUint32);
1544 for (
int i = 0; i < numPtsValues; i++)
1545 ptsValues[i] = ptsValues[i + 1] - ptsValues[i];
1546 qsort(ptsValues, numPtsValues,
sizeof(uint32_t),
CmpUint32);
1547 int Div = framesPerPayloadUnit;
1548 if (framesPerPayloadUnit > 1)
1549 Div += parser->IFrameTemporalReferenceOffset();
1552 uint32_t Delta = ptsValues[0] / Div;
1555 if (abs(Delta - 3600) <= 1)
1556 framesPerSecond = 25.0;
1557 else if (Delta % 3003 == 0)
1558 framesPerSecond = 30.0 / 1.001;
1559 else if (abs(Delta - 1800) <= 1)
1560 framesPerSecond = 50.0;
1561 else if (Delta == 1501)
1562 framesPerSecond = 60.0 / 1.001;
1569 framesPerSecond = double(
PTSTICKS) / Delta;
1570 dbgframes(
"\nDelta = %d FPS = %5.2f FPPU = %d NF = %d TRO = %d\n", Delta, framesPerSecond, framesPerPayloadUnit, numPtsValues + 1, parser->IFrameTemporalReferenceOffset());
1572 parser->SetDebug(
false);
1577 else if (Pid ==
PATPID && synced && Processed)
1582 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.
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 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.
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)
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)
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
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.