From: ghost Date: Wed, 16 Feb 2011 13:31:31 +0000 (+0100) Subject: Merge branch 'bug_124_m2ts_support' X-Git-Url: http://code.vuplus.com/gitweb/?p=vuplus_dvbapp;a=commitdiff_plain;h=dec9693d8437a31dab8e4010b33b57e1476a315c;hp=-c Merge branch 'bug_124_m2ts_support' Conflicts: lib/dvb/pmt.cpp lib/service/Makefile.am --- dec9693d8437a31dab8e4010b33b57e1476a315c diff --combined lib/dvb/esection.h index 833cc93,b4782f8..3e097cc --- a/lib/dvb/esection.h +++ b/lib/dvb/esection.h @@@ -63,7 -63,7 +63,7 @@@ protected else TABLE_eDebugNoNewLine("-"); - TABLE_eDebug(" %d/%d TID %02x", avail.size(), max, data[0]); + TABLE_eDebug(" %zd/%d TID %02x", avail.size(), max, data[0]); if (avail.size() == max) { @@@ -100,6 -100,10 +100,10 @@@ class eAUTable: public eAUGTabl int first; ePtr m_demux; eMainloop *ml; + + /* needed to detect broken table version handling (seen on some m2ts files) */ + struct timespec m_prev_table_update; + int m_table_cnt; public: eAUTable() @@@ -119,6 -123,7 +123,7 @@@ int begin(eMainloop *m, const eDVBTableSpec &spec, ePtr demux) { + m_table_cnt = 0; ml = m; m_demux = demux; first= 1; @@@ -197,6 -202,24 +202,24 @@@ if (current && (!current->getSpec(spec))) { + /* detect broken table version handling (seen on some m2ts files) */ + if (m_table_cnt) + { + if (abs(timeout_usec(m_prev_table_update)) > 500000) + m_table_cnt = -1; + else if (m_table_cnt > 1) // two pmt update within one second + { + eDebug("Seen two consecutive table version changes within 500ms. " + "This seems broken, so auto update for pid %04x, table %02x is now disabled!!", + spec.pid, spec.tid); + m_table_cnt = 0; + return; + } + } + + ++m_table_cnt; + clock_gettime(CLOCK_MONOTONIC, &m_prev_table_update); + next = new Table(); CONNECT(next->tableReady, eAUTable::slotTableReady); spec.flags &= ~(eDVBTableSpec::tfAnyVersion|eDVBTableSpec::tfThisVersion|eDVBTableSpec::tfHaveTimeout); diff --combined lib/dvb/pmt.cpp index ca56141,dc2e9a8..4ad4e76 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@@ -20,13 -20,14 +20,14 @@@ #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; 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); } eDVBServicePMTHandler::~eDVBServicePMTHandler() @@@ -126,30 -127,60 +127,60 @@@ void eDVBServicePMTHandler::PMTready(in } } + 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); } -PyObject *eDVBServicePMTHandler::getCaIds() +PyObject *eDVBServicePMTHandler::getCaIds(bool pair) { ePyObject ret; @@@ -157,37 -188,20 +188,37 @@@ if ( !getProgramInfo(prog) ) { - int cnt=prog.caids.size(); - if (cnt) + if (pair) { + int cnt=prog.caids.size(); + if (cnt) + { + ret=PyList_New(cnt); + std::list::iterator it(prog.caids.begin()); + while(cnt--) + { + ePyObject tuple = PyTuple_New(2); + PyTuple_SET_ITEM(tuple, 0, PyInt_FromLong(it->caid)); + PyTuple_SET_ITEM(tuple, 1, PyInt_FromLong((it++)->capid)); + PyList_SET_ITEM(ret, cnt, tuple); + } + } + } + else + { + std::set set(prog.caids.begin(), prog.caids.end()); + std::set::iterator it(set.begin()); + int cnt=set.size(); ret=PyList_New(cnt); - std::set::iterator it(prog.caids.begin()); while(cnt--) - PyList_SET_ITEM(ret, cnt, PyInt_FromLong(*it++)); + PyList_SET_ITEM(ret, cnt, PyInt_FromLong((it++)->caid)); } } return ret ? (PyObject*)ret : (PyObject*)PyList_New(0); } -int eDVBServicePMTHandler::getProgramInfo(struct program &program) +int eDVBServicePMTHandler::getProgramInfo(program &program) { ePtr > ptr; int cached_apid_ac3 = -1; @@@ -230,8 -244,26 +261,29 @@@ 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.caids.insert(descr->getCaSystemId()); ++ 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) { @@@ -287,25 -319,34 +339,34 @@@ 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 { @@@ -477,10 -518,7 +538,10 @@@ case CA_DESCRIPTOR: { CaDescriptor *descr = (CaDescriptor*)(*desc); - program.caids.insert(descr->getCaSystemId()); + program::capid_pair pair; + pair.caid = descr->getCaSystemId(); + pair.capid = descr->getCaPid(); + program.caids.push_back(pair); break; } default: @@@ -497,9 -535,9 +558,9 @@@ 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)) @@@ -537,18 -575,6 +598,6 @@@ 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; @@@ -612,12 -638,8 +661,12 @@@ 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); + for (CAID_LIST::iterator it(caids.begin()); it != caids.end(); ++it) { + program::capid_pair pair; + pair.caid = *it; + pair.capid = -1; // not known yet + program.caids.push_back(pair); + } if ( cnt ) ret = 0; } @@@ -710,8 -732,8 +759,8 @@@ int eDVBServicePMTHandler::tuneExt(eSer { RESULT res=0; m_reference = ref; - m_use_decode_demux = use_decode_demux; + m_no_pat_entry_delay->stop(); /* 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; @@@ -735,13 -757,12 +784,12 @@@ { 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,6 -772,8 +799,8 @@@ m_pmt_pid = pmt_pid; } } + else + eWarning("no valid source to find PMT pid!"); } eDebug("alloc PVR"); /* allocate PVR */ diff --combined lib/dvb/pmt.h index 86b634f,e9816b4..1888e05 --- a/lib/dvb/pmt.h +++ b/lib/dvb/pmt.h @@@ -102,6 -102,7 +102,7 @@@ class eDVBServicePMTHandler: public Obj int m_use_decode_demux; uint8_t m_decode_demux_num; + ePtr m_no_pat_entry_delay; public: eDVBServicePMTHandler(); ~eDVBServicePMTHandler(); @@@ -144,7 -145,7 +145,7 @@@ public { int pid, rdsPid; // hack for some radio services which transmit radiotext on different pid (i.e. harmony fm, HIT RADIO FFH, ...) - enum { atMPEG, atAC3, atDTS, atAAC, atAACHE, atLPCM }; + enum { atMPEG, atAC3, atDTS, atAAC, atAACHE, atLPCM, atDTSHD }; int type; // mpeg2, ac3, dts, ... int component_tag; @@@ -181,17 -182,11 +182,17 @@@ struct program { + struct capid_pair + { + uint16_t caid; + int capid; + bool operator< (const struct capid_pair &t) const { return t.caid < caid; } + }; std::vector videoStreams; std::vector audioStreams; int defaultAudioStream; std::vector subtitleStreams; - std::set caids; + std::list caids; int pcrPid; int pmtPid; int textPid; @@@ -199,10 -194,10 +200,10 @@@ PyObject *createPythonObject(); }; - int getProgramInfo(struct program &program); + int getProgramInfo(program &program); int getDataDemux(ePtr &demux); int getDecodeDemux(ePtr &demux); - PyObject *getCaIds(); + PyObject *getCaIds(bool pair=false); // caid / ecmpid pair int getPVRChannel(ePtr &pvr_channel); int getServiceReference(eServiceReferenceDVB &service) { service = m_reference; return 0; } @@@ -210,6 -205,7 +211,7 @@@ int getPMT(ePtr > &ptr) { return m_PMT.getCurrent(ptr); } int getChannel(eUsePtr &channel); void resetCachedProgram() { m_have_cached_program = false; } + void sendEventNoPatEntry(); /* deprecated interface */ int tune(eServiceReferenceDVB &ref, int use_decode_demux, eCueSheet *sg=0, bool simulate=false, eDVBService *service = 0); diff --combined lib/dvb/tstools.cpp index 9b47f9b,e93cfc0..6cd855c --- a/lib/dvb/tstools.cpp +++ b/lib/dvb/tstools.cpp @@@ -40,7 -40,7 +40,7 @@@ int eDVBTSTools::openFile(const char *f if (f->open(filename, 1) < 0) return -1; - setSource(src, filename); + setSource(src, nostreaminfo ? NULL : filename); return 0; } @@@ -212,6 -212,8 +212,8 @@@ int eDVBTSTools::getPTS(off_t &offset, break; case 0x71: // AC3 / DTS break; + case 0x72: // DTS - HD + break; default: eDebug("skip unknwn stream_id_extension %02x\n", payload[9+offs]); continue; @@@ -700,26 -702,9 +702,26 @@@ int eDVBTSTools::findFrame(off_t &_offs else if (direction == +1) direction = 0; } - /* let's find the next frame after the given offset */ off_t start = offset; +#if 0 + /* backtrack to find the previous sequence start, in case of MPEG2 */ + if ((data & 0xFF) == 0x00) { + do { + --start; + if (m_streaminfo.getStructureEntry(start, data, 0)) + { + eDebug("get previous failed"); + return -1; + } + } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00) && ((data & 0xFF) != 0xB3)); /* sequence start or previous frame */ + if ((data & 0xFF) != 0xB3) + start = offset; /* Failed to find corresponding sequence start, so never mind */ + } + +#endif + + /* let's find the next frame after the given offset */ do { if (m_streaminfo.getStructureEntry(offset, data, 1)) { @@@ -734,11 -719,9 +736,11 @@@ // eDebug("%08llx@%llx (next)", data, offset); } while (((data & 0xFF) != 9) && ((data & 0xFF) != 0x00)); /* next frame */ +#if 0 /* align to TS pkt start */ -// start = start - (start % 188); -// offset = offset - (offset % 188); + start = start - (start % 188); + offset = offset - (offset % 188); +#endif len = offset - start; _offset = start; diff --combined lib/python/Plugins/Extensions/MediaPlayer/plugin.py index b44a247,d61dbc7..6ff1c5a mode 100644,100755..100644 --- a/lib/python/Plugins/Extensions/MediaPlayer/plugin.py +++ b/lib/python/Plugins/Extensions/MediaPlayer/plugin.py @@@ -110,7 -110,7 +110,7 @@@ class MediaPlayer(Screen, InfoBarBase, # 'None' is magic to start at the list of mountpoints defaultDir = config.mediaplayer.defaultDir.getValue() - self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|m4v|mkv|mp4|m4a|dat|flac|mov)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") + self.filelist = FileList(defaultDir, matchingPattern = "(?i)^.*\.(mp2|mp3|ogg|ts|wav|wave|m3u|pls|e2pls|mpg|vob|avi|divx|m4v|mkv|mp4|m4a|dat|flac|mov|m2ts)", useServiceRef = True, additionalExtensions = "4098:m3u 4098:e2pls 4098:pls") self["filelist"] = self.filelist self.playlist = MyPlayList() @@@ -1041,6 -1041,6 +1041,6 @@@ def filescan(**kwargs) from Plugins.Plugin import PluginDescriptor def Plugins(**kwargs): return [ - PluginDescriptor(name = "MediaPlayer", description = "Play back media files", where = PluginDescriptor.WHERE_MENU, fnc = menu), - PluginDescriptor(name = "MediaPlayer", where = PluginDescriptor.WHERE_FILESCAN, fnc = filescan) + PluginDescriptor(name = "MediaPlayer", description = "Play back media files", where = PluginDescriptor.WHERE_MENU, needsRestart = False, fnc = menu), + PluginDescriptor(name = "MediaPlayer", where = PluginDescriptor.WHERE_FILESCAN, needsRestart = False, fnc = filescan) ] diff --combined lib/service/Makefile.am index edafd1a,795900a..9f956b6 --- a/lib/service/Makefile.am +++ b/lib/service/Makefile.am @@@ -1,37 -1,8 +1,39 @@@ -INCLUDES = \ - -I$(top_srcdir)/include +AM_CPPFLAGS = \ + -I$(top_srcdir) \ + -I$(top_srcdir)/include \ + -include Python.h \ + -include $(top_builddir)/enigma2_config.h + +AM_CXXFLAGS = \ + $(LIBXINE_CFLAGS) noinst_LIBRARIES = libenigma_service.a libenigma_service_a_SOURCES = \ - listboxservice.cpp service.cpp servicemp3.cpp servicedvb.cpp servicefs.cpp \ - servicem2ts.cpp event.cpp servicedvbrecord.cpp + event.cpp \ + listboxservice.cpp \ + service.cpp \ + servicedvb.cpp \ + servicedvbrecord.cpp \ + servicefs.cpp \ - servicemp3.cpp ++ servicemp3.cpp \ ++ servicem2ts.cpp + +serviceincludedir = $(pkgincludedir)/lib/service +serviceinclude_HEADERS = \ + event.h \ + iservice.h \ + listboxservice.h \ + service.h \ + servicedvb.h \ + servicedvbrecord.h \ + servicefs.h \ - servicemp3.h ++ servicemp3.h \ ++ servicem2ts.h + +if HAVE_LIBXINE +libenigma_service_a_SOURCES += \ + servicexine.cpp +serviceinclude_HEADERS += \ + servicexine.h +endif diff --combined lib/service/servicedvb.cpp index 914d6bf,0a2146d..8650989 --- a/lib/service/servicedvb.cpp +++ b/lib/service/servicedvb.cpp @@@ -309,9 -309,7 +309,9 @@@ eStaticServiceDVBPVRInformation::eStati RESULT eStaticServiceDVBPVRInformation::getName(const eServiceReference &ref, std::string &name) { ASSERT(ref == m_ref); - if (m_parser.m_name.size()) + if (!ref.name.empty()) + name = ref.name; + else if (!m_parser.m_name.empty()) name = m_parser.m_name; else { @@@ -905,7 -903,7 +905,7 @@@ RESULT eServiceFactoryDVB::lookupServic /* we are sure to have a ..DVB reference as the info() call was forwarded here according to it's ID. */ if ((err = db->getService((eServiceReferenceDVB&)ref, service)) != 0) { - eDebug("getService failed!"); +// eDebug("getService failed!"); return err; } } @@@ -1591,7 -1589,7 +1591,7 @@@ int eDVBServicePlay::getInfo(int w { eDVBServicePMTHandler::program program; - if (w == sCAIDs) + if (w == sCAIDs || w == sCAIDPIDs) return resIsPyObject; eDVBServicePMTHandler &h = m_timeshift_active ? m_service_handler_timeshift : m_service_handler; @@@ -1732,8 -1730,6 +1732,8 @@@ PyObject *eDVBServicePlay::getInfoObjec { case sCAIDs: return m_service_handler.getCaIds(); + case sCAIDPIDs: + return m_service_handler.getCaIds(true); case sTransponderData: return eStaticServiceDVBInformation().getInfoObject(m_reference, w); default: @@@ -1801,6 -1797,8 +1801,8 @@@ RESULT eDVBServicePlay::getTrackInfo(st info.m_description = "AAC-HE"; else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTS) info.m_description = "DTS"; + else if (program.audioStreams[i].type == eDVBServicePMTHandler::audioStream::atDTSHD) + info.m_description = "DTS-HD"; else info.m_description = "???"; @@@ -2403,7 -2401,7 +2405,7 @@@ void eDVBServicePlay::updateDecoder(boo eDebug("getting program info failed."); else { - eDebugNoNewLine("have %d video stream(s)", program.videoStreams.size()); + eDebugNoNewLine("have %zd video stream(s)", program.videoStreams.size()); if (!program.videoStreams.empty()) { eDebugNoNewLine(" ("); @@@ -2422,7 -2420,7 +2424,7 @@@ } eDebugNoNewLine(")"); } - eDebugNoNewLine(", and %d audio stream(s)", program.audioStreams.size()); + eDebugNoNewLine(", and %zd audio stream(s)", program.audioStreams.size()); if (!program.audioStreams.empty()) { eDebugNoNewLine(" ("); @@@ -2599,7 -2597,7 +2601,7 @@@ void eDVBServicePlay::loadCuesheet( m_cue_entries.insert(cueEntry(where, what)); } fclose(f); - eDebug("%d entries", m_cue_entries.size()); + eDebug("%zd entries", m_cue_entries.size()); } else eDebug("cutfile not found!");