 mythtv/libs/libmythtv/dvbrecorder.cpp |   93 ++++++++++++++++++---------------
 mythtv/libs/libmythtv/dvbrecorder.h   |   10 +++-
 2 files changed, 59 insertions(+), 44 deletions(-)

diff --git a/mythtv/libs/libmythtv/dvbrecorder.cpp b/mythtv/libs/libmythtv/dvbrecorder.cpp
index d348359..24e0f00 100644
--- a/mythtv/libs/libmythtv/dvbrecorder.cpp
+++ b/mythtv/libs/libmythtv/dvbrecorder.cpp
@@ -93,6 +93,8 @@ DVBRecorder::DVBRecorder(TVRec *rec, DVB
       dvbchannel(advbchannel),
       _stream_data(NULL),
       _reset_pid_filters(true),
+      _open_pid_filters(0),
+      _max_pid_filters(1<<13),
       _pid_lock(true),
       _input_pat(NULL),
       _input_pmt(NULL),
@@ -314,15 +316,20 @@ void DVBRecorder::CloseFilters(void)
     PIDInfoMap::iterator it;
     for (it = _pid_infos.begin(); it != _pid_infos.end(); ++it)
     {
-        (*it)->Close();
+        _open_pid_filters = (*it)->Close(_open_pid_filters);
         delete *it;
     }
     _pid_infos.clear();
     _eit_pids.clear();
+    _open_pid_filters = 0;
+    _max_pid_filters  = 1<<13;
 }
 
 int DVBRecorder::OpenFilterFd(uint pid, int pes_type, uint stream_type)
 {
+    if (_open_pid_filters >= _max_pid_filters)
+        return -1;
+
     // bits per millisecond
     uint bpms = (StreamID::IsVideo(stream_type)) ? 19200 : 500;
     // msec of buffering we want
@@ -378,9 +385,11 @@ int DVBRecorder::OpenFilterFd(uint pid,
         close(fd_tmp);
 
         VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set demux filter." + ENO);
+        _max_pid_filters = _open_pid_filters;
         return -1;
     }
 
+    _open_pid_filters++;
     return fd_tmp;
 }
 
@@ -404,58 +413,58 @@ bool DVBRecorder::OpenFilter(uint pid, i
         if (info->pesType == pes_type)
             fd_tmp = info->filter_fd;
         else
-            info->Close();
+            _open_pid_filters = info->Close(_open_pid_filters);
+
+        _pid_infos.erase(it);
+        delete info;
     }
 
     if (fd_tmp < 0)
+    {
         fd_tmp = OpenFilterFd(pid, pes_type, stream_type);
 
-    // try to close a low priority filter
-    if (fd_tmp < 0)
-    {
-        // no free filters available
-        avail = false;
-        PIDInfoMap::iterator lp_it = _pid_infos.begin();
-        for (;lp_it != _pid_infos.end(); ++lp_it)
+        if (fd_tmp < 0)
         {
-            if (lp_it != it && (*lp_it)->priority < kFilterPriorityHigh)
+            // no free filters, try to close a low priority filter
+            avail = false;
+            int min_priority = kFilterPriorityHigh;
+            PIDInfoMap::iterator min_it;
+
+            PIDInfoMap::iterator lp_it = _pid_infos.begin();
+            for (;lp_it != _pid_infos.end(); ++lp_it)
+                if ((*lp_it)->priority < kFilterPriorityHigh)
+                {
+                    (*lp_it)->priority--;
+                    if ((*lp_it)->priority < min_priority)
+                    {
+                        min_priority = (*lp_it)->priority;
+                        min_it = lp_it;
+                    }
+                }
+
+            if (min_priority < kFilterPriorityHigh)
             {
-                (*lp_it)->Close();
-                break;
+                _open_pid_filters = (*min_it)->Close(_open_pid_filters);
+                VERBOSE(VB_RECORD, LOC + "Closing low priority PID filter "
+                        + QString("on PID 0x%1.").arg(min_it.key(), 0, 16));
+                // PMT PIDs are the only low priority pids
+                _pmt_monitoring_pids.push_back(min_it.key());
+                delete *min_it;
+                _pid_infos.erase(min_it);
+            }
+            else
+            {
+                VERBOSE(VB_IMPORTANT, LOC_ERR + "Out of PID filters!");
+                return false;
             }
-        }
-        if (lp_it != _pid_infos.end())
-        {
-            // PMT PIDs are the only low priority pids
-            uint lp_pid = lp_it.key();
-
-            VERBOSE(VB_RECORD, LOC + "Closing low priority PID filter " +
-                    QString("on PID 0x%1.").arg(lp_pid, 0, 16));
-
-            _pmt_monitoring_pids.push_back(lp_pid);
-            delete *lp_it;
-            _pid_infos.erase(lp_it);
-
             fd_tmp = OpenFilterFd(pid, pes_type, stream_type);
         }
-        else
-        {
-            VERBOSE(VB_RECORD, LOC_ERR + "Out of PID filters!");
-        }
     }
 
     if (fd_tmp < 0)
-    {
-        if (info)
-        {
-            delete *it;
-            _pid_infos.erase(it);
-        }
-        return avail;
-    }
-
-    if (!info)
-        info = new PIDInfo();
+        return false;
+    
+    info = new PIDInfo();
 
     // Add the file descriptor to the filter list
     info->filter_fd  = fd_tmp;
@@ -565,7 +574,7 @@ bool DVBRecorder::AdjustFilters(void)
         // Delete pids we are no longer interested in
         _stream_data->RemoveListeningPID(it.key());
         _stream_data->RemoveWritingPID(it.key());
-        (*it)->Close();
+        _open_pid_filters = (*it)->Close(_open_pid_filters);
         delete *it;
         _pid_infos.erase(it);
     }
@@ -640,7 +649,7 @@ void DVBRecorder::AdjustMonitoringPMTPID
     if (VB_RECORD & print_verbose_messages)
     {
         QString tmp0 = ""; 
-        QString tmp1 = QString("%1 PID filters open.").arg(_pid_infos.size());
+        QString tmp1 = QString("%1 PID filters open.").arg(_open_pid_filters);
 
         int sz = _pmt_monitoring_pids.size();
         if (sz)
diff --git a/mythtv/libs/libmythtv/dvbrecorder.h b/mythtv/libs/libmythtv/dvbrecorder.h
index f2ab97a..fbbc309 100644
--- a/mythtv/libs/libmythtv/dvbrecorder.h
+++ b/mythtv/libs/libmythtv/dvbrecorder.h
@@ -43,7 +43,7 @@ class PIDInfo
     int    priority;          ///< filters with priority < 0 can be closed
                               //   if a new filter can't be opened
 
-    inline void Close(void);
+    inline uint Close(uint open_filters);
     inline bool CheckCC(uint cc);
 };
 typedef QMap<uint,PIDInfo*> PIDInfoMap;
@@ -134,6 +134,8 @@ class DVBRecorder : public DTVRecorder,
     /// Set when we want to generate a new filter set
     MPEGStreamData *_stream_data;
     bool            _reset_pid_filters;
+    uint            _open_pid_filters;
+    uint            _max_pid_filters;
     QMutex          _pid_lock;
     PIDInfoMap      _pid_infos;
     uint_vec_t      _eit_pids;
@@ -186,10 +188,14 @@ class DVBRecorder : public DTVRecorder,
     static const int kFilterPriorityLow;
 };
 
-inline void PIDInfo::Close(void)
+inline uint PIDInfo::Close(uint open_filters)
 {
     if (filter_fd >= 0)
+    {
         close(filter_fd);
+        return open_filters-1;
+    }
+    return open_filters;
 }
 
 inline bool PIDInfo::CheckCC(uint new_cnt)
