X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/c5245596a287e0519d0684eb10ea111da75b9360..6aa0ed7fff929c4b2651667ab809d0ace1dac56d:/lib/dvb/pmt.cpp diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index 4ce35394..d6f002e6 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -5,6 +5,8 @@ #include #include #include +#include +#include #include #include #include @@ -12,9 +14,10 @@ #include 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); @@ -35,7 +38,7 @@ 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); @@ -43,7 +46,10 @@ void eDVBServicePMTHandler::channelStateChanged(iDVBChannel *channel) { 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); @@ -79,9 +85,9 @@ void eDVBServicePMTHandler::PMTready(int error) { 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; @@ -92,7 +98,7 @@ void eDVBServicePMTHandler::PMTready(int error) 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); } @@ -122,84 +128,6 @@ void eDVBServicePMTHandler::PATready(int) if (eServiceID((*program)->getProgramNumber()) == m_reference.getServiceID()) pmtpid = (*program)->getProgramMapPid(); } - if (pmtpid == -1) - { - if ( m_reference.path.find(".ts") != std::string::npos ) // recorded ts - { - // 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 - { - 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) ) - { -#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) - { - 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; - } - } - delete [] buf; - close(fd); - } - } - } - if (pmtpid == -1) serviceEvent(eventNoPATEntry); else @@ -208,30 +136,51 @@ void eDVBServicePMTHandler::PATready(int) 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::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 > ptr; + int cached_apid_ac3 = -1; + int cached_apid_mpeg = -1; + int cached_vpid = -1; + int cached_tpid = -1; program.videoStreams.clear(); program.audioStreams.clear(); program.pcrPid = -1; - program.isCrypted = false; program.pmtPid = -1; program.textPid = -1; - if (!m_PMT.getCurrent(ptr)) + if ( m_service && !m_service->cacheEmpty() ) + { + 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); + } + + if ( ((m_service && m_service->usePMT()) || !m_service) && !m_PMT.getCurrent(ptr)) { - int cached_apid_ac3 = -1; - int cached_apid_mpeg = -1; - int cached_vpid = -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); - } eDVBTableSpec table_spec; ptr->getSpec(table_spec); program.pmtPid = table_spec.pid < 0x1fff ? table_spec.pid : -1; @@ -244,7 +193,7 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) 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; @@ -252,9 +201,12 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) 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; @@ -279,6 +231,20 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) 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) { @@ -301,9 +267,12 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) ((StreamIdentifierDescriptor*)*desc)->getComponentTag(); break; case CA_DESCRIPTOR: - ++cadescriptors; + { + CaDescriptor *descr = (CaDescriptor*)(*desc); + program.caids.insert(descr->getCaSystemId()); break; } + } } break; } @@ -330,66 +299,62 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) } 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 cached_pcrpid = m_service->getCacheEntry(eDVBService::cPCRPID), + vpidtype = m_service->getCacheEntry(eDVBService::cVTYPE), cnt=0; - if ( vpid != -1 ) + if ( vpidtype == -1 ) + vpidtype = videoStream::vtMPEG2; + if ( cached_vpid != -1 ) { videoStream s; - s.pid = vpid; + s.pid = cached_vpid; + s.type = vpidtype; program.videoStreams.push_back(s); ++cnt; } - if ( apid_ac3 != -1 ) + if ( cached_apid_ac3 != -1 ) { audioStream s; s.type = audioStream::atAC3; - s.pid = apid_ac3; + s.pid = cached_apid_ac3; program.audioStreams.push_back(s); ++cnt; } - if ( apid_mpeg != -1 ) + if ( cached_apid_mpeg != -1 ) { audioStream s; s.type = audioStream::atMPEG; - s.pid = apid_mpeg; + s.pid = cached_apid_mpeg; program.audioStreams.push_back(s); ++cnt; } - if ( pcrpid != -1 ) + if ( cached_pcrpid != -1 ) { ++cnt; - program.pcrPid = pcrpid; + program.pcrPid = cached_pcrpid; } - if ( tpid != -1 ) + if ( cached_tpid != -1 ) { ++cnt; - program.textPid = tpid; + program.textPid = cached_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; } @@ -424,6 +389,8 @@ int eDVBServicePMTHandler::getDecodeDemux(ePtr &demux) 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) @@ -441,6 +408,28 @@ int eDVBServicePMTHandler::getPVRChannel(ePtr &pvr_channel) return -1; } +void eDVBServicePMTHandler::SDTScanEvent(int event) +{ + switch (event) + { + case eDVBScan::evtFinish: + { + ePtr 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; @@ -455,17 +444,36 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, ref.getChannelID(chid); res = m_resourceManager->allocateChannel(chid, m_channel); eDebug("allocate Channel: res %d", res); + + ePtr db; + if (!m_resourceManager->getChannelList(db)) + db->getService((eServiceReferenceDVB&)m_reference, m_service); + + 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("try %s", m_reference.toString().c_str()); - + eDebug("alloc PVR"); /* allocate PVR */ res = m_resourceManager->allocatePVRChannel(m_pvr_channel); @@ -473,7 +481,7 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, eDebug("allocatePVRChannel failed!\n"); m_channel = m_pvr_channel; } - + if (m_channel) { m_channel->connectStateChange( @@ -485,6 +493,13 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, 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); @@ -497,15 +512,15 @@ int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, m_pvr_channel->playFile(ref.path.c_str()); } - ePtr 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}; @@ -519,10 +534,12 @@ void eDVBServicePMTHandler::free() ePtr > ptr; m_PMT.getCurrent(ptr); eDVBCAService::unregister_service(m_reference, demuxes, ptr); - eDVBCIInterfaces::getInstance()->removePMTHandler(this); m_ca_servicePtr = 0; } + if (m_channel) + eDVBCIInterfaces::getInstance()->removePMTHandler(this); + if (m_pvr_channel) { m_pvr_channel->stopFile();