Ticket #1970: dvbrecorder_save_pidfilters.4.diff

File dvbrecorder_save_pidfilters.4.diff, 8.0 KB (added by Janne <janne-mythtv@…>, 13 years ago)
  • libs/libmythtv/dvbrecorder.cpp

    old new const int DVBRecorder::POLL_WARNING_TIME 
    7676
    7777#define TS_TICKS_PER_SEC    90000
    7878#define DUMMY_VIDEO_PID     VIDEO_PID(0x20)
     79#define PMT_LOW_PRIORITY    -7
    7980
    8081#define LOC      QString("DVBRec(%1): ").arg(_card_number_option)
    8182#define LOC_WARN QString("DVBRec(%1) Warning: ").arg(_card_number_option)
    int DVBRecorder::OpenFilterFd(uint pid,  
    374375    {
    375376        close(fd_tmp);
    376377
    377         VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set demux filter." + ENO);
     378        VERBOSE(VB_IMPORTANT, LOC_ERR + "Failed to set demux filter. "
     379                "Probably listening on more PMT PIDs than filters available."
     380                + ENO);
    378381        return -1;
    379382    }
    380383
    381384    return fd_tmp;
    382385}
    383386
    384 void DVBRecorder::OpenFilter(uint pid, int pes_type, uint stream_type)
     387/** \fn DVBRecorder::OpenFilter(uint, int, uint)
     388 *  \brief management of pid filter opening
     389 *  \returns false if a low priority was closed or no filter was opened
     390 *           true  otherwise
     391 */
     392bool DVBRecorder::OpenFilter(uint pid, int pes_type, uint stream_type,
     393                             int priority)
    385394{
    386395    PIDInfo *info   = NULL;
    387396    int      fd_tmp = -1;
     397    bool     avail  = true;
    388398
    389399    QMutexLocker change_lock(&_pid_lock);
    390400    PIDInfoMap::iterator it = _pid_infos.find(pid);
    void DVBRecorder::OpenFilter(uint pid, i 
    400410    if (fd_tmp < 0)
    401411        fd_tmp = OpenFilterFd(pid, pes_type, stream_type);
    402412
     413    // try to close a low priority filter
     414    if (fd_tmp < 0)
     415    {
     416        // no free filters available
     417        avail = false;
     418        PIDInfoMap::iterator lp_it = _pid_infos.begin();
     419        for (;lp_it != _pid_infos.end(); ++lp_it)
     420        {
     421            if (lp_it != it && (*lp_it)->priority < 0)
     422            {
     423                (*lp_it)->Close();
     424                break;
     425            }
     426        }
     427        if (lp_it != _pid_infos.end())
     428        {
     429            // PMT PIDs are the only low priority pids
     430            uint lp_pid = lp_it.key();
     431            VERBOSE(VB_RECORD, LOC + QString("Closing low priority PID filter "
     432                                             "on PID 0x%1.").arg(lp_pid, 0, 16));
     433            _pmt_monitoring_pids.push_back(lp_pid);
     434            delete *lp_it;
     435            _pid_infos.erase(lp_it);
     436            fd_tmp = OpenFilterFd(pid, pes_type, stream_type);
     437        }
     438        else
     439            VERBOSE(VB_RECORD, LOC + "No low priority PID filter available, "
     440                    "open will fail.");
     441    }
     442
    403443    if (fd_tmp < 0)
    404444    {
    405445        if (info)
    void DVBRecorder::OpenFilter(uint pid, i 
    407447            delete *it;
    408448            _pid_infos.erase(it);
    409449        }
    410         return;
     450        return avail;
    411451    }
    412452
    413453    if (!info)
    void DVBRecorder::OpenFilter(uint pid, i 
    417457    info->filter_fd  = fd_tmp;
    418458    info->streamType = stream_type;
    419459    info->pesType    = pes_type;
     460    info->priority   = priority;
    420461
    421462    // Add the new info to the map
    422463    _pid_infos[pid] = info;
     464
     465    return avail;
    423466}
    424467
    425468bool DVBRecorder::AdjustFilters(void)
    bool DVBRecorder::AdjustFilters(void) 
    427470    StopDummyVideo(); // Stop the dummy video before acquiring the lock.
    428471
    429472    QMutexLocker change_lock(&_pid_lock);
     473    _pmt_monitoring_pids.clear();
    430474
    431475    if (!_input_pat || !_input_pmt)
    432476        return false;
    bool DVBRecorder::AdjustFilters(void) 
    437481    add_stream_type.push_back(StreamID::PrivSec);
    438482    _stream_data->AddListeningPID(MPEG_PAT_PID);
    439483
    440     for (uint i = 0; i < _input_pat->ProgramCount(); i++)
    441     {
    442         add_pid.push_back(_input_pat->ProgramPID(i));
    443         add_stream_type.push_back(StreamID::PrivSec);
    444         _stream_data->AddListeningPID(_input_pat->ProgramPID(i));
    445     }
    446 
    447484    // Record the streams in the PMT...
    448485    bool need_pcr_pid = true;
    449486    for (uint i = 0; i < _input_pmt->StreamCount(); i++)
    bool DVBRecorder::AdjustFilters(void) 
    470507        _stream_data->AddListeningPID(_eit_pids[i]);
    471508    }
    472509
     510    // Adding PMT PIDs to monitoring queue and register them with StreamData
     511    uint input_pmt_pid = _input_pat->FindPID(_input_pmt->ProgramNumber());
     512    for (uint i = 0; i < _input_pat->ProgramCount(); i++)
     513    {
     514        uint pmt_pid = _input_pat->ProgramPID(i);
     515        _stream_data->AddListeningPID(pmt_pid);
     516        if (pmt_pid == input_pmt_pid)
     517        {
     518            add_pid.push_back(input_pmt_pid);
     519            add_stream_type.push_back(StreamID::PrivSec);
     520        }
     521        else
     522            _pmt_monitoring_pids.push_back(pmt_pid);
     523    }
     524
    473525    // Delete filters for pids we no longer wish to monitor
    474526    PIDInfoMap::iterator it   = _pid_infos.begin();
    475527    PIDInfoMap::iterator next = it;
    bool DVBRecorder::AdjustEITPIDs(void) 
    536588    return true;
    537589}
    538590
     591void DVBRecorder::AdjustMonitoringPMTPIDs()
     592{
     593    QMutexLocker change_lock(&_pid_lock);
     594    bool filters_available = true;
     595
     596    while (!_pmt_monitoring_pids.empty() && filters_available)
     597    {
     598        uint pid = _pmt_monitoring_pids.front();
     599        filters_available = OpenFilter(pid, DMX_PES_OTHER, StreamID::PrivSec,
     600                                       PMT_LOW_PRIORITY);
     601        _pmt_monitoring_pids.pop_front();
     602    }
     603    VERBOSE(VB_RECORD, LOC + QString("Currently not listening on %1 PMT PIDs, "
     604                                     "%3 PID filters open")
     605            .arg(_pmt_monitoring_pids.size()-1).arg(_pid_infos.size()));
     606}
     607
    539608void DVBRecorder::StartRecording(void)
    540609{
    541610    if (!Open())
    void DVBRecorder::StartRecording(void) 
    565634    }
    566635    _drb->Start();
    567636
     637    int count = 0;
    568638    while (_request_recording && !_error)
    569639    {
    570640        if (PauseAndWait())
    void DVBRecorder::StartRecording(void) 
    602672            }
    603673        }
    604674
     675        if (count-- <= 0)
     676        {
     677            AdjustMonitoringPMTPIDs();
     678            count = 250;
     679        }
     680
    605681        ssize_t len = _drb->Read(_buffer, _buffer_size);
    606682        if (len > 0)
    607683            ProcessDataTS(_buffer, len);
  • libs/libmythtv/dvbrecorder.h

    old new  
    1010
    1111// C++ includes
    1212#include <vector>
     13#include <deque>
    1314using namespace std;
    1415
    1516// Qt includes
    class PIDInfo 
    3132    PIDInfo() :
    3233        filter_fd(-1),      continuityCount(0xFF),
    3334        streamType(0),      pesType(-1),
    34         isEncrypted(false), payloadStartSeen(false) {;}
     35        isEncrypted(false), payloadStartSeen(false), priority(0) {;}
    3536
    3637    int    filter_fd;         ///< Input filter file descriptor
    3738    uint   continuityCount;   ///< last Continuity Count (sentinel 0xFF)
    class PIDInfo 
    3940    int    pesType;           ///< PESStreamID
    4041    bool   isEncrypted;       ///< true if PID is marked as encrypted
    4142    bool   payloadStartSeen;  ///< true if payload start packet seen on PID
     43    int    priority;          ///< filters with priority < 0 can be closed
     44                              //   if a new filter can't be opened
    4245
    4346    inline void Close(void);
    4447    inline bool CheckCC(uint cc);
    class DVBRecorder : public DTVRecorder, 
    9194
    9295    bool AdjustFilters(void);
    9396    bool AdjustEITPIDs(void);
     97    void AdjustMonitoringPMTPIDs(void);
    9498    void CloseFilters(void);
    95     void OpenFilter(uint pid, int pes_type, uint mpeg_stream_type);
     99    bool OpenFilter(uint pid, int pes_type, uint mpeg_stream_type,
     100                    int priority=0);
    96101    int  OpenFilterFd(uint pid, int pes_type, uint stream_type);
    97102
    98103    void SetOutputPAT(ProgramAssociationTable*);
    class DVBRecorder : public DTVRecorder, 
    132137    PIDInfoMap      _pid_infos;
    133138    uint_vec_t      _eit_pids;
    134139
     140    deque<uint>     _pmt_monitoring_pids;
     141
    135142    /// PAT on input side
    136143    ProgramAssociationTable *_input_pat;
    137144    /// PMT on input side