mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
147 lines
5.6 KiB
C
147 lines
5.6 KiB
C
/*
|
|
* 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);
|
|
}
|