X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=blobdiff_plain;f=lib%2Fdvb%2Fpmt.cpp;h=fbd9b8f815285b0f8f8ebc6e3dd16812007433a9;hp=ca56141bc89115c4ba32bdc15f27a1bf4f465503;hb=eb510064c67c19fec47fd04ea03017c17569e3c5;hpb=32c942bb429ba650aeeed2887f6caed7deed0e39 diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index ca56141..fbd9b8f 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -18,15 +18,31 @@ #include #include #include +#include + +#include +#include +#include +#include + eDVBServicePMTHandler::eDVBServicePMTHandler() - :m_ca_servicePtr(0), m_dvb_scan(0), m_decode_demux_num(0xFF) + :m_ca_servicePtr(0), m_dvb_scan(0), m_decode_demux_num(0xFF), m_no_pat_entry_delay(eTimer::create()) { m_use_decode_demux = 0; m_pmt_pid = -1; + m_dsmcc_pid = -1; + m_service_type = livetv; + m_descramble = true; + m_ca_disabled = false; + m_pmt_ready = false; eDVBResourceManager::getInstance(m_resourceManager); CONNECT(m_PMT.tableReady, eDVBServicePMTHandler::PMTready); CONNECT(m_PAT.tableReady, eDVBServicePMTHandler::PATready); + CONNECT(m_no_pat_entry_delay->timeout, eDVBServicePMTHandler::sendEventNoPatEntry); + + CONNECT(m_AIT.tableReady, eDVBServicePMTHandler::AITready); + CONNECT(m_OC.tableReady, eDVBServicePMTHandler::OCready); } eDVBServicePMTHandler::~eDVBServicePMTHandler() @@ -43,8 +59,15 @@ void eDVBServicePMTHandler::channelStateChanged(iDVBChannel *channel) && (state == iDVBChannel::state_ok) && (!m_demux)) { if (m_channel) - if (m_channel->getDemux(m_demux, (!m_use_decode_demux) ? 0 : iDVBChannel::capDecode)) + { + if (m_pvr_demux_tmp) + { + m_demux = m_pvr_demux_tmp; + m_pvr_demux_tmp = NULL; + } + else if (m_channel->getDemux(m_demux, (!m_use_decode_demux) ? 0 : iDVBChannel::capDecode)) eDebug("Allocating %s-decoding a demux for now tuned-in channel failed.", m_use_decode_demux ? "" : "non-"); + } serviceEvent(eventTuned); @@ -84,36 +107,54 @@ void eDVBServicePMTHandler::channelEvent(iDVBChannel *channel, int event) case iDVBChannel::evtSOF: serviceEvent(eventSOF); break; + case iDVBChannel::evtFailed+3: + serviceEvent(eventNoDiskSpace); + break; default: break; } } +void eDVBServicePMTHandler::registerCAService() +{ + int demuxes[2] = {0,0}; + uint8_t demuxid; + m_demux->getCADemuxID(demuxid); + demuxes[0]=demuxid; + if (m_decode_demux_num != 0xFF) + demuxes[1]=m_decode_demux_num; + else + demuxes[1]=demuxes[0]; + eDVBCAService::register_service(m_reference, demuxes, m_ca_servicePtr); +} + void eDVBServicePMTHandler::PMTready(int error) { if (error) serviceEvent(eventNoPMT); else { + m_pmt_ready = true; m_have_cached_program = false; serviceEvent(eventNewProgramInfo); - if (!m_pvr_channel) // don't send campmt to camd.socket for playbacked services + + mDemuxId = m_decode_demux_num; + if (!m_pvr_channel) { eEPGCache::getInstance()->PMTready(this); + } + + if (m_descramble) + { 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]; - eDVBCAService::register_service(m_reference, demuxes, m_ca_servicePtr); + registerCAService(); + } + if (!m_ca_disabled) + { eDVBCIInterfaces::getInstance()->recheckPMTHandlers(); + eDVBCIInterfaces::getInstance()->gotPMT(this); } - eDVBCIInterfaces::getInstance()->gotPMT(this); } if (m_ca_servicePtr) { @@ -123,32 +164,292 @@ void eDVBServicePMTHandler::PMTready(int error) else eDebug("eDVBServicePMTHandler cannot call buildCAPMT"); } + + if (m_service_type == pvrDescramble) + serviceEvent(eventStartPvrDescramble); } } +void eDVBServicePMTHandler::sendEventNoPatEntry() +{ + serviceEvent(eventNoPATEntry); +} + void eDVBServicePMTHandler::PATready(int) { + eDebug("PATready"); ePtr > ptr; if (!m_PAT.getCurrent(ptr)) { + int service_id_single = -1; + int pmtpid_single = -1; int pmtpid = -1; + int cnt=0; std::vector::const_iterator i; for (i = ptr->getSections().begin(); pmtpid == -1 && i != ptr->getSections().end(); ++i) { const ProgramAssociationSection &pat = **i; ProgramAssociationConstIterator program; for (program = pat.getPrograms()->begin(); pmtpid == -1 && program != pat.getPrograms()->end(); ++program) + { + ++cnt; if (eServiceID((*program)->getProgramNumber()) == m_reference.getServiceID()) pmtpid = (*program)->getProgramMapPid(); + if (++cnt == 1 && pmtpid_single == -1 && pmtpid == -1) + { + pmtpid_single = (*program)->getProgramMapPid(); + service_id_single = (*program)->getProgramNumber(); + } + else + pmtpid_single = service_id_single = -1; + } } - if (pmtpid == -1) - serviceEvent(eventNoPATEntry); - else + if (pmtpid_single != -1) // only one PAT entry .. and not valid pmtpid found + { + eDebug("use single pat entry!"); + m_reference.setServiceID(eServiceID(service_id_single)); + pmtpid = pmtpid_single; + } + if (pmtpid == -1) { + eDebug("no PAT entry found.. start delay"); + m_no_pat_entry_delay->start(1000, true); + } + else { + eDebug("use pmtpid %04x for service_id %04x", pmtpid, m_reference.getServiceID().get()); + m_no_pat_entry_delay->stop(); m_PMT.begin(eApp, eDVBPMTSpec(pmtpid, m_reference.getServiceID().get()), m_demux); + } } else serviceEvent(eventNoPAT); } +static void eraseHbbTVApplications(HbbTVApplicationInfoList *applications) +{ + if(applications->size() == 0) + return; + for(HbbTVApplicationInfoListConstIterator info = applications->begin() ; info != applications->end() ; ++info) + delete(*info); + applications->clear(); +} + +void saveData(int orgid, unsigned char* data, int sectionLength) +{ + int fd = 0, rc = 0; + char fileName[255] = {0}; + sprintf(fileName, "/tmp/ait.%d", orgid); + + if (data[6] > 0) { + eDebug("section_number %d > 0", data[6]); + data[6] = 0; + } + if (data[7] > data[6]) { + eDebug("last_section_number %d > section_number %d", data[7], data[6]); + data[7] = data[6]; + } + + if((fd = open(fileName, O_RDWR|O_CREAT|O_TRUNC)) < 0) + { + eDebug("Fail to save a AIT Data."); + return; + } + rc = write(fd, data, sectionLength); + eDebug("Save Data Len : [%d]", rc); + close(fd); +} + +#include +#include +#include +#define PACK_VERSION(major,minor,micro) (((major) << 16) + ((minor) << 8) + (micro)) +#define UNPACK_VERSION(version,major,minor,micro) { \ + major = (version)&0xff; \ + minor = (version>>8)&0xff; \ + micro = (version>>16)&0xff; \ +} +void eDVBServicePMTHandler::AITready(int error) +{ + eDebug("AITready"); + ePtr > ptr; + if (!m_AIT.getCurrent(ptr)) + { + short profilecode = 0; + int orgid = 0, appid = 0, profileVersion = 0; + m_ApplicationName = m_HBBTVUrl = ""; + + eraseHbbTVApplications(&m_HbbTVApplications); + + int sectionLength = 0; + for (std::vector::const_iterator it = ptr->getSections().begin(); it != ptr->getSections().end(); ++it) + { + std::list::const_iterator i = (*it)->getApplicationInformation()->begin(); + memcpy(m_AITData, ptr->getBufferData(), 4096); + sectionLength = (*it)->getSectionLength() + 3; + eDebug("Section Length : %d, Total Section Length : %d", (*it)->getSectionLength(), sectionLength); + for (; i != (*it)->getApplicationInformation()->end(); ++i) + { + std::string hbbtvUrl = "", applicaionName = ""; + std::string boundaryExtension = ""; + + int controlCode = (*i)->getApplicationControlCode(); + const ApplicationIdentifier * applicationIdentifier = (*i)->getApplicationIdentifier(); + profilecode = 0; + orgid = applicationIdentifier->getOrganisationId(); + appid = applicationIdentifier->getApplicationId(); + eDebug("found applicaions ids >> pid : %x, orgid : %d, appid : %d", m_ait_pid, orgid, appid); + if (controlCode == 1) + saveData(orgid, m_AITData, sectionLength); + if (controlCode == 1 || controlCode == 2) /* 1:AUTOSTART, 2:ETC */ + { + for (DescriptorConstIterator desc = (*i)->getDescriptors()->begin(); + desc != (*i)->getDescriptors()->end(); ++desc) + { + switch ((*desc)->getTag()) + { + case APPLICATION_DESCRIPTOR: + { + ApplicationDescriptor* applicationDescriptor = (ApplicationDescriptor*)(*desc); + const ApplicationProfileList* applicationProfiles = applicationDescriptor->getApplicationProfiles(); + ApplicationProfileConstIterator interactionit = applicationProfiles->begin(); + for(; interactionit != applicationProfiles->end(); ++interactionit) + { + profilecode = (*interactionit)->getApplicationProfile(); + profileVersion = PACK_VERSION( + (*interactionit)->getVersionMajor(), + (*interactionit)->getVersionMinor(), + (*interactionit)->getVersionMicro() + ); + } + break; + } + case APPLICATION_NAME_DESCRIPTOR: + { + ApplicationNameDescriptor *nameDescriptor = (ApplicationNameDescriptor*)(*desc); + ApplicationNameConstIterator interactionit = nameDescriptor->getApplicationNames()->begin(); + for(; interactionit != nameDescriptor->getApplicationNames()->end(); ++interactionit) + { + applicaionName = (*interactionit)->getApplicationName(); + if(controlCode == 1) m_ApplicationName = applicaionName; + break; + } + break; + } + case TRANSPORT_PROTOCOL_DESCRIPTOR: + { + TransportProtocolDescriptor *transport = (TransportProtocolDescriptor*)(*desc); + switch (transport->getProtocolId()) + { + case 1: /* object carousel */ + if (m_dsmcc_pid >= 0) + { + m_OC.begin(eApp, eDVBDSMCCDLDataSpec(m_dsmcc_pid), m_demux); + } + break; + case 2: /* ip */ + break; + case 3: /* interaction */ + { + InterActionTransportConstIterator interactionit = transport->getInteractionTransports()->begin(); + for(; interactionit != transport->getInteractionTransports()->end(); ++interactionit) + { + hbbtvUrl = (*interactionit)->getUrlBase()->getUrl(); + break; + } + break; + } + } + break; + } + case GRAPHICS_CONSTRAINTS_DESCRIPTOR: + break; + case SIMPLE_APPLICATION_LOCATION_DESCRIPTOR: + { + SimpleApplicationLocationDescriptor *applicationlocation = (SimpleApplicationLocationDescriptor*)(*desc); + hbbtvUrl += applicationlocation->getInitialPath(); + break; + } + case APPLICATION_USAGE_DESCRIPTOR: + break; + case SIMPLE_APPLICATION_BOUNDARY_DESCRIPTOR: + break; + } + } + } + if(!hbbtvUrl.empty()) + { + const char* uu = hbbtvUrl.c_str(); + if(!strncmp(uu, "http://", 7) || !strncmp(uu, "dvb://", 6) || !strncmp(uu, "https://", 8)) + { + if(controlCode == 1) m_HBBTVUrl = hbbtvUrl; + switch(profileVersion) + { + case 65793: + case 66049: + m_HbbTVApplications.push_back(new HbbTVApplicationInfo(controlCode, orgid, appid, hbbtvUrl, applicaionName, profilecode)); + break; + case 1280: + case 65538: + default: + m_HbbTVApplications.push_back(new HbbTVApplicationInfo((-1)*controlCode, orgid, appid, hbbtvUrl, applicaionName, profilecode)); + break; + } + } + else if (!boundaryExtension.empty()) { + if(boundaryExtension.at(boundaryExtension.length()-1) != '/') { + boundaryExtension += "/"; + } + boundaryExtension += hbbtvUrl; + if(controlCode == 1) m_HBBTVUrl = boundaryExtension; + switch(profileVersion) + { + case 65793: + case 66049: + m_HbbTVApplications.push_back(new HbbTVApplicationInfo(controlCode, orgid, appid, boundaryExtension, applicaionName, profilecode)); + break; + case 1280: + case 65538: + default: + m_HbbTVApplications.push_back(new HbbTVApplicationInfo((-1)*controlCode, orgid, appid, boundaryExtension, applicaionName, profilecode)); + break; + } + } + } + } + } + + if (m_HbbTVApplications.size()) + { + for(HbbTVApplicationInfoListConstIterator infoiter = m_HbbTVApplications.begin() ; infoiter != m_HbbTVApplications.end() ; ++infoiter) + { + char fileName[255] = {0}; + sprintf(fileName, "/tmp/ait.%d", (*infoiter)->m_OrgId); + if (access(fileName, 0) < 0) + saveData((*infoiter)->m_OrgId, m_AITData, sectionLength); + eDebug("Found : control[%d], name[%s], url[%s]", + (*infoiter)->m_ControlCode, (*infoiter)->m_ApplicationName.c_str(), (*infoiter)->m_HbbTVUrl.c_str()); + } + serviceEvent(eventHBBTVInfo); + } + else eDebug("No found anything."); + } + /* for now, do not keep listening for table updates */ + m_AIT.stop(); +} + +void eDVBServicePMTHandler::OCready(int error) +{ + eDebug("OCready"); + ePtr > ptr; + if (!m_OC.getCurrent(ptr)) + { + for (std::vector::const_iterator it = ptr->getSections().begin(); it != ptr->getSections().end(); ++it) + { + unsigned char* sectionData = (unsigned char*)(*it)->getData(); + } + } + /* for now, do not keep listening for table updates */ + m_OC.stop(); +} + PyObject *eDVBServicePMTHandler::getCaIds(bool pair) { ePyObject ret; @@ -187,11 +488,35 @@ PyObject *eDVBServicePMTHandler::getCaIds(bool pair) return ret ? (PyObject*)ret : (PyObject*)PyList_New(0); } +PyObject *eDVBServicePMTHandler::getHbbTVApplications(void) +{ + ePyObject ret= PyList_New(0);; + if(m_HbbTVApplications.size()) + { + for(HbbTVApplicationInfoListConstIterator infoiter = m_HbbTVApplications.begin() ; infoiter != m_HbbTVApplications.end() ; ++infoiter) + { + ePyObject tuple = PyTuple_New(6); + PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong((*infoiter)->m_ControlCode)); + PyTuple_SET_ITEM(tuple, 1, PyString_FromString((*infoiter)->m_ApplicationName.c_str())); + PyTuple_SET_ITEM(tuple, 2, PyString_FromString((*infoiter)->m_HbbTVUrl.c_str())); + PyTuple_SET_ITEM(tuple, 3, PyInt_FromLong((*infoiter)->m_OrgId)); + PyTuple_SET_ITEM(tuple, 4, PyInt_FromLong((*infoiter)->m_AppId)); + PyTuple_SET_ITEM(tuple, 5, PyInt_FromLong((*infoiter)->m_ProfileCode)); + PyList_Append(ret, tuple); + Py_DECREF(tuple); + } + } + return (PyObject*)ret; +} + int eDVBServicePMTHandler::getProgramInfo(program &program) { ePtr > ptr; int cached_apid_ac3 = -1; + int cached_apid_ddp = -1; int cached_apid_mpeg = -1; + int cached_apid_aache = -1; + int cached_apid_aac = -1; int cached_vpid = -1; int cached_tpid = -1; int ret = -1; @@ -201,6 +526,9 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) program.pcrPid = -1; program.pmtPid = -1; program.textPid = -1; + program.aitPid = -1; + program.isCached = false; + program.pmtVersion = -1; int first_ac3 = -1; program.defaultAudioStream = 0; @@ -209,8 +537,11 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) if ( m_service && !m_service->cacheEmpty() ) { cached_vpid = m_service->getCacheEntry(eDVBService::cVPID); - cached_apid_mpeg = m_service->getCacheEntry(eDVBService::cAPID); + cached_apid_mpeg = m_service->getCacheEntry(eDVBService::cMPEGAPID); cached_apid_ac3 = m_service->getCacheEntry(eDVBService::cAC3PID); + cached_apid_ddp = m_service->getCacheEntry(eDVBService::cDDPPID); + cached_apid_aache = m_service->getCacheEntry(eDVBService::cAACHEAPID); + cached_apid_aac = m_service->getCacheEntry(eDVBService::cAACAPID); cached_tpid = m_service->getCacheEntry(eDVBService::cTPID); } @@ -226,12 +557,34 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) eDVBTableSpec table_spec; ptr->getSpec(table_spec); program.pmtPid = table_spec.pid < 0x1fff ? table_spec.pid : -1; + program.pmtVersion = table_spec.version; std::vector::const_iterator i; for (i = ptr->getSections().begin(); i != ptr->getSections().end(); ++i) { const ProgramMapSection &pmt = **i; + int is_hdmv = 0; + program.pcrPid = pmt.getPcrPid(); + for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); + desc != pmt.getDescriptors()->end(); ++desc) + { + if ((*desc)->getTag() == CA_DESCRIPTOR) + { + CaDescriptor *descr = (CaDescriptor*)(*desc); + program::capid_pair pair; + pair.caid = descr->getCaSystemId(); + pair.capid = descr->getCaPid(); + program.caids.push_back(pair); + } + else if ((*desc)->getTag() == REGISTRATION_DESCRIPTOR) + { + RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc); + if (d->getFormatIdentifier() == 0x48444d56) // HDMV + is_hdmv = 1; + } + } + ElementaryStreamInfoConstIterator es; for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es) { @@ -250,6 +603,13 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) video.type = videoStream::vtMPEG4_H264; isvideo = 1; //break; fall through !!! + case 0x24: // H265 HEVC + if (!isvideo) + { + video.type = videoStream::vtH265_HEVC; + isvideo = 1; + } + //break; fall through !!! case 0x10: // MPEG 4 Part 2 if (!isvideo) { @@ -287,25 +647,34 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) audio.type = audioStream::atAACHE; forced_audio = 1; } - case 0x80: // user private ... but blueray LPCM - if (!isvideo && !isaudio) + case 0x80: // user private ... but bluray LPCM + case 0xA0: // bluray secondary LPCM + if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atLPCM; } - case 0x81: // user private ... but blueray AC3 - if (!isvideo && !isaudio) + case 0x81: // user private ... but bluray AC3 + case 0xA1: // bluray secondary AC3 + if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atAC3; } - case 0x82: // Blueray DTS (dvb user private...) - case 0xA2: // Blueray secondary DTS - if (!isvideo && !isaudio) + case 0x82: // bluray DTS (dvb user private...) + case 0xA2: // bluray secondary DTS + if (!isvideo && !isaudio && is_hdmv) { isaudio = 1; audio.type = audioStream::atDTS; } + case 0x86: // bluray DTS-HD (dvb user private...) + case 0xA6: // bluray secondary DTS-HD + if (!isvideo && !isaudio && is_hdmv) + { + isaudio = 1; + audio.type = audioStream::atDTSHD; + } case 0x06: // PES Private case 0xEA: // TS_PSI_ST_SMPTE_VC1 { @@ -403,9 +772,28 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) audio.type = audioStream::atAACHE; // MPEG4-AAC break; case AC3_DESCRIPTOR: - isaudio = 1; + { + Ac3Descriptor *ac = (Ac3Descriptor*)(*desc); + + isaudio = 1; audio.type = audioStream::atAC3; + + if(ac->getAc3TypeFlag()) + { + + uint8_t ac3type = ac->getAc3Type(); + if( ( ac3type & 0x80 ) && ( (ac3type<<5) == 0xA0 || (ac3type<<5) == 0xC0) ) // From EN-300 468 v1.7.1 Table D.1 + audio.type = audioStream::atDDP; + } + break; + } + case ENHANCED_AC3_DESCRIPTOR: + isaudio = 1; + audio.type = audioStream::atDDP; + break; + + case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */ { RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc); @@ -494,12 +882,44 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) } prev_audio = 0; } + case 0x05: /* ITU-T Rec. H.222.0 | ISO/IEC 13818-1 private sections */ + { + for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); + desc != (*es)->getDescriptors()->end(); ++desc) + { + m_ait_pid = -1; + switch ((*desc)->getTag()) + { + case APPLICATION_SIGNALLING_DESCRIPTOR: + m_ait_pid = program.aitPid = (*es)->getPid(); + m_AIT.begin(eApp, eDVBAITSpec(program.aitPid), m_demux); + break; + } + } + break; + } + case 0x0b: /* ISO/IEC 13818-6 DSM-CC U-N Messages */ + { + for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); + desc != (*es)->getDescriptors()->end(); ++desc) + { + switch ((*desc)->getTag()) + { + case CAROUSEL_IDENTIFIER_DESCRIPTOR: + m_dsmcc_pid = (*es)->getPid(); + break; + case STREAM_IDENTIFIER_DESCRIPTOR: + break; + } + } + break; + } default: break; } - if (isteletext && (isaudio || isvideo)) + if (isteletext && (isaudio || isvideo)) { - eDebug("ambiguous streamtype for PID %04x detected.. forced as teletext!", (*es)->getPid()); + eDebug("ambiguous streamtype for PID %04x detected.. forced as teletext!", (*es)->getPid()); continue; // continue with next PID } else if (issubtitle && (isaudio || isvideo)) @@ -524,11 +944,11 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) audio.pid = (*es)->getPid(); /* if we find the cached pids, this will be our default stream */ - if (audio.pid == cached_apid_ac3 || audio.pid == cached_apid_mpeg) + if (audio.pid == cached_apid_ac3 || audio.pid == cached_apid_ddp || audio.pid == cached_apid_mpeg || audio.pid == cached_apid_aache || audio.pid == cached_apid_aac) program.defaultAudioStream = program.audioStreams.size(); /* also, we need to know the first non-mpeg (i.e. "ac3"/dts/...) stream */ - if ((audio.type != audioStream::atMPEG) && ((first_ac3 == -1) || (audio.pid == cached_apid_ac3))) + if ((audio.type != audioStream::atMPEG) && ((first_ac3 == -1) || (audio.pid == cached_apid_ac3) || (audio.pid == cached_apid_ddp))) first_ac3 = program.audioStreams.size(); program.audioStreams.push_back(audio); @@ -537,18 +957,6 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) else continue; } - for (DescriptorConstIterator desc = pmt.getDescriptors()->begin(); - desc != pmt.getDescriptors()->end(); ++desc) - { - if ((*desc)->getTag() == CA_DESCRIPTOR) - { - CaDescriptor *descr = (CaDescriptor*)(*desc); - program::capid_pair pair; - pair.caid = descr->getCaSystemId(); - pair.capid = descr->getCaPid(); - program.caids.push_back(pair); - } - } } ret = 0; @@ -573,6 +981,9 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) int cached_pcrpid = m_service->getCacheEntry(eDVBService::cPCRPID), vpidtype = m_service->getCacheEntry(eDVBService::cVTYPE), cnt=0; + + program.isCached = true; + if ( vpidtype == -1 ) vpidtype = videoStream::vtMPEG2; if ( cached_vpid != -1 ) @@ -592,6 +1003,33 @@ int eDVBServicePMTHandler::getProgramInfo(program &program) program.audioStreams.push_back(s); ++cnt; } + if ( cached_apid_ddp != -1 ) + { + audioStream s; + s.type = audioStream::atDDP; + s.pid = cached_apid_ddp; + s.rdsPid = -1; + program.audioStreams.push_back(s); + ++cnt; + } + if ( cached_apid_aache != -1 ) + { + audioStream s; + s.type = audioStream::atAACHE; + s.pid = cached_apid_aache; + s.rdsPid = -1; + program.audioStreams.push_back(s); + ++cnt; + } + if ( cached_apid_aac != -1 ) + { + audioStream s; + s.type = audioStream::atAAC; + s.pid = cached_apid_aac; + s.rdsPid = -1; + program.audioStreams.push_back(s); + ++cnt; + } if ( cached_apid_mpeg != -1 ) { audioStream s; @@ -700,18 +1138,20 @@ void eDVBServicePMTHandler::SDTScanEvent(int event) } } -int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, eCueSheet *cue, bool simulate, eDVBService *service) +int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, eCueSheet *cue, bool simulate, eDVBService *service, serviceType type, bool descramble) { ePtr s; - return tuneExt(ref, use_decode_demux, s, NULL, cue, simulate, service); + return tuneExt(ref, use_decode_demux, s, NULL, cue, simulate, service, type, descramble); } -int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_demux, ePtr &source, const char *streaminfo_file, eCueSheet *cue, bool simulate, eDVBService *service) +int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_demux, ePtr &source, const char *streaminfo_file, eCueSheet *cue, bool simulate, eDVBService *service, serviceType type, bool descramble) { RESULT res=0; m_reference = ref; - m_use_decode_demux = use_decode_demux; + m_no_pat_entry_delay->stop(); + m_service_type = type; + m_descramble = descramble; /* use given service as backup. This is used for timeshift where we want to clone the live stream using the cache, but in fact have a PVR channel */ m_service = service; @@ -725,23 +1165,25 @@ int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_dem if (!simulate) eDebug("allocate Channel: res %d", res); + if (!res) + serviceEvent(eventChannelAllocated); + ePtr db; if (!m_resourceManager->getChannelList(db)) db->getService((eServiceReferenceDVB&)m_reference, m_service); - if (!res && !simulate) + if (!res && !simulate && m_descramble && !m_ca_disabled) eDVBCIInterfaces::getInstance()->addPMTHandler(this); } else if (!simulate) // no simulation of playback services { if (!ref.getServiceID().get() /* incorrect sid in meta file or recordings.epl*/ ) { - eWarning("no .meta file found, trying to find PMT pid"); eDVBTSTools tstools; + bool b = source || !tstools.openFile(ref.path.c_str(), 1); + eWarning("no .meta file found, trying to find PMT pid"); if (source) - tstools.setSource(source, streaminfo_file ? streaminfo_file : ref.path.c_str()); - else if (tstools.openFile(ref.path.c_str())) - eWarning("failed to open file"); - else + tstools.setSource(source, NULL); + if (b) { int service_id, pmt_pid; if (!tstools.findPMT(pmt_pid, service_id)) @@ -751,12 +1193,22 @@ int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_dem m_pmt_pid = pmt_pid; } } + else + eWarning("no valid source to find PMT pid!"); } eDebug("alloc PVR"); /* allocate PVR */ - res = m_resourceManager->allocatePVRChannel(m_pvr_channel); + eDVBChannelID chid; + if (m_service_type == streamclient) ref.getChannelID(chid); + res = m_resourceManager->allocatePVRChannel(chid, m_pvr_channel); if (res) + { eDebug("allocatePVRChannel failed!\n"); + } + else if (descramble) + { + eDVBCIInterfaces::getInstance()->addPMTHandler(this); + } m_channel = m_pvr_channel; } @@ -792,7 +1244,10 @@ int eDVBServicePMTHandler::tuneExt(eServiceReferenceDVB &ref, int use_decode_dem if (m_pvr_channel) { m_pvr_channel->setCueSheet(cue); - if (source) + + if (m_pvr_channel->getDemux(m_pvr_demux_tmp, (!m_use_decode_demux) ? 0 : iDVBChannel::capDecode)) + eDebug("[eDVBServicePMTHandler] Allocating %s-decoding a demux for PVR channel failed.", m_use_decode_demux ? "" : "non-"); + else if (source) m_pvr_channel->playSource(source, streaminfo_file); else m_pvr_channel->playFile(ref.path.c_str()); @@ -831,6 +1286,9 @@ void eDVBServicePMTHandler::free() m_pvr_channel->setCueSheet(0); } + m_OC.stop(); + m_AIT.stop(); + m_PMT.stop(); m_PAT.stop(); m_service = 0; @@ -839,6 +1297,32 @@ void eDVBServicePMTHandler::free() m_demux = 0; } +void eDVBServicePMTHandler::addCaHandler() +{ + m_ca_disabled = false; + if (m_channel) + { + eDVBCIInterfaces::getInstance()->addPMTHandler(this); + if (m_pmt_ready) + { + eDVBCIInterfaces::getInstance()->recheckPMTHandlers(); + eDVBCIInterfaces::getInstance()->gotPMT(this); + } + } +} + +void eDVBServicePMTHandler::removeCaHandler() +{ + m_ca_disabled = true; + if (m_channel) + eDVBCIInterfaces::getInstance()->removePMTHandler(this); +} + +bool eDVBServicePMTHandler::isCiConnected() +{ + eDVBCIInterfaces::getInstance()->isCiConnected(this); +} + CAServiceMap eDVBCAService::exist; ChannelMap eDVBCAService::exist_channels; ePtr eDVBCAService::m_chanAddedConn;