Ticket #1728: 02_one_active_eitscanner_per_backend.diff

File 02_one_active_eitscanner_per_backend.diff, 14.7 KB (added by Janne <janne-mythtv@…>, 14 years ago)
  • libs/libmythtv/tv_rec.cpp

    === libs/libmythtv/tv_rec.cpp
    ==================================================================
     
    770770    eitScanStartTime = QDateTime::currentDateTime();   
    771771    if ((internalState == kState_None) && (genOpt.cardtype == "DVB"))
    772772    {
    773         // Add some randomness to avoid all cards starting
    774         // EIT scanning at nearly the same time.
     773        // start the eit scanning only if the encoder is idle_start sec idle
    775774        uint idle_start = gContext->GetNumSetting("EITCrawIdleStart", 60);
    776         uint timeout = idle_start + (random() % 59);
    777         eitScanStartTime = eitScanStartTime.addSecs(timeout);
     775        eitScanStartTime = eitScanStartTime.addSecs(idle_start);
    778776    }
    779777    else
    780778        eitScanStartTime = eitScanStartTime.addYears(1);
     
    12461244    SetFlags(kFlagRunMainLoop);
    12471245    ClearFlags(kFlagExitPlayer | kFlagFinishRecording);
    12481246
    1249     // Add some randomness to avoid all cards starting
    1250     // EIT scanning at nearly the same time.
     1247    // start the eit scanning only if the encoder is idle_start sec idle
    12511248    uint idle_start = gContext->GetNumSetting("EITCrawIdleStart", 60);
    1252     uint timeout = idle_start + (random() % 59);
    1253     eitScanStartTime = QDateTime::currentDateTime().addSecs(timeout);
     1249    eitScanStartTime = QDateTime::currentDateTime().addSecs(idle_start);
    12541250
    12551251    while (HasFlags(kFlagRunMainLoop))
    12561252    {
     
    31513147    VERBOSE(VB_RECORD, LOC + "SetChannel()" + " -- end");
    31523148}
    31533149
     3150/** \fn TVRec::StartEITScan(QString)
     3151 *  \brief Starts EIT scanning on the named channel and the current tuner.
     3152 *
     3153 *  \param name channum of channel to scan on
     3154 */
     3155bool TVRec::StartEITScan(QString name)
     3156{
     3157    // initialize eit scanner if needed
     3158    if (!scanner && eitcache)
     3159        scanner = new EITScanner(eitcache);
     3160
     3161    if (QDateTime::currentDateTime() > eitScanStartTime)
     3162    {
     3163        SetChannel(name, kFlagEITScan);
     3164        uint ignore = gContext->GetNumSetting("EITIgnoresSource", 0);
     3165        return true;
     3166    }
     3167    VERBOSE(VB_EIT, LOC + QString("Now: %1 - start scan only after: %2")
     3168            .arg(QDateTime::currentDateTime().toString())
     3169            .arg(eitScanStartTime.toString()));
     3170
     3171    return false;
     3172}
     3173
    31543174/** \fn TVRec::GetNextProgram(int,QString&,QString&,QString&,QString&,QString&,QString&,QString&,QString&,QString&,QString&,QString&,QString&)
    31553175 *  \brief Returns information about the program that would be seen if we changed
    31563176 *         the channel using ChangeChannel(int) with "direction".
  • libs/libmythtv/tv_rec.h

    === libs/libmythtv/tv_rec.h
    ==================================================================
     
    221221        { SetChannel(QString("NextChannel %1").arg((int)dir)); }
    222222    void SetChannel(QString name, uint requestType = kFlagDetect);
    223223
     224    bool StartEITScan(QString name);
     225
    224226    int SetSignalMonitoringRate(int msec, int notifyFrontend = 1);
    225227    int ChangeColour(bool direction);
    226228    int ChangeContrast(bool direction);
  • programs/mythbackend/encoderlink.h

    === programs/mythbackend/encoderlink.h
    ==================================================================
     
    8282    void ToggleChannelFavorite(void);
    8383    void ChangeChannel(int channeldirection);
    8484    void SetChannel(const QString &name);
     85    bool StartEITScan(const QString chanid);
    8586    int ChangeContrast(bool direction);
    8687    int ChangeBrightness(bool direction);
    8788    int ChangeColour(bool direction);
  • programs/mythbackend/mythbackend.pro

    === programs/mythbackend/mythbackend.pro
    ==================================================================
     
    1313
    1414# Input
    1515HEADERS += autoexpire.h encoderlink.h filetransfer.h httpstatus.h mainserver.h
    16 HEADERS += playbacksock.h scheduler.h server.h housekeeper.h
     16HEADERS += playbacksock.h scheduler.h server.h housekeeper.h eitactivescanner.h
    1717
    1818SOURCES += autoexpire.cpp encoderlink.cpp filetransfer.cpp httpstatus.cpp
    1919SOURCES += main.cpp mainserver.cpp playbacksock.cpp scheduler.cpp server.cpp
    20 SOURCES += housekeeper.cpp
     20SOURCES += housekeeper.cpp eitactivescanner.cpp
    2121
    2222using_oss:DEFINES += USING_OSS
    2323
  • programs/mythbackend/main.cpp

    === programs/mythbackend/main.cpp
    ==================================================================
     
    2626#include "encoderlink.h"
    2727#include "remoteutil.h"
    2828#include "housekeeper.h"
     29#include "eitactivescanner.h"
    2930
    3031#include "libmyth/mythcontext.h"
    3132#include "libmyth/mythdbcon.h"
     
    4243QString lockfile_location;
    4344HouseKeeper *housekeeping = NULL;
    4445QString logfile = "";
     46EITActiveScanner *eitscanner = NULL;
    4547
    4648bool setupTVs(bool ismaster, bool &error)
    4749{
     
    595597    else
    596598        jobqueue = new JobQueue(ismaster);
    597599
     600    eitscanner = new EITActiveScanner(ismaster, &tvList);
    598601    VERBOSE(VB_IMPORTANT, QString("%1 version: %2 www.mythtv.org")
    599602                            .arg(binname).arg(MYTH_BINARY_VERSION));
    600603
  • programs/mythbackend/eitactivescanner.cpp

    === programs/mythbackend/eitactivescanner.cpp
    ==================================================================
     
     1// -*- Mode: c++ -*-
     2
     3#include "eitactivescanner.h"
     4
     5#include "libmythtv/tv_rec.h"
     6
     7
     8/*****************************************************************************
     9 *
     10 * Active EIT scanner: controls the TVRecs on the master backend
     11                       and holds a persistant event cache on each backend
     12*/
     13
     14EITActiveScanner::EITActiveScanner(bool _ismaster, QMap<int, EncoderLink *> *tvList)
     15    : exitThread(false), eitCache(new EITCache()),
     16      cardList(tvList), ismaster(_ismaster)
     17{
     18    pthread_create(&eventThread, NULL, SpawnEventLoop, this);
     19}
     20/*
     21void EITActiveScanner::TeardownAll(void)
     22{
     23    StopActiveScan();
     24    if (!exitThread)
     25    {
     26        exitThread = true;
     27        exitThreadCond.wakeAll();
     28        pthread_join(eventThread, NULL);
     29    }
     30}*/
     31
     32/** \fn EITActiveScanner::SpawnEventLoop(void*)
     33 *  \brief Thunk that allows scanner_thread pthread to
     34 *         call EITActiveScanner::RunEventLoop().
     35 */
     36void *EITActiveScanner::SpawnEventLoop(void *param)
     37{
     38    EITActiveScanner *scanner = (EITActiveScanner*) param;
     39    scanner->RunEventLoop();
     40    return NULL;
     41}
     42
     43/** \fn EITActiveScanner::RunEventLoop()
     44 *  \brief This runs the event loop for EITActiveScanner until 'exitThread' is true.
     45 */
     46void EITActiveScanner::RunEventLoop(void)
     47{
     48    exitThread = false;
     49
     50//     QMap<int, EncoderLink *>::iterator it = cardList->begin();
     51//     for (; it != cardList->end(); ++it)
     52//     {
     53//         TVRec *rec = it.data()->GetTVRec();
     54//         if (rec)
     55//         {
     56//             rec->SetEITCache(eitCache);
     57//         }
     58//     }
     59//    if (ismaster)
     60        StartActiveScan();
     61
     62
     63
     64    while (!exitThread)
     65    {
     66        if (ismaster && (QDateTime::currentDateTime() > activeScanNextTrig)
     67            && !cardList->isEmpty())
     68        {
     69//             cerr << eitCache->GetStatistics() << endl;
     70            if (activeScanNextCard == cardIDToSourceID.end())
     71            {
     72                activeScanNextCard = cardIDToSourceID.begin();
     73            }
     74
     75            uint source = *activeScanNextCard;
     76
     77            int curCardID = activeScanNextCard.key();
     78            if (activeScanNextChan[source] == activeScanChannels[source].end())
     79                activeScanNextChan[source] = activeScanChannels[source].begin();
     80
     81            if (!(*(activeScanNextChan[source])).isEmpty() &&
     82                (*cardList)[curCardID]->StartEITScan(*(activeScanNextChan[source])))
     83            {
     84                VERBOSE(VB_GENERAL, QString("(%1)Now looking for EIT data on "
     85                                            "multiplex of channel %2 of source %3")
     86                        .arg(curCardID).arg(*(activeScanNextChan[source])).arg(source));
     87                activeScanNextChan[source]++;
     88            }
     89            else
     90            {
     91                VERBOSE(VB_GENERAL, QString("Skipping card %1 in scan for EIT data on "
     92                                            "multiplex of channel %2 of source %3")
     93                        .arg(curCardID).arg(*(activeScanNextChan[source])).arg(source));
     94            }
     95
     96            activeScanNextTrig = QDateTime::currentDateTime()
     97                .addSecs(activeScanTrigTime);
     98
     99            activeScanNextCard++;
     100        }
     101        // TODO: prune old eit cache entries every now and then
     102           
     103        exitThreadCond.wait(200); // sleep up to 200 ms.
     104    }
     105}
     106
     107void EITActiveScanner::StartActiveScan()
     108{
     109    if (!activeScanSources.size())
     110    {
     111        // get all source ids with useeit == 1
     112        MSqlQuery query(MSqlQuery::InitCon());
     113        query.prepare(
     114            "SELECT DISTINCT channel.sourceid "
     115            "FROM channel, videosource "
     116            "WHERE videosource.sourceid = channel.sourceid AND "
     117            "      channel.mplexid        IS NOT NULL      AND "
     118            "      useonairguide        = 1                AND "
     119            "      useeit               = 1 "
     120            "GROUP BY mplexid "
     121            "ORDER BY channel.sourceid, atscsrcid, mplexid");
     122       
     123        if (!query.exec() || !query.isActive())
     124        {
     125            MythContext::DBError("EITActiveScanner::StartActiveScan", query);
     126            return;
     127        }
     128       
     129        while (query.next())
     130            activeScanSources.push_back(query.value(0).toUInt());
     131
     132        // getting mapping from cardid to sourceid with useeit == 1
     133        query.prepare(
     134            "SELECT cardid, videosource.sourceid "
     135            "FROM videosource,cardinput "
     136            "WHERE videosource.sourceid = cardinput.sourceid AND "
     137            "      useeit               = 1 "
     138            "ORDER BY cardid");
     139       
     140        if (!query.exec() || !query.isActive())
     141        {
     142            MythContext::DBError("EITActiveScanner::StartActiveScan", query);
     143            return;
     144        }
     145       
     146        while (query.next())
     147            cardIDToSourceID[query.value(0).toInt()] = query.value(1).toUInt();
     148
     149
     150        // get one channel with sourceid per mplexid
     151        query.prepare(
     152            "SELECT channel.sourceid, min(channum) "
     153            "FROM channel, videosource "
     154            "WHERE videosource.sourceid = channel.sourceid AND "
     155            "      channel.mplexid        IS NOT NULL      AND "
     156            "      useonairguide        = 1                AND "
     157            "      useeit               = 1                AND "
     158            "      channum             != '' "
     159            "GROUP BY mplexid "
     160            "ORDER BY channel.sourceid, atscsrcid, mplexid");
     161
     162        if (!query.exec() || !query.isActive())
     163        {
     164            MythContext::DBError("EITScanner::StartActiveScan", query);
     165            return;
     166        }
     167
     168        while (query.next())
     169        {
     170            VERBOSE(VB_EIT,QString("Adding channel %1 for source %2 to scan list")
     171            .arg(query.value(0).toString()).arg(query.value(1).toUInt()));
     172            activeScanChannels[query.value(0).toUInt()].push_back(query.value(1).toString());
     173        }
     174    }
     175    int number = 0;
     176    for (vector<uint>::iterator it = activeScanSources.begin(); it != activeScanSources.end(); ++it)
     177    {
     178        activeScanNextChan[*it] = activeScanChannels[*it].begin();
     179        number += activeScanChannels[*it].size();
     180    }
     181
     182    VERBOSE(VB_EIT,
     183            QString("StartActiveScan called with %1 multiplexes on %2 sources")
     184            .arg(number).arg(activeScanSources.size()));
     185
     186    if (activeScanSources.size())
     187    {
     188        uint max_seconds_per_source = gContext->GetNumSetting("EITTransportTimeout", 5) * 60;
     189
     190        activeScanNextTrig = QDateTime::currentDateTime();
     191        activeScanTrigTime = max_seconds_per_source / cardList->size();
     192        activeScanNextCard = cardIDToSourceID.begin();
     193    }
     194}
  • programs/mythbackend/eitactivescanner.h

    Property changes on: programs/mythbackend/eitactivescanner.cpp
    ___________________________________________________________________
    Name: svn:mime-type
     +text/cpp
    
    === programs/mythbackend/eitactivescanner.h
    ==================================================================
     
     1// -*- Mode: c++ -*-
     2#ifndef EITACTIVESCANNER_H
     3#define EITACTIVESCANNER_H
     4
     5// C includes
     6#include <pthread.h>
     7
     8// Qt includes
     9#include <qobject.h>
     10#include <qdatetime.h>
     11#include <qstringlist.h>
     12#include <qwaitcondition.h>
     13
     14// myth includes
     15#include "encoderlink.h"
     16
     17#include "libmythtv/eitcache.h"
     18
     19
     20
     21class EITActiveScanner
     22{
     23  public:
     24    EITActiveScanner(bool _ismaster, QMap<int, EncoderLink *> *tvList);
     25    ~EITActiveScanner() {}
     26
     27  private:
     28    void StartActiveScan(void);
     29    void RunEventLoop(void);
     30    static void *SpawnEventLoop(void*);
     31
     32    QMutex           lock;
     33
     34    pthread_t        eventThread;
     35    bool             exitThread;
     36    QWaitCondition   exitThreadCond;
     37
     38    EITCache         *eitCache;
     39
     40    QDateTime        activeScanNextTrig;
     41    uint             activeScanTrigTime;
     42
     43    vector<uint>                      activeScanSources;
     44    QMap<uint, QStringList>           activeScanChannels;
     45    QMap<uint, QStringList::iterator> activeScanNextChan;
     46
     47    QMap<int, EncoderLink *>   *cardList;
     48    QMap<int, uint>            cardIDToSourceID;
     49    QMap<int, uint>::iterator  activeScanNextCard;
     50
     51    bool             ismaster;
     52};
     53
     54#endif //EITACTIVESCANNER_H
  • programs/mythbackend/encoderlink.cpp

    Property changes on: programs/mythbackend/eitactivescanner.h
    ___________________________________________________________________
    Name: svn:mime-type
     +text/cpp
    
    === programs/mythbackend/encoderlink.cpp
    ==================================================================
     
    199199    return retval;
    200200}
    201201
     202/** \fn EncoderLink::StartEITScan(const QString)
     203 *  \brief Tells TVRec to scan for EIT on channel chanid.
     204 *  \param chanid      Channel to scan
     205 */
     206bool EncoderLink::StartEITScan(const QString chanid)
     207{
     208    if (local)
     209        return tv->StartEITScan(chanid);
     210    else if (sock)
     211    {
     212        VERBOSE(VB_IMPORTANT, "StartEITScan is currently only supported locally");
     213        return false;
     214        /*return sock->StartEITScan(m_capturecardnum, chanid);*/
     215    }
     216}
     217
     218
    202219/** \fn EncoderLink::RecordPending(const ProgramInfo*, int)
    203220 *  \brief Tells TVRec there is a pending recording "rec" in "secsleft" seconds.
    204221 *  \param rec      Recording to make.