scansdt: add code to scan current sdt for updates

This commit is contained in:
[CST] Focus
2012-01-19 16:51:36 +04:00
parent 772d8d365f
commit ff1a43aba0
2 changed files with 109 additions and 34 deletions

View File

@@ -23,32 +23,31 @@
#ifndef __zapit_scan_sdt_h__
#define __zapit_scan_sdt_h__
#include <zapit/channel.h>
#include <zapit/pat.h>
#include <dmx.h>
#include <dvbsi++/service_description_section.h>
#include <dvbsi++/service_descriptor.h>
#define SDT_SECTION_SIZE 1026
#if 0
typedef std::map<int,int> sidpmt_map_t;
typedef sidpmt_map_t::iterator sidpmt_map_iterator_t;
typedef std::pair<int,int> sidpmt_map_pair_t;
#endif
class CSdt
{
private:
int dmxnum;
bool parsed;
bool cable;
t_transport_stream_id transport_stream_id;
t_original_network_id original_network_id;
t_satellite_position satellitePosition;
freq_id_t freq_id;
std::string lastProviderName;
ServiceDescriptionSectionList sections;
CPat pat;
/* current sdt to check updates */
bool current;
transponder_id_t current_tp_id;
uint8_t FixServiceType(uint8_t type);
bool CheckScanType(uint8_t service_type);
@@ -60,9 +59,9 @@ class CSdt
bool ParseServiceDescriptor(ServiceDescription * service, ServiceDescriptor * sd);
public:
CSdt(t_satellite_position spos, freq_id_t frq, int dnum = 0);
CSdt(t_satellite_position spos, freq_id_t frq, bool curr = false, int dnum = 0);
~CSdt();
bool Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid);
bool Parse(t_transport_stream_id &tsid, t_original_network_id &onid);
};
#endif

View File

@@ -1,12 +1,11 @@
/*
* $Id: sdt.cpp,v 1.44 2003/03/14 08:22:04 obi Exp $
* Copyright (C) 2011 CoolStream International Ltd
*
* (C) 2002, 2003 by Andreas Oberritter <obi@tuxbox.org>
* License: GPLv2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
* the Free Software Foundation;
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -40,12 +39,16 @@
#include <zapit/dvbstring.h>
extern CZapitClient::scanType scanType; // FIXME
extern int scan_fta_flag; // FIXME
CSdt::CSdt(t_satellite_position spos, freq_id_t frq, int dnum)
CSdt::CSdt(t_satellite_position spos, freq_id_t frq, bool curr, int dnum)
{
satellitePosition = spos;
freq_id = frq;
dmxnum = dnum;
current = curr;
transport_stream_id = 0;
original_network_id = 0;
cable = (CServiceScan::getInstance()->GetFrontend()->getInfo()->type == FE_QAM);
}
@@ -57,6 +60,7 @@ CSdt::~CSdt()
}
}
/* read all sdt sections */
bool CSdt::Read()
{
int secdone[255];
@@ -77,12 +81,28 @@ bool CSdt::Read()
filter[0] = 0x42;
mask[0] = 0xFF;
if (transport_stream_id && original_network_id) {
flen = 8;
filter[1] = (transport_stream_id >> 8) & 0xff;
filter[2] = transport_stream_id & 0xff;
filter[6] = (original_network_id >> 8) & 0xff;
filter[7] = original_network_id & 0xff;
mask[1] = 0xFF;
mask[2] = 0xFF;
mask[6] = 0xFF;
mask[7] = 0xFF;
}
if (!dmx->sectionFilter(0x11, filter, mask, flen)) {
delete dmx;
return false;
}
do {
_repeat:
if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid())
break;
if (dmx->Read(buffer, SDT_SECTION_SIZE) < 0) {
delete dmx;
return false;
@@ -107,19 +127,29 @@ _repeat:
sections.push_back(sdt);
} while(sectotal < buffer[7]);
if(cable && !cable_hack_done && sectotal == 0) {
cable_hack_done = true;
secdone[0] = 0;
goto _repeat;
}
delete dmx;
if(current_tp_id != CFEManager::getInstance()->getLiveFE()->getTsidOnid())
return false;
return true;
}
bool CSdt::Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid)
/* parse sdt sections */
bool CSdt::Parse(t_transport_stream_id &tsid, t_original_network_id &onid)
{
ServiceDescriptionSectionIterator it;
if(current) {
transport_stream_id = tsid;
original_network_id = onid;
}
current_tp_id = CFEManager::getInstance()->getLiveFE()->getTsidOnid();
if(!Read())
return false;
@@ -129,7 +159,6 @@ bool CSdt::Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid)
transport_stream_id = sdt->getTransportStreamId();
original_network_id = sdt->getOriginalNetworkId();
//ServiceDescriptionSection sdt(buffer);
printf("SDT: tid %02x onid %02x\n", sdt->getTransportStreamId(), sdt->getOriginalNetworkId());
const ServiceDescriptionList &slist = *sdt->getDescriptions();
for (ServiceDescriptionConstIterator sit = slist.begin(); sit != slist.end(); ++sit) {
@@ -138,7 +167,6 @@ bool CSdt::Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid)
DescriptorConstIterator dit;
for (dit = service->getDescriptors()->begin(); dit != service->getDescriptors()->end(); ++dit) {
Descriptor * d = *dit;
//printf("SDT: sid %x descriptor %02x\n", service->getServiceId(), d->getTag());
switch (d->getTag()) {
case SERVICE_DESCRIPTOR:
{
@@ -150,19 +178,29 @@ bool CSdt::Parse(t_transport_stream_id *p_tsid, t_original_network_id *p_onid)
{
CaIdentifierDescriptor * cad = (CaIdentifierDescriptor *) d;
const CaSystemIdList * calist = cad->getCaSystemIds();
printf("CASYS: ");
for(CaSystemIdConstIterator cit = calist->begin(); cit != calist->end(); ++cit)
printf("CASYS %02x\n", *cit);
printf("%02x ", *cit);
printf("\n");
}
break;
default:
printf("SDT: sid %x descriptor %02x\n", service->getServiceId(), d->getTag());
{
printf("SDT: sid %x descriptor %02x: ", service->getServiceId(), d->getTag());
uint8_t len = d->getLength();
uint8_t buf[len];
d->writeToBuffer(buf);
for(uint8_t i = 0; i < len; i++)
printf("%02x ", buf[i]);
printf("\n");
}
break;
}
}
}
}
*p_tsid = transport_stream_id;
*p_onid = original_network_id;
tsid = transport_stream_id;
onid = original_network_id;
return true;
}
@@ -183,6 +221,9 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto
t_service_id service_id = service->getServiceId();
bool free_ca = service->getFreeCaMode();
if(!current && free_ca && scan_fta_flag)
return false;
int tsidonid = (transport_stream_id << 16) | original_network_id;
std::string providerName = stringDVBUTF8(sd->getServiceProviderName(), 0, tsidonid);
std::string serviceName = stringDVBUTF8(sd->getServiceName(), 0, tsidonid);
@@ -192,7 +233,7 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto
if (!CheckScanType(service_type))
return false;
if(serviceName.empty() || serviceName == "."){
if (serviceName.empty() || serviceName == "."){
char buf_tmp[64];
snprintf(buf_tmp, sizeof(buf_tmp), "unknown (0x%04X_0x%04X)", transport_stream_id, service_id);
serviceName = buf_tmp;
@@ -200,10 +241,34 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto
FixWhiteSpaces(serviceName);
}
if(providerName.empty()) {
providerName = "Unknown Provider";
t_channel_id channel_id = CZapitChannel::makeChannelId(satellitePosition,
freq_id, transport_stream_id, original_network_id, service_id);
if(current) {
if(CServiceManager::getInstance()->FindCurrentChannel(channel_id))
return false;
CZapitChannel * channel = new CZapitChannel(serviceName, channel_id,
real_type, satellitePosition, freq_id);
CServiceManager::getInstance()->AddCurrentChannel(channel);
channel->scrambled = free_ca;
if(pat.Parse(channel)) {
CPmt pmt;
if(pmt.haveCaSys(channel->getPmtPid(), channel->getServiceId()))
channel->scrambled = true;
}
return true;
}
if (providerName.empty()) {
if(lastProviderName.empty())
providerName = "Unknown Provider";
else
providerName = lastProviderName;
} else {
FixWhiteSpaces(providerName);
lastProviderName = providerName;
}
CServiceScan::getInstance()->ChannelFound(service_type, providerName, serviceName);
@@ -213,24 +278,29 @@ bool CSdt::ParseServiceDescriptor(ServiceDescription * service, ServiceDescripto
channel->setName(serviceName);
channel->setServiceType(real_type);
} else {
channel = new CZapitChannel (
serviceName,
service_id,
transport_stream_id,
original_network_id,
real_type,
satellitePosition,
freq_id
);
channel = new CZapitChannel(serviceName, channel_id,
real_type, satellitePosition, freq_id);
CServiceManager::getInstance()->AddChannel(channel);
}
channel->scrambled = free_ca;
AddToBouquet(providerName, channel);
if (CZapit::getInstance()->scanPids()) {
if(pat.Parse(channel)) {
CPmt pmt;
pmt.parse_pmt(channel);
}
}
if(service_type == ST_DIGITAL_TELEVISION_SERVICE && !channel->scrambled) {
CZapit::getInstance()->SetCurrentChannelID(channel->getChannelID());
}
return true;
}
/* check current freq from -2 to +2 to find if channel already exist */
CZapitChannel * CSdt::CheckChannelId(t_service_id service_id)
{
int flist[5] = { freq_id, freq_id-1, freq_id+1, freq_id-2, freq_id+2 };
@@ -245,6 +315,7 @@ CZapitChannel * CSdt::CheckChannelId(t_service_id service_id)
return NULL;
}
/* strip repeated and begin/end whitespaces */
void CSdt::FixWhiteSpaces(std::string &str)
{
size_t found;
@@ -257,8 +328,12 @@ void CSdt::FixWhiteSpaces(std::string &str)
str = str.substr(0, str.length()-1);
}
/* check if service type wanted in current scan type */
bool CSdt::CheckScanType(uint8_t service_type)
{
if(current)
return true;
switch ( scanType ) {
case CZapitClient::ST_TVRADIO:
if ( (service_type == 1 ) || (service_type == 2) )
@@ -279,6 +354,7 @@ bool CSdt::CheckScanType(uint8_t service_type)
return false;
}
/* create bouquet if not exist, and add channel to bouquet */
bool CSdt::AddToBouquet(std::string &providerName, CZapitChannel *channel)
{
switch (channel->getServiceType()) {