#include <lib/dvb/metaparser.h>
#include <lib/dvb_ci/dvbci.h>
#include <lib/dvb/epgcache.h>
+#include <dvbsi++/ca_descriptor.h>
#include <dvbsi++/ca_program_map_section.h>
#include <dvbsi++/teletext_descriptor.h>
#include <dvbsi++/descriptor_tag.h>
:m_ca_servicePtr(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);
{
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);
pmtpid = (*program)->getProgramMapPid();
}
if (pmtpid == -1)
+ serviceEvent(eventNoPATEntry);
+ else
+ m_PMT.begin(eApp, eDVBPMTSpec(pmtpid, m_reference.getServiceID().get()), m_demux);
+ } else
+ serviceEvent(eventNoPAT);
+}
+
+PyObject *eDVBServicePMTHandler::getCaIds()
+{
+ PyObject *ret=0;
+
+ ePtr<eTable<ProgramMapSection> > ptr;
+
+ if ( ((m_service && m_service->usePMT()) || !m_service) && !m_PMT.getCurrent(ptr))
+ {
+ uint16_t caids[255];
+ memset(caids, 0, sizeof(caids));
+ std::vector<ProgramMapSection*>::const_iterator i = ptr->getSections().begin();
+ for (; i != ptr->getSections().end(); ++i)
{
- if ( m_reference.path.find(".ts") != std::string::npos ) // recorded ts
+ const ProgramMapSection &pmt = **i;
+ ElementaryStreamInfoConstIterator es = pmt.getEsInfo()->begin();
+ for (; es != pmt.getEsInfo()->end(); ++es)
{
- // we try to find manual the correct sid
- int fd = open( m_reference.path.c_str(), O_RDONLY|O_LARGEFILE );
- if ( fd < 0 )
- eDebug("open %s failed");
- else
+ for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
+ desc != (*es)->getDescriptors()->end(); ++desc)
{
- eDebug("parse ts file for find the correct pmtpid");
- unsigned char *buf = new unsigned char[256*1024]; // 256 kbyte
- int rd=0;
- while ( pmtpid == -1 && (rd < 1024*1024*5) )
+ switch ((*desc)->getTag())
{
-#define MAX_PIDS 64
- int pids[MAX_PIDS];
- int pididx=-1;
- int r = ::read( fd, buf, 256*1024 );
- if ( r <= 0 )
- break;
- rd+=r;
- int cnt=0;
- while(cnt < r)
- {
- while ( (buf[cnt] != 0x47) && ((cnt+188) < r) && (buf[cnt+188] != 0x47) )
- {
-// eDebug("search sync byte %02x %02x, %d %d", buf[cnt], buf[cnt+188], cnt+188, r);
- cnt++;
- }
- if ( buf[cnt] == 0x47 )
- {
- int pid = ((buf[cnt+1]&0x3F) << 8) | buf[cnt+2];
- int idx=0;
- while(idx <= pididx) // check if we already have this pid
- {
- if ( pids[idx] == pid )
- break;
- ++idx;
- }
- if (idx > pididx && (pididx+1) < MAX_PIDS)
- {
- eDebug("found pid %04x", pid);
- pids[++pididx]=pid;
- }
- cnt+=188;
- }
- else
- break;
- }
- while(pididx > -1 && pmtpid == -1)
+ case CA_DESCRIPTOR:
{
- for (i = ptr->getSections().begin(); i != ptr->getSections().end() && pmtpid == -1; ++i)
- {
- const ProgramAssociationSection &pat = **i;
- ProgramAssociationConstIterator program;
- for (program = pat.getPrograms()->begin(); program != pat.getPrograms()->end(); ++program)
- {
- int pid = (*program)->getProgramMapPid();
- if ( pid == pids[pididx])
- {
- int sid = (*program)->getProgramNumber();
- pmtpid = pid;
- m_reference.setServiceID(eServiceID(sid));
- eDebug("found pmt for service id %04x with pid %04x", sid, pid);
- break;
- }
- }
- }
- --pididx;
+ const CaDescriptor *cadescr = (const CaDescriptor*)*desc;
+ uint16_t caid = cadescr->getCaSystemId();
+ int idx=0;
+ while (caids[idx] && caids[idx] != caid)
+ ++idx;
+ caids[idx]=caid;
+ break;
}
}
- delete [] buf;
- close(fd);
+ }
+ }
+ for (DescriptorConstIterator desc = pmt.getDescriptors()->begin();
+ desc != pmt.getDescriptors()->end(); ++desc)
+ {
+ switch ((*desc)->getTag())
+ {
+ case CA_DESCRIPTOR:
+ {
+ const CaDescriptor *cadescr = (const CaDescriptor*)*desc;
+ uint16_t caid = cadescr->getCaSystemId();
+ int idx=0;
+ while (caids[idx] && caids[idx] != caid)
+ ++idx;
+ caids[idx]=caid;
+ break;
+ }
}
}
}
-
- if (pmtpid == -1)
- serviceEvent(eventNoPATEntry);
- else
- m_PMT.begin(eApp, eDVBPMTSpec(pmtpid, m_reference.getServiceID().get()), m_demux);
- } else
- serviceEvent(eventNoPAT);
+ int cnt=0;
+ while (caids[cnt])
+ ++cnt;
+ if (cnt)
+ {
+ ret=PyList_New(cnt);
+ while(cnt--)
+ PyList_SET_ITEM(ret, cnt, PyInt_FromLong(caids[cnt]));
+ }
+ }
+
+ if (!ret)
+ ret=PyList_New(0);
+
+ return ret;
}
int eDVBServicePMTHandler::getProgramInfo(struct program &program)
program.pmtPid = -1;
program.textPid = -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;
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)
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("try %s", m_reference.toString().c_str());
-
+
eDebug("alloc PVR");
/* allocate PVR */
res = m_resourceManager->allocatePVRChannel(m_pvr_channel);
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_pvr_channel->playFile(ref.path.c_str());
}
- ePtr<iDVBChannelList> db;
- if (!m_resourceManager->getChannelList(db))
- db->getService((eServiceReferenceDVB&)m_reference, m_service);
-
return res;
}