Ticket #8695: optimize_UpdateFiltersFromStreamData_v3.patch

File optimize_UpdateFiltersFromStreamData_v3.patch, 17.8 KB (added by Rune Petersen <rune@…>, 14 years ago)

fully functional Poc for DVB (other sources are broken)

  • libs/libmythtv/dvbstreamhandler.cpp

     
    146146
    147147    _stream_data_list.push_back(data);
    148148
     149    vector<uint> pids;
     150    data->GetPIDs(pids);
     151    vector<uint>::iterator it = pids.begin();
     152    for (; it != pids.end(); ++it)
     153    {
     154        AddPIDFilter(*it, StreamID::PrivSec,DMX_PES_OTHER);
     155    }
     156
    149157    _listener_lock.unlock();
    150158
    151159    Start();
     
    184192    {
    185193        _listener_lock.unlock();
    186194    }
     195   
     196    vector<uint> pids;
     197    data->GetPIDs(pids);
     198    vector<uint>::iterator pit = pids.begin();
     199    for (; pit != pids.end(); ++pit)
     200    {
     201        RemovePIDFilter(*pit);
     202    }
    187203
    188204    VERBOSE(VB_RECORD, LOC + "RemoveListener("<<data<<") -- end");
    189205}
     
    460476    VERBOSE(VB_RECORD, LOC + "RunSR(): " + "end");
    461477}
    462478
    463 bool DVBStreamHandler::AddPIDFilter(PIDInfo *info)
     479bool DVBStreamHandler::AddPIDFilter(uint pid, uint stream_type, uint pes_type)
    464480{
    465481#ifdef DEBUG_PID_FILTERS
    466482    VERBOSE(VB_RECORD, LOC + QString("AddPIDFilter(0x%1) priority %2")
    467             .arg(info->_pid, 0, 16).arg(GetPIDPriority(info->_pid)));
     483            .arg(pid, 0, 16).arg(GetPIDPriority(pid)));
    468484#endif // DEBUG_PID_FILTERS
    469485
    470486    QMutexLocker writing_locker(&_pid_lock);
    471     _pid_info[info->_pid] = info;
     487    PIDInfo *info = _pid_info[pid];
    472488
    473     CycleFiltersByPriority();
     489    if(info == NULL)
     490    {
     491        info = new PIDInfo(pid, stream_type,
     492                                pes_type);
     493        _pid_info[pid] = info;
     494    }
     495    info->refcount++;
    474496
    475497    return true;
    476498}
     
    625647        return false;
    626648
    627649    PIDInfo *tmp = *it;
     650
     651    if(--tmp->refcount)
     652    {
     653        return true;
     654    }
     655
    628656    _pid_info.erase(it);
    629657
    630658    bool ok = true;
     
    632660    {
    633661        ok = tmp->Close(_dvb_dev);
    634662        _open_pid_filters--;
    635 
    636         CycleFiltersByPriority();
    637663    }
    638664
    639665    delete tmp;
     
    648674#ifdef DEBUG_PID_FILTERS
    649675    VERBOSE(VB_RECORD, LOC + "RemoveAllPIDFilters()");
    650676#endif // DEBUG_PID_FILTERS
    651 
    652     vector<int> del_pids;
     677    bool ok = true;
    653678    PIDInfoMap::iterator it = _pid_info.begin();
    654679    for (; it != _pid_info.end(); ++it)
    655         del_pids.push_back(it.key());
     680    {
     681        PIDInfo *filter = *it;
    656682
    657     bool ok = true;
    658     vector<int>::iterator dit = del_pids.begin();
    659     for (; dit != del_pids.end(); ++dit)
    660         ok &= RemovePIDFilter(*dit);
     683        if (filter->IsOpen())
     684        {
     685            ok = filter->Close(_dvb_dev);
     686        }
    661687
     688        delete filter;
     689    }
     690    _pid_info.clear();
     691    _open_pid_filters = 0;
     692
     693    CycleFiltersByPriority();
    662694    return ok;
    663695}
    664696
     
    696728{
    697729    UpdateListeningForEIT();
    698730
    699     pid_map_t pids;
    700 
     731    pidchanges_vec_t pidchanges;
    701732    {
    702733        QMutexLocker read_locker(&_listener_lock);
    703734
    704735        for (uint i = 0; i < _stream_data_list.size(); i++)
    705             _stream_data_list[i]->GetPIDs(pids);
     736            _stream_data_list[i]->GetPIDChanges(pidchanges);
    706737    }
    707738
    708     QMap<uint, PIDInfo*> add_pids;
    709     vector<uint>         del_pids;
    710 
     739    if( !pidchanges.empty() )
    711740    {
    712         QMutexLocker read_locker(&_pid_lock);
    713 
    714         // PIDs that need to be added..
    715         pid_map_t::const_iterator lit = pids.constBegin();
    716         for (; lit != pids.constEnd(); ++lit)
     741        bool ok = true;
     742        pidchanges_vec_t::const_iterator it = pidchanges.begin();
     743        for (; it != pidchanges.end(); ++it)
    717744        {
    718             if (*lit && (_pid_info.find(lit.key()) == _pid_info.end()))
     745            switch(it->change)
    719746            {
    720                 add_pids[lit.key()] = new PIDInfo(
    721                     lit.key(), StreamID::PrivSec,  DMX_PES_OTHER);
     747            case kPIDChangeAdd:
     748                ok &= AddPIDFilter(it->pid, StreamID::PrivSec,
     749                                DMX_PES_OTHER);
     750                break;
     751            case kPIDChangeRemove:
     752                ok &= RemovePIDFilter(it->pid);
    722753            }
    723754        }
    724755
    725         // PIDs that need to be removed..
    726         PIDInfoMap::const_iterator fit = _pid_info.begin();
    727         for (; fit != _pid_info.end(); ++fit)
    728         {
    729             bool in_pids = pids.find(fit.key()) != pids.end();
    730             if (!in_pids)
    731                 del_pids.push_back(fit.key());
    732         }
     756        CycleFiltersByPriority();
     757        return ok;
    733758    }
    734759
    735     // Remove PIDs
    736     bool ok = true;
    737     vector<uint>::iterator dit = del_pids.begin();
    738     for (; dit != del_pids.end(); ++dit)
    739         ok &= RemovePIDFilter(*dit);
    740 
    741     // Add PIDs
    742     QMap<uint, PIDInfo*>::iterator ait = add_pids.begin();
    743     for (; ait != add_pids.end(); ++ait)
    744         ok &= AddPIDFilter(*ait);
    745 
    746760    // Cycle filters if it's been a while
    747761    if (_cycle_timer.elapsed() > 1000)
    748762        CycleFiltersByPriority();
    749763
    750     return ok;
     764    return true;
    751765}
    752766
    753767void DVBStreamHandler::SetRetuneAllowed(
     
    831845    }
    832846
    833847    bool supports_ts = false;
    834     if (AddPIDFilter(new PIDInfo(pat_pid)))
     848    if (AddPIDFilter(pat_pid))
    835849    {
    836850        supports_ts = true;
    837851        RemovePIDFilter(pat_pid);
  • libs/libmythtv/dvbstreamhandler.h

     
    2727{
    2828  public:
    2929    PIDInfo() :
    30         _pid(0xffffffff), filter_fd(-1), streamType(0), pesType(-1) {;}
     30        _pid(0xffffffff), filter_fd(-1), streamType(0), pesType(-1),
     31        refcount(0) {;}
    3132    PIDInfo(uint pid) :
    32         _pid(pid),        filter_fd(-1), streamType(0), pesType(-1) {;}
     33        _pid(pid),        filter_fd(-1), streamType(0), pesType(-1),
     34        refcount(0) {;}
    3335    PIDInfo(uint pid, uint stream_type, uint pes_type) :
    3436        _pid(pid),                       filter_fd(-1),
    35         streamType(stream_type),         pesType(pes_type) {;}
     37        streamType(stream_type),         pesType(pes_type),
     38        refcount(0) {;}
    3639
    3740    bool Open(const QString &dvb_dev, bool use_section_reader);
    3841    bool Close(const QString &dvb_dev);
     
    4245    int         filter_fd;         ///< Input filter file descriptor
    4346    uint        streamType;        ///< StreamID
    4447    int         pesType;           ///< PESStreamID
     48    uint        refcount;          ///< Count of listeners on this pid.
    4549};
    4650typedef QMap<uint,PIDInfo*> PIDInfoMap;
    4751
     
    8387
    8488    void UpdateListeningForEIT(void);
    8589    bool UpdateFiltersFromStreamData(void);
    86     bool AddPIDFilter(PIDInfo *info);
     90    bool AddPIDFilter(uint pid, uint stream_type=0, uint pes_type=-1);
    8791    bool RemovePIDFilter(uint pid);
    8892    bool RemoveAllPIDFilters(void);
    8993    void CycleFiltersByPriority(void);
  • libs/libmythtv/mpeg/mpegstreamdata.cpp

     
    5454/** \fn MPEGStreamData::MPEGStreamData(int, bool)
    5555 *  \brief Initializes MPEGStreamData.
    5656 *
    57  *   This adds the PID of the PAT table to "_pids_listening"
     57 *   This adds the PID of the PAT table to "_pids (type=listening)"
    5858 *
    5959 *  \param desiredProgram If you want rewritten PAT and PMTs, for
    6060 *                        a desired program set this to a value > -1
     
    184184        DeletePartialPES(it.key());
    185185    _partial_pes_packet_cache.clear();
    186186
    187     _pids_listening.clear();
    188     _pids_notlistening.clear();
    189     _pids_writing.clear();
    190     _pids_audio.clear();
     187    RemoveAllPIDs();
    191188
    192     _pid_video_single_program = _pid_pmt_single_program = 0xffffffff;
     189    _pid_pmt_single_program = 0xffffffff;
    193190
    194191    _pat_version.clear();
    195192    _pat_section_seen.clear();
     
    618615        return false;
    619616    }
    620617
    621     _pids_audio.clear();
     618    RemoveAllAudioPIDs();
    622619    for (uint i = 0; i < audioPIDs.size(); i++)
    623620        AddAudioPID(audioPIDs[i]);
    624621
     622    RemoveAllVideoPIDs();
    625623    if (videoPIDs.size() >= 1)
    626         _pid_video_single_program = videoPIDs[0];
     624        AddVideoPID(videoPIDs[0]);
    627625    for (uint i = 1; i < videoPIDs.size(); i++)
    628626        AddWritingPID(videoPIDs[i]);
    629627
     
    985983            return true;
    986984        }
    987985
    988         if (IsAudioPID(tspacket.PID()))
     986        PIDType type = GetPIDType(tspacket.PID());
     987        switch (type)
    989988        {
     989        case kPIDTypeAudio:
    990990            for (uint j = 0; j < _ts_av_listeners.size(); j++)
    991991                _ts_av_listeners[j]->ProcessAudioTSPacket(tspacket);
    992992
    993993            return true;
    994         }
    995994
    996         if (IsWritingPID(tspacket.PID()) && _ts_writing_listeners.size())
    997         {
     995        case kPIDTypeWriting:
    998996            for (uint j = 0; j < _ts_writing_listeners.size(); j++)
    999997                _ts_writing_listeners[j]->ProcessTSPacket(tspacket);
    1000         }
    1001998
    1002         if (IsListeningPID(tspacket.PID()))
    1003         {
     999            return true;
     1000
     1001        case kPIDTypeListening:
    10041002            HandleTSTables(&tspacket);
     1003            return true;
     1004
     1005        default:;
    10051006        }
    10061007    }
    10071008    else if (!tspacket.ScramplingControl() && IsWritingPID(tspacket.PID()))
     
    10341035    return pos;
    10351036}
    10361037
     1038void MPEGStreamData::RemoveAllPIDs()
     1039{
     1040    RemoveAllVideoPIDs();
     1041
     1042    pid_map_t::const_iterator it = _pids.begin();
     1043    for (; it != _pids.end(); ++it)
     1044    {
     1045        AddPIDChange(PIDChange(kPIDChangeRemove, it.key()));
     1046    }
     1047    _pids.clear();
     1048}
     1049
     1050void MPEGStreamData::RemoveAllAudioPIDs()
     1051{
     1052    pid_map_t::iterator it = _pids.begin();
     1053    while( it != _pids.end() )
     1054    {
     1055        if (it->type == kPIDTypeAudio)
     1056        {
     1057            AddPIDChange(PIDChange(kPIDChangeRemove, it.key()));
     1058            it = _pids.erase(it);
     1059            continue;
     1060        }
     1061        it++;
     1062    }
     1063}
     1064
     1065void MPEGStreamData::RemoveAllVideoPIDs()
     1066{
     1067    RemoveVideoPID(_pid_video_single_program);
     1068}
     1069
    10371070bool MPEGStreamData::IsListeningPID(uint pid) const
    10381071{
    1039     pid_map_t::const_iterator it = _pids_listening.find(pid);
    1040     return it != _pids_listening.end();
     1072    pid_map_t::const_iterator it = _pids.find(pid);
     1073    return it != _pids.end() && it->type == kPIDTypeListening;
    10411074}
    10421075
    10431076bool MPEGStreamData::IsNotListeningPID(uint pid) const
    10441077{
    1045     pid_map_t::const_iterator it = _pids_notlistening.find(pid);
    1046     return it != _pids_notlistening.end();
     1078    pid_map_t::const_iterator it = _pids.find(pid);
     1079    return it != _pids.end() && it->type == kPIDTypeNotListening;
    10471080}
    10481081
    10491082bool MPEGStreamData::IsWritingPID(uint pid) const
    10501083{
    1051     pid_map_t::const_iterator it = _pids_writing.find(pid);
    1052     return it != _pids_writing.end();
     1084    pid_map_t::const_iterator it = _pids.find(pid);
     1085    return it != _pids.end() && it->type == kPIDTypeWriting;
    10531086}
    10541087
    10551088bool MPEGStreamData::IsAudioPID(uint pid) const
    10561089{
    1057     pid_map_t::const_iterator it = _pids_audio.find(pid);
    1058     return it != _pids_audio.end();
     1090    pid_map_t::const_iterator it = _pids.find(pid);
     1091    return it != _pids.end() && it->type == kPIDTypeAudio;
    10591092}
    10601093
    1061 uint MPEGStreamData::GetPIDs(pid_map_t &pids) const
     1094uint MPEGStreamData::GetPIDs(vector<uint> &pids) const
    10621095{
    1063     uint sz = pids.size();
     1096    if (_pid_video_single_program != 0xffffffff)
     1097    {
     1098        pids.push_back(_pid_video_single_program);
     1099    }
     1100    pid_map_t::const_iterator it = _pids.begin();
     1101    for (; it != _pids.end(); ++it)
     1102    {
     1103        pids.push_back(it.key());
     1104    }
     1105    return 0;
     1106}
    10641107
    1065     if (_pid_video_single_program < 0x1fff)
    1066         pids[_pid_video_single_program] = kPIDPriorityHigh;
     1108PIDType MPEGStreamData::GetPIDType(uint pid) const
     1109{
     1110    pid_map_t::const_iterator it = _pids.find(pid);
     1111   
     1112    if (it != _pids.end())
     1113    {
     1114        return it->type;
     1115    }
    10671116
    1068     pid_map_t::const_iterator it = _pids_listening.begin();
    1069     for (; it != _pids_listening.end(); ++it)
    1070         pids[it.key()] = max(pids[it.key()], *it);
    1071 
    1072     it = _pids_audio.begin();
    1073     for (; it != _pids_audio.end(); ++it)
    1074         pids[it.key()] = max(pids[it.key()], *it);
    1075 
    1076     it = _pids_writing.begin();
    1077     for (; it != _pids_writing.end(); ++it)
    1078         pids[it.key()] = max(pids[it.key()], *it);
    1079 
    1080     return pids.size() - sz;
     1117    return kPIDTypeNone;
    10811118}
    10821119
    10831120PIDPriority MPEGStreamData::GetPIDPriority(uint pid) const
     
    10851122    if (_pid_video_single_program == pid)
    10861123        return kPIDPriorityHigh;
    10871124
    1088     pid_map_t::const_iterator it;
    1089     it = _pids_listening.find(pid);
    1090     if (it != _pids_listening.end())
    1091         return *it;
    1092     it = _pids_notlistening.find(pid);
    1093     if (it != _pids_notlistening.end())
    1094         return *it;
    1095     it = _pids_writing.find(pid);
    1096     if (it != _pids_writing.end())
    1097         return *it;
    1098     it = _pids_audio.find(pid);
    1099     if (it != _pids_audio.end())
    1100         return *it;
     1125    pid_map_t::const_iterator it = _pids.find(pid);
     1126   
     1127    if (it != _pids.end())
     1128    {
     1129        return it->priority;
     1130    }
    11011131
    11021132    return kPIDPriorityNone;
    11031133}
  • libs/libmythtv/mpeg/mpegstreamdata.h

     
    8181    kPIDPriorityNormal = 2,
    8282    kPIDPriorityHigh   = 3,
    8383} PIDPriority;
    84 typedef QMap<uint, PIDPriority> pid_map_t;
    8584
     85enum PIDType
     86{
     87    kPIDTypeNone,
     88    kPIDTypeListening,
     89    kPIDTypeNotListening,
     90    kPIDTypeWriting,
     91    kPIDTypeAudio,
     92};
     93
     94struct PIDDesc
     95{
     96    PIDDesc(PIDType _type, PIDPriority _priority)
     97        : type(_type), priority(_priority) {}
     98
     99    PIDType     type;
     100    PIDPriority priority;
     101};
     102typedef QMap<uint, PIDDesc> pid_map_t;
     103
     104enum ChangeAction
     105{
     106    kPIDChangeAdd = 0,
     107    kPIDChangeRemove = 1,
     108};
     109
     110struct PIDChange
     111{
     112    PIDChange(ChangeAction _change, uint32_t _pid)
     113     : change(_change)
     114     , pid(_pid)
     115    {}
     116
     117    ChangeAction change;
     118    uint32_t    pid;
     119};
     120
     121typedef vector<PIDChange> pidchanges_vec_t;
     122
    86123class MPEGStreamData : public EITSource
    87124{
    88125  public:
     
    118155    // Listening
    119156    virtual void AddListeningPID(
    120157        uint pid, PIDPriority priority = kPIDPriorityNormal)
    121         { _pids_listening[pid] = priority; }
     158    { AddPID(pid, kPIDTypeListening, priority); }
     159
    122160    virtual void AddNotListeningPID(uint pid)
    123         { _pids_notlistening[pid] = kPIDPriorityNormal; }
     161    { AddPID(pid, kPIDTypeNotListening, kPIDPriorityNormal); }
     162
    124163    virtual void AddWritingPID(
    125164        uint pid, PIDPriority priority = kPIDPriorityHigh)
    126         { _pids_writing[pid] = priority; }
     165    { AddPID(pid, kPIDTypeWriting, priority); }
     166
    127167    virtual void AddAudioPID(
    128168        uint pid, PIDPriority priority = kPIDPriorityHigh)
    129         { _pids_audio[pid] = priority; }
     169    { AddPID(pid, kPIDTypeAudio, priority); }
    130170
    131     virtual void RemoveListeningPID(uint pid) { _pids_listening.remove(pid);  }
    132     virtual void RemoveNotListeningPID(uint pid)
    133         { _pids_notlistening.remove(pid); }
    134     virtual void RemoveWritingPID(uint pid) { _pids_writing.remove(pid);    }
    135     virtual void RemoveAudioPID(uint pid)   { _pids_audio.remove(pid);      }
     171    void AddPID(uint pid, PIDType type,
     172                PIDPriority priority = kPIDPriorityHigh)
     173    {
     174        _pids.insert(pid, PIDDesc(type, priority));
     175        AddPIDChange(PIDChange(kPIDChangeAdd, pid));
     176    }
    136177
     178    virtual void AddVideoPID(uint pid)
     179    {
     180        _pid_video_single_program = pid;
     181        AddPIDChange(PIDChange(kPIDChangeAdd, pid));
     182    }
     183
     184    virtual void RemoveListeningPID(uint pid) { RemovePID(pid); }
     185    virtual void RemoveNotListeningPID(uint pid) { RemovePID(pid); }
     186    virtual void RemoveWritingPID(uint pid) { RemovePID(pid); }
     187    virtual void RemoveAudioPID(uint pid) { RemovePID(pid); }
     188
     189    void RemovePID(uint pid)
     190    {
     191        _pids.remove(pid);
     192        AddPIDChange(PIDChange(kPIDChangeRemove, pid));
     193    }
     194
     195    virtual void RemoveVideoPID(uint pid)
     196    {
     197        if (_pid_video_single_program == pid && pid != 0xffffffff)
     198        {
     199            AddPIDChange(PIDChange(kPIDChangeRemove, pid));
     200            _pid_video_single_program = 0xffffffff;
     201        }
     202    }
     203
     204    void AddPIDChange(const PIDChange &pidChange)
     205    {
     206        pidchanges_vec_t::iterator it = _pidchanges.begin();
     207        for (; it != _pidchanges.end(); ++it)
     208        {
     209            if (it->pid == pidChange.pid)
     210            {
     211                if (it->change != pidChange.change)
     212                {
     213                    _pidchanges.erase(it);
     214                }
     215                return;
     216            }
     217        }
     218        _pidchanges.push_back(pidChange);
     219    }
     220
     221    virtual void RemoveAllPIDs();
     222    virtual void RemoveAllAudioPIDs();
     223    virtual void RemoveAllVideoPIDs();
     224
    137225    virtual bool IsListeningPID(uint pid) const;
    138226    virtual bool IsNotListeningPID(uint pid) const;
    139227    virtual bool IsWritingPID(uint pid) const;
     
    141229        { return _pid_video_single_program == pid; }
    142230    virtual bool IsAudioPID(uint pid) const;
    143231
    144     const pid_map_t& ListeningPIDs(void) const
    145         { return _pids_listening; }
    146     const pid_map_t& AudioPIDs(void) const
    147         { return _pids_audio; }
    148     const pid_map_t& WritingPIDs(void) const
    149         { return _pids_writing; }
     232    uint GetPIDs(pid_map_t &pids) const {return 0; }
     233    uint GetPIDs(vector<uint> &pids) const;
     234    uint GetPIDChanges(pidchanges_vec_t &changes)
     235    {
     236        uint size = _pidchanges.size();
     237        changes.insert(changes.begin(), _pidchanges.begin(), _pidchanges.end());
     238        _pidchanges.clear();
     239        return size;
     240    }
    150241
    151     uint GetPIDs(pid_map_t&) const;
    152 
     242    PIDType     GetPIDType(uint pid) const;
    153243    // PID Priorities
    154244    PIDPriority GetPIDPriority(uint pid) const;
    155245
     
    327417    float                     _eit_rate;
    328418
    329419    // Listening
    330     pid_map_t _pids_listening;
    331     pid_map_t _pids_notlistening;
    332     pid_map_t _pids_writing;
    333     pid_map_t _pids_audio;
     420    pid_map_t _pids;
     421    pidchanges_vec_t _pidchanges;
    334422
    335423    // Encryption monitoring
    336424    mutable QMutex            _encryption_lock;