X-Git-Url: https://git.cweiske.de/enigma2.git/blobdiff_plain/008552809692c70b231d58032408790e578a6306..3931e5f4380d167e1d651f0d056618294cf8234f:/lib/dvb/pmt.cpp?ds=sidebyside diff --git a/lib/dvb/pmt.cpp b/lib/dvb/pmt.cpp index 842d6979..e1aa096d 100644 --- a/lib/dvb/pmt.cpp +++ b/lib/dvb/pmt.cpp @@ -16,6 +16,8 @@ #include #include #include +#include +#include eDVBServicePMTHandler::eDVBServicePMTHandler() :m_ca_servicePtr(0), m_dvb_scan(0), m_decode_demux_num(0xFF) @@ -50,10 +52,13 @@ void eDVBServicePMTHandler::channelStateChanged(iDVBChannel *channel) { eDebug("ok ... now we start!!"); - 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->usePMT()) + { + 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); @@ -205,44 +210,101 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) { const ProgramMapSection &pmt = **i; program.pcrPid = pmt.getPcrPid(); - + ElementaryStreamInfoConstIterator es; for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es) { - int isaudio = 0, isvideo = 0; + int isaudio = 0, isvideo = 0, issubtitle = 0, forced_video = 0, forced_audio = 0; videoStream video; audioStream audio; audio.component_tag=video.component_tag=-1; video.type = videoStream::vtMPEG2; + audio.type = audioStream::atMPEG; switch ((*es)->getType()) { case 0x1b: // AVC Video Stream (MPEG4 H264) video.type = videoStream::vtMPEG4_H264; + isvideo = 1; + //break; fall through !!! + case 0x10: // MPEG 4 Part 2 + if (!isvideo) + { + video.type = videoStream::vtMPEG4_Part2; + isvideo = 1; + } + //break; fall through !!! case 0x01: // MPEG 1 video + if (!isvideo) + video.type = videoStream::vtMPEG1; + //break; fall through !!! case 0x02: // MPEG 2 video isvideo = 1; + forced_video = 1; //break; fall through !!! case 0x03: // MPEG 1 audio case 0x04: // MPEG 2 audio: - if (!isvideo) + if (!isvideo) { + isaudio = 1; + forced_audio = 1; + } + //break; fall through !!! + case 0x0f: // MPEG 2 AAC + if (!isvideo && !isaudio) { isaudio = 1; - audio.type = audioStream::atMPEG; + audio.type = audioStream::atAAC; + forced_audio = 1; } //break; fall through !!! + case 0x11: // MPEG 4 AAC + if (!isvideo && !isaudio) + { + isaudio = 1; + audio.type = audioStream::atAACHE; + forced_audio = 1; + } + case 0x80: // user private ... but blueray LPCM + if (!isvideo && !isaudio) + { + isaudio = 1; + audio.type = audioStream::atLPCM; + } + case 0x81: // user private ... but blueray AC3 + if (!isvideo && !isaudio) + { + isaudio = 1; + audio.type = audioStream::atAC3; + } + case 0x82: // Blueray DTS (dvb user private...) + case 0xA2: // Blueray secondary DTS + if (!isvideo && !isaudio) + { + isaudio = 1; + audio.type = audioStream::atDTS; + } case 0x06: // PES Private - case 0x81: // user private + case 0xEA: // TS_PSI_ST_SMPTE_VC1 for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin(); - desc != (*es)->getDescriptors()->end(); ++desc) + desc != (*es)->getDescriptors()->end(); ++desc) { uint8_t tag = (*desc)->getTag(); - if (!isaudio && !isvideo) + /* check descriptors to get the exakt stream type. */ + if (!forced_video && !forced_audio) { - /* PES private can contain AC-3, DTS or lots of other stuff. - check descriptors to get the exakt type. */ switch (tag) { + case AUDIO_STREAM_DESCRIPTOR: + isaudio = 1; + break; + case VIDEO_STREAM_DESCRIPTOR: + { + isvideo = 1; + VideoStreamDescriptor *d = (VideoStreamDescriptor*)(*desc); + if (d->getMpeg1OnlyFlag()) + video.type = videoStream::vtMPEG1; + break; + } case SUBTITLING_DESCRIPTOR: { SubtitlingDescriptor *d = (SubtitlingDescriptor*)(*desc); @@ -268,6 +330,7 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) s.language_code = (*it)->getIso639LanguageCode(); // eDebug("add dvb subtitle %s PID %04x, type %d, composition page %d, ancillary_page %d", // s.language_code.c_str(), s.pid, s.subtitling_type, s.composition_page_id, s.ancillary_page_id); + issubtitle=1; program.subtitleStreams.push_back(s); } break; @@ -292,6 +355,8 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) // eDebug("add teletext subtitle %s PID %04x, page number %d, magazine number %d", // s.language_code.c_str(), s.pid, s.teletext_page_number, s.teletext_magazine_number); program.subtitleStreams.push_back(s); + issubtitle=1; + default: break; } } @@ -301,9 +366,14 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) isaudio = 1; audio.type = audioStream::atDTS; break; + case 0x2B: // TS_PSI_DT_MPEG2_AAC + isaudio = 1; + audio.type = audioStream::atAAC; // MPEG2-AAC + break; + case 0x1C: // TS_PSI_DT_MPEG4_Audio case AAC_DESCRIPTOR: isaudio = 1; - audio.type = audioStream::atAAC; + audio.type = audioStream::atAACHE; // MPEG4-AAC break; case AC3_DESCRIPTOR: isaudio = 1; @@ -311,56 +381,103 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) break; case REGISTRATION_DESCRIPTOR: /* some services don't have a separate AC3 descriptor */ { - /* libdvbsi++ doesn't yet support this descriptor type, so work around. */ - if ((*desc)->getLength() != 4) - break; - unsigned char descr[6]; - (*desc)->writeToBuffer(descr); - int format_identifier = (descr[2] << 24) | (descr[3] << 16) | (descr[4] << 8) | (descr[5]); - switch (format_identifier) + RegistrationDescriptor *d = (RegistrationDescriptor*)(*desc); + switch (d->getFormatIdentifier()) { - case 0x41432d33: + case 0x44545331 ... 0x44545333: // DTS1/DTS2/DTS3 + isaudio = 1; + audio.type = audioStream::atDTS; + break; + case 0x41432d33: // == 'AC-3' isaudio = 1; audio.type = audioStream::atAC3; break; + case 0x42535344: // == 'BSSD' (LPCM) + isaudio = 1; + audio.type = audioStream::atLPCM; + break; + case 0x56432d31: // == 'VC-1' + { + const AdditionalIdentificationInfoVector *vec = d->getAdditionalIdentificationInfo(); + if (vec->size() > 1 && (*vec)[1] == 0x01) // subdescriptor tag + { + if ((*vec)[2] >= 0x90) // profile_level + video.type = videoStream::vtVC1; // advanced profile + else + video.type = videoStream::vtVC1_SM; // simple main + isvideo = 1; + } + } default: break; } break; } + case 0x28: // TS_PSI_DT_AVC + isvideo = 1; + video.type = videoStream::vtMPEG4_H264; + break; + case 0x1B: // TS_PSI_DT_MPEG4_Video + isvideo = 1; + video.type = videoStream::vtMPEG4_Part2; + break; default: break; } } switch (tag) { - case ISO_639_LANGUAGE_DESCRIPTOR: - if (!isvideo) + case ISO_639_LANGUAGE_DESCRIPTOR: + if (!isvideo) + { + int cnt=0; + const Iso639LanguageList *languages = ((Iso639LanguageDescriptor*)*desc)->getIso639Languages(); + /* use last language code */ + for (Iso639LanguageConstIterator i(languages->begin()); i != languages->end(); ++i, ++cnt) { - const Iso639LanguageList *languages = ((Iso639LanguageDescriptor*)*desc)->getIso639Languages(); - /* use last language code */ - for (Iso639LanguageConstIterator i(languages->begin()); i != languages->end(); ++i) + if (cnt == 0) audio.language_code = (*i)->getIso639LanguageCode(); + else + audio.language_code += "/" + (*i)->getIso639LanguageCode(); } - break; - case STREAM_IDENTIFIER_DESCRIPTOR: - audio.component_tag = - video.component_tag = - ((StreamIdentifierDescriptor*)*desc)->getComponentTag(); - break; - case CA_DESCRIPTOR: - { - CaDescriptor *descr = (CaDescriptor*)(*desc); - program.caids.insert(descr->getCaSystemId()); - break; } - default: - break; + break; + case STREAM_IDENTIFIER_DESCRIPTOR: + audio.component_tag = + video.component_tag = + ((StreamIdentifierDescriptor*)*desc)->getComponentTag(); + break; + case CA_DESCRIPTOR: + { + CaDescriptor *descr = (CaDescriptor*)(*desc); + program.caids.insert(descr->getCaSystemId()); + break; + } + default: + break; } } + default: break; } - if (isaudio) + if (issubtitle && (isaudio || isvideo)) + eDebug("ambiguous streamtype for PID %04x detected.. forced as subtitle!", (*es)->getPid()); + else if (isaudio && isvideo) + eDebug("ambiguous streamtype for PID %04x detected.. forced as video!", (*es)->getPid()); + if (issubtitle) + continue; + else if (isvideo) + { + video.pid = (*es)->getPid(); + if ( !program.videoStreams.empty() && video.pid == cached_vpid ) + { + program.videoStreams.push_back(program.videoStreams[0]); + program.videoStreams[0] = video; + } + else + program.videoStreams.push_back(video); + } + else if (isaudio) { audio.pid = (*es)->getPid(); @@ -374,17 +491,6 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) program.audioStreams.push_back(audio); } - else if (isvideo) - { - video.pid = (*es)->getPid(); - if ( !program.videoStreams.empty() && video.pid == cached_vpid ) - { - program.videoStreams.push_back(program.videoStreams[0]); - program.videoStreams[0] = video; - } - else - program.videoStreams.push_back(video); - } else continue; } @@ -400,7 +506,6 @@ int eDVBServicePMTHandler::getProgramInfo(struct program &program) } ret = 0; - /* finally some fixup: if our default audio stream is an MPEG audio stream, and we have 'defaultac3' set, use the first available ac3 stream instead. (note: if an ac3 audio stream was selected before, this will be also stored @@ -543,12 +648,15 @@ void eDVBServicePMTHandler::SDTScanEvent(int event) } } -int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, eCueSheet *cue, bool simulate) +int eDVBServicePMTHandler::tune(eServiceReferenceDVB &ref, int use_decode_demux, eCueSheet *cue, bool simulate, eDVBService *service) { RESULT res=0; m_reference = ref; m_use_decode_demux = use_decode_demux; + + /* 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; /* is this a normal (non PVR) channel? */ if (ref.path.empty()) @@ -1143,8 +1251,8 @@ void eDVBCAService::sendCAPMT() static PyObject *createTuple(int pid, const char *type) { PyObject *r = PyTuple_New(2); - PyTuple_SetItem(r, 0, PyInt_FromLong(pid)); - PyTuple_SetItem(r, 1, PyString_FromString(type)); + PyTuple_SET_ITEM(r, 0, PyInt_FromLong(pid)); + PyTuple_SET_ITEM(r, 1, PyString_FromString(type)); return r; } @@ -1154,17 +1262,18 @@ static inline void PyList_AppendSteal(PyObject *list, PyObject *item) Py_DECREF(item); } +extern void PutToDict(ePyObject &dict, const char*key, ePyObject item); // defined in dvb/frontend.cpp + PyObject *eDVBServicePMTHandler::program::createPythonObject() { - PyObject *r = PyDict_New(); + ePyObject r = PyDict_New(); + ePyObject l = PyList_New(0); - PyObject *l = PyList_New(0); - PyList_AppendSteal(l, createTuple(0, "pat")); if (pmtPid != -1) PyList_AppendSteal(l, createTuple(pmtPid, "pmt")); - + for (std::vector::const_iterator i(videoStreams.begin()); i != videoStreams.end(); ++i) @@ -1184,7 +1293,8 @@ PyObject *eDVBServicePMTHandler::program::createPythonObject() if (textPid != -1) PyList_AppendSteal(l, createTuple(textPid, "text")); - - PyDict_SetItemString(r, "pids", l); + + PutToDict(r, "pids", l); + return r; }