diff options
Diffstat (limited to 'sdt.c')
-rw-r--r-- | sdt.c | 146 |
1 files changed, 146 insertions, 0 deletions
@@ -0,0 +1,146 @@ +/* + * sdt.c: SDT section filter + * + * See the main source file 'vdr.c' for copyright information and + * how to reach the author. + * + * $Id: sdt.c 1.1 2004/01/04 11:54:42 kls Exp $ + */ + +#include "sdt.h" +#include "channels.h" +#include "libsi/section.h" +#include "libsi/descriptor.h" + +// --- cSDT ------------------------------------------------------------------ + +class cSDT : public SI::SDT { +public: + cSDT(int Source, int Transponder, uchar &lastSdtVersion, cPatFilter *PatFilter, const u_char *Data); + }; + +cSDT::cSDT(int Source, int Transponder, uchar &lastSdtVersion, cPatFilter *PatFilter, const u_char *Data) +:SI::SDT(Data, false) +{ + if (!CheckCRCAndParse()) + return; + + if (getVersionNumber() == lastSdtVersion) + return; + + if (!Channels.Lock(true, 10)) + return; + + lastSdtVersion = getVersionNumber(); + + SI::SDT::Service SiSdtService; + for (SI::Loop::Iterator it; serviceLoop.hasNext(it); ) { + SiSdtService = serviceLoop.getNext(it); + + cChannel *Channel = Channels.GetByChannelID(tChannelID(Source, getOriginalNetworkId(), getTransportStreamId(), SiSdtService.getServiceId())); + if (!Channel) + Channel = Channels.GetByChannelID(tChannelID(Source, 0, Transponder, SiSdtService.getServiceId())); + + SI::Descriptor *d; + for (SI::Loop::Iterator it2; (d = SiSdtService.serviceDescriptors.getNext(it2)); ) { + switch (d->getDescriptorTag()) { + case SI::ServiceDescriptorTag: { + SI::ServiceDescriptor *sd = (SI::ServiceDescriptor *)d; + switch (sd->getServiceType()) { + case 0x01: // digital television service + //XXX TODO case 0x02: // digital radio sound service + //XXX TODO case 0x04: // NVOD reference service + //XXX TODO case 0x05: // NVOD time-shifted service + { + char buffer[1024]; + char *p = sd->serviceName.getText(buffer); + char NameBuf[1024]; + char ShortNameBuf[1024]; + char *pn = NameBuf; + char *ps = ShortNameBuf; + int IsShortName = 0; + while (*p) { + if ((uchar)*p == 0x86) + IsShortName++; + else if ((uchar)*p == 0x87) + IsShortName--; + else { + *pn++ = *p; + if (IsShortName) + *ps++ = *p; + } + p++; + } + *pn = *ps = 0; + pn = NameBuf; + if (*NameBuf && *ShortNameBuf) { + *ps++ = ','; + strcpy(ps, NameBuf); + pn = ShortNameBuf; + } + if (Channel) { + Channel->SetId(getOriginalNetworkId(), getTransportStreamId(), SiSdtService.getServiceId()); + Channel->SetName(pn); + // Using SiSdtService.getFreeCaMode() is no good, because some + // tv stations set this flag even for non-encrypted channels :-( + // The special value 0xFFFF was supposed to mean "unknown encryption" + // and would have been overwritten with real CA values later: + // Channel->SetCa(SiSdtService.getFreeCaMode() ? 0xFFFF : 0); + } + else if (*pn) { + Channel = Channels.NewChannel(Source, Transponder, pn, getOriginalNetworkId(), getTransportStreamId(), SiSdtService.getServiceId()); + PatFilter->Trigger(); + } + } + } + } + break; + // Using the CaIdentifierDescriptor is no good, because some tv stations + // just don't use it. The actual CA values are collected in pat.c: + /* + case SI::CaIdentifierDescriptorTag: { + SI::CaIdentifierDescriptor *cid = (SI::CaIdentifierDescriptor *)d; + if (Channel) { + for (SI::Loop::Iterator it; cid->identifiers.hasNext(it); ) + Channel->SetCa(cid->identifiers.getNext(it)); + } + } + break; + */ + case SI::NVODReferenceDescriptorTag: { + SI::NVODReferenceDescriptor *nrd = (SI::NVODReferenceDescriptor *)d; + for (SI::Loop::Iterator it; nrd->serviceLoop.hasNext(it); ) { + SI::NVODReferenceDescriptor::Service Service = nrd->serviceLoop.getNext(it); + //printf(" %04X-%04X-%04X\n", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId());//XXX TODO + } + } + break; + default: ; + } + delete d; + } + } + Channels.Unlock(); +} + + +// --- cSdtFilter ------------------------------------------------------------ + +cSdtFilter::cSdtFilter(cPatFilter *PatFilter) +{ + lastSdtVersion = 0xFF; + patFilter = PatFilter; + Set(0x11, 0x42); // SDT +} + +void cSdtFilter::SetStatus(bool On) +{ + cFilter::SetStatus(On); + lastSdtVersion = 0xFF; +} + +void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length) +{ + if (Source() && Transponder()) + cSDT SDT(Source(), Transponder(), lastSdtVersion, patFilter, Data); +} |