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) {
45 if (ContinuationHeader)
46 *ContinuationHeader = ((Data[6] == 0x80) && !Data[7] && !Data[8]);
55 for (
int i = 0; i < 16; i++) {
71 if (ContinuationHeader)
72 *ContinuationHeader =
false;
86 if (ContinuationHeader)
87 *ContinuationHeader =
true;
98#define VIDEO_STREAM_S 0xE0
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);
147int 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);
164 if (Pid < 0 ||
TsPid(p) == Pid) {
220 p[ 9] = ((Pts >> 29) & 0x0E) | (p[9] & 0xF1);
222 p[11] = ((Pts >> 14) & 0xFE) | 0x01;
224 p[13] = ((Pts << 1) & 0xFE) | 0x01;
229 p[14] = ((Dts >> 29) & 0x0E) | (p[14] & 0xF1);
231 p[16] = ((Dts >> 14) & 0xFE) | 0x01;
233 p[18] = ((Dts << 1) & 0xFE) | 0x01;
238 int64_t d = Pts2 - Pts1;
258 Setup(Data, Length, Pid);
334 if (Index >= 0 && Index <
length)
340 int OldIndex =
index;
345 Scanner = (Scanner << 8) |
GetByte();
379 TsPacket[3] = (TsPacket[3] & 0xF0) | Counter;
380 if (++Counter > 0x0F)
386 if (++Version > 0x1F)
403 Target[i++] = 0xE0 | (Pid >> 8);
425 Target[i++] = *Language++;
426 Target[i++] = *Language++;
427 Target[i++] = *Language++;
428 Target[i++] = SubtitlingType;
429 Target[i++] = CompositionPageId >> 8;
430 Target[i++] = CompositionPageId & 0xFF;
431 Target[i++] = AncillaryPageId >> 8;
432 Target[i++] = AncillaryPageId & 0xFF;
442 Target[Length] = 0x00;
443 for (
const char *End = Language + strlen(Language); Language < End; ) {
444 Target[i++] = *Language++;
445 Target[i++] = *Language++;
446 Target[i++] = *Language++;
448 Target[Length] += 0x04;
449 if (*Language ==
'+')
460 Target[i++] = crc >> 24;
461 Target[i++] = crc >> 16;
462 Target[i++] = crc >> 8;
468#define P_PMT_PID 0x0084
473 bool Used[
MAXPID] = {
false };
474#define SETPID(p) { if ((p) >= 0 && (p) < MAXPID) Used[p] = true; }
475#define SETPIDS(l) { const int *p = l; while (*p) { SETPID(*p); p++; } }
488 memset(
pat, 0xFF,
sizeof(
pat));
496 int PayloadStart = i;
499 int SectionLength = i;
508 p[i++] = 0xE0 | (
pmtPid >> 8);
510 pat[SectionLength] = i - SectionLength - 1 + 4;
515void cPatPmtGenerator::SetPids(
int Vpid,
int Vtype,
int Ppid,
int Tpid,
const int *Apids,
const int *Atypes,
const char Alangs[][
MAXLANGCODE2],
const int *Dpids,
const int *Dtypes,
const char Dlangs[][
MAXLANGCODE2],
const int *Spids,
const uchar *Stypes,
const char Slangs[][
MAXLANGCODE2],
const uint16_t *CompositionPageIds,
const uint16_t *AncillaryPageIds)
521 memset(buf, 0xFF,
sizeof(buf));
526 int SectionLength = i;
534 p[i++] = 0xE0 | (Ppid >> 8);
541 for (
int n = 0; Apids[n]; n++) {
542 i +=
MakeStream(buf + i, Atypes[n], Apids[n]);
545 for (
int n = 0; Dpids[n]; n++) {
550 for (
int n = 0; Spids[n]; n++) {
555 int sl = i - SectionLength - 2 + 4;
556 buf[SectionLength] |= (sl >> 8) & 0x0F;
557 buf[SectionLength + 1] = sl;
590 SetPids(Channel->
Vpid(), Channel->
Vtype(), Channel->
Ppid(), Channel->
Tpid(), Channel->
Apids(), Channel->
Atypes(), Channel->
Alangs(), Channel->
Dpids(), Channel->
Dtypes(), Channel->
Dlangs(), Channel->
Spids(), Channel->
Stypes(), Channel->
Slangs(), Channel->
CompositionPageIds(), Channel->
AncillaryPageIds());
617 if (PatPmtSize <= Size) {
652 Data += PayloadOffset;
653 Length -= PayloadOffset;
655 if ((Length -= Data[0] + 1) <= 0)
677 esyslog(
"ERROR: can't parse PAT");
685 Data += PayloadOffset;
686 Length -= PayloadOffset;
690 if ((Length -= Data[0] + 1) <= 0)
694 if (Length <=
int(
sizeof(
pmt))) {
695 memcpy(
pmt, Data, Length);
699 esyslog(
"ERROR: PMT packet length too big (%d byte)!", Length);
711 esyslog(
"ERROR: PMT section length too big (%d byte)!",
pmtSize + Length);
766 char *s =
alangs[NumApids];
816 char *s =
slangs[NumSpids];
850 dpids[NumDpids] = dpid;
936 esyslog(
"ERROR: can't parse PMT");
945 int Pid =
TsPid(Data);
978 int L = (M < 3) ? 1 : 0;
979 return 14956 + D + int((Y - L) * 365.25) + int((M + 1 + L * 12) * 30.6001);
989 *p++ = ParentalRating;
997 uchar *DescriptorsStart;
998 memset(
eit, 0xFF,
sizeof(
eit));
1000 time_t t = time(NULL) - 3600;
1001 tm *tm = localtime_r(&t, &tm_r);
1002 uint16_t MJD =
YMDtoMJD(tm->tm_year, tm->tm_mon + 1, tm->tm_mday);
1008 *p++ = 0x10 | (
counter++ & 0x0F);
1039 DescriptorsStart = p;
1042 *(SectionStart - 1) = p - SectionStart + 4;
1043 *(DescriptorsStart - 1) = p - DescriptorsStart;
1045 int crc =
SI::CRC32::crc32((
char *)PayloadStart, p - PayloadStart, 0xFFFFFFFF);
1085 esyslog(
"ERROR: out of memory");
1094#define MAXPESLENGTH 0xFFF0
1114 memmove(p,
data, 4);
1159void BlockDump(
const char *Name,
const u_char *Data,
int Length)
1161 printf(
"--- %s\n", Name);
1162 for (
int i = 0; i < Length; i++) {
1163 if (i && (i % 16) == 0)
1165 printf(
" %02X", Data[i]);
1170void TsDump(
const char *Name,
const u_char *Data,
int Length)
1172 printf(
"%s: %04X", Name, Length);
1173 int n =
min(Length, 20);
1174 for (
int i = 0; i < n; i++)
1175 printf(
" %02X", Data[i]);
1178 n =
max(n, Length - 10);
1179 for (n =
max(n, Length - 10); n < Length; n++)
1180 printf(
" %02X", Data[n]);
1185void PesDump(
const char *Name,
const u_char *Data,
int Length)
1187 TsDump(Name, Data, Length);
1242 virtual int Parse(
const uchar *Data,
int Length,
int Pid)
override;
1282 virtual int Parse(
const uchar *Data,
int Length,
int Pid)
override;
1296 bool SeenPayloadStart =
false;
1299 SeenPayloadStart =
true;
1305 uint32_t OldScanner =
scanner;
1307 if (!SeenPayloadStart && tsPayload.
AtTsStart())
1317 int TemporalReference = (b1 << 2 ) + ((b2 & 0xC0) >> 6);
1318 uchar FrameType = (b2 >> 3) & 0x07;
1319 if (tsPayload.
Find(0x000001B5)) {
1320 if (((tsPayload.
GetByte() & 0xF0) >> 4) == 0x08) {
1323 if (PictureStructure == 0x02)
1339 static const char FrameTypes[] =
"?IPBD???";
1359 uchar frame_rate_value = b & 0x0F;
1360 if (frame_rate_value > 0 && frame_rate_value <= 8)
1364 if ((tsPayload.
GetByte() & 0xF0) == 0x10) {
1378 return tsPayload.
Used();
1419 virtual int Parse(
const uchar *Data,
int Length,
int Pid)
override;
1460 return (
byte & (1 <<
bit--)) ? 1 : 0;
1474 for (
int b = 0; !b && z < 32; z++)
1476 return (1 << z) - 1 +
GetBits(z);
1483 if ((v & 0x01) != 0)
1486 return -int32_t(v / 2);
1504 if ((
scanner & 0xFFFFFF00) == 0x00000100) {
1506 switch (NalUnitType) {
1543 int chroma_format_idc = 0;
1549 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) {
1551 if (chroma_format_idc == 3)
1557 for (
int i = 0; i < ((chroma_format_idc != 3) ? 8 : 12); i++) {
1559 int SizeOfScalingList = (i < 6) ? 16 : 64;
1562 for (
int j = 0; j < SizeOfScalingList; j++) {
1564 NextScale = (LastScale +
GetGolombSe() + 256) % 256;
1566 LastScale = NextScale;
1574 if (pic_order_cnt_type == 0)
1576 else if (pic_order_cnt_type == 1) {
1595 bool frame_cropping_flag =
GetBit();
1596 if (frame_cropping_flag) {
1600 uint16_t frame_crop_bottom_offset =
GetGolombUe();
1601 uint16_t CropUnitX = 1;
1604 if (chroma_format_idc == 1) {
1608 else if (chroma_format_idc == 2)
1611 frame_Width -= CropUnitX * (frame_crop_left_offset + frame_crop_right_offset);
1612 frame_Height -= CropUnitY * (frame_crop_top_offset + frame_crop_bottom_offset);
1613 if (frame_Height > 1080 && frame_Height <= 1090)
1614 frame_Height = 1080;
1621 int aspect_ratio_idc =
GetBits(8);
1622 if (aspect_ratio_idc == 255)
1624 else if (
frameHeight >= 720 && (aspect_ratio_idc == 1 || aspect_ratio_idc == 14 || aspect_ratio_idc == 15 || aspect_ratio_idc == 16))
1640 uint32_t num_units_in_tick =
GetBits(32);
1641 uint32_t time_scale =
GetBits(32);
1642 if (num_units_in_tick > 0)
1666 static const char SliceTypes[] =
"PBIpi";
1667 dbgframes(
"%c", SliceTypes[slice_type % 5]);
1721 virtual int Parse(
const uchar *Data,
int Length,
int Pid)
override;
1739 if ((
scanner & 0xFFFFFF00) == 0x00000100) {
1766 uint8_t sub_layer_profile_present_flag[8];
1767 uint8_t sub_layer_level_present_flag[8];
1769 int sps_max_sub_layers_minus1 =
GetBits(3) & 7;
1777 bool general_progressive_source_flag =
GetBit();
1787 for (
int i = 0; i < sps_max_sub_layers_minus1; i++ ) {
1788 sub_layer_profile_present_flag[i] =
GetBit();
1789 sub_layer_level_present_flag[i] =
GetBit();
1791 if (sps_max_sub_layers_minus1 > 0) {
1792 for (
int i = sps_max_sub_layers_minus1; i < 8; i++ )
1795 for (
int i = 0; i < sps_max_sub_layers_minus1; i++ ) {
1796 if (sub_layer_profile_present_flag[i] )
1798 if (sub_layer_level_present_flag[i])
1804 if (chroma_format_idc == 3)
1808 bool conformance_window_flag =
GetBit();
1809 if (conformance_window_flag) {
1814 uint16_t SubWidthC = 1;
1815 uint16_t SubHeightC = 1;
1817 if (chroma_format_idc == 1) {
1821 else if (chroma_format_idc == 2)
1824 frameWidth -= SubWidthC * (conf_win_left_offset + conf_win_right_offset);
1825 frameHeight -= SubHeightC * (conf_win_top_offset + conf_win_bottom_offset);
1829 int log2_max_pic_order_cnt_lsb_minus4 =
GetGolombUe();
1830 int sps_sub_layer_ordering_info_present_flag =
GetBit();
1831 for (
int i = sps_sub_layer_ordering_info_present_flag ? 0 : sps_max_sub_layers_minus1; i <= sps_max_sub_layers_minus1; ++i) {
1845 for (
int sizeId = 0; sizeId < 4; ++sizeId) {
1846 for (
int matrixId = 0; matrixId < 6; matrixId += (sizeId == 3) ? 3 : 1) {
1850 int coefNum =
min(64, (1 << (4 + (sizeId << 1))));
1853 for (
int i = 0; i < coefNum; ++i)
1868 uint32_t num_short_term_ref_pic_sets =
GetGolombUe();
1869 uint32_t NumDeltaPocs[num_short_term_ref_pic_sets];
1870 for (uint32_t stRpsIdx = 0; stRpsIdx < num_short_term_ref_pic_sets; ++stRpsIdx) {
1872 bool inter_ref_pic_set_prediction_flag =
false;
1874 inter_ref_pic_set_prediction_flag =
GetBit();
1875 if (inter_ref_pic_set_prediction_flag) {
1876 uint32_t RefRpsIdx, delta_idx_minus1 = 0;
1877 if (stRpsIdx == num_short_term_ref_pic_sets)
1881 RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1);
1882 NumDeltaPocs[stRpsIdx] = 0;
1883 for (uint32_t j = 0; j <= NumDeltaPocs[RefRpsIdx]; ++j) {
1886 NumDeltaPocs[stRpsIdx]++;
1889 NumDeltaPocs[stRpsIdx]++;
1895 for (uint32_t j = 0; j < num_negative_pics; ++j) {
1899 for (uint32_t j = 0; j < num_positive_pics; ++j) {
1903 NumDeltaPocs[stRpsIdx] = num_negative_pics + num_positive_pics;
1908 uint32_t num_long_term_ref_pics_sps =
GetGolombUe();
1909 for (uint32_t i = 0; i < num_long_term_ref_pics_sps; ++i) {
1910 GetBits(log2_max_pic_order_cnt_lsb_minus4 + 4);
1918 int aspect_ratio_idc =
GetBits(8);
1919 if (aspect_ratio_idc == 255)
1921 else if (aspect_ratio_idc == 1 || aspect_ratio_idc == 14)
1944 uint32_t vui_num_units_in_tick =
GetBits(32);
1945 uint32_t vui_time_scale =
GetBits(32);
1946 if (vui_num_units_in_tick > 0)
1968#define TS_CC_UNKNOWN 0xFF
1975 void Report(
int Pid,
const char *Message);
2006 fprintf(stderr,
"%s: TS error #%d on PID %d (%s)\n", *
TimeToString(time(NULL)),
errors, Pid, Message);
2019 int Pid =
TsPid(Data);
2025 Report(Pid,
"scrambled");
2031 Report(Pid,
"continuity");
2045 return PtsDiff(*(
const int64_t *)b, *(
const int64_t *)a);
2060 void AddPts(int64_t Pts,
bool IndependentFrame =
false);
2084 int Delta = INT_MAX;
2085 for (
int i = 1; i <
pts.
Size(); i++) {
2087 if (d > 0 && d < Delta)
2090 if (Delta < INT_MAX)
2097 if (Number > 0 &&
pts[Number - 1] ==
lastPts) {
2102 for (
int i = 1; i < Number; i++) {
2123 if (IndependentFrame) {
2179 return Errors || Missing;
2229 if (*(uint32_t *)p1 < *(uint32_t *)p2)
return -1;
2230 if (*(uint32_t *)p1 > *(uint32_t *)p2)
return 1;
2243 else if (
type == 0x1B)
2245 else if (
type == 0x24)
2250 esyslog(
"ERROR: unknown stream type %d (PID %d) in frame detector",
type,
pid);
2264 if (MissingFrames) {
2300 if (
int Skipped =
TS_SYNC(Data, Length))
2301 return Processed + Skipped;
2305 int Pid =
TsPid(Data);
2385 else if (abs(Delta - 3600) <= 1)
2387 else if (Delta % 3003 == 0)
2389 else if (abs(Delta - 1800) <= 1)
2391 else if (Delta == 1501)
2420 Processed += Handled;
static u_int32_t crc32(const char *d, int len, u_int32_t CRCvalue)
Descriptor * getNext(Iterator &it)
DescriptorTag getDescriptorTag() const
StructureLoop< Language > languageLoop
bool getCurrentNextIndicator() const
int getSectionNumber() const
int getLastSectionNumber() const
int getVersionNumber() const
StructureLoop< Association > associationLoop
int getTransportStreamId() const
DescriptorLoop streamDescriptors
int getStreamType() const
StructureLoop< Stream > streamLoop
int getSubtitlingType() const
int getAncillaryPageId() const
int getCompositionPageId() const
StructureLoop< Subtitling > subtitlingLoop
virtual int Parse(const uchar *Data, int Length, int Pid) override
Parses the given Data, which is a sequence of Length bytes of TS packets.
const int * Dpids(void) const
const char(* Alangs() const)[MAXLANGCODE2]
const uchar * Stypes(void) const
const int * Atypes(void) const
const char(* Slangs() const)[MAXLANGCODE2]
const uint16_t * CompositionPageIds(void) const
const int * Dtypes(void) const
const int * Apids(void) const
const char(* Dlangs() const)[MAXLANGCODE2]
const uint16_t * AncillaryPageIds(void) const
const int * Spids(void) const
static cDevice * PrimaryDevice(void)
Returns the primary device.
void EnsureAudioTrack(bool Force=false)
Makes sure an audio track is selected that is actually available.
void ClrAvailableTracks(bool DescriptionsOnly=false, bool IdsOnly=false)
Clears the list of currently available tracks.
void EnsureSubtitleTrack(void)
Makes sure one of the preferred language subtitle tracks is selected.
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.
uchar * AddParentalRatingDescriptor(uchar *p, uchar ParentalRating=0)
uint16_t YMDtoMJD(int Y, int M, int D)
uchar * Generate(int Sid)
int TotalErrors(void)
Returns the total number of all errors and missing frames detected in the data given to the calls to ...
bool Check(const uchar *Data, int Length, bool Independent, bool &Errors, bool &Missing, bool Final, int Pid)
Check Length bytes of the given Data (which must be a complete frame), with Independent telling wheth...
uint32_t ptsValues[MaxPtsValues]
int Errors(bool *PreviousErrors=NULL, bool *MissingFrames=NULL)
Returns the total number of errors so far.
bool NewFrame(int *PreviousErrors=NULL, int *MissingFrames=NULL)
int Analyze(const uchar *Data, int Length, bool ErrorCheck=true)
Analyzes the TS packets pointed to by Data.
cFrameDetector(int Pid=0, int Type=0)
Sets up a frame detector for the given Pid and stream Type.
void SetLastPts(int64_t LastPts)
If this is a resumed recording, call this function with the last PTS of the previous recording.
void SetPid(int Pid, int Type)
Sets the Pid and stream Type to detect frames for.
uint16_t FrameWidth(void)
void SetDebug(bool Debug)
double FramesPerSecond(void)
bool IndependentFrame(void)
int iFrameTemporalReferenceOffset
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.
eAspectRatio AspectRatio(void)
uint16_t FrameHeight(void)
int IFrameTemporalReferenceOffset(void)
uint32_t GetBits(int Bits)
void ParseAccessUnitDelimiter(void)
@ nutSequenceParameterSet
bool separate_colour_plane_flag
bool gotAccessUnitDelimiter
virtual int Parse(const uchar *Data, int Length, int Pid) override
Parses the given Data, which is a sequence of Length bytes of TS packets.
uint32_t GetGolombUe(void)
uchar GetByte(bool Raw=false)
Gets the next data byte.
void ParseSliceHeader(void)
void ParseSequenceParameterSet(void)
bool gotSequenceParameterSet
int32_t GetGolombSe(void)
cH264Parser(void)
Sets up a new H.264 parser.
virtual int Parse(const uchar *Data, int Length, int Pid) override
Parses the given Data, which is a sequence of Length bytes of TS packets.
@ nutSliceSegmentIDRWRADL
@ nutSliceSegmentBLAWRADL
@ nutSliceSegmentTrailingR
@ nutSequenceParameterSet
@ nutSliceSegmentTrailingN
void ParseSequenceParameterSet(void)
bool seenIndependentFrame
int lastIFrameTemporalReference
const double frame_rate_table[9]
virtual int Parse(const uchar *Data, int Length, int Pid) override
Parses the given Data, which is a sequence of Length bytes of TS packets.
int MakeCRC(uchar *Target, const uchar *Data, int Length)
uchar * GetPmt(int &Index)
Returns a pointer to the Index'th TS packet of the PMT section.
void SetChannel(const cChannel *Channel)
Sets the Channel for which the PAT/PMT shall be generated.
void IncEsInfoLength(int Length)
void IncCounter(int &Counter, uchar *TsPacket)
cPatPmtGenerator(const cChannel *Channel=NULL)
void SetVersions(int PatVersion, int PmtVersion)
Sets the version numbers for the generated PAT and PMT, in case this generator is used to,...
int MakeAC3Descriptor(uchar *Target, uchar Type)
void GeneratePat(void)
Generates a PAT section for later use with GetPat().
int GetPatPmtSize(void)
Returns the combined size of PAT and all PMT packets.
uchar * GetPat(void)
Returns a pointer to the PAT section, which consists of exactly one TS packet.
uchar pmt[MAX_PMT_TS][TS_SIZE]
int MakeLanguageDescriptor(uchar *Target, const char *Language)
void SetPids(int Vpid, int Vtype, int Ppid, int Tpid, const int *Apids, const int *Atypes, const char Alangs[][MAXLANGCODE2], const int *Dpids, const int *Dtypes, const char Dlangs[][MAXLANGCODE2], const int *Spids, const uchar *Stypes, const char Slangs[][MAXLANGCODE2], const uint16_t *CompositionPageIds, const uint16_t *AncillaryPageIds)
Sets the PIDs this PAT/PMT shall contain.
int GetPatPmt(uchar *Dest, int Size)
Writes the PAT and all PMT packets to Dest.
int MakeStream(uchar *Target, uchar Type, int Pid)
void GeneratePmtPid(int Vpid, int Ppid, int Tpid, const int *Apids, const int *Dpids, const int *Spids)
Generates a PMT pid that doesn't collide with any of the given pids.
int MakeSubtitlingDescriptor(uchar *Target, const char *Language, uchar SubtitlingType, uint16_t CompositionPageId, uint16_t AncillaryPageId)
void IncVersion(int &Version)
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...
uchar pmt[MAX_SECTION_SIZE]
cPatPmtParser(bool UpdatePrimaryDevice=false)
void Reset(void)
Resets the parser.
void ParsePat(const uchar *Data, int Length)
Parses the PAT data from the single TS packet in Data.
char dlangs[MAXDPIDS][MAXLANGCODE2]
bool ParsePatPmt(const uchar *Data, int Length)
Parses the given Data (which may consist of several TS packets, typically an entire frame) and extrac...
int pmtPids[MAX_PMT_PIDS+1]
uchar subtitlingTypes[MAXSPIDS]
uint16_t ancillaryPageIds[MAXSPIDS]
int SectionLength(const uchar *Data, int Length)
void ParsePmt(const uchar *Data, int Length)
Parses the PMT data from the single TS packet in Data.
bool IsPmtPid(int Pid) const
Returns true if Pid the one of the PMT pids as defined by the current PAT.
uint16_t compositionPageIds[MAXSPIDS]
char alangs[MAXAPIDS][MAXLANGCODE2]
char slangs[MAXSPIDS][MAXLANGCODE2]
void SetFrameDelta(int FrameDelta)
void AddPts(int64_t Pts, bool IndependentFrame=false)
static void SetBrokenLink(uchar *Data, int Length)
static cString sprintf(const char *fmt,...) __attribute__((format(printf
void CheckTs(const uchar *Data, int Length)
void Report(int Pid, const char *Message)
bool AtPayloadStart(void)
Returns true if this payload handler is currently pointing to the first byte of a TS packet that star...
int Used(void)
Returns the number of raw bytes that have already been used (e.g.
bool Eof(void) const
Returns true if all available bytes of the TS payload have been processed.
void SetByte(uchar Byte, int Index)
Sets the TS data byte at the given Index to the value Byte.
uchar GetByte(void)
Gets the next byte of the TS payload, skipping any intermediate TS header data.
bool AtTsStart(void)
Returns true if this payload handler is currently pointing to first byte of a TS packet.
int GetLastIndex(void)
Returns the index into the TS data of the payload byte that has most recently been read.
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...
bool SkipPesHeader(void)
Skips all bytes belonging to the PES header of the payload.
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 Find(uint32_t Code)
Searches for the four byte sequence given in Code and returns true if it was found within the payload...
bool SkipBytes(int Bytes)
Skips the given number of bytes in the payload and returns true if there is still data left to read.
void PutTs(const uchar *Data, int Length)
Puts the payload data of the single TS packet at Data into the converter.
void SetRepeatLast(void)
Makes the next call to GetPes() return exactly the same data as the last one (provided there was no c...
const uchar * GetPes(int &Length)
Gets a pointer to the complete PES packet, or NULL if the packet is not complete yet.
void Reset(void)
Resets the converter.
void Sort(__compar_fn_t Compare)
virtual void Remove(int Index, int Count=1)
virtual void Append(T Data)
const char * I18nNormalizeLanguageCode(const char *Code)
Returns a 3 letter language code that may not be zero terminated.
@ EnhancedAC3DescriptorTag
@ SubtitlingDescriptorTag
@ ISO639LanguageDescriptorTag
@ ParentalRatingDescriptorTag
#define DEFAULTFRAMESPERSECOND
void TsSetPcr(uchar *p, int64_t Pcr)
const char * AspectRatioTexts[]
#define WRN_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION
#define WRN_TS_PACKETS_FOR_FRAME_DETECTOR
void PesDump(const char *Name, const u_char *Data, int Length)
int64_t PtsDiff(int64_t Pts1, int64_t Pts2)
Returns the difference between two PTS values.
const char * ScanTypeChars
void TsHidePayload(uchar *p)
static int CmpUint32(const void *p1, const void *p2)
void PesSetDts(uchar *p, int64_t Dts)
int64_t TsGetDts(const uchar *p, int l)
static int ComparePts(const void *a, const void *b)
void TsSetDts(uchar *p, int l, int64_t Dts)
void TsSetPts(uchar *p, int l, int64_t Pts)
ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader)
void PesSetPts(uchar *p, int64_t Pts)
void BlockDump(const char *Name, const u_char *Data, int Length)
int TsSync(const uchar *Data, int Length, const char *File, const char *Function, int Line)
void TsDump(const char *Name, const u_char *Data, int Length)
int64_t TsGetPts(const uchar *p, int l, int Pid)
#define MAX_TS_PACKETS_FOR_VIDEO_FRAME_DETECTION
bool TsError(const uchar *p)
int TsPid(const uchar *p)
bool TsHasPayload(const uchar *p)
int PesPayloadOffset(const uchar *p)
bool TsIsScrambled(const uchar *p)
uchar TsContinuityCounter(const uchar *p)
int TsGetPayload(const uchar **p)
#define TS_PAYLOAD_EXISTS
bool PesHasPts(const uchar *p)
bool PesLongEnough(int Length)
int64_t PesGetDts(const uchar *p)
#define TS_ADAPT_FIELD_EXISTS
int64_t PesGetPts(const uchar *p)
bool TsPayloadStart(const uchar *p)
#define TS_SYNC(Data, Length)
int TsPayloadOffset(const uchar *p)
bool PesHasDts(const uchar *p)
int64_t TsGetPts(const uchar *p, int l, int Pid=-1)
bool PesHasLength(const uchar *p)
bool TsHasAdaptationField(const uchar *p)
ePesHeader AnalyzePesHeader(const uchar *Data, int Count, int &PesPayloadOffset, bool *ContinuationHeader=NULL)
#define MIN_TS_PACKETS_FOR_FRAME_DETECTOR
int PesLength(const uchar *p)
int64_t PtsAdd(int64_t Pts1, int64_t Pts2)
Adds the given PTS values, taking into account the 33bit wrap around.