Merge commit 'origin/bug_449_fix_wlan_usbstick_recognition'
[enigma2.git] / lib / dvb / scan.cpp
index 379ab8e9a01b56924486e70cc370d4c9b1f2c57a..fd29617a3054aa249983b64b12a92ac9428831f7 100644 (file)
@@ -5,6 +5,7 @@
 #include <dvbsi++/terrestrial_delivery_system_descriptor.h>
 #include <dvbsi++/cable_delivery_system_descriptor.h>
 #include <dvbsi++/ca_identifier_descriptor.h>
+#include <dvbsi++/registration_descriptor.h>
 #include <lib/dvb/specs.h>
 #include <lib/dvb/esection.h>
 #include <lib/dvb/scan.h>
@@ -46,6 +47,8 @@ int eDVBScan::isValidONIDTSID(int orbital_position, eOriginalNetworkID onid, eTr
                return orbital_position == 192;
        case 0x00B1:
                return tsid != 0x00B0;
+       case 0x00eb:
+               return tsid != 0x4321;
        case 0x0002:
                return abs(orbital_position-282) < 6;
        default:
@@ -137,7 +140,7 @@ RESULT eDVBScan::nextChannel()
 RESULT eDVBScan::startFilter()
 {
        bool startSDT=true;
-       assert(m_demux);
+       ASSERT(m_demux);
 
                        /* only start required filters filter */
 
@@ -163,7 +166,7 @@ RESULT eDVBScan::startFilter()
                {
                        std::vector<ProgramAssociationSection*>::const_iterator i =
                                m_PAT->getSections().begin();
-                       assert(i != m_PAT->getSections().end());
+                       ASSERT(i != m_PAT->getSections().end());
                        tsid = (*i)->getTableIdExtension(); // in PAT this is the transport stream id
                        m_pat_tsid = eTransportStreamID(tsid);
                        for (; i != m_PAT->getSections().end(); ++i)
@@ -279,6 +282,7 @@ void eDVBScan::PMTready(int err)
                bool have_video = false;
                unsigned short pcrpid = 0xFFFF;
                std::vector<ProgramMapSection*>::const_iterator i;
+
                for (i = m_PMT->getSections().begin(); i != m_PMT->getSections().end(); ++i)
                {
                        const ProgramMapSection &pmt = **i;
@@ -289,64 +293,82 @@ void eDVBScan::PMTready(int err)
                        ElementaryStreamInfoConstIterator es;
                        for (es = pmt.getEsInfo()->begin(); es != pmt.getEsInfo()->end(); ++es)
                        {
-                               int isaudio = 0, isvideo = 0, is_scrambled = 0;
+                               int isaudio = 0, isvideo = 0, is_scrambled = 0, forced_audio = 0, forced_video = 0;
                                switch ((*es)->getType())
                                {
                                case 0x1b: // AVC Video Stream (MPEG4 H264)
+                               case 0x10: // MPEG 4 Part 2
                                case 0x01: // MPEG 1 video
                                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)
+                               case 0x04: // MPEG 2 audio
+                               case 0x0f: // MPEG 2 AAC
+                               case 0x11: // MPEG 4 AAC
+                                       if (!isvideo) 
+                                       {
+                                               forced_audio = 1;
                                                isaudio = 1;
-                                       //break; fall through !!!
+                                       }
                                case 0x06: // PES Private
                                case 0x81: // user private
-                                               /* PES private can contain AC-3, DTS or lots of other stuff.
-                                                  check descriptors to get the exact type. */
+                               case 0xEA: // TS_PSI_ST_SMPTE_VC1
                                        for (DescriptorConstIterator desc = (*es)->getDescriptors()->begin();
                                                        desc != (*es)->getDescriptors()->end(); ++desc)
                                        {
                                                uint8_t tag = (*desc)->getTag();
-                                               if (!isaudio && !isvideo)
+                                               /* PES private can contain AC-3, DTS or lots of other stuff.
+                                                  check descriptors to get the exakt type. */
+                                               if (!forced_video && !forced_audio)
                                                {
                                                        switch (tag)
                                                        {
-                                                       case DTS_DESCRIPTOR:
+                                                       case 0x1C: // TS_PSI_DT_MPEG4_Audio
+                                                       case 0x2B: // TS_PSI_DT_MPEG2_AAC
                                                        case AAC_DESCRIPTOR:
                                                        case AC3_DESCRIPTOR:
+                                                       case DTS_DESCRIPTOR:
+                                                       case AUDIO_STREAM_DESCRIPTOR:
                                                                isaudio = 1;
                                                                break;
+                                                       case 0x28: // TS_PSI_DT_AVC
+                                                       case 0x1B: // TS_PSI_DT_MPEG4_Video
+                                                       case VIDEO_STREAM_DESCRIPTOR:
+                                                               isvideo = 1;
+                                                               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
+                                                               case 0x41432d33: // == 'AC-3'
+                                                               case 0x42535344: // == 'BSSD' (LPCM)
                                                                        isaudio = 1;
+                                                                       break;
+                                                               case 0x56432d31: // == 'VC-1'
+                                                                       isvideo = 1;
+                                                                       break;
                                                                default:
                                                                        break;
                                                                }
-                                                               break;
                                                        }
+                                                       default:
+                                                               break;
                                                        }
                                                }
                                                if (tag == CA_DESCRIPTOR)
                                                        is_scrambled = 1;
                                        }
+                               default:
                                        break;
                                }
-                               if (isaudio)
-                                       have_audio = true;
-                               else if (isvideo)
+                               if (isvideo)
                                        have_video = true;
+                               else if (isaudio)
+                                       have_audio = true;
                                else
                                        continue;
                                if (is_scrambled)
@@ -684,9 +706,12 @@ void eDVBScan::channelDone()
                   here, and not before.
                */
 
+       int type;
+       if (m_ch_current->getSystem(type))
+               type = -1;
+
        for (m_pmt_in_progress = m_pmts_to_read.begin(); m_pmt_in_progress != m_pmts_to_read.end();)
        {
-               int type;
                eServiceReferenceDVB ref;
                ePtr<eDVBService> service = new eDVBService;
 
@@ -712,7 +737,7 @@ void eDVBScan::channelDone()
                ref.setServiceID(m_pmt_in_progress->first);
                ref.setServiceType(m_pmt_in_progress->second.serviceType);
 
-               if (!m_ch_current->getSystem(type))
+               if (type != -1)
                {
                        char sname[255];
                        char pname[255];
@@ -740,20 +765,11 @@ void eDVBScan::channelDone()
                                }
                                case iDVBFrontend::feTerrestrial:
                                {
-                                       ePtr<iDVBFrontend> fe;
                                        eDVBFrontendParametersTerrestrial parm;
                                        m_ch_current->getDVBT(parm);
                                        snprintf(sname, 255, "%d SID 0x%02x",
                                                parm.frequency/1000,
                                                m_pmt_in_progress->first);
-                                       if (!m_channel->getFrontend(fe))
-                                       {
-                                               ePyObject tp_dict = PyDict_New();
-                                               fe->getTransponderData(tp_dict, false);
-                                               m_corrected_frequencys[m_chid_current] =
-                                                       PyInt_AsLong(PyDict_GetItemString(tp_dict, "frequency"));
-                                               Py_DECREF(tp_dict);
-                                       }
                                        break;
                                }
                                case iDVBFrontend::feCable:
@@ -790,10 +806,36 @@ void eDVBScan::channelDone()
        if (!m_chid_current)
                eWarning("SCAN: the current channel's ID was not corrected - not adding channel.");
        else
+       {
                addKnownGoodChannel(m_chid_current, m_ch_current);
-       
+               if (m_chid_current)
+               {
+                       switch(type)
+                       {
+                               case iDVBFrontend::feSatellite:
+                               case iDVBFrontend::feTerrestrial:
+                               case iDVBFrontend::feCable:
+                               {
+                                       ePtr<iDVBFrontend> fe;
+                                       if (!m_channel->getFrontend(fe))
+                                       {
+                                               ePyObject tp_dict = PyDict_New();
+                                               fe->getTransponderData(tp_dict, false);
+//                                             eDebug("add tuner data for tsid %04x, onid %04x, ns %08x",
+//                                                     m_chid_current.transport_stream_id.get(), m_chid_current.original_network_id.get(),
+//                                                     m_chid_current.dvbnamespace.get());
+                                               m_tuner_data.insert(std::pair<eDVBChannelID, ePyObjectWrapper>(m_chid_current, tp_dict));
+                                               Py_DECREF(tp_dict);
+                                       }
+                               }
+                               default:
+                                       break;
+                       }
+               }
+       }
+
        m_ch_scanned.push_back(m_ch_current);
-       
+
        for (std::list<ePtr<iDVBFrontendParameters> >::iterator i(m_ch_toScan.begin()); i != m_ch_toScan.end();)
        {
                if (sameChannel(*i, m_ch_current))
@@ -815,6 +857,7 @@ void eDVBScan::start(const eSmartPtrList<iDVBFrontendParameters> &known_transpon
        m_ch_scanned.clear();
        m_ch_unavailable.clear();
        m_new_channels.clear();
+       m_tuner_data.clear();
        m_new_services.clear();
        m_last_service = m_new_services.end();
 
@@ -934,27 +977,34 @@ void eDVBScan::insertInto(iDVBChannelList *db, bool dontRemoveOldFlags)
        {
                int system;
                ch->second->getSystem(system);
-               if (system == iDVBFrontend::feTerrestrial)
+               std::map<eDVBChannelID, ePyObjectWrapper>::iterator it = m_tuner_data.find(ch->first);
+
+               switch(system)
                {
-                       std::map<eDVBChannelID, unsigned int>::iterator it = m_corrected_frequencys.find(ch->first);
-                       if (it != m_corrected_frequencys.end())
+                       case iDVBFrontend::feTerrestrial:
                        {
                                eDVBFrontendParameters *p = (eDVBFrontendParameters*)&(*ch->second);
                                eDVBFrontendParametersTerrestrial parm;
+                               int freq = PyInt_AsLong(PyDict_GetItemString(it->second, "frequency"));
                                p->getDVBT(parm);
-                               eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
-                                       ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
-                                       ch->first.dvbnamespace.get(), it->second, parm.frequency);
-                               parm.frequency = it->second;
+//                             eDebug("corrected freq for tsid %04x, onid %04x, ns %08x is %d, old was %d",
+//                                     ch->first.transport_stream_id.get(), ch->first.original_network_id.get(),
+//                                     ch->first.dvbnamespace.get(), freq, parm.frequency);
+                               parm.frequency = freq;
                                p->setDVBT(parm);
-                               m_corrected_frequencys.erase(it);
+                               break;
                        }
+                       case iDVBFrontend::feSatellite: // no update of any transponder parameter yet
+                       case iDVBFrontend::feCable:
+                               break;
                }
+
                if (m_flags & scanOnlyFree)
                {
                        eDVBFrontendParameters *ptr = (eDVBFrontendParameters*)&(*ch->second);
                        ptr->setFlags(iDVBFrontendParameters::flagOnlyFree);
                }
+
                db->addChannelToList(ch->first, ch->second);
        }