vdr  2.4.1
sdt.c
Go to the documentation of this file.
1 /*
2  * sdt.c: SDT section filter
3  *
4  * See the main source file 'vdr.c' for copyright information and
5  * how to reach the author.
6  *
7  * $Id: sdt.c 4.5 2015/08/02 11:33:23 kls Exp $
8  */
9 
10 #include "sdt.h"
11 #include "channels.h"
12 #include "config.h"
13 #include "libsi/section.h"
14 #include "libsi/descriptor.h"
15 
16 // Set to 'true' for debug output:
17 static bool DebugSdt = false;
18 
19 #define dbgsdt(a...) if (DebugSdt) fprintf(stderr, a)
20 
21 // --- cSdtFilter ------------------------------------------------------------
22 
24 {
26  patFilter = PatFilter;
27  Set(0x11, 0x42); // SDT
28 }
29 
30 void cSdtFilter::SetStatus(bool On)
31 {
32  cMutexLock MutexLock(&mutex);
35  if (!On)
37 }
38 
39 void cSdtFilter::Trigger(int Source)
40 {
41  cMutexLock MutexLock(&mutex);
42  source = Source;
43 }
44 
45 void cSdtFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
46 {
47  cMutexLock MutexLock(&mutex);
48  if (!(source && Transponder()))
49  return;
50  SI::SDT sdt(Data, false);
51  if (!sdt.CheckCRCAndParse())
52  return;
54  return;
55  cStateKey StateKey;
56  cChannels *Channels = cChannels::GetChannelsWrite(StateKey, 10);
57  if (!Channels) {
58  sectionSyncer.Repeat(); // let's not miss any section of the SDT
59  return;
60  }
61  dbgsdt("SDT: %2d %2d %2d %s %d\n", sdt.getVersionNumber(), sdt.getSectionNumber(), sdt.getLastSectionNumber(), *cSource::ToString(source), Transponder());
62  bool ChannelsModified = false;
63  SI::SDT::Service SiSdtService;
64  for (SI::Loop::Iterator it; sdt.serviceLoop.getNext(SiSdtService, it); ) {
66  if (!Channel)
67  Channel = Channels->GetByChannelID(tChannelID(source, 0, Transponder(), SiSdtService.getServiceId()));
68  if (Channel)
69  Channel->SetSeen();
70 
71  cLinkChannels *LinkChannels = NULL;
72  SI::Descriptor *d;
73  for (SI::Loop::Iterator it2; (d = SiSdtService.serviceDescriptors.getNext(it2)); ) {
74  switch (d->getDescriptorTag()) {
77  switch (sd->getServiceType()) {
78  case 0x01: // digital television service
79  case 0x02: // digital radio sound service
80  case 0x04: // NVOD reference service
81  case 0x05: // NVOD time-shifted service
82  case 0x16: // digital SD television service
83  case 0x19: // digital HD television service
84  {
85  char NameBuf[Utf8BufSize(1024)];
86  char ShortNameBuf[Utf8BufSize(1024)];
87  char ProviderNameBuf[Utf8BufSize(1024)];
88  sd->serviceName.getText(NameBuf, ShortNameBuf, sizeof(NameBuf), sizeof(ShortNameBuf));
89  char *pn = compactspace(NameBuf);
90  char *ps = compactspace(ShortNameBuf);
91  if (!*ps && cSource::IsCable(source)) {
92  // Some cable providers don't mark short channel names according to the
93  // standard, but rather go their own way and use "name>short name":
94  char *p = strchr(pn, '>'); // fix for UPC Wien
95  if (p && p > pn) {
96  *p++ = 0;
97  strcpy(ShortNameBuf, skipspace(p));
98  }
99  }
100  // Avoid ',' in short name (would cause trouble in channels.conf):
101  for (char *p = ShortNameBuf; *p; p++) {
102  if (*p == ',')
103  *p = '.';
104  }
105  sd->providerName.getText(ProviderNameBuf, sizeof(ProviderNameBuf));
106  char *pp = compactspace(ProviderNameBuf);
107  if (Channel) {
108  ChannelsModified |= Channel->SetId(Channels, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
109  if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3)
110  ChannelsModified |= Channel->SetName(pn, ps, pp);
111  // Using SiSdtService.getFreeCaMode() is no good, because some
112  // tv stations set this flag even for non-encrypted channels :-(
113  // The special value 0xFFFF was supposed to mean "unknown encryption"
114  // and would have been overwritten with real CA values later:
115  // Channel->SetCa(SiSdtService.getFreeCaMode() ? 0xFFFF : 0);
116  }
117  else if (*pn && Setup.UpdateChannels >= 4) {
118  dbgsdt(" %5d %5d %5d %s/%s %d %s\n", sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId(), *cSource::ToString(this->Channel()->Source()), *cSource::ToString(source), this->Channel()->Transponder(), pn);
119  Channel = Channels->NewChannel(this->Channel(), pn, ps, pp, sdt.getOriginalNetworkId(), sdt.getTransportStreamId(), SiSdtService.getServiceId());
120  Channel->SetSource(source); // in case this comes from a satellite with a slightly different position
121  ChannelsModified = true;
122  patFilter->Trigger(SiSdtService.getServiceId());
123  }
124  }
125  default: ;
126  }
127  }
128  break;
129  // Using the CaIdentifierDescriptor is no good, because some tv stations
130  // just don't use it. The actual CA values are collected in pat.c:
131  /*
132  case SI::CaIdentifierDescriptorTag: {
133  SI::CaIdentifierDescriptor *cid = (SI::CaIdentifierDescriptor *)d;
134  if (Channel) {
135  for (SI::Loop::Iterator it; cid->identifiers.hasNext(it); )
136  Channel->SetCa(Channels, cid->identifiers.getNext(it));
137  }
138  }
139  break;
140  */
144  for (SI::Loop::Iterator it; nrd->serviceLoop.getNext(Service, it); ) {
145  cChannel *link = Channels->GetByChannelID(tChannelID(source, Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId()));
146  if (!link && Setup.UpdateChannels >= 4) {
147  link = Channels->NewChannel(this->Channel(), "NVOD", "", "", Service.getOriginalNetworkId(), Service.getTransportStream(), Service.getServiceId());
148  patFilter->Trigger(Service.getServiceId());
149  ChannelsModified = true;
150  }
151  if (link) {
152  if (!LinkChannels)
153  LinkChannels = new cLinkChannels;
154  LinkChannels->Add(new cLinkChannel(link));
155  ChannelsModified = true;
156  }
157  }
158  }
159  break;
160  default: ;
161  }
162  delete d;
163  }
164  if (LinkChannels) {
165  if (Channel)
166  ChannelsModified |= Channel->SetLinkChannels(LinkChannels);
167  else
168  delete LinkChannels;
169  }
170  }
171  if (sdt.getSectionNumber() == sdt.getLastSectionNumber()) {
172  if (Setup.UpdateChannels == 1 || Setup.UpdateChannels >= 3) {
173  ChannelsModified |= Channels->MarkObsoleteChannels(source, sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
174  if (source != Source())
175  ChannelsModified |= Channels->MarkObsoleteChannels(Source(), sdt.getOriginalNetworkId(), sdt.getTransportStreamId());
176  }
177  }
178  StateKey.Remove(ChannelsModified);
179 }
cFilter::SetStatus
virtual void SetStatus(bool On)
Turns this filter on or off, depending on the value of On.
Definition: filter.c:129
cFilter::Transponder
int Transponder(void)
Returns the transponder of the data delivered to this filter.
Definition: filter.c:119
cChannel::SetName
bool SetName(const char *Name, const char *ShortName, const char *Provider)
Definition: channels.c:258
cFilter::Set
void Set(u_short Pid, u_char Tid, u_char Mask=0xFF)
Sets the given filter data by calling Add() with Sticky = true.
Definition: filter.c:162
cSdtFilter::mutex
cMutex mutex
Definition: sdt.h:18
SI::NVODReferenceDescriptor::serviceLoop
StructureLoop< Service > serviceLoop
Definition: descriptor.h:291
SI::Loop::Iterator
Definition: si.h:333
cSource::ToString
static cString ToString(int Code)
Definition: sources.c:55
cPatFilter
Definition: pat.h:19
cSdtFilter::patFilter
cPatFilter * patFilter
Definition: sdt.h:21
section.h
SI::NVODReferenceDescriptor::Service
Definition: descriptor.h:280
cSdtFilter::Trigger
void Trigger(int Source)
Definition: sdt.c:39
SI::CRCSection::CheckCRCAndParse
bool CheckCRCAndParse()
Definition: si.c:75
SI::SDT::Service::getServiceId
int getServiceId() const
Definition: section.c:142
SI::ServiceDescriptorTag
@ ServiceDescriptorTag
Definition: si.h:96
cSdtFilter::source
int source
Definition: sdt.h:20
cListBase::Add
void Add(cListObject *Object, cListObject *After=NULL)
Definition: tools.c:2152
cSetup::UpdateChannels
int UpdateChannels
Definition: config.h:318
cSdtFilter::SetStatus
virtual void SetStatus(bool On)
Turns this filter on or off, depending on the value of On.
Definition: sdt.c:30
SI::u_char
unsigned char u_char
Definition: headers.h:38
cChannels::GetChannelsWrite
static cChannels * GetChannelsWrite(cStateKey &StateKey, int TimeoutMs=0)
Gets the list of channels for write access.
Definition: channels.c:855
cMutexLock
Definition: thread.h:141
SI::NumberedSection::getLastSectionNumber
int getLastSectionNumber() const
Definition: si.c:102
tChannelID
Definition: channels.h:49
Setup
cSetup Setup
Definition: config.c:372
cChannel::SetId
bool SetId(cChannels *Channels, int Nid, int Tid, int Sid, int Rid=0)
Definition: channels.c:227
SI::NumberedSection::getSectionNumber
int getSectionNumber() const
Definition: si.c:98
cStateKey
Definition: thread.h:233
cChannel::SetLinkChannels
bool SetLinkChannels(cLinkChannels *LinkChannels)
Definition: channels.c:487
cPatFilter::Trigger
void Trigger(int Sid=-1)
Definition: pat.c:306
sdt.h
SI::SDT::Service
Definition: section.h:137
cSectionSyncer::Repeat
void Repeat(void)
Definition: filter.c:29
SI::NVODReferenceDescriptor::Service::getServiceId
int getServiceId() const
Definition: descriptor.c:556
channels.h
cChannels::MarkObsoleteChannels
bool MarkObsoleteChannels(int Source, int Nid, int Tid)
Definition: channels.c:1132
cChannel::SetSeen
void SetSeen(void)
Definition: channels.c:433
SI::Descriptor::getDescriptorTag
DescriptorTag getDescriptorTag() const
Definition: si.c:110
cSdtFilter::Process
virtual void Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
Processes the data delivered to this filter.
Definition: sdt.c:45
cSource::IsCable
static bool IsCable(int Code)
Definition: sources.h:56
SI::NVODReferenceDescriptor::Service::getOriginalNetworkId
int getOriginalNetworkId() const
Definition: descriptor.c:552
dbgsdt
#define dbgsdt(a...)
Definition: sdt.c:19
cStateKey::Remove
void Remove(bool IncState=true)
Removes this key from the lock it was previously used with.
Definition: thread.c:859
cChannels::GetByChannelID
const cChannel * GetByChannelID(tChannelID ChannelID, bool TryWithoutRid=false, bool TryWithoutPolarization=false) const
Definition: channels.c:1018
cChannels
Definition: channels.h:210
cFilter::Channel
const cChannel * Channel(void)
Returns the channel of the data delivered to this filter.
Definition: filter.c:124
SI::NVODReferenceDescriptor
Definition: descriptor.h:278
cSectionSyncer::Reset
void Reset(void)
Definition: filter.c:20
SI::Descriptor
Definition: si.h:312
cChannels::NewChannel
cChannel * NewChannel(const cChannel *Transponder, const char *Name, const char *ShortName, const char *Provider, int Nid, int Tid, int Sid, int Rid=0)
Definition: channels.c:1113
cChannel
Definition: channels.h:89
cLinkChannel
Definition: channels.h:75
cSource::stNone
@ stNone
Definition: sources.h:18
SI::ServiceDescriptor::getServiceType
int getServiceType() const
Definition: descriptor.c:531
skipspace
char * skipspace(const char *s)
Definition: tools.h:209
Utf8BufSize
#define Utf8BufSize(s)
Definition: tools.h:141
cSectionSyncer::Sync
bool Sync(uchar Version, int Number, int LastNumber)
Definition: filter.c:36
cLinkChannels
Definition: channels.h:83
DebugSdt
static bool DebugSdt
Definition: sdt.c:17
SI::SDT::Service::serviceDescriptors
DescriptorLoop serviceDescriptors
Definition: section.h:145
SI::DescriptorLoop::getNext
Descriptor * getNext(Iterator &it)
Definition: si.c:122
SI::ServiceDescriptor::providerName
String providerName
Definition: descriptor.h:271
config.h
cChannel::SetSource
bool SetSource(int Source)
Definition: channels.c:214
SI::NVODReferenceDescriptor::Service::getTransportStream
int getTransportStream() const
Definition: descriptor.c:548
SI::SDT
Definition: section.h:133
cFilter::Source
int Source(void)
Returns the source of the data delivered to this filter.
Definition: filter.c:114
SI::String::getText
char * getText()
Definition: si.c:232
cSdtFilter::sectionSyncer
cSectionSyncer sectionSyncer
Definition: sdt.h:19
compactspace
char * compactspace(char *s)
Definition: tools.c:213
SI::SDT::getTransportStreamId
int getTransportStreamId() const
Definition: section.c:134
SI::ServiceDescriptor::serviceName
String serviceName
Definition: descriptor.h:270
cSdtFilter::cSdtFilter
cSdtFilter(cPatFilter *PatFilter)
Definition: sdt.c:23
SI::NVODReferenceDescriptorTag
@ NVODReferenceDescriptorTag
Definition: si.h:99
SI::NumberedSection::getVersionNumber
int getVersionNumber() const
Definition: si.c:94
SI::SDT::getOriginalNetworkId
int getOriginalNetworkId() const
Definition: section.c:138
SI::SDT::serviceLoop
StructureLoop< Service > serviceLoop
Definition: section.h:153
descriptor.h
SI::ServiceDescriptor
Definition: descriptor.h:267