--- recorder.c +++ recorder.c.orig @@ -48,10 +48,17 @@ cRecorder::cRecorder(const char *FileNam fileSize = 0; lastDiskSpaceCheck = time(NULL); fileName = new cFileName(FileName, true); + int Tpid = 0; +#if 1 + Tpid = Channel->Tpid(); + if (Tpid) { + AddPid(Tpid); + } +#endif int PatVersion, PmtVersion; if (fileName->GetLastPatPmtVersions(PatVersion, PmtVersion)) patPmtGenerator.SetVersions(PatVersion + 1, PmtVersion + 1); - patPmtGenerator.SetChannel(Channel); + patPmtGenerator.SetChannel(Channel, Tpid != 0); recordFile = fileName->Open(); if (!recordFile) return; --- remux.h +++ remux.h.orig @@ -172,17 +172,18 @@ protected: int MakeAC3Descriptor(uchar *Target, uchar Type); int MakeSubtitlingDescriptor(uchar *Target, const char *Language, uchar SubtitlingType, uint16_t CompositionPageId, uint16_t AncillaryPageId); int MakeLanguageDescriptor(uchar *Target, const char *Language); + int MakeTTXDescriptor(uchar *Target, const char *Language, int InitialPageId); int MakeCRC(uchar *Target, const uchar *Data, int Length); void GeneratePmtPid(const 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(). - void GeneratePmt(const cChannel *Channel); + void GeneratePmt(const cChannel *Channel, bool WithTTX = false); ///< Generates a PMT section for the given Channel, for later use ///< with GetPmt(). public: - cPatPmtGenerator(const cChannel *Channel = NULL); + cPatPmtGenerator(const cChannel *Channel = NULL, bool WithTTX = false); void SetVersions(int PatVersion, int PmtVersion); ///< Sets the version numbers for the generated PAT and PMT, in case ///< this generator is used to, e.g., continue a previously interrupted @@ -192,7 +193,7 @@ public: ///< higher bits will automatically be cleared. ///< SetVersions() needs to be called before SetChannel() in order to ///< have an effect from the very start. - void SetChannel(const cChannel *Channel); + void SetChannel(const cChannel *Channel, bool WithTTX = false); ///< 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 --- remux.c +++ remux.c.orig @@ -144,14 +144,14 @@ void TsSetTeiOnBrokenPackets(uchar *p, i // --- cPatPmtGenerator ------------------------------------------------------ -cPatPmtGenerator::cPatPmtGenerator(const cChannel *Channel) +cPatPmtGenerator::cPatPmtGenerator(const cChannel *Channel, bool WithTTX) { numPmtPackets = 0; patCounter = pmtCounter = 0; patVersion = pmtVersion = 0; pmtPid = 0; esInfoLength = NULL; - SetChannel(Channel); + SetChannel(Channel, WithTTX); } void cPatPmtGenerator::IncCounter(int &Counter, uchar *TsPacket) @@ -234,6 +234,20 @@ int cPatPmtGenerator::MakeLanguageDescri return i; } +int cPatPmtGenerator::MakeTTXDescriptor(uchar *Target, const char *Language, int InitialPageId) +{ + int i = 0; + Target[i++] = SI::TeletextDescriptorTag; + Target[i++] = 0x05; // length + Target[i++] = *Language++; + Target[i++] = *Language++; + Target[i++] = *Language++; + Target[i++] = 0x08 + (InitialPageId >> 8); + Target[i++] = InitialPageId & 0xFF; + IncEsInfoLength(i); + return i; +} + int cPatPmtGenerator::MakeCRC(uchar *Target, const uchar *Data, int Length) { int crc = SI::CRC32::crc32((const char *)Data, Length, 0xFFFFFFFF); @@ -293,7 +307,7 @@ void cPatPmtGenerator::GeneratePat(void) IncVersion(patVersion); } -void cPatPmtGenerator::GeneratePmt(const cChannel *Channel) +void cPatPmtGenerator::GeneratePmt(const cChannel *Channel, bool WithTTX) { // generate the complete PMT section: uchar buf[MAX_SECTION_SIZE]; @@ -335,6 +349,13 @@ void cPatPmtGenerator::GeneratePmt(const i += MakeSubtitlingDescriptor(buf + i, Channel->Slang(n), Channel->SubtitlingType(n), Channel->CompositionPageId(n), Channel->AncillaryPageId(n)); } + if (WithTTX) { + i += MakeStream(buf + i, 0x06, Channel->Tpid()); + // XXX should add teletext language to channels.conf so we + // dont have to use the first audio language here... + i += MakeTTXDescriptor(buf + i, Channel->Alang(0), 0x100); + } + int sl = i - SectionLength - 2 + 4; // -2 = SectionLength storage, +4 = length of CRC buf[SectionLength] |= (sl >> 8) & 0x0F; buf[SectionLength + 1] = sl; @@ -368,12 +389,12 @@ void cPatPmtGenerator::SetVersions(int P pmtVersion = PmtVersion & 0x1F; } -void cPatPmtGenerator::SetChannel(const cChannel *Channel) +void cPatPmtGenerator::SetChannel(const cChannel *Channel, bool WithTTX) { if (Channel) { GeneratePmtPid(Channel); GeneratePat(); - GeneratePmt(Channel); + GeneratePmt(Channel, WithTTX); } }