23 #define dbgpatpmt(a...) if (DebugPatPmt) fprintf(stderr, a)
24 #define dbgframes(a...) if (DebugFrames) fprintf(stderr, a)
26 #define EMPTY_SCANNER (0xFFFFFFFF)
33 if ((Data[6] & 0xC0) == 0x80) {
37 PesPayloadOffset = 6 + 3 + Data[8];
38 if (Count < PesPayloadOffset)
41 if (ContinuationHeader)
42 *ContinuationHeader = ((Data[6] == 0x80) && !Data[7] && !Data[8]);
51 for (
int i = 0; i < 16; i++) {
52 if (Data[PesPayloadOffset] != 0xFF)
55 if (Count <= ++PesPayloadOffset)
60 if ((Data[PesPayloadOffset] & 0xC0) == 0x40) {
61 PesPayloadOffset += 2;
63 if (Count <= PesPayloadOffset)
67 if (ContinuationHeader)
68 *ContinuationHeader =
false;
70 if ((Data[PesPayloadOffset] & 0xF0) == 0x20) {
72 PesPayloadOffset += 5;
74 else if ((Data[PesPayloadOffset] & 0xF0) == 0x30) {
76 PesPayloadOffset += 10;
78 else if (Data[PesPayloadOffset] == 0x0F) {
82 if (ContinuationHeader)
83 *ContinuationHeader =
true;
88 if (Count < PesPayloadOffset)
94 #define VIDEO_STREAM_S 0xE0
102 for (
int i = PesPayloadOffset; i < Length - 7; i++) {
103 if (Data[i] == 0 && Data[i + 1] == 0 && Data[i + 2] == 1 && Data[i + 3] == 0xB8) {
104 if (!(Data[i + 7] & 0x40))
109 dsyslog(
"SetBrokenLink: no GOP header found in video packet");
112 dsyslog(
"SetBrokenLink: no video packet in frame");
124 memset(p + 6, 0xFF,
TS_SIZE - 6);
137 p[10] = (b << 7) | (p[10] & 0x7E) | ((e >> 8) & 0x01);
201 p[ 9] = ((Pts >> 29) & 0x0E) | (p[9] & 0xF1);
203 p[11] = ((Pts >> 14) & 0xFE) | 0x01;
205 p[13] = ((Pts << 1) & 0xFE) | 0x01;
210 p[14] = ((Dts >> 29) & 0x0E) | (p[14] & 0xF1);
212 p[16] = ((Dts >> 14) & 0xFE) | 0x01;
214 p[18] = ((Dts << 1) & 0xFE) | 0x01;
219 int64_t d = Pts2 - Pts1;
239 Setup(Data, Length, Pid);
298 if (Index >= 0 && Index <
length)
304 int OldIndex =
index;
307 Scanner = (Scanner << 8) |
GetByte();
343 if (Offset == 4 && Offset < NewPayload)
345 if (Offset == 5 && Offset < NewPayload)
346 Packet[Offset++] = 0;
347 while (Offset < NewPayload)
348 Packet[Offset++] = 0xff;
365 TsPacket[3] = (TsPacket[3] & 0xF0) | Counter;
366 if (++Counter > 0x0F)
372 if (++Version > 0x1F)
389 Target[i++] = 0xE0 | (Pid >> 8);
412 Target[i++] = *Language++;
413 Target[i++] = *Language++;
414 Target[i++] = *Language++;
415 Target[i++] = SubtitlingType;
416 Target[i++] = CompositionPageId >> 8;
417 Target[i++] = CompositionPageId & 0xFF;
418 Target[i++] = AncillaryPageId >> 8;
419 Target[i++] = AncillaryPageId & 0xFF;
430 for (
int n = 0; n < pageCount; n++) {
432 Target[i++] = *Language++;
433 Target[i++] = *Language++;
434 Target[i++] = *Language++;
435 Target[i++] = (pages[n].
ttxtType << 3) + pages[n].ttxtMagazine;
452 Target[Length] = 0x00;
453 for (
const char *End = Language + strlen(Language); Language < End; ) {
454 Target[i++] = *Language++;
455 Target[i++] = *Language++;
456 Target[i++] = *Language++;
458 Target[Length] += 0x04;
459 if (*Language ==
'+')
470 Target[i++] = crc >> 24;
471 Target[i++] = crc >> 16;
472 Target[i++] = crc >> 8;
477 #define P_TSID 0x8008 // pseudo TS ID
478 #define P_PMT_PID 0x0084 // pseudo PMT pid
479 #define MAXPID 0x2000 // the maximum possible number of pids
483 bool Used[
MAXPID] = {
false };
484 #define SETPID(p) { if ((p) >= 0 && (p) < MAXPID) Used[p] = true; }
485 #define SETPIDS(l) { const int *p = l; while (*p) { SETPID(*p); p++; } }
498 memset(
pat, 0xFF,
sizeof(
pat));
506 int PayloadStart = i;
509 int SectionLength = i;
518 p[i++] = 0xE0 | (
pmtPid >> 8);
520 pat[SectionLength] = i - SectionLength - 1 + 4;
529 memset(buf, 0xFF,
sizeof(buf));
532 int Vpid = Channel->
Vpid();
533 int Ppid = Channel->
Ppid();
534 int Tpid = Channel->
Tpid();
538 int SectionLength = i;
546 p[i++] = 0xE0 | (Ppid >> 8);
553 for (
int n = 0; Channel->
Apid(n); n++) {
555 const char *Alang = Channel->
Alang(n);
558 for (
int n = 0; Channel->
Dpid(n); n++) {
563 for (
int n = 0; Channel->
Spid(n); n++) {
572 int sl = i - SectionLength - 2 + 4;
573 buf[SectionLength] |= (sl >> 8) & 0x0F;
574 buf[SectionLength + 1] = sl;
651 Data += PayloadOffset;
652 Length -= PayloadOffset;
654 if ((Length -= Data[0] + 1) <= 0)
676 esyslog(
"ERROR: can't parse PAT");
684 Data += PayloadOffset;
685 Length -= PayloadOffset;
689 if ((Length -= Data[0] + 1) <= 0)
693 if (Length <=
int(
sizeof(
pmt))) {
694 memcpy(
pmt, Data, Length);
698 esyslog(
"ERROR: PMT packet length too big (%d byte)!", Length);
710 esyslog(
"ERROR: PMT section length too big (%d byte)!",
pmtSize + Length);
766 char *s =
alangs[NumApids];
816 char *s =
slangs[NumSpids];
872 dpids[NumDpids] = dpid;
922 esyslog(
"ERROR: can't parse PMT");
931 int Pid =
TsPid(Data);
984 esyslog(
"ERROR: out of memory");
993 #define MAXPESLENGTH 0xFFF0
1013 memmove(p,
data, 4);
1060 printf(
"--- %s\n", Name);
1061 for (
int i = 0; i < Length; i++) {
1062 if (i && (i % 16) == 0)
1064 printf(
" %02X", Data[i]);
1071 printf(
"%s: %04X", Name, Length);
1072 int n =
min(Length, 20);
1073 for (
int i = 0; i < n; i++)
1074 printf(
" %02X", Data[i]);
1077 n =
max(n, Length - 10);
1078 for (n =
max(n, Length - 10); n < Length; n++)
1079 printf(
" %02X", Data[n]);
1086 TsDump(Name, Data, Length);
1099 virtual int Parse(
const uchar *Data,
int Length,
int Pid) = 0;
1123 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1150 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1162 bool SeenPayloadStart =
false;
1163 cTsPayload tsPayload(const_cast<uchar *>(Data), Length, Pid);
1165 SeenPayloadStart =
true;
1171 uint32_t OldScanner =
scanner;
1173 if (!SeenPayloadStart && tsPayload.
AtTsStart())
1188 static const char FrameTypes[] =
"?IPBD???";
1199 return tsPayload.
Used();
1240 virtual int Parse(
const uchar *Data,
int Length,
int Pid);
1281 return (
byte & (1 <<
bit--)) ? 1 : 0;
1295 for (
int b = 0; !b; z++)
1297 return (1 << z) - 1 +
GetBits(z);
1304 if ((v & 0x01) != 0)
1307 return -int32_t(v / 2);
1325 if ((
scanner & 0xFFFFFF00) == 0x00000100) {
1327 switch (NalUnitType) {
1365 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) {
1367 if (chroma_format_idc == 3)
1373 for (
int i = 0; i < ((chroma_format_idc != 3) ? 8 : 12); i++) {
1375 int SizeOfScalingList = (i < 6) ? 16 : 64;
1378 for (
int j = 0; j < SizeOfScalingList; j++) {
1380 NextScale = (LastScale +
GetGolombSe() + 256) % 256;
1382 LastScale = NextScale;
1390 if (pic_order_cnt_type == 0)
1392 else if (pic_order_cnt_type == 1) {
1418 static const char SliceTypes[] =
"PBIpi";
1419 dbgframes(
"%c", SliceTypes[slice_type % 5]);
1452 if (*(uint32_t *)p1 < *(uint32_t *)p2)
return -1;
1453 if (*(uint32_t *)p1 > *(uint32_t *)p2)
return 1;
1466 else if (
type == 0x1B)
1468 else if (
type == 0x04 ||
type == 0x06)
1471 esyslog(
"ERROR: unknown stream type %d (PID %d) in frame detector",
type,
pid);
1484 while (Skipped < Length && (Data[Skipped] !=
TS_SYNC_BYTE || Length - Skipped > TS_SIZE && Data[Skipped + TS_SIZE] !=
TS_SYNC_BYTE))
1486 esyslog(
"ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
1487 return Processed + Skipped;
1492 int Pid =
TsPid(Data);
1552 if (abs(Delta - 3600) <= 1)
1554 else if (Delta % 3003 == 0)
1556 else if (abs(Delta - 1800) <= 1)
1558 else if (Delta == 1501)
1579 Processed += Handled;
1610 int LastKeepByte = -1;
1619 for (
int i=0; i<size; i++) {
1625 bool DropByte =
false;
1652 if (Payload[i] == 0xFF)
1656 else if (Payload[i] == 0x80)
1663 dsyslog(
"cNaluDumper: Unexpected NALU fill data: %02x", Payload[i]);
1665 if (LastKeepByte == -1)
1677 if (LastKeepByte == -1)
1705 dsyslog(
"cNaluDumper: TS continuity offset %i", Offset);
1749 if (DropThisPayload && HasAdaption)
1753 DropThisPayload =
false;
1756 if (DropThisPayload)
1789 esyslog(
"cNaluStreamProcessor::PutBuffer: New data before old data was processed!");
1812 if (tempLength < TS_SIZE && length > 0)
1834 esyslog(
"ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
1838 OutLength = Skipped;
1870 uchar *OutEnd = Out;
1878 esyslog(
"ERROR: skipped %d bytes to sync on start of TS packet", Skipped);
1882 memcpy(OutEnd,
data, Skipped);
1923 OutLength = (OutEnd - Out);
1924 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
uchar subtitlingTypes[MAXSPIDS]
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 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.
uint16_t ancillaryPageIds[MAXSPIDS]
bool IsPmtPid(int Pid) const
Returns true if Pid the one of the PMT pids as defined by the current PAT.
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
char alangs[MAXAPIDS][MAXLANGCODE2]
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
uint32_t ptsValues[MaxPtsValues]
StructureLoop< Stream > streamLoop
char slangs[MAXSPIDS][MAXLANGCODE2]
#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 Vpid(void) const
Returns the video pid as defined by the current PMT, or 0 if no video pid has been detected...
int MakeTeletextDescriptor(uchar *Target, const tTeletextSubtitlePage *pages, int pageCount)
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)
cPatPmtParser * pPatPmtParser
int MakeAC3Descriptor(uchar *Target, uchar Type)
tTeletextSubtitlePage teletextSubtitlePages[MAXTXTPAGES]
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 SectionLength(const uchar *Data, int Length)
int Available(void)
Returns the number of raw bytes (including any TS headers) still available in the TS payload handler...
int MakeStream(uchar *Target, uchar Type, int Pid)
uchar GetByte(bool Raw=false)
Gets the next data byte.
bool Eof(void) const
Returns true if all available bytes of the TS payload have been processed.
uchar pmt[MAX_PMT_TS][TS_SIZE]
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.
long long int DroppedPackets
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 Vtype(void) const
Returns the video stream type as defined by the current PMT, or 0 if no video stream type has been de...
int TsContinuityCounter(const uchar *p)
cH264Parser(void)
Sets up a new H.264 parser.
char dlangs[MAXDPIDS][MAXLANGCODE2]
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...
virtual int Parse(const uchar *Data, int Length, int Pid)=0
Parses the given Data, which is a sequence of Length bytes of TS packets.
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)
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
int TsGetPayload(const uchar **p)
int getTeletextType() const
long long int TotalPackets
void GeneratePmt(const cChannel *Channel)
Generates a PMT section for the given Channel, for later use with GetPmt().
uchar pmt[MAX_SECTION_SIZE]
int32_t GetGolombSe(void)
void TsHidePayload(uchar *p)
uint16_t compositionPageIds[MAXSPIDS]
int getStreamType() const
void PesDump(const char *Name, const u_char *Data, int Length)
int pmtPids[MAX_PMT_PIDS+1]
uint32_t GetBits(int Bits)
static void SetBrokenLink(uchar *Data, int Length)
char ttxtLanguage[MAXLANGCODE1]
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
int totalTtxtSubtitlePages
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
eNaluFillState NaluFillState
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.
uchar tempBuffer[TS_SIZE]