Ticket #11018: 0002-libmythtv-EIT-ActiveScan-Control-optimized.patch

File 0002-libmythtv-EIT-ActiveScan-Control-optimized.patch, 15.8 KB (added by Shinck@…, 12 years ago)

Stop EIT-Scan on all capture cards if record or liveTV is ongoing and start again afterwards

  • mythtv/libs/libmythtv/eitscanner.cpp

    From 70748b69495c62140e43bd579c654250da4b3f18 Mon Sep 17 00:00:00 2001
    From: Sascha Hinck <SHinck@web.de>
    Date: Tue, 7 Aug 2012 01:10:11 +0200
    Subject: [PATCH] libmythtv: Stop EIT-Active scan during recording
    
    During recording and Live-TV EIT-Active scan will be stopped on all
    Capture-Cards. Active-Scan-IdleTimer will be restarted after the last
    recording exited.
    ---
     mythtv/libs/libmythtv/eitscanner.cpp         |   14 ++-
     mythtv/libs/libmythtv/tv_rec.cpp             |  171 +++++++++++++++++++++++---
     mythtv/libs/libmythtv/tv_rec.h               |    6 +-
     mythtv/programs/mythbackend/main_helpers.cpp |    4 +-
     4 files changed, 175 insertions(+), 24 deletions(-)
    
    diff --git a/mythtv/libs/libmythtv/eitscanner.cpp b/mythtv/libs/libmythtv/eitscanner.cpp
    index 6135e08..e419a8f 100644
    a b void EITScanner::run(void) 
    133133            if (!(*activeScanNextChan).isEmpty())
    134134            {
    135135                eitHelper->WriteEITCache();
    136                 rec->SetChannel(*activeScanNextChan, TVRec::kFlagEITScan);
    137                 LOG(VB_EIT, LOG_INFO,
    138                     LOC_ID + QString("Now looking for EIT data on "
    139                                      "multiplex of channel %1")
     136                if (rec->QueueEITChannelChange(*activeScanNextChan))
     137                {
     138                    LOG(VB_EIT, LOG_INFO,
     139                        LOC_ID + QString("Now looking for EIT data on "
     140                                         "multiplex of channel %1")
    140141                        .arg(*activeScanNextChan));
     142                }
    141143            }
    142144
    143145            activeScanNextTrig = QDateTime::currentDateTime()
    void EITScanner::StopPassiveScan(void) 
    216218
    217219    eitHelper->WriteEITCache();
    218220    eitHelper->SetSourceID(0);
     221
     222    LOG(VB_EIT, LOG_INFO, LOC_ID + "Stopped passive scan.");
    219223}
    220224
    221225void EITScanner::StartActiveScan(TVRec *_rec, uint max_seconds_per_source)
    void EITScanner::StopActiveScan() 
    280284    activeScan = false;
    281285    rec = NULL;
    282286    StopPassiveScan();
     287
     288    LOG(VB_EIT, LOG_INFO, LOC_ID + "Stopped active scan.");
    283289}
  • mythtv/libs/libmythtv/tv_rec.cpp

    diff --git a/mythtv/libs/libmythtv/tv_rec.cpp b/mythtv/libs/libmythtv/tv_rec.cpp
    index 3d38c6d..9b53f5f 100644
    a b  
    3636#include "tv_rec.h"
    3737#include "mythmiscutil.h"
    3838#include "osd.h"
     39#include "cardutil.h"
    3940
    4041#define DEBUG_CHANNEL_PREFIX 0 /**< set to 1 to channel prefixing */
    4142
    static QString load_profile(QString,void*,RecordingInfo*,RecordingProfile&); 
    5253static int init_jobs(const RecordingInfo *rec, RecordingProfile &profile,
    5354                     bool on_host, bool transcode_bfr_comm, bool on_line_comm);
    5455static void apply_broken_dvb_driver_crc_hack(ChannelBase*, MPEGStreamData*);
    55 
     56static int eit_start_rand(uint cardid, int eitTransportTimeout);
    5657
    5758/** \class TVRec
    5859 *  \brief This is the coordinating class of the \ref recorder_subsystem.
    bool TVRec::Init(void) 
    161162        gCoreContext->GetNumSetting("AutoTranscodeBeforeAutoCommflag", 0);
    162163    earlyCommFlag     = gCoreContext->GetNumSetting("AutoCommflagWhileRecording", 0);
    163164    runJobOnHostOnly  = gCoreContext->GetNumSetting("JobsRunOnRecordHost", 0);
    164     eitTransportTimeout=gCoreContext->GetNumSetting("EITTransportTimeout", 5) * 60;
     165    eitTransportTimeout =
     166        max(gCoreContext->GetNumSetting("EITTransportTimeout", 5) * 60, 6);
    165167    eitCrawlIdleStart = gCoreContext->GetNumSetting("EITCrawIdleStart", 60);
    166168    audioSampleRateDB = gCoreContext->GetNumSetting("AudioSampleRate");
    167169    overRecordSecNrml = gCoreContext->GetNumSetting("RecordOverTime");
    void TVRec::HandleStateChange(void) 
    974976
    975977    bool changed = false;
    976978
     979    LOG(VB_GENERAL, LOG_INFO, LOC + "GetCardIDs to stop EITscan");
     980    vector<uint> cardids = CardUtil::GetCardIDs("","DVB","");
     981    uint no_cards = cardids.size();
     982
    977983    QString transMsg = QString(" %1 to %2")
    978984        .arg(StateToString(nextState))
    979985        .arg(StateToString(desiredNextState));
    void TVRec::HandleStateChange(void) 
    9981004    if (TRANSITION(kState_None, kState_WatchingLiveTV))
    9991005    {
    10001006        tuningRequests.enqueue(TuningRequest(kFlagLiveTV));
     1007        for (uint i = 0; i < no_cards; i++)
     1008        {
     1009           if (cardids[i] != cardid)
     1010            {       
     1011               TVRec *rec = GetTVRec(cardids[i]);
     1012               if (rec && !rec->HasFlags(kFlagEITScanPaused))
     1013                   rec->SetFlags(kFlagEITScanPaused);
     1014           }
     1015        }       
    10011016        SET_NEXT();
    10021017    }
    10031018    else if (TRANSITION(kState_WatchingLiveTV, kState_None))
    10041019    {
    10051020        tuningRequests.enqueue(TuningRequest(kFlagKillRec|kFlagKillRingBuffer));
     1021         eitScanStartTime = QDateTime::currentDateTime();
     1022         uint j = 0;
     1023         TVRec *arec = NULL;
     1024        for (uint i = 0; i < no_cards; i++)
     1025         {
     1026            if (cardids[i] != cardid)
     1027            {       
     1028                TVRec *rec = GetTVRec(cardids[i]);       
     1029                if (!HasFlags(kFlagEITScanPaused))
     1030                {               
     1031                    if (rec && rec->HasFlags(kFlagEITScanPaused))
     1032                    {
     1033                        rec->eitScanStartTime = eitScanStartTime.addSecs(
     1034                            eitCrawlIdleStart + eit_start_rand(cardids[i], eitTransportTimeout));
     1035                        rec->ClearFlags(kFlagEITScanPaused);
     1036                        LOG(VB_IDLE, LOG_INFO, LOC + "Start EIT-ActiveScanIdle-Timer for " +
     1037                            QString("cardid %1, next start time: ").arg(cardids[i]) +
     1038                                 rec->eitScanStartTime.toString(Qt::ISODate));
     1039                    }
     1040                }
     1041                else if (rec && rec->GetState() != kState_None)
     1042                     arec = rec; j++;
     1043             }                 
     1044         }
     1045         if (j == 1)
     1046             arec->ClearFlags(kFlagEITScanPaused);       
    10061047        SET_NEXT();
    10071048    }
    10081049    else if (TRANSITION(kState_WatchingLiveTV, kState_RecordingOnly))
    void TVRec::HandleStateChange(void) 
    10151058    {
    10161059        SetPseudoLiveTVRecording(NULL);
    10171060        tuningRequests.enqueue(TuningRequest(kFlagRecording, curRecording));
     1061        for (uint i = 0; i < no_cards; i++)
     1062        {
     1063            if (cardids[i] != cardid)
     1064            {       
     1065                TVRec *rec = GetTVRec(cardids[i]);
     1066                if (rec && !rec->HasFlags(kFlagEITScanPaused))
     1067                        rec->SetFlags(kFlagEITScanPaused);
     1068            }
     1069        }       
    10181070        SET_NEXT();
    10191071    }
    10201072    else if (TRANSITION(kState_RecordingOnly, kState_None))
    void TVRec::HandleStateChange(void) 
    10221074        tuningRequests.enqueue(
    10231075            TuningRequest(kFlagCloseRec|kFlagKillRingBuffer|
    10241076                          (GetFlags()&kFlagKillRec)));
     1077        eitScanStartTime = QDateTime::currentDateTime();
     1078        uint j = 0;
     1079        TVRec *arec = NULL;
     1080        for (uint i = 0; i < no_cards; i++)
     1081        {
     1082            if (cardids[i] != cardid)
     1083            {       
     1084                TVRec *rec = GetTVRec(cardids[i]);       
     1085                if (!HasFlags(kFlagEITScanPaused))
     1086                {               
     1087                    if (rec && rec->HasFlags(kFlagEITScanPaused))
     1088                    {
     1089                        rec->eitScanStartTime = eitScanStartTime.addSecs(
     1090                             eitCrawlIdleStart + eit_start_rand(cardids[i], eitTransportTimeout));
     1091                        rec->ClearFlags(kFlagEITScanPaused);
     1092                        LOG(VB_IDLE, LOG_INFO, LOC + "Start EIT-ActiveScanIdle-Timer for " +
     1093                            QString("cardid %1, next start time: ").arg(cardids[i]) +
     1094                                rec->eitScanStartTime.toString(Qt::ISODate));
     1095                    }
     1096                }
     1097                else if (rec && rec->GetState() != kState_None)
     1098                    arec = rec; j++;
     1099            }                   
     1100        }
     1101        if (j == 1)
     1102            arec->ClearFlags(kFlagEITScanPaused);       
    10251103        SET_NEXT();
    10261104    }
    10271105
    void TVRec::HandleStateChange(void) 
    10341114
    10351115    eitScanStartTime = QDateTime::currentDateTime();
    10361116    if (scanner && (internalState == kState_None))
    1037         eitScanStartTime = eitScanStartTime.addSecs(eitCrawlIdleStart);
     1117    {
     1118        eitScanStartTime = eitScanStartTime.addSecs(
     1119            eitCrawlIdleStart + eit_start_rand(cardid, eitTransportTimeout));
     1120    }
    10381121    else
    10391122        eitScanStartTime = eitScanStartTime.addYears(1);
    10401123}
    void TVRec::CloseChannel(void) 
    11301213         CardUtil::IsV4L(genOpt.cardtype)))
    11311214    {
    11321215        channel->Close();
     1216        LOG(VB_GENERAL, LOG_INFO, LOC + QString("Close Card %1")
     1217                .arg(CardUtil::ProbeDVBFrontendName(CardUtil::GetVideoDevice(cardid))) );
     1218//                      GetDeviceLabel(cardid))
    11331219    }
    11341220}
    11351221
    static int no_capturecards(uint cardid) 
    12131299    return -1;
    12141300}
    12151301
     1302static int eit_start_rand(uint cardid, int eitTransportTimeout)
     1303{
     1304    // randomize start time a bit
     1305    int timeout = random() % (eitTransportTimeout / 3);
     1306    // get the number of capture cards and the position of the current card
     1307    // to distribute the the scan start evenly over eitTransportTimeout
     1308    int card_pos = no_capturecards(cardid);
     1309    int no_cards = no_capturecards(0);
     1310    if (no_cards > 0 && card_pos >= 0)
     1311        timeout += eitTransportTimeout * card_pos / no_cards;
     1312    return timeout;
     1313}
     1314
    12161315/// \brief Event handling method, contains event loop.
    12171316void TVRec::run(void)
    12181317{
    void TVRec::run(void) 
    12271326        (dvbOpt.dvb_eitscan || get_use_eit(cardid)))
    12281327    {
    12291328        scanner = new EITScanner(cardid);
    1230         uint timeout = eitCrawlIdleStart;
    1231         // get the number of capture cards and the position of the current card
    1232         // to distribute the the scan start evenly over eitTransportTimeout
    1233         int card_pos = no_capturecards(cardid);
    1234         int no_cards = no_capturecards(0);
    1235         if (no_cards > 0 && card_pos >= 0)
    1236             timeout += eitTransportTimeout * card_pos / no_cards;
    1237         else
    1238             timeout += random() % eitTransportTimeout;
    1239 
    1240         eitScanStartTime = eitScanStartTime.addSecs(timeout);
     1329        eitScanStartTime = eitScanStartTime.addSecs(
     1330            eitCrawlIdleStart + eit_start_rand(cardid, eitTransportTimeout));
    12411331    }
    12421332    else
    12431333        eitScanStartTime = eitScanStartTime.addYears(1);
    void TVRec::run(void) 
    13701460        }
    13711461
    13721462        if (scanner && channel &&
    1373             QDateTime::currentDateTime() > eitScanStartTime)
     1463            QDateTime::currentDateTime() > eitScanStartTime &&
     1464            !HasFlags(kFlagEITScanPaused))
    13741465        {
    13751466            if (!dvbOpt.dvb_eitscan)
    13761467            {
    void TVRec::run(void) 
    13921483            }
    13931484        }
    13941485
     1486        //Stop EIT-Scanning if recording begins on another card,
     1487        if (scanner && HasFlags(kFlagEITScanPaused) &&
     1488            HasFlags(kFlagEITScannerRunning))
     1489        {
     1490            scanner->StopActiveScan();
     1491            ClearFlags(kFlagEITScannerRunning);
     1492            TuningShutdowns(TuningRequest(kFlagNoRec));
     1493        }
     1494
    13951495        // We should be no more than a few thousand milliseconds,
    13961496        // as the end recording code does not have a trigger...
    13971497        // NOTE: If you change anything here, make sure that
    void TVRec::SetChannel(QString name, uint requestType) 
    30523152    // Clear the RingBuffer reset flag, in case we wait for a reset below
    30533153    ClearFlags(kFlagRingBufferReady);
    30543154
     3155    // Clear out any EITScan channel change requests
     3156    TuningQueue::iterator it = tuningRequests.begin();
     3157    while (it != tuningRequests.end())
     3158    {
     3159        if ((*it).flags & kFlagEITScan)
     3160            it = tuningRequests.erase(it);
     3161        else
     3162            ++it;
     3163    }
     3164
    30553165    // Actually add the tuning request to the queue, and
    30563166    // then wait for it to start tuning
    30573167    tuningRequests.enqueue(TuningRequest(requestType, name));
    void TVRec::SetChannel(QString name, uint requestType) 
    30663176    LOG(VB_CHANNEL, LOG_INFO, LOC + QString("SetChannel(%1) -- end").arg(name));
    30673177}
    30683178
     3179/** \brief Queues up a channel change for the EITScanner.
     3180 *
     3181 *   Unlike the normal SetChannel() this does not block until
     3182 *   the channel change occurs to avoid a deadlock if
     3183 *   EITScanner::StopActiveScan() is called with the stateChangeLock
     3184 *   held while the EITScanner is calling TVRec::SetChannel().
     3185 */
     3186bool TVRec::QueueEITChannelChange(const QString &name)
     3187{
     3188    LOG(VB_CHANNEL, LOG_INFO, LOC +
     3189        QString("QueueEITChannelChange(%1) -- begin").arg(name));
     3190
     3191    bool ok = false;
     3192    if (stateChangeLock.tryLock())
     3193    {
     3194        if (tuningRequests.empty())
     3195        {
     3196            tuningRequests.enqueue(TuningRequest(kFlagEITScan, name));
     3197            ok = true;
     3198        }
     3199        stateChangeLock.unlock();
     3200    }
     3201
     3202    LOG(VB_CHANNEL, LOG_INFO, LOC +
     3203        QString("QueueEITChannelChange(%1) -- end --> %2").arg(name).arg(ok));
     3204
     3205    return ok;
     3206}
     3207
    30693208void TVRec::GetNextProgram(BrowseDirection direction,
    30703209                           QString &title,       QString &subtitle,
    30713210                           QString &desc,        QString &category,
    QString TVRec::FlagToString(uint f) 
    42044343        msg += "Errored,";
    42054344    if (kFlagCancelNextRecording & f)
    42064345        msg += "CancelNextRecording,";
     4346    if (kFlagEITScanPaused & f)
     4347        msg += "EITScanPaused,";
    42074348
    42084349    // Tuning flags
    42094350    if ((kFlagRec & f) == kFlagRec)
  • mythtv/libs/libmythtv/tv_rec.h

    diff --git a/mythtv/libs/libmythtv/tv_rec.h b/mythtv/libs/libmythtv/tv_rec.h
    index a830c33..b169434 100644
    a b class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable 
    156156    void FinishRecording(void)  { SetFlags(kFlagFinishRecording); }
    157157    /// \brief Tells TVRec that the frontend's TV class is ready for messages.
    158158    void FrontendReady(void)    { SetFlags(kFlagFrontendReady); }
     159    void PauseEITActiveScan(void)    { SetFlags(kFlagEITScanPaused); }
     160    void RestartEITActiveScan(void)    { ClearFlags(kFlagEITScanPaused); }
    159161    void CancelNextRecording(bool cancel);
    160162    ProgramInfo *GetRecording(void);
    161163
    class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable 
    198200    void ChangeChannel(ChannelChangeDirection dir)
    199201        { SetChannel(QString("NextChannel %1").arg((int)dir)); }
    200202    void SetChannel(QString name, uint requestType = kFlagDetect);
     203    bool QueueEITChannelChange(const QString &name);
    201204
    202205    int SetSignalMonitoringRate(int msec, int notifyFrontend = 1);
    203206    int  GetPictureAttribute(PictureAttribute attr);
    class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable 
    409412    static const uint kFlagFinishRecording      = 0x00000008;
    410413    static const uint kFlagErrored              = 0x00000010;
    411414    static const uint kFlagCancelNextRecording  = 0x00000020;
     415    static const uint kFlagEITScanPaused        = 0x00000040;
    412416
    413417    // Tuning flags
    414418    /// final result desired is LiveTV recording
    class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable 
    432436
    433437    // Waiting stuff
    434438    static const uint kFlagWaitingForRecPause   = 0x00100000;
    435     static const uint kFlagWaitingForSignal     = 0x00200000;
     439    static const uint kFlagWaitingForSignal     = 0x00200000;   
    436440    static const uint kFlagNeedToStartRecorder  = 0x00800000;
    437441    static const uint kFlagPendingActions       = 0x00F00000;
    438442
  • mythtv/programs/mythbackend/main_helpers.cpp

    diff --git a/mythtv/programs/mythbackend/main_helpers.cpp b/mythtv/programs/mythbackend/main_helpers.cpp
    index 28d5a4a..d2283ca 100644
    a b bool setupTVs(bool ismaster, bool &error) 
    192192                }
    193193                else
    194194                {
    195                     LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards" +
    196                             cidmsg + "failed init");
     195                    LOG(VB_GENERAL, LOG_ERR, "Problem with capture cards - " +
     196                            cidmsg + " failed init");
    197197                    delete tv;
    198198                }
    199199            }