#include <dvbsi++/terrestrial_delivery_system_descriptor.h>
#include <dvbsi++/cable_delivery_system_descriptor.h>
#include <dvbsi++/ca_identifier_descriptor.h>
+#include <dvbsi++/registration_descriptor.h>
#include <lib/dvb/specs.h>
#include <lib/dvb/esection.h>
#include <lib/dvb/scan.h>
#include <lib/base/estring.h>
#include <errno.h>
-static bool scan_debug;
-#define SCAN_eDebug(x...) do { if (scan_debug) eDebug(x); } while(0)
-#define SCAN_eDebugNoNewLine(x...) do { if (scan_debug) eDebugNoNewLine(x); } while(0)
+#define SCAN_eDebug(x...) do { if (m_scan_debug) eDebug(x); } while(0)
+#define SCAN_eDebugNoNewLine(x...) do { if (m_scan_debug) eDebugNoNewLine(x); } while(0)
DEFINE_REF(eDVBScan);
eDVBScan::eDVBScan(iDVBChannel *channel, bool usePAT, bool debug)
:m_channel(channel), m_channel_state(iDVBChannel::state_idle)
,m_ready(0), m_ready_all(usePAT ? (readySDT|readyPAT) : readySDT)
- ,m_pmt_running(false), m_abort_current_pmt(false), m_flags(0), m_usePAT(usePAT)
+ ,m_pmt_running(false), m_abort_current_pmt(false), m_flags(0)
+ ,m_usePAT(usePAT), m_scan_debug(debug)
{
- scan_debug=debug;
if (m_channel->getDemux(m_demux))
SCAN_eDebug("scan: failed to allocate demux!");
m_channel->connectStateChange(slot(*this, &eDVBScan::stateChange), m_stateChanged_connection);
case 0:
case 0x1111:
return 0;
+ case 0x13E: // workaround for 11258H and 11470V on hotbird with same ONID/TSID (0x13E/0x578)
+ return orbital_position != 130 || tsid != 0x578;
case 1:
return orbital_position == 192;
case 0x00B1:
return tsid != 0x00B0;
+ case 0x00eb:
+ return tsid != 0x4321;
case 0x0002:
return abs(orbital_position-282) < 6;
default:
RESULT eDVBScan::startFilter()
{
bool startSDT=true;
- assert(m_demux);
+ ASSERT(m_demux);
/* only start required filters filter */
if (m_ready_all & readyPAT)
startSDT = m_ready & readyPAT;
+ // m_ch_current is not set, when eDVBScan is just used for a SDT update
+ if (!m_ch_current)
+ {
+ unsigned int channelFlags;
+ m_channel->getCurrentFrontendParameters(m_ch_current);
+ m_ch_current->getFlags(channelFlags);
+ if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
+ m_flags |= scanOnlyFree;
+ }
+
m_SDT = 0;
if (startSDT && (m_ready_all & readySDT))
{
- m_SDT = new eTable<ServiceDescriptionSection>();
+ m_SDT = new eTable<ServiceDescriptionSection>(m_scan_debug);
int tsid=-1;
if (m_ready & readyPAT && m_ready & validPAT)
{
std::vector<ProgramAssociationSection*>::const_iterator i =
m_PAT->getSections().begin();
- assert(i != m_PAT->getSections().end());
+ ASSERT(i != m_PAT->getSections().end());
tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
m_pat_tsid = eTransportStreamID(tsid);
for (; i != m_PAT->getSections().end(); ++i)
for (; program != pat.getPrograms()->end(); ++program)
m_pmts_to_read.insert(std::pair<unsigned short, service>((*program)->getProgramNumber(), service((*program)->getProgramMapPid())));
}
- m_PMT = new eTable<ProgramMapSection>();
+ m_PMT = new eTable<ProgramMapSection>(m_scan_debug);
CONNECT(m_PMT->tableReady, eDVBScan::PMTready);
- PMTready(-1);
-
+ PMTready(-2);
// KabelBW HACK ... on 618Mhz and 626Mhz the transport stream id in PAT and SDT is different
+
{
int type;
m_ch_current->getSystem(type);
m_PAT = 0;
if (m_ready_all & readyPAT)
{
- m_PAT = new eTable<ProgramAssociationSection>();
- if (m_PAT->start(m_demux, eDVBPATSpec()))
+ m_PAT = new eTable<ProgramAssociationSection>(m_scan_debug);
+ if (m_PAT->start(m_demux, eDVBPATSpec(4000)))
return -1;
CONNECT(m_PAT->tableReady, eDVBScan::PATready);
}
m_NIT = 0;
if (m_ready_all & readyNIT)
{
- m_NIT = new eTable<NetworkInformationSection>();
+ m_NIT = new eTable<NetworkInformationSection>(m_scan_debug);
if (m_NIT->start(m_demux, eDVBNITSpec()))
return -1;
CONNECT(m_NIT->tableReady, eDVBScan::NITready);
m_BAT = 0;
if (m_ready_all & readyBAT)
{
- m_BAT = new eTable<BouquetAssociationSection>();
+ m_BAT = new eTable<BouquetAssociationSection>(m_scan_debug);
if (m_BAT->start(m_demux, eDVBBATSpec()))
return -1;
CONNECT(m_BAT->tableReady, eDVBScan::BATready);
}
}
-
return 0;
}
bool have_video = false;
unsigned short pcrpid = 0xFFFF;
std::vector<ProgramMapSection*>::const_iterator i;
+
for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
{
const ProgramMapSection &pmt = **i;
if (pcrpid == 0xFFFF)
pcrpid = pmt.getPcrPid();
else
- eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
+ SCAN_eDebug("already have a pcrpid %04x %04x", pcrpid, pmt.getPcrPid());
ElementaryStreamInfoConstIterator es;
for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
{
- int isaudio = 0, isvideo = 0, is_scrambled = 0;
+ int isaudio = 0, isvideo = 0, is_scrambled = 0, forced_audio = 0, forced_video = 0;
switch ((*es)->getType())
{
case 0x1b: // AVC Video Stream (MPEG4 H264)
+ case 0x10: // MPEG 4 Part 2
case 0x01: // MPEG 1 video
case 0x02: // MPEG 2 video
isvideo = 1;
+ forced_video = 1;
//break; fall through !!!
case 0x03: // MPEG 1 audio
- case 0x04: // MPEG 2 audio:
- if (!isvideo)
+ case 0x04: // MPEG 2 audio
+ case 0x0f: // MPEG 2 AAC
+ case 0x11: // MPEG 4 AAC
+ if (!isvideo)
+ {
+ forced_audio = 1;
isaudio = 1;
- //break; fall through !!!
+ }
case 0x06: // PES Private
case 0x81: // user private
- /* PES private can contain AC-3, DTS or lots of other stuff.
- check descriptors to get the exact type. */
+ case 0xEA: // TS_PSI_ST_SMPTE_VC1
for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
desc != (*es)->getDescriptors()->end(); ++desc)
{
- switch ((*desc)->getTag())
- {
- case DTS_DESCRIPTOR:
- case AAC_DESCRIPTOR:
- isaudio = 1;
- case AC3_DESCRIPTOR:
- isaudio = 1;
- break;
- case CA_DESCRIPTOR:
- is_scrambled = 1;
- break;
- case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
+ uint8_t tag = (*desc)->getTag();
+ /* PES private can contain AC-3, DTS or lots of other stuff.
+ check descriptors to get the exakt type. */
+ if (!forced_video && !forced_audio)
{
- /* libdvbsi++ doesn't yet support this descriptor type, so work around. */
- if ((*desc)->getLength() != 4)
- break;
- unsigned char descr[6];
- (*desc)->writeToBuffer(descr);
- int format_identifier = (descr[2] << 24) | (descr[3] << 16) | (descr[4] << 8) | (descr[5]);
- switch (format_identifier)
+ switch (tag)
{
- case 0x41432d33:
+ case 0x1C: // TS_PSI_DT_MPEG4_Audio
+ case 0x2B: // TS_PSI_DT_MPEG2_AAC
+ case AAC_DESCRIPTOR:
+ case AC3_DESCRIPTOR:
+ case DTS_DESCRIPTOR:
+ case AUDIO_STREAM_DESCRIPTOR:
isaudio = 1;
+ break;
+ case 0x28: // TS_PSI_DT_AVC
+ case 0x1B: // TS_PSI_DT_MPEG4_Video
+ case VIDEO_STREAM_DESCRIPTOR:
+ isvideo = 1;
+ break;
+ case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */
+ {
+ RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc);
+ switch (d->getFormatIdentifier())
+ {
+ case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3
+ case 0x41432d33: // == 'AC-3'
+ case 0x42535344: // == 'BSSD' (LPCM)
+ isaudio = 1;
+ break;
+ case 0x56432d31: // == 'VC-1'
+ isvideo = 1;
+ break;
+ default:
+ break;
+ }
+ }
default:
break;
}
- break;
- }
}
+ if (tag == CA_DESCRIPTOR)
+ is_scrambled = 1;
}
+ default:
break;
}
- if (isaudio)
- have_audio = true;
- else if (isvideo)
+ if (isvideo)
have_video = true;
+ else if (isaudio)
+ have_audio = true;
else
continue;
if (is_scrambled)
else
m_pmt_in_progress->second.serviceType = 100;
}
- if (err == -2) // aborted in sdt progress
+ if (err == -1) // timeout or removed by sdt
m_pmts_to_read.erase(m_pmt_in_progress++);
else if (m_pmt_running)
++m_pmt_in_progress;
}
if (m_pmt_in_progress != m_pmts_to_read.end())
- m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first));
+ m_PMT->start(m_demux, eDVBPMTSpec(m_pmt_in_progress->second.pmtPid, m_pmt_in_progress->first, 4000));
else
{
+ m_PMT = 0;
m_pmt_running = false;
channelDone();
}
{
eDVBFrontendParametersSatellite parm;
feparm->getDVBS(parm);
- eDebug("try to add %d %d %d %d %d %d",
+ SCAN_eDebug("try to add %d %d %d %d %d %d",
parm.orbital_position, parm.frequency, parm.symbol_rate, parm.polarisation, parm.fec, parm.modulation);
break;
}
{
eDVBFrontendParametersCable parm;
feparm->getDVBC(parm);
- eDebug("try to add %d %d %d %d",
+ SCAN_eDebug("try to add %d %d %d %d",
parm.frequency, parm.symbol_rate, parm.modulation, parm.fec_inner);
break;
}
{
eDVBFrontendParametersTerrestrial parm;
feparm->getDVBT(parm);
- eDebug("try to add %d %d %d %d %d %d %d %d",
+ SCAN_eDebug("try to add %d %d %d %d %d %d %d %d",
parm.frequency, parm.modulation, parm.transmission_mode, parm.hierarchy,
parm.guard_interval, parm.code_rate_LP, parm.code_rate_HP, parm.bandwidth);
break;
if (!found_count)
{
*i = feparm; // update
- eDebug("update");
+ SCAN_eDebug("update");
}
else
{
- eDebug("remove dupe");
+ SCAN_eDebug("remove dupe");
m_ch_toScan.erase(i++);
continue;
}
if (found_count > 0)
{
- eDebug("already in todo list");
+ SCAN_eDebug("already in todo list");
return;
}
for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_scanned.begin()); i != m_ch_scanned.end(); ++i)
if (sameChannel(*i, feparm))
{
- eDebug("successfully scanned");
+ SCAN_eDebug("successfully scanned");
return;
}
for (std::list<ePtr<iDVBFrontendParameters> >::const_iterator i(m_ch_unavailable.begin()); i != m_ch_unavailable.end(); ++i)
if (sameChannel(*i, feparm, true))
{
- eDebug("scanned but not available");
+ SCAN_eDebug("scanned but not available");
return;
}
/* ... on the current channel */
if (sameChannel(m_ch_current, feparm))
{
- eDebug("is current");
+ SCAN_eDebug("is current");
return;
}
- eDebug("really add");
+ SCAN_eDebug("really add");
/* otherwise, add it to the todo list. */
m_ch_toScan.push_front(feparm); // better.. then the rotor not turning wild from east to west :)
}
{
unsigned long hash = 0;
- // m_ch_current is not set, when eDVBScan is just used for a SDT update
- if (!m_ch_current)
- {
- unsigned int channelFlags;
- m_channel->getCurrentFrontendParameters(m_ch_current);
- m_ch_current->getFlags(channelFlags);
- if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
- m_flags |= scanOnlyFree;
- }
-
m_ch_current->getHash(hash);
eDVBNamespace dvbnamespace = buildNamespace(
if (m_ready & validNIT)
{
- eDebug("validNIT");
int system;
std::list<ePtr<iDVBFrontendParameters> > m_ch_toScan_backup;
m_ch_current->getSystem(system);
if ( abs(abs(3600 - p.orbital_position) - sat.orbital_position) < 5 )
{
- eDebug("found transponder with incorrect west/east flag ... correct this");
+ SCAN_eDebug("found transponder with incorrect west/east flag ... correct this");
sat.orbital_position = p.orbital_position;
}
{
unsigned long hash = 0;
- // m_ch_current is not set, when eDVBScan is just used for a SDT update
- if (!m_ch_current)
- {
- unsigned int channelFlags;
- m_channel->getCurrentFrontendParameters(m_ch_current);
- m_ch_current->getFlags(channelFlags);
- if (channelFlags & iDVBFrontendParameters::flagOnlyFree)
- m_flags |= scanOnlyFree;
- }
-
m_ch_current->getHash(hash);
m_chid_current = eDVBChannelID(
}
case iDVBFrontend::feTerrestrial:
{
+ ePtr<iDVBFrontend> fe;
eDVBFrontendParametersTerrestrial parm;
m_ch_current->getDVBT(parm);
snprintf(sname, 255, "%d SID 0x%02x",
parm.frequency/1000,
m_pmt_in_progress->first);
+ if (!m_channel->getFrontend(fe))
+ {
+ ePyObject tp_dict = PyDict_New();
+ fe->getTransponderData(tp_dict, false);
+ m_corrected_frequencys[m_chid_current] =
+ PyInt_AsLong(PyDict_GetItemString(tp_dict, "frequency"));
+ Py_DECREF(tp_dict);
+ }
break;
}
case iDVBFrontend::feCable:
SCAN_eDebug("name '%s', provider_name '%s'", sname, pname);
service->m_service_name = convertDVBUTF8(sname);
service->genSortName();
- service->m_provider_name = pname;
+ service->m_provider_name = convertDVBUTF8(pname);
}
- std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
-
- if (i.second)
- {
- m_last_service = i.first;
- m_event(evtNewService);
+ if (!(m_flags & scanOnlyFree) || !m_pmt_in_progress->second.scrambled) {
+ SCAN_eDebug("add not scrambled!");
+ std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
+ m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
+ if (i.second)
+ {
+ m_last_service = i.first;
+ m_event(evtNewService);
+ }
}
+ else
+ SCAN_eDebug("dont add... is scrambled!");
m_pmts_to_read.erase(m_pmt_in_progress++);
}
{
if (sameChannel(*i, m_ch_current))
{
- eDebug("remove dupe 2");
+ SCAN_eDebug("remove dupe 2");
m_ch_toScan.erase(i++);
continue;
}
std::list<ePtr<iDVBFrontendParameters> >::iterator it(m_ch_scanned.begin());
for (;it != m_ch_scanned.end(); ++it)
{
- if (m_flags & scanDontRemoveUnscanned) {
- eDebug("scanDontRemoveUnscanned!");
+ if (m_flags & scanDontRemoveUnscanned)
db->removeServices(&(*(*it)));
- }
else
{
int system;
for (std::map<eDVBChannelID, ePtr<iDVBFrontendParameters> >::const_iterator
ch(m_new_channels.begin()); ch != m_new_channels.end(); ++ch)
{
+ int system;
+ ch->second->getSystem(system);
+ if (system == iDVBFrontend::feTerrestrial)
+ {
+ std::map<eDVBChannelID, unsigned int>::iterator it = m_corrected_frequencys.find(ch->first);
+ if (it != m_corrected_frequencys.end())
+ {
+ eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
+ eDVBFrontendParametersTerrestrial parm;
+ p->getDVBT(parm);
+ eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
+ ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
+ ch->first.dvbnamespace.get(), it->second, parm.frequency);
+ parm.frequency = it->second;
+ p->setDVBT(parm);
+ m_corrected_frequencys.erase(it);
+ }
+ }
if (m_flags & scanOnlyFree)
{
eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
SCAN_eDebug("is scrambled!");
add = false;
}
+ else
+ SCAN_eDebug("is free");
}
- else
+ else {
SCAN_eDebug("not found in PAT.. so we assume it is scrambled!!");
+ add = false;
+ }
}
if (add)
}
}
- std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i = m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
+ std::pair<std::map<eServiceReferenceDVB, ePtr<eDVBService> >::iterator, bool> i =
+ m_new_services.insert(std::pair<eServiceReferenceDVB, ePtr<eDVBService> >(ref, service));
if (i.second)
{