Ticket #1970: dvbrecorder_save_pidfilters.3.diff

File dvbrecorder_save_pidfilters.3.diff, 7.6 KB (added by Janne <janne-mythtv@…>, 13 years ago)

final version

  • 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 available." + ENO);
    378380        return -1;
    379381    }
    380382
    381383    return fd_tmp;
    382384}
    383385
    384 void DVBRecorder::OpenFilter(uint pid, int pes_type, uint stream_type)
     386/** \fn DVBRecorder::OpenFilter(uint, int, uint)
     387 *  \brief management of pid filter opening
     388 *  \returns false if a low priority was closed or no filter was opened
     389 *           true  otherwise
     390 */
     391bool DVBRecorder::OpenFilter(uint pid, int pes_type, uint stream_type,
     392                             int priority)
    385393{
    386394    PIDInfo *info   = NULL;
    387395    int      fd_tmp = -1;
     396    bool     avail  = true;
    388397
    389398    QMutexLocker change_lock(&_pid_lock);
    390399    PIDInfoMap::iterator it = _pid_infos.find(pid);
    void DVBRecorder::OpenFilter(uint pid, i 
    400409    if (fd_tmp < 0)
    401410        fd_tmp = OpenFilterFd(pid, pes_type, stream_type);
    402411
     412    // try to close a low priority filter
     413    if (fd_tmp < 0)
     414    {
     415        // no free filters available
     416        avail = false;
     417        PIDInfoMap::iterator lp_it = _pid_infos.begin();
     418        for (;lp_it != _pid_infos.end(); ++lp_it)
     419        {
     420            if (lp_it != it && (*lp_it)->priority < 0)
     421            {
     422                (*lp_it)->Close();
     423                break;
     424            }
     425        }
     426        if (lp_it != _pid_infos.end())
     427        {
     428            // PMT PIDs are the only low priority pids
     429            uint lp_pid = lp_it.key();
     430            VERBOSE(VB_RECORD, LOC + QString("Closing low priority PID filter "
     431                                             "on PID 0x%1.").arg(lp_pid, 0, 16));
     432            _pmt_monitoring_pids.push_back(lp_pid);
     433            delete *lp_it;
     434            _pid_infos.erase(lp_it);
     435            fd_tmp = OpenFilterFd(pid, pes_type, stream_type);
     436        }
     437        else
     438            VERBOSE(VB_RECORD, LOC + "No low priority PID filter available, "
     439                    "open will fail.");
     440    }
     441
    403442    if (fd_tmp < 0)
    404443    {
    405444        if (info)
    void DVBRecorder::OpenFilter(uint pid, i 
    407446            delete *it;
    408447            _pid_infos.erase(it);
    409448        }
    410         return;
     449        return avail;
    411450    }
    412451
    413452    if (!info)
    void DVBRecorder::OpenFilter(uint pid, i 
    417456    info->filter_fd  = fd_tmp;
    418457    info->streamType = stream_type;
    419458    info->pesType    = pes_type;
     459    info->priority   = priority;
    420460
    421461    // Add the new info to the map
    422462    _pid_infos[pid] = info;
     463
     464    return avail;
    423465}
    424466
    425467bool DVBRecorder::AdjustFilters(void)
    426468{
     469    _pmt_monitoring_pids.clear();
    427470    StopDummyVideo(); // Stop the dummy video before acquiring the lock.
    428471
    429472    QMutexLocker change_lock(&_pid_lock);
    bool DVBRecorder::AdjustFilters(void) 
    437480    add_stream_type.push_back(StreamID::PrivSec);
    438481    _stream_data->AddListeningPID(MPEG_PAT_PID);
    439482
    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 
    447483    // Record the streams in the PMT...
    448484    bool need_pcr_pid = true;
    449485    for (uint i = 0; i < _input_pmt->StreamCount(); i++)
    bool DVBRecorder::AdjustFilters(void) 
    470506        _stream_data->AddListeningPID(_eit_pids[i]);
    471507    }
    472508
     509    // Adding PMT PIDs to monitoring queue and register them with StreamData
     510    for (uint i = 0; i < _input_pat->ProgramCount(); i++)
     511    {
     512        uint pid = _input_pat->ProgramPID(i);
     513        _stream_data->AddListeningPID(pid);
     514        _pmt_monitoring_pids.push_back(pid);
     515    }
     516
    473517    // Delete filters for pids we no longer wish to monitor
    474518    PIDInfoMap::iterator it   = _pid_infos.begin();
    475519    PIDInfoMap::iterator next = it;
    bool DVBRecorder::AdjustEITPIDs(void) 
    536580    return true;
    537581}
    538582
     583void DVBRecorder::AdjustMonitoringPMTPIDs()
     584{
     585    QMutexLocker change_lock(&_pid_lock);
     586    bool filters_available = true;
     587
     588    while (!_pmt_monitoring_pids.empty() && filters_available)
     589    {
     590        uint pid = _pmt_monitoring_pids.front();
     591        filters_available = OpenFilter(pid, DMX_PES_OTHER, StreamID::PrivSec,
     592                                       PMT_LOW_PRIORITY);
     593        _pmt_monitoring_pids.pop_front();
     594    }
     595    VERBOSE(VB_RECORD, LOC + QString("Currently not listening on %1 PMT PIDs, "
     596                                     "%3 PID filters open")
     597            .arg(_pmt_monitoring_pids.size()-1).arg(_pid_infos.size()));
     598}
     599
    539600void DVBRecorder::StartRecording(void)
    540601{
    541602    if (!Open())
    void DVBRecorder::StartRecording(void) 
    565626    }
    566627    _drb->Start();
    567628
     629    int count = 0;
    568630    while (_request_recording && !_error)
    569631    {
    570632        if (PauseAndWait())
    void DVBRecorder::StartRecording(void) 
    602664            }
    603665        }
    604666
     667        if (count-- <= 0)
     668        {
     669            AdjustMonitoringPMTPIDs();
     670            count = 250;
     671        }
     672
    605673        ssize_t len = _drb->Read(_buffer, _buffer_size);
    606674        if (len > 0)
    607675            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