#include <lib/dvb/metaparser.h>
#include <lib/dvb_ci/dvbci.h>
#include <lib/dvb/epgcache.h>
+#include <lib/dvb/scan.h>
+#include <dvbsi++/ca_descriptor.h>
#include <dvbsi++/ca_program_map_section.h>
#include <dvbsi++/teletext_descriptor.h>
#include <dvbsi++/descriptor_tag.h>
#include <dvbsi++/stream_identifier_descriptor.h>
eDVBServicePMTHandler::eDVBServicePMTHandler()
- :m_ca_servicePtr(0), m_decode_demux_num(0xFF)
+ :m_ca_servicePtr(0), m_dvb_scan(0), m_decode_demux_num(0xFF)
{
m_use_decode_demux = 0;
+ m_pmt_pid = -1;
eDVBResourceManager::getInstance(m_resourceManager);
CONNECT(m_PMT.tableReady, eDVBServicePMTHandler::PMTready);
CONNECT(m_PAT.tableReady, eDVBServicePMTHandler::PATready);
eDVBServicePMTHandler::~eDVBServicePMTHandler()
{
- if (m_ca_servicePtr)
- {
- eDebug("unregister caservice");
- int demuxes[2] = {0,0};
- uint8_t tmp;
- m_demux->getCADemuxID(tmp);
- demuxes[0]=tmp;
- if (m_decode_demux_num != 0xFF)
- demuxes[1]=m_decode_demux_num;
- else
- demuxes[1]=demuxes[0];
- ePtr<eTable<ProgramMapSection> > ptr;
- m_PMT.getCurrent(ptr);
- eDVBCAService::unregister_service(m_reference, demuxes, ptr);
- eDVBCIInterfaces::getInstance()->removePMTHandler(this);
- }
+ free();
}
void eDVBServicePMTHandler::channelStateChanged(iDVBChannel *channel)
{
if (m_channel)
if (m_channel->getDemux(m_demux, (!m_use_decode_demux) ? 0 : iDVBChannel::capDecode))
- eDebug("Allocating a demux for now tuned-in channel failed.");
+ eDebug("Allocating %s-decoding a demux for now tuned-in channel failed.", m_use_decode_demux ? "" : "non-");
serviceEvent(eventTuned);
{
eDebug("ok ... now we start!!");
- m_PAT.begin(eApp, eDVBPATSpec(), m_demux);
+ if (m_pmt_pid == -1)
+ m_PAT.begin(eApp, eDVBPATSpec(), m_demux);
+ else
+ m_PMT.begin(eApp, eDVBPMTSpec(m_pmt_pid, m_reference.getServiceID().get()), m_demux);
if ( m_service && !m_service->cacheEmpty() )
serviceEvent(eventNewProgramInfo);
case iDVBChannel::evtEOF:
serviceEvent(eventEOF);
break;
+ case iDVBChannel::evtSOF:
+ serviceEvent(eventSOF);
+ break;
default:
break;
}
{
serviceEvent(eventNewProgramInfo);
eEPGCache::getInstance()->PMTready(this);
- if (!m_pvr_channel)
+ if (!m_pvr_channel) // don't send campmt to camd.socket for playbacked services
{
- if(!m_ca_servicePtr) // don't send campmt to camd.socket for playbacked services
+ if(!m_ca_servicePtr)
{
int demuxes[2] = {0,0};
uint8_t tmp;
else
demuxes[1]=demuxes[0];
eDVBCAService::register_service(m_reference, demuxes, m_ca_servicePtr);
- eDVBCIInterfaces::getInstance()->addPMTHandler(this);
+ eDVBCIInterfaces::getInstance()->recheckPMTHandlers();
}
- eDVBCIInterfaces::getInstance()->gotPMT(this);
+ else
+ eDVBCIInterfaces::getInstance()->gotPMT(this);
}
if (m_ca_servicePtr)
{
serviceEvent(eventNoPAT);
}
+PyObject *eDVBServicePMTHandler::getCaIds()
+{
+ PyObject *ret=0;
+
+ program prog;
+
+ if ( !getProgramInfo(prog) )
+ {
+ int cnt=prog.caids.size();
+ if (cnt)
+ {
+ ret=PyList_New(cnt);
+ std::set<uint16_t>::iterator it(prog.caids.begin());
+ while(cnt--)
+ PyList_SET_ITEM(ret, cnt, PyInt_FromLong(*it++));
+ }
+ }
+
+ return ret ? ret : PyList_New(0);
+}
+
int eDVBServicePMTHandler::getProgramInfo(struct program &program)
{
ePtr<eTable<ProgramMapSection> > ptr;
program.videoStreams.clear();
program.audioStreams.clear();
program.pcrPid = -1;
- program.isCrypted = false;
program.pmtPid = -1;
program.textPid = -1;
+ program.audioChannel = m_service ? m_service->getCacheEntry(eDVBService::cACHANNEL) : -1;
- if (!m_PMT.getCurrent(ptr))
+ if ( ((m_service && m_service->usePMT()) || !m_service) && !m_PMT.getCurrent(ptr))
{
int cached_apid_ac3 = -1;
int cached_apid_mpeg = -1;
int cached_tpid = -1;
if ( m_service && !m_service->cacheEmpty() )
{
- cached_vpid = m_service->getCachePID(eDVBService::cVPID);
- cached_apid_mpeg = m_service->getCachePID(eDVBService::cAC3PID);
- cached_apid_ac3 = m_service->getCachePID(eDVBService::cAPID);
- cached_tpid = m_service->getCachePID(eDVBService::cTPID);
+ cached_vpid = m_service->getCacheEntry(eDVBService::cVPID);
+ cached_apid_mpeg = m_service->getCacheEntry(eDVBService::cAC3PID);
+ cached_apid_ac3 = m_service->getCacheEntry(eDVBService::cAPID);
+ cached_tpid = m_service->getCacheEntry(eDVBService::cTPID);
}
eDVBTableSpec table_spec;
ptr->getSpec(table_spec);
ElementaryStreamInfoConstIterator es;
for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
{
- int isaudio = 0, isvideo = 0, cadescriptors = 0;
+ int isaudio = 0, isvideo = 0;
videoStream video;
audioStream audio;
audio.component_tag=-1;
video.pid = (*es)->getPid();
audio.pid = (*es)->getPid();
+ video.type = videoStream::vtMPEG2;
switch ((*es)->getType())
{
+ case 0x1b: // AVC Video Stream (MPEG4 H264)
+ video.type = videoStream::vtMPEG4_H264;
case 0x01: // MPEG 1 video
case 0x02: // MPEG 2 video
isvideo = 1;
if ( program.textPid == -1 || (*es)->getPid() == cached_tpid )
program.textPid = (*es)->getPid();
break;
+ case DTS_DESCRIPTOR:
+ if (!isvideo)
+ {
+ isaudio = 1;
+ audio.type = audioStream::atDTS;
+ }
+ break;
+ case AAC_DESCRIPTOR:
+ if (!isvideo)
+ {
+ isaudio = 1;
+ audio.type = audioStream::atAAC;
+ }
+ break;
case AC3_DESCRIPTOR:
if (!isvideo)
{
((StreamIdentifierDescriptor*)*desc)->getComponentTag();
break;
case CA_DESCRIPTOR:
- ++cadescriptors;
+ {
+ CaDescriptor *descr = (CaDescriptor*)(*desc);
+ program.caids.insert(descr->getCaSystemId());
break;
}
+ }
}
break;
}
}
else
continue;
- if ( cadescriptors > 0 )
- program.isCrypted=true;
}
- if ( !program.isCrypted )
+ for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
+ desc != pmt.getDescriptors()->end(); ++desc)
{
- for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
- desc != pmt.getDescriptors()->end(); ++desc)
+ if ((*desc)->getTag() == CA_DESCRIPTOR)
{
- switch ((*desc)->getTag())
- {
- case CA_DESCRIPTOR:
- program.isCrypted=true;
- break;
- }
+ CaDescriptor *descr = (CaDescriptor*)(*desc);
+ program.caids.insert(descr->getCaSystemId());
}
- break;
}
}
return 0;
} else if ( m_service && !m_service->cacheEmpty() )
{
- int vpid = m_service->getCachePID(eDVBService::cVPID),
- apid_ac3 = m_service->getCachePID(eDVBService::cAC3PID),
- apid_mpeg = m_service->getCachePID(eDVBService::cAPID),
- pcrpid = m_service->getCachePID(eDVBService::cPCRPID),
- tpid = m_service->getCachePID(eDVBService::cTPID),
+ int vpid = m_service->getCacheEntry(eDVBService::cVPID),
+ apid_ac3 = m_service->getCacheEntry(eDVBService::cAC3PID),
+ apid_mpeg = m_service->getCacheEntry(eDVBService::cAPID),
+ pcrpid = m_service->getCacheEntry(eDVBService::cPCRPID),
+ tpid = m_service->getCacheEntry(eDVBService::cTPID),
+ vpidtype = m_service->getCacheEntry(eDVBService::cVTYPE),
cnt=0;
+ if ( vpidtype == -1 )
+ vpidtype = videoStream::vtMPEG2;
if ( vpid != -1 )
{
videoStream s;
s.pid = vpid;
+ s.type = vpidtype;
program.videoStreams.push_back(s);
++cnt;
}
++cnt;
program.textPid = tpid;
}
+ CAID_LIST &caids = m_service->m_ca;
+ for (CAID_LIST::iterator it(caids.begin()); it != caids.end(); ++it)
+ program.caids.insert(*it);
if ( cnt )
return 0;
}
demux = m_demux;
return ret;
}
+
+ ASSERT(m_channel); /* calling without a previous ::tune is certainly bad. */
ret = m_channel->getDemux(demux, iDVBChannel::capDecode);
if (!ret)
return -1;
}
-int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux)
+void eDVBServicePMTHandler::SDTScanEvent(int event)
+{
+ switch (event)
+ {
+ case eDVBScan::evtFinish:
+ {
+ ePtr<iDVBChannelList> db;
+ if (m_resourceManager->getChannelList(db) != 0)
+ eDebug("no channel list");
+ else
+ {
+ m_dvb_scan->insertInto(db, true);
+ eDebug("sdt update done!");
+ }
+ break;
+ }
+
+ default:
+ break;
+ }
+}
+
+int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, eCueSheet *cue)
{
RESULT res;
m_reference = ref;
ref.getChannelID(chid);
res = m_resourceManager->allocateChannel(chid, m_channel);
eDebug("allocate Channel: res %d", res);
+ if (!res)
+ eDVBCIInterfaces::getInstance()->addPMTHandler(this);
} else
{
eDVBMetaParser parser;
if (parser.parseFile(ref.path))
- eWarning("no .meta file found, trying original service ref.");
- else
+ {
+ eWarning("no .meta file found, trying to find PMT pid");
+ eDVBTSTools tstools;
+ if (tstools.openFile(ref.path.c_str()))
+ eWarning("failed to open file");
+ else
+ {
+ int service_id, pmt_pid;
+ if (!tstools.findPMT(pmt_pid, service_id))
+ {
+ eDebug("PMT pid found on pid %04x, service id %d", pmt_pid, service_id);
+ m_reference.setServiceID(service_id);
+ m_pmt_pid = pmt_pid;
+ }
+ }
+ } else
m_reference = parser.m_ref;
eDebug("alloc PVR");
eDebug("allocatePVRChannel failed!\n");
m_channel = m_pvr_channel;
}
-
+
+ ePtr<iDVBChannelList> db;
+ if (!m_resourceManager->getChannelList(db))
+ db->getService((eServiceReferenceDVB&)m_reference, m_service);
+
if (m_channel)
{
m_channel->connectStateChange(
m_channel->connectEvent(
slot(*this, &eDVBServicePMTHandler::channelEvent),
m_channelEvent_connection);
+
+ if (ref.path.empty())
+ {
+ delete m_dvb_scan;
+ m_dvb_scan = new eDVBScan(m_channel, false, false);
+ m_dvb_scan->connectEvent(slot(*this, &eDVBServicePMTHandler::SDTScanEvent), m_scan_event_connection);
+ }
} else
{
serviceEvent(eventTuneFailed);
}
if (m_pvr_channel)
+ {
+ m_pvr_channel->setCueSheet(cue);
m_pvr_channel->playFile(ref.path.c_str());
-
- ePtr<iDVBChannelList> db;
- if (!m_resourceManager->getChannelList(db))
- db->getService((eServiceReferenceDVB&)m_reference, m_service);
+ }
return res;
}
void eDVBServicePMTHandler::free()
{
+ eDVBScan *tmp = m_dvb_scan; // do a copy on stack (recursive call of free()) !!!
+ m_dvb_scan = 0;
+ delete m_dvb_scan;
+
+ if (m_ca_servicePtr)
+ {
+ int demuxes[2] = {0,0};
+ uint8_t tmp;
+ m_demux->getCADemuxID(tmp);
+ demuxes[0]=tmp;
+ if (m_decode_demux_num != 0xFF)
+ demuxes[1]=m_decode_demux_num;
+ else
+ demuxes[1]=demuxes[0];
+ ePtr<eTable<ProgramMapSection> > ptr;
+ m_PMT.getCurrent(ptr);
+ eDVBCAService::unregister_service(m_reference, demuxes, ptr);
+ m_ca_servicePtr = 0;
+ }
+
+ if (m_channel)
+ eDVBCIInterfaces::getInstance()->removePMTHandler(this);
+
+ if (m_pvr_channel)
+ {
+ m_pvr_channel->stopFile();
+ m_pvr_channel->setCueSheet(0);
+ }
m_PMT.stop();
m_PAT.stop();
m_service = 0;