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);
218 p[ 9] = ((Pts >> 29) & 0x0E) | (p[9] & 0xF1);
220 p[11] = ((Pts >> 14) & 0xFE) | 0x01;
222 p[13] = ((Pts << 1) & 0xFE) | 0x01;
227 p[14] = ((Dts >> 29) & 0x0E) | (p[14] & 0xF1);
229 p[16] = ((Dts >> 14) & 0xFE) | 0x01;
231 p[18] = ((Dts << 1) & 0xFE) | 0x01;
236 int64_t d = Pts2 - Pts1;
256 Setup(Data, Length, Pid);
332 if (Index >= 0 && Index <
length)
338 int OldIndex =
index;
343 Scanner = (Scanner << 8) |
GetByte();
375 TsPacket[3] = (TsPacket[3] & 0xF0) | Counter;
376 if (++Counter > 0x0F)
382 if (++Version > 0x1F)
399 Target[i++] = 0xE0 | (Pid >> 8);
422 Target[i++] = *Language++;
423 Target[i++] = *Language++;
424 Target[i++] = *Language++;
425 Target[i++] = SubtitlingType;
426 Target[i++] = CompositionPageId >> 8;
427 Target[i++] = CompositionPageId & 0xFF;
428 Target[i++] = AncillaryPageId >> 8;
429 Target[i++] = AncillaryPageId & 0xFF;
439 Target[Length] = 0x00;
440 for (
const char *End = Language + strlen(Language); Language < End; ) {
441 Target[i++] = *Language++;
442 Target[i++] = *Language++;
443 Target[i++] = *Language++;
445 Target[Length] += 0x04;
446 if (*Language ==
'+')
457 Target[i++] = crc >> 24;
458 Target[i++] = crc >> 16;
459 Target[i++] = crc >> 8;
465#define P_PMT_PID 0x0084
470 bool Used[
MAXPID] = {
false };
471#define SETPID(p) { if ((p) >= 0 && (p) < MAXPID) Used[p] = true; }
472#define SETPIDS(l) { const int *p = l; while (*p) { SETPID(*p); p++; } }
485 memset(
pat, 0xFF,
sizeof(
pat));
493 int PayloadStart = i;
496 int SectionLength = i;
505 p[i++] = 0xE0 | (
pmtPid >> 8);
507 pat[SectionLength] = i - SectionLength - 1 + 4;
516 memset(buf, 0xFF,
sizeof(buf));
519 int Vpid = Channel->
Vpid();
520 int Ppid = Channel->
Ppid();
524 int SectionLength = i;
532 p[i++] = 0xE0 | (Ppid >> 8);
539 for (
int n = 0; Channel->
Apid(n); n++) {
541 const char *Alang = Channel->
Alang(n);
544 for (
int n = 0; Channel->
Dpid(n); n++) {
549 for (
int n = 0; Channel->
Spid(n); n++) {
554 int sl = i - SectionLength - 2 + 4;
555 buf[SectionLength] |= (sl >> 8) & 0x0F;
556 buf[SectionLength + 1] = sl;
633 Data += PayloadOffset;
634 Length -= PayloadOffset;
636 if ((Length -= Data[0] + 1) <= 0)
658 esyslog(
"ERROR: can't parse PAT");
666 Data += PayloadOffset;
667 Length -= PayloadOffset;
671 if ((Length -= Data[0] + 1) <= 0)
675 if (Length <=
int(
sizeof(
pmt))) {
676 memcpy(
pmt, Data, Length);
680 esyslog(
"ERROR: PMT packet length too big (%d byte)!", Length);
692 esyslog(
"ERROR: PMT section length too big (%d byte)!",
pmtSize + Length);
747 char *s =
alangs[NumApids];
797 char *s =
slangs[NumSpids];
831 dpids[NumDpids] = dpid;
917 esyslog(
"ERROR: can't parse PMT");
926 int Pid =
TsPid(Data);
959 int L = (M < 3) ? 1 : 0;
960 return 14956 + D + int((Y - L) * 365.25) + int((M + 1 + L * 12) * 30.6001);
970 *p++ = ParentalRating;
978 uchar *DescriptorsStart;
979 memset(
eit, 0xFF,
sizeof(
eit));
981 time_t t = time(NULL) - 3600;
982 tm *tm = localtime_r(&t, &tm_r);
983 uint16_t MJD =
YMDtoMJD(tm->tm_year, tm->tm_mon + 1, tm->tm_mday);
989 *p++ = 0x10 | (
counter++ & 0x0F);
1020 DescriptorsStart = p;
1023 *(SectionStart - 1) = p - SectionStart + 4;
1024 *(DescriptorsStart - 1) = p - DescriptorsStart;
1026 int crc =
SI::CRC32::crc32((
char *)PayloadStart, p - PayloadStart, 0xFFFFFFFF);
1066 esyslog(
"ERROR: out of memory");
1075#define MAXPESLENGTH 0xFFF0
1095 memmove(p,
data, 4);
1140void BlockDump(
const char *Name,
const u_char *Data,
int Length)
1142 printf(
"--- %s\n", Name);
1143 for (
int i = 0; i < Length; i++) {
1144 if (i && (i % 16) == 0)
1146 printf(
" %02X", Data[i]);
1151void TsDump(
const char *Name,
const u_char *Data,
int Length)
1153 printf(
"%s: %04X", Name, Length);
1154 int n =
min(Length, 20);
1155 for (
int i = 0; i < n; i++)
1156 printf(
" %02X", Data[i]);
1159 n =
max(n, Length - 10);
1160 for (n =
max(n, Length - 10); n < Length; n++)
1161 printf(
" %02X", Data[n]);
1166void PesDump(
const char *Name,
const u_char *Data,
int Length)
1168 TsDump(Name, Data, Length);
1223 virtual int Parse(
const uchar *Data,
int Length,
int Pid)
override;
1263 virtual int Parse(
const uchar *Data,
int Length,
int Pid)
override;
1277 bool SeenPayloadStart =
false;
1280 SeenPayloadStart =
true;
1286 uint32_t OldScanner =
scanner;
1288 if (!SeenPayloadStart && tsPayload.
AtTsStart())
1298 int TemporalReference = (b1 << 2 ) + ((b2 & 0xC0) >> 6);
1299 uchar FrameType = (b2 >> 3) & 0x07;
1300 if (tsPayload.
Find(0x000001B5)) {
1301 if (((tsPayload.
GetByte() & 0xF0) >> 4) == 0x08) {
1304 if (PictureStructure == 0x02)
1318 static const char FrameTypes[] =
"?IPBD???";
1338 uchar frame_rate_value = b & 0x0F;
1339 if (frame_rate_value > 0 && frame_rate_value <= 8)
1343 if ((tsPayload.
GetByte() & 0xF0) == 0x10) {
1357 return tsPayload.
Used();
1398 virtual int Parse(
const uchar *Data,
int Length,
int Pid)
override;
1439 return (
byte & (1 <<
bit--)) ? 1 : 0;
1453 for (
int b = 0; !b && z < 32; z++)
1455 return (1 << z) - 1 +
GetBits(z);
1462 if ((v & 0x01) != 0)
1465 return -int32_t(v / 2);
1483 if ((
scanner & 0xFFFFFF00) == 0x00000100) {
1485 switch (NalUnitType) {
1522 int chroma_format_idc = 0;
1528 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) {
1530 if (chroma_format_idc == 3)
1536 for (
int i = 0; i < ((chroma_format_idc != 3) ? 8 : 12); i++) {
1538 int SizeOfScalingList = (i < 6) ? 16 : 64;
1541 for (
int j = 0; j < SizeOfScalingList; j++) {
1543 NextScale = (LastScale +
GetGolombSe() + 256) % 256;
1545 LastScale = NextScale;
1553 if (pic_order_cnt_type == 0)
1555 else if (pic_order_cnt_type == 1) {
1574 bool frame_cropping_flag =
GetBit();
1575 if (frame_cropping_flag) {
1579 uint16_t frame_crop_bottom_offset =
GetGolombUe();
1580 uint16_t CropUnitX = 1;
1583 if (chroma_format_idc == 1) {
1587 else if (chroma_format_idc == 2)
1590 frame_Width -= CropUnitX * (frame_crop_left_offset + frame_crop_right_offset);
1591 frame_Height -= CropUnitY * (frame_crop_top_offset + frame_crop_bottom_offset);
1592 if (frame_Height > 1080 && frame_Height <= 1090)
1593 frame_Height = 1080;
1600 int aspect_ratio_idc =
GetBits(8);
1601 if (aspect_ratio_idc == 255)
1603 else if (
frameHeight >= 720 && (aspect_ratio_idc == 1 || aspect_ratio_idc == 14 || aspect_ratio_idc == 15 || aspect_ratio_idc == 16))
1619 uint32_t num_units_in_tick =
GetBits(32);
1620 uint32_t time_scale =
GetBits(32);
1621 if (num_units_in_tick > 0)
1645 static const char SliceTypes[] =
"PBIpi";
1646 dbgframes(
"%c", SliceTypes[slice_type % 5]);
1700 virtual int Parse(
const uchar *Data,
int Length,
int Pid)
override;
1718 if ((
scanner & 0xFFFFFF00) == 0x00000100) {
1745 uint8_t sub_layer_profile_present_flag[8];
1746 uint8_t sub_layer_level_present_flag[8];
1748 int sps_max_sub_layers_minus1 =
GetBits(3) & 7;
1756 bool general_progressive_source_flag =
GetBit();
1766 for (
int i = 0; i < sps_max_sub_layers_minus1; i++ ) {
1767 sub_layer_profile_present_flag[i] =
GetBit();
1768 sub_layer_level_present_flag[i] =
GetBit();
1770 if (sps_max_sub_layers_minus1 > 0) {
1771 for (
int i = sps_max_sub_layers_minus1; i < 8; i++ )
1774 for (
int i = 0; i < sps_max_sub_layers_minus1; i++ ) {
1775 if (sub_layer_profile_present_flag[i] )
1777 if (sub_layer_level_present_flag[i])
1783 if (chroma_format_idc == 3)
1787 bool conformance_window_flag =
GetBit();
1788 if (conformance_window_flag) {
1793 uint16_t SubWidthC = 1;
1794 uint16_t SubHeightC = 1;
1796 if (chroma_format_idc == 1) {
1800 else if (chroma_format_idc == 2)
1803 frameWidth -= SubWidthC * (conf_win_left_offset + conf_win_right_offset);
1804 frameHeight -= SubHeightC * (conf_win_top_offset + conf_win_bottom_offset);
1808 int log2_max_pic_order_cnt_lsb_minus4 =
GetGolombUe();
1809 int sps_sub_layer_ordering_info_present_flag =
GetBit();
1810 for (
int i = sps_sub_layer_ordering_info_present_flag ? 0 : sps_max_sub_layers_minus1; i <= sps_max_sub_layers_minus1; ++i) {
1824 for (
int sizeId = 0; sizeId < 4; ++sizeId) {
1825 for (
int matrixId = 0; matrixId < 6; matrixId += (sizeId == 3) ? 3 : 1) {
1829 int coefNum =
min(64, (1 << (4 + (sizeId << 1))));
1832 for (
int i = 0; i < coefNum; ++i)
1847 uint32_t num_short_term_ref_pic_sets =
GetGolombUe();
1848 uint32_t NumDeltaPocs[num_short_term_ref_pic_sets];
1849 for (uint32_t stRpsIdx = 0; stRpsIdx < num_short_term_ref_pic_sets; ++stRpsIdx) {
1851 bool inter_ref_pic_set_prediction_flag =
false;
1853 inter_ref_pic_set_prediction_flag =
GetBit();
1854 if (inter_ref_pic_set_prediction_flag) {
1855 uint32_t RefRpsIdx, delta_idx_minus1 = 0;
1856 if (stRpsIdx == num_short_term_ref_pic_sets)
1860 RefRpsIdx = stRpsIdx - (delta_idx_minus1 + 1);
1861 NumDeltaPocs[stRpsIdx] = 0;
1862 for (uint32_t j = 0; j <= NumDeltaPocs[RefRpsIdx]; ++j) {
1865 NumDeltaPocs[stRpsIdx]++;
1868 NumDeltaPocs[stRpsIdx]++;
1874 for (uint32_t j = 0; j < num_negative_pics; ++j) {
1878 for (uint32_t j = 0; j < num_positive_pics; ++j) {
1882 NumDeltaPocs[stRpsIdx] = num_negative_pics + num_positive_pics;
1887 uint32_t num_long_term_ref_pics_sps =
GetGolombUe();
1888 for (uint32_t i = 0; i < num_long_term_ref_pics_sps; ++i) {
1889 GetBits(log2_max_pic_order_cnt_lsb_minus4 + 4);
1897 int aspect_ratio_idc =
GetBits(8);
1898 if (aspect_ratio_idc == 255)
1900 else if (aspect_ratio_idc == 1 || aspect_ratio_idc == 14)
1923 uint32_t vui_num_units_in_tick =
GetBits(32);
1924 uint32_t vui_time_scale =
GetBits(32);
1925 if (vui_num_units_in_tick > 0)
1947#define TS_CC_UNKNOWN 0xFF
1953 void Report(
int Pid,
const char *Message);
1971 fprintf(stderr,
"%s: TS error #%d on PID %d (%s)\n", *
TimeToString(time(NULL)),
errors, Pid, Message);
1977 int Pid =
TsPid(Data);
1983 Report(Pid,
"scrambled");
1989 Report(Pid,
"continuity");
2001#define MAX_BACK_REFS 32
2013 void Report(
const char *Message,
int NumErrors = 1);
2019 void CheckFrame(
const uchar *Data,
int Length,
bool IndependentFrame);
2039 fprintf(stderr,
"%s: frame error #%d (%s)\n", *
TimeToString(time(NULL)),
errors, Message);
2053 int64_t Pts =
TsGetPts(Data, Length);
2061 Report(
"missing backref");
2070 else if (Diff < 0) {
2073 int b = 1 << (Diff - 1);
2075 Report(
"duplicate backref");
2079 Report(
"rev diff too big");
2086 else if (IndependentFrame)
2131 if (*(uint32_t *)p1 < *(uint32_t *)p2)
return -1;
2132 if (*(uint32_t *)p1 > *(uint32_t *)p2)
return 1;
2145 else if (
type == 0x1B)
2147 else if (
type == 0x24)
2152 esyslog(
"ERROR: unknown stream type %d (PID %d) in frame detector",
type,
pid);
2179 if (
int Skipped =
TS_SYNC(Data, Length))
2180 return Processed + Skipped;
2184 int Pid =
TsPid(Data);
2196 int n =
parser->Parse(Data, Length,
pid);
2198 if (
parser->NewFrame()) {
2209 if (
parser->FramesPerSecond() > 0.0) {
2256 Div +=
parser->IFrameTemporalReferenceOffset();
2264 else if (abs(Delta - 3600) <= 1)
2266 else if (Delta % 3003 == 0)
2268 else if (abs(Delta - 1800) <= 1)
2270 else if (Delta == 1501)
2294 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
uint16_t AncillaryPageId(int i) const
uint16_t CompositionPageId(int i) const
const char * Slang(int i) const
uchar SubtitlingType(int i) const
const char * Dlang(int i) const
const int * Apids(void) const
const char * Alang(int i) 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)
void Report(const char *Message, int NumErrors=1)
void SetFrameDelta(int FrameDelta)
void CheckTs(const uchar *Data, int Length)
void CheckFrame(const uchar *Data, int Length, bool IndependentFrame)
uint32_t ptsValues[MaxPtsValues]
cFrameChecker * frameChecker
bool NewFrame(int *PreviousErrors=NULL, int *MissingFrames=NULL)
Returns true if the data given to the last call to Analyze() started a new frame.
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 SetMissing(void)
Call if this is a resumed recording, which has missing frames.
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().
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 GeneratePmt(const cChannel *Channel)
Generates a PMT section for the given Channel, for later use with GetPmt().
void GeneratePmtPid(const cChannel *Channel)
Generates a PMT pid that doesn't collide with any of the actual pids of the Channel.
int MakeStream(uchar *Target, uchar Type, int Pid)
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]
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.
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)
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)
int64_t TsGetPts(const uchar *p, int l)
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)
#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)
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)