diff --git a/HISTORY b/HISTORY index ba080b3c..e34a8774 100644 --- a/HISTORY +++ b/HISTORY @@ -5952,3 +5952,5 @@ Video Disk Recorder Revision History Schmirler). - Checking the pointer field in cPatPmtParser::ParsePmt() only in 'payload start' packets (suggested by Frank Schmirler). +- Changed cPatPmtGenerator to make sure the PMT pid doesn't collide with any of + the actual pids of the channel. diff --git a/recorder.c b/recorder.c index 83024ac1..6bf299eb 100644 --- a/recorder.c +++ b/recorder.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: recorder.c 2.1 2009/01/06 12:38:01 kls Exp $ + * $Id: recorder.c 2.2 2009/01/23 16:44:29 kls Exp $ */ #include "recorder.h" @@ -44,7 +44,7 @@ cRecorder::cRecorder(const char *FileName, tChannelID ChannelID, int Priority, i Type = 0x06; } frameDetector = new cFrameDetector(Pid, Type); - patPmtGenerator.GeneratePmt(ChannelID); + patPmtGenerator.SetChannel(Channel); fileName = NULL; index = NULL; fileSize = 0; diff --git a/remux.c b/remux.c index 54ba8723..cb37c4f2 100644 --- a/remux.c +++ b/remux.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: remux.c 2.10 2009/01/23 16:43:23 kls Exp $ + * $Id: remux.c 2.11 2009/01/23 16:44:29 kls Exp $ */ #include "remux.h" @@ -111,13 +111,14 @@ void cRemux::SetBrokenLink(uchar *Data, int Length) // --- cPatPmtGenerator ------------------------------------------------------ -cPatPmtGenerator::cPatPmtGenerator(void) +cPatPmtGenerator::cPatPmtGenerator(cChannel *Channel) { numPmtPackets = 0; patCounter = pmtCounter = 0; patVersion = pmtVersion = 0; + pmtPid = 0; esInfoLength = NULL; - GeneratePat(); + SetChannel(Channel); } void cPatPmtGenerator::IncCounter(int &Counter, uchar *TsPacket) @@ -206,8 +207,23 @@ int cPatPmtGenerator::MakeCRC(uchar *Target, const uchar *Data, int Length) } #define P_TSID 0x8008 // pseudo TS ID -#define P_PNR 0x0084 // pseudo Program Number #define P_PMT_PID 0x0084 // pseudo PMT pid +#define MAXPID 0x2000 // the maximum possible number of pids + +void cPatPmtGenerator::GeneratePmtPid(cChannel *Channel) +{ + bool Used[MAXPID] = { false }; +#define SETPID(p) { if ((p) >= 0 && (p) < MAXPID) Used[p] = true; } +#define SETPIDS(l) { const int *p = l; while (*p) { SETPID(*p); p++; } } + SETPID(Channel->Vpid()); + SETPID(Channel->Ppid()); + SETPID(Channel->Tpid()); + SETPIDS(Channel->Apids()); + SETPIDS(Channel->Dpids()); + SETPIDS(Channel->Spids()); + for (pmtPid = P_PMT_PID; Used[pmtPid]; pmtPid++) + ; +} void cPatPmtGenerator::GeneratePat(void) { @@ -229,22 +245,21 @@ void cPatPmtGenerator::GeneratePat(void) p[i++] = 0xC1 | (patVersion << 1); // dummy (2), version number (5), current/next indicator (1) p[i++] = 0x00; // section number p[i++] = 0x00; // last section number - p[i++] = P_PNR >> 8; // program number hi - p[i++] = P_PNR & 0xFF; // program number lo - p[i++] = 0xE0 | (P_PMT_PID >> 8); // dummy (3), PMT pid hi (5) - p[i++] = P_PMT_PID & 0xFF; // PMT pid lo + p[i++] = pmtPid >> 8; // program number hi + p[i++] = pmtPid & 0xFF; // program number lo + p[i++] = 0xE0 | (pmtPid >> 8); // dummy (3), PMT pid hi (5) + p[i++] = pmtPid & 0xFF; // PMT pid lo pat[SectionLength] = i - SectionLength - 1 + 4; // -2 = SectionLength storage, +4 = length of CRC MakeCRC(pat + i, pat + PayloadStart, i - PayloadStart); IncVersion(patVersion); } -void cPatPmtGenerator::GeneratePmt(tChannelID ChannelID) +void cPatPmtGenerator::GeneratePmt(cChannel *Channel) { // generate the complete PMT section: uchar buf[MAX_SECTION_SIZE]; memset(buf, 0xFF, sizeof(buf)); numPmtPackets = 0; - cChannel *Channel = Channels.GetByChannelID(ChannelID); if (Channel) { int Vpid = Channel->Vpid(); uchar *p = buf; @@ -253,8 +268,8 @@ void cPatPmtGenerator::GeneratePmt(tChannelID ChannelID) int SectionLength = i; p[i++] = 0xB0; // section syntax indicator (1), dummy (3), section length hi (4) p[i++] = 0x00; // section length lo (filled in later) - p[i++] = P_PNR >> 8; // program number hi - p[i++] = P_PNR & 0xFF; // program number lo + p[i++] = pmtPid >> 8; // program number hi + p[i++] = pmtPid & 0xFF; // program number lo p[i++] = 0xC1 | (pmtVersion << 1); // dummy (2), version number (5), current/next indicator (1) p[i++] = 0x00; // section number p[i++] = 0x00; // last section number @@ -293,8 +308,8 @@ void cPatPmtGenerator::GeneratePmt(tChannelID ChannelID) uchar *p = pmt[numPmtPackets++]; int j = 0; p[j++] = TS_SYNC_BYTE; // TS indicator - p[j++] = (pusi ? TS_PAYLOAD_START : 0x00) | (P_PNR >> 8); // flags (3), pid hi (5) - p[j++] = P_PNR & 0xFF; // pid lo + p[j++] = (pusi ? TS_PAYLOAD_START : 0x00) | (pmtPid >> 8); // flags (3), pid hi (5) + p[j++] = pmtPid & 0xFF; // pid lo p[j++] = 0x10; // flags (4), continuity counter (4) if (pusi) { p[j++] = 0x00; // pointer field (payload unit start indicator is set) @@ -307,8 +322,15 @@ void cPatPmtGenerator::GeneratePmt(tChannelID ChannelID) } IncVersion(pmtVersion); } - else - esyslog("ERROR: can't find channel %s", *ChannelID.ToString()); +} + +void cPatPmtGenerator::SetChannel(cChannel *Channel) +{ + if (Channel) { + GeneratePmtPid(Channel); + GeneratePat(); + GeneratePmt(Channel); + } } uchar *cPatPmtGenerator::GetPat(void) diff --git a/remux.h b/remux.h index 6b09b713..b65da73b 100644 --- a/remux.h +++ b/remux.h @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: remux.h 2.5 2009/01/23 16:40:27 kls Exp $ + * $Id: remux.h 2.6 2009/01/23 16:44:46 kls Exp $ */ #ifndef __REMUX_H @@ -153,6 +153,7 @@ private: int pmtCounter; int patVersion; int pmtVersion; + int pmtPid; uchar *esInfoLength; void IncCounter(int &Counter, uchar *TsPacket); void IncVersion(int &Version); @@ -163,14 +164,18 @@ protected: int MakeSubtitlingDescriptor(uchar *Target, const char *Language); int MakeLanguageDescriptor(uchar *Target, const char *Language); int MakeCRC(uchar *Target, const uchar *Data, int Length); -public: - cPatPmtGenerator(void); + void GeneratePmtPid(cChannel *Channel); + ///< Generates a PMT pid that doesn't collide with any of the actual + ///< pids of the Channel. void GeneratePat(void); ///< Generates a PAT section for later use with GetPat(). - ///< This function is called by default from the constructor. - void GeneratePmt(tChannelID ChannelID); - ///< Generates a PMT section for the given ChannelId, for later use + void GeneratePmt(cChannel *Channel); + ///< Generates a PMT section for the given Channel, for later use ///< with GetPmt(). +public: + cPatPmtGenerator(cChannel *Channel = NULL); + void SetChannel(cChannel *Channel); + ///< Sets the Channel for which the PAT/PMT shall be generated. uchar *GetPat(void); ///< Returns a pointer to the PAT section, which consists of exactly ///< one TS packet. diff --git a/transfer.c b/transfer.c index ddd84736..0616f9b9 100644 --- a/transfer.c +++ b/transfer.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: transfer.c 2.2 2009/01/16 15:16:08 kls Exp $ + * $Id: transfer.c 2.3 2009/01/23 16:44:29 kls Exp $ */ #include "transfer.h" @@ -14,7 +14,7 @@ cTransfer::cTransfer(tChannelID ChannelID, int VPid, const int *APids, const int *DPids, const int *SPids) :cReceiver(ChannelID, -1, VPid, APids, Setup.UseDolbyDigital ? DPids : NULL, SPids) { - patPmtGenerator.GeneratePmt(ChannelID); + patPmtGenerator.SetChannel(Channels.GetByChannelID(ChannelID)); } cTransfer::~cTransfer()