diff options
author | etobi <git@e-tobi.net> | 2010-02-12 21:55:04 +0100 |
---|---|---|
committer | etobi <git@e-tobi.net> | 2013-03-10 12:04:12 +0100 |
commit | a932f6d2b2569e64d7fc56b5f128917709ff5a8c (patch) | |
tree | 13f4305423ae014c62d17b05cf1fff1217ab1cb9 | |
parent | 4c59501a6b52816000d6c483fae619ebccfcdc9b (diff) | |
download | vdr-patches-a932f6d2b2569e64d7fc56b5f128917709ff5a8c.tar.gz vdr-patches-a932f6d2b2569e64d7fc56b5f128917709ff5a8c.tar.bz2 |
Record teletext subtitles
-rw-r--r-- | channels.c | 20 | ||||
-rw-r--r-- | channels.h | 16 | ||||
-rw-r--r-- | pat.c | 18 | ||||
-rw-r--r-- | receiver.c | 3 | ||||
-rw-r--r-- | remux.c | 29 | ||||
-rw-r--r-- | remux.h | 3 |
6 files changed, 87 insertions, 2 deletions
@@ -408,6 +408,26 @@ void cChannel::SetSubtitlingDescriptors(uchar *SubtitlingTypes, uint16_t *Compos } } +void cChannel::SetTeletextSubtitlePages(tTeletextSubtitlePage pages[], int numberOfPages) +{ + int mod = CHANNELMOD_NONE; + if (totalTtxtSubtitlePages != numberOfPages) + mod |= CHANNELMOD_PIDS; + totalTtxtSubtitlePages = 0; + for (int i = 0; (i < numberOfPages) && (totalTtxtSubtitlePages < MAXTXTPAGES); i++) { + if (teletextSubtitlePages[totalTtxtSubtitlePages].ttxtMagazine != pages[i].ttxtMagazine || + teletextSubtitlePages[totalTtxtSubtitlePages].ttxtPage != pages[i].ttxtPage || + teletextSubtitlePages[totalTtxtSubtitlePages].ttxtType != pages[i].ttxtType || + strcmp(teletextSubtitlePages[totalTtxtSubtitlePages].ttxtLanguage, pages[i].ttxtLanguage)) { + mod |= CHANNELMOD_PIDS; + teletextSubtitlePages[totalTtxtSubtitlePages] = pages[i]; + } + totalTtxtSubtitlePages++; + } + modification |= mod; + Channels.SetModified(); +} + void cChannel::SetCaIds(const int *CaIds) { if (caids[0] && caids[0] <= CA_USER_MAX) @@ -35,6 +35,7 @@ #define MAXDPIDS 16 // dolby (AC3 + DTS) #define MAXSPIDS 32 // subtitles #define MAXCAIDS 12 // conditional access +#define MAXTXTPAGES 8 // teletext pages #define MAXLANGCODE1 4 // a 3 letter language code, zero terminated #define MAXLANGCODE2 8 // up to two 3 letter language codes, separated by '+' and zero terminated @@ -71,6 +72,16 @@ public: static const tChannelID InvalidID; }; +struct tTeletextSubtitlePage { + tTeletextSubtitlePage(void) { ttxtPage = ttxtMagazine = 0; ttxtType = 0x02; strcpy(ttxtLanguage, "und"); } + tTeletextSubtitlePage(int page) { ttxtMagazine = (page / 100) & 0x7; ttxtPage = (((page % 100) / 10) << 4) + (page % 10); ttxtType = 0x02; strcpy(ttxtLanguage, "und"); } + char ttxtLanguage[MAXLANGCODE1]; + uchar ttxtPage; + uchar ttxtMagazine; + uchar ttxtType; + int PageNumber(void) const { return BCDCHARTOINT(ttxtMagazine) * 100 + BCDCHARTOINT(ttxtPage); } + }; + class cChannel; class cLinkChannel : public cListObject { @@ -115,6 +126,8 @@ private: uint16_t compositionPageIds[MAXSPIDS]; uint16_t ancillaryPageIds[MAXSPIDS]; int tpid; + int totalTtxtSubtitlePages; + tTeletextSubtitlePage teletextSubtitlePages[MAXTXTPAGES]; int caids[MAXCAIDS + 1]; // list is zero-terminated int nid; int tid; @@ -166,6 +179,8 @@ public: uint16_t CompositionPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? compositionPageIds[i] : uint16_t(0); } uint16_t AncillaryPageId(int i) const { return (0 <= i && i < MAXSPIDS) ? ancillaryPageIds[i] : uint16_t(0); } int Tpid(void) const { return tpid; } + const tTeletextSubtitlePage *TeletextSubtitlePages() const { return teletextSubtitlePages; } + int TotalTeletextSubtitlePages() const { return totalTtxtSubtitlePages; } const int *Caids(void) const { return caids; } int Ca(int Index = 0) const { return Index < MAXCAIDS ? caids[Index] : 0; } int Nid(void) const { return nid; } @@ -192,6 +207,7 @@ public: void SetName(const char *Name, const char *ShortName, const char *Provider); void SetPortalName(const char *PortalName); void SetPids(int Vpid, int Ppid, int Vtype, int *Apids, int *Atypes, char ALangs[][MAXLANGCODE2], int *Dpids, int *Dtypes, char DLangs[][MAXLANGCODE2], int *Spids, char SLangs[][MAXLANGCODE2], int Tpid); + void SetTeletextSubtitlePages(tTeletextSubtitlePage pages[], int numberOfPages); void SetCaIds(const int *CaIds); // list must be zero-terminated void SetCaDescriptors(int Level); void SetLinkChannels(cLinkChannels *LinkChannels); @@ -343,6 +343,8 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length char DLangs[MAXDPIDS][MAXLANGCODE2] = { "" }; char SLangs[MAXSPIDS][MAXLANGCODE2] = { "" }; int Tpid = 0; + tTeletextSubtitlePage TeletextSubtitlePages[MAXTXTPAGES]; + int NumTPages = 0; int NumApids = 0; int NumDpids = 0; int NumSpids = 0; @@ -434,8 +436,21 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length NumSpids++; } break; - case SI::TeletextDescriptorTag: + case SI::TeletextDescriptorTag: { Tpid = esPid; + SI::TeletextDescriptor *sd = (SI::TeletextDescriptor *)d; + SI::TeletextDescriptor::Teletext ttxt; + for (SI::Loop::Iterator it; sd->teletextLoop.getNext(ttxt, it); ) { + bool isSubtitlePage = (ttxt.getTeletextType() == 0x02) || (ttxt.getTeletextType() == 0x05); + if ((NumTPages < MAXTXTPAGES) && ttxt.languageCode[0] && isSubtitlePage) { + strn0cpy(TeletextSubtitlePages[NumTPages].ttxtLanguage, I18nNormalizeLanguageCode(ttxt.languageCode), MAXLANGCODE1); + TeletextSubtitlePages[NumTPages].ttxtPage = ttxt.getTeletextPageNumber(); + TeletextSubtitlePages[NumTPages].ttxtMagazine = ttxt.getTeletextMagazineNumber(); + TeletextSubtitlePages[NumTPages].ttxtType = ttxt.getTeletextType(); + NumTPages++; + } + } + } break; case SI::ISO639LanguageDescriptorTag: { SI::ISO639LanguageDescriptor *ld = (SI::ISO639LanguageDescriptor *)d; @@ -547,6 +562,7 @@ void cPatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length } if (Setup.UpdateChannels >= 2) { Channel->SetPids(Vpid, Ppid, Vtype, Apids, Atypes, ALangs, Dpids, Dtypes, DLangs, Spids, SLangs, Tpid); + Channel->SetTeletextSubtitlePages(TeletextSubtitlePages, NumTPages); Channel->SetCaIds(CaDescriptors->CaIds()); Channel->SetSubtitlingDescriptors(SubtitlingTypes, CompositionPageIds, AncillaryPageIds); } @@ -67,7 +67,8 @@ bool cReceiver::SetPids(const cChannel *Channel) (Channel->Ppid() == Channel->Vpid() || AddPid(Channel->Ppid())) && AddPids(Channel->Apids()) && AddPids(Channel->Dpids()) && - AddPids(Channel->Spids()); + AddPids(Channel->Spids()) && + AddPid(Channel->Tpid()); } return true; } @@ -385,6 +385,29 @@ int cPatPmtGenerator::MakeSubtitlingDescriptor(uchar *Target, const char *Langua return i; } +int cPatPmtGenerator::MakeTeletextDescriptor(uchar *Target, const tTeletextSubtitlePage *pages, int pageCount) +{ + int i = 0, j = 0; + Target[i++] = SI::TeletextDescriptorTag; + int l = i; + Target[i++] = 0x00; // length + for (int n = 0; n < pageCount; n++) { + const char* Language = pages[n].ttxtLanguage; + Target[i++] = *Language++; + Target[i++] = *Language++; + Target[i++] = *Language++; + Target[i++] = (pages[n].ttxtType << 3) + pages[n].ttxtMagazine; + Target[i++] = pages[n].ttxtPage; + j++; + } + if (j > 0) { + Target[l] = j * 5; // update length + IncEsInfoLength(i); + return i; + } + return 0; +} + int cPatPmtGenerator::MakeLanguageDescriptor(uchar *Target, const char *Language) { int i = 0; @@ -472,6 +495,7 @@ void cPatPmtGenerator::GeneratePmt(const cChannel *Channel) if (Channel) { int Vpid = Channel->Vpid(); int Ppid = Channel->Ppid(); + int Tpid = Channel->Tpid(); uchar *p = buf; int i = 0; p[i++] = 0x02; // table id @@ -504,6 +528,10 @@ void cPatPmtGenerator::GeneratePmt(const cChannel *Channel) i += MakeStream(buf + i, 0x06, Channel->Spid(n)); i += MakeSubtitlingDescriptor(buf + i, Channel->Slang(n), Channel->SubtitlingType(n), Channel->CompositionPageId(n), Channel->AncillaryPageId(n)); } + if (Tpid) { + i += MakeStream(buf + i, 0x06, Tpid); + i += MakeTeletextDescriptor(buf + i, Channel->TeletextSubtitlePages(), Channel->TotalTeletextSubtitlePages()); + } int sl = i - SectionLength - 2 + 4; // -2 = SectionLength storage, +4 = length of CRC buf[SectionLength] |= (sl >> 8) & 0x0F; @@ -670,6 +698,7 @@ void cPatPmtParser::ParsePmt(const uchar *Data, int Length) spids[0] = 0; atypes[0] = 0; dtypes[0] = 0; + totalTtxtSubtitlePages = 0; SI::PMT::Stream stream; for (SI::Loop::Iterator it; Pmt.streamLoop.getNext(stream, it); ) { dbgpatpmt(" stream type = %02X, pid = %d", stream.getStreamType(), stream.getPid()); @@ -294,6 +294,7 @@ protected: int MakeStream(uchar *Target, uchar Type, int Pid); int MakeAC3Descriptor(uchar *Target, uchar Type); int MakeSubtitlingDescriptor(uchar *Target, const char *Language, uchar SubtitlingType, uint16_t CompositionPageId, uint16_t AncillaryPageId); + int MakeTeletextDescriptor(uchar *Target, const tTeletextSubtitlePage *pages, int pageCount); int MakeLanguageDescriptor(uchar *Target, const char *Language); int MakeCRC(uchar *Target, const uchar *Data, int Length); void GeneratePmtPid(const cChannel *Channel); @@ -353,6 +354,8 @@ private: uint16_t compositionPageIds[MAXSPIDS]; uint16_t ancillaryPageIds[MAXSPIDS]; bool updatePrimaryDevice; + int totalTtxtSubtitlePages; + tTeletextSubtitlePage teletextSubtitlePages[MAXTXTPAGES]; protected: int SectionLength(const uchar *Data, int Length) { return (Length >= 3) ? ((int(Data[1]) & 0x0F) << 8)| Data[2] : 0; } public: |