vdr
1.7.27
|
00001 /* 00002 * sdt.c: SDT section filter 00003 * 00004 * See the main source file 'vdr.c' for copyright information and 00005 * how to reach the author. 00006 * 00007 * $Id: sdt.c 2.5 2010/05/16 14:23:21 kls Exp $ 00008 */ 00009 00010 #include "sdt.h" 00011 #include "channels.h" 00012 #include "config.h" 00013 #include "libsi/section.h" 00014 #include "libsi/descriptor.h" 00015 00016 // --- cSdtFilter ------------------------------------------------------------ 00017 00018 cSdtFilter::cSdtFilter(cPatFilter *PatFilter) 00019 { 00020 patFilter = PatFilter; 00021 Set(0x11, 0x42); // SDT 00022 } 00023 00024 void cSdtFilter::SetStatus(bool On) 00025 { 00026 cFilter::SetStatus(On); 00027 sectionSyncer.Reset(); 00028 } 00029 00030 void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length) 00031 { 00032 if (!(Source() && Transponder())) 00033 return; 00034 SI::SDT sdt(Data, false); 00035 if (!sdt.CheckCRCAndParse()) 00036 return; 00037 if (!sectionSyncer.Sync(sdt.getVersionNumber(), sdt.getSectionNumber(), sdt.getLastSectionNumber())) 00038 return; 00039 if (!Channels.Lock(true, 10)) 00040 return; 00041 SI::SDT::Service SiSdtService; 00042 for (SI::Loop::Iterator it; sdt.serviceLoop.getNext(SiSdtService, it); ) { 00043 cChannel *channel = Channels.GetByChannelID(tChannelID(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId())); 00044 if (!channel) 00045 channel = Channels.GetByChannelID(tChannelID(Source(), 0, Transponder(), SiSdtService.getServiceId())); 00046 00047 cLinkChannels *LinkChannels = NULL; 00048 SI::Descriptor *d; 00049 for (SI::Loop::Iterator it2; (d = SiSdtService.serviceDescriptors.getNext(it2)); ) { 00050 switch (d->getDescriptorTag()) { 00051 case SI::ServiceDescriptorTag: { 00052 SI::ServiceDescriptor *sd = (SI::ServiceDescriptor *)d; 00053 switch (sd->getServiceType()) { 00054 case 0x01: // digital television service 00055 case 0x02: // digital radio sound service 00056 case 0x04: // NVOD reference service 00057 case 0x05: // NVOD time-shifted service 00058 case 0x16: // digital SD television service 00059 case 0x19: // digital HD television service 00060 { 00061 char NameBuf[Utf8BufSize(1024)]; 00062 char ShortNameBuf[Utf8BufSize(1024)]; 00063 char ProviderNameBuf[Utf8BufSize(1024)]; 00064 sd->serviceName.getText(NameBuf, ShortNameBuf, sizeof(NameBuf), sizeof(ShortNameBuf)); 00065 char *pn = compactspace(NameBuf); 00066 char *ps = compactspace(ShortNameBuf); 00067 if (!*ps && cSource::IsCable(Source())) { 00068 // Some cable providers don't mark short channel names according to the 00069 // standard, but rather go their own way and use "name>short name": 00070 char *p = strchr(pn, '>'); // fix for UPC Wien 00071 if (p && p > pn) { 00072 *p++ = 0; 00073 strcpy(ShortNameBuf, skipspace(p)); 00074 } 00075 } 00076 // Avoid ',' in short name (would cause trouble in channels.conf): 00077 for (char *p = ShortNameBuf; *p; p++) { 00078 if (*p == ',') 00079 *p = '.'; 00080 } 00081 sd->providerName.getText(ProviderNameBuf, sizeof(ProviderNameBuf)); 00082 char *pp = compactspace(ProviderNameBuf); 00083 if (channel) { 00084 channel->SetId(sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId()); 00085 if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) 00086 channel->SetName(pn, ps, pp); 00087 // Using SiSdtService.getFreeCaMode() is no good, because some 00088 // tv stations set this flag even for non-encrypted channels :-( 00089 // The special value 0xFFFF was supposed to mean "unknown encryption" 00090 // and would have been overwritten with real CA values later: 00091 // channel->SetCa(SiSdtService.getFreeCaMode() ? 0xFFFF : 0); 00092 } 00093 else if (*pn && Setup.UpdateChannels >= 4) { 00094 channel = Channels.NewChannel(Channel(), pn, ps, pp, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId()); 00095 patFilter->Trigger(); 00096 } 00097 } 00098 default: ; 00099 } 00100 } 00101 break; 00102 // Using the CaIdentifierDescriptor is no good, because some tv stations 00103 // just don't use it. The actual CA values are collected in pat.c: 00104 /* 00105 case SI::CaIdentifierDescriptorTag: { 00106 SI::CaIdentifierDescriptor *cid = (SI::CaIdentifierDescriptor *)d; 00107 if (channel) { 00108 for (SI::Loop::Iterator it; cid->identifiers.hasNext(it); ) 00109 channel->SetCa(cid->identifiers.getNext(it)); 00110 } 00111 } 00112 break; 00113 */ 00114 case SI::NVODReferenceDescriptorTag: { 00115 SI::NVODReferenceDescriptor *nrd = (SI::NVODReferenceDescriptor *)d; 00116 SI::NVODReferenceDescriptor::Service Service; 00117 for (SI::Loop::Iterator it; nrd->serviceLoop.getNext(Service, it); ) { 00118 cChannel *link = Channels.GetByChannelID(tChannelID(Source(), Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId())); 00119 if (!link && Setup.UpdateChannels >= 4) { 00120 link = Channels.NewChannel(Channel(), "NVOD", "", "", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId()); 00121 patFilter->Trigger(); 00122 } 00123 if (link) { 00124 if (!LinkChannels) 00125 LinkChannels = new cLinkChannels; 00126 LinkChannels->Add(new cLinkChannel(link)); 00127 } 00128 } 00129 } 00130 break; 00131 default: ; 00132 } 00133 delete d; 00134 } 00135 if (LinkChannels) { 00136 if (channel) 00137 channel->SetLinkChannels(LinkChannels); 00138 else 00139 delete LinkChannels; 00140 } 00141 } 00142 Channels.Unlock(); 00143 }