Ticket #1728: 20060425_eit_refactoring.patch
File 20060425_eit_refactoring.patch, 31.7 KB (added by , 18 years ago) |
---|
-
libs/libmythtv/eitcache.h
=== libs/libmythtv/eitcache.h ==================================================================
1 /* 1 /* -*- Mode: c++ -*- 2 2 * Copyright 2006 (C) Stuart Auchterlonie <stuarta at squashedfrog.net> 3 3 * License: GPL v2 4 4 */ … … 10 10 11 11 // Qt headers 12 12 #include <qmap.h> 13 #include <qmutex.h> 13 14 #include <qstring.h> 14 15 15 16 typedef QMap<uint64_t, uint64_t> key_map_t; … … 20 21 EITCache(); 21 22 ~EITCache() {}; 22 23 23 bool IsNewEIT(const uint tsid, const uint eventid, 24 const uint serviceid, const uint tableid, 25 const uint version, 26 const unsigned char * const eitdata, 27 const uint eitlength); 24 bool IsNewEIT(const uint onid, const uint tsid, 25 const uint serviceid, const uint eventid, 26 const uint tableid, const uint version, 27 const uint endtime); 28 28 29 uint PruneOldEntries(uint timestamp); 30 29 31 void ResetStatistics(void); 30 QString GetStatistics(void) const;32 QString GetStatistics(void); 31 33 32 34 private: 33 35 // event key cache 34 36 key_map_t eventMap; 35 37 38 QMutex eventMapLock; 39 40 uint lastPruneTime; 41 36 42 // statistics 37 43 uint accessCnt; 38 44 uint hitCnt; 39 45 uint tblChgCnt; 40 46 uint verChgCnt; 47 uint pruneCnt; 48 uint prunedHitCnt; 41 49 42 50 static const uint kVersionMax; 43 51 }; -
libs/libmythtv/eithelper.cpp
=== libs/libmythtv/eithelper.cpp ==================================================================
26 26 #define LOC QString("EITHelper: ") 27 27 #define LOC_ERR QString("EITHelper, Error: ") 28 28 29 EITHelper::EITHelper( ) :30 eitfixup(new EITFixUp()), eitcache( new EITCache()),29 EITHelper::EITHelper(EITCache *cache) : 30 eitfixup(new EITFixUp()), eitcache(cache), 31 31 gps_offset(-1 * GPS_LEAP_SECONDS), utc_offset(0), 32 32 sourceid(0) 33 33 { … … 209 209 210 210 for (uint i = 0; i < eit->EventCount(); i++) 211 211 { 212 QDateTime starttime = MythUTCToLocal(eit->StartTimeUTC(i)); 212 213 // Skip event if we have already processed it before... 213 if (!eitcache->IsNewEIT( 214 eit->TSID(), eit->EventID(i), 215 eit->ServiceID(), eit->TableID(), 216 eit->Version(), 217 eit->Descriptors(i), eit->DescriptorsLength(i))) 214 if (!eitcache->IsNewEIT(eit->OriginalNetworkID(), eit->TSID(), 215 eit->ServiceID(), eit->EventID(i), 216 eit->TableID(), eit->Version(), 217 starttime.toTime_t()+eit->DurationInSeconds(i))) 218 218 { 219 219 continue; 220 220 } … … 320 320 if (!chanid) 321 321 continue; 322 322 323 QDateTime starttime = MythUTCToLocal(eit->StartTimeUTC(i));324 323 EITFixUp::TimeFix(starttime); 325 324 QDateTime endtime = starttime.addSecs(eit->DurationInSeconds(i)); 326 325 -
libs/libmythtv/eitcache.cpp
=== libs/libmythtv/eitcache.cpp ==================================================================
1 1 // -*- Mode: c++ -*- 2 2 /* 3 3 * Copyright 2006 (C) Stuart Auchterlonie <stuarta at squashedfrog.net> 4 * Copyright 2006 (C) Janne Grunau <janne-mythtv at grunau.be> 4 5 * License: GPL v2 5 6 */ 6 7 8 9 #include <iostream> 10 using namespace std; 11 12 #include <qdatetime.h> 13 7 14 #include "eitcache.h" 8 #include <stdio.h>15 #include "mythcontext.h" 9 16 17 #define LOC "EITCache: " 18 10 19 // Highest version number. version is 5bits 11 20 const uint EITCache::kVersionMax = 31; 12 21 13 22 EITCache::EITCache() 14 : accessCnt(0), hitCnt(0), tblChgCnt(0), verChgCnt(0) 23 : accessCnt(0), hitCnt(0), tblChgCnt(0), verChgCnt(0), 24 pruneCnt(0), prunedHitCnt(0) 15 25 { 26 // six hours ago 27 lastPruneTime = QDateTime::currentDateTime().addSecs(-21600).toTime_t(); 16 28 } 17 29 18 30 void EITCache::ResetStatistics(void) … … 21 33 hitCnt = 0; 22 34 tblChgCnt = 0; 23 35 verChgCnt = 0; 36 pruneCnt = 0; 37 prunedHitCnt = 0; 24 38 } 25 39 26 QString EITCache::GetStatistics(void) const40 QString EITCache::GetStatistics(void) 27 41 { 42 QMutexLocker locker(&eventMapLock); 28 43 return QString( 29 44 "EITCache::statistics: Accesses: %1, Hits: %2, " 30 "Table Upgrades %3, New Versions: %4") 31 .arg(accessCnt).arg(hitCnt).arg(tblChgCnt).arg(verChgCnt); 45 "Table Upgrades %3, New Versions: %4, Entries: %5 " 46 "Pruned entries: %6, pruned Hits: %7.") 47 .arg(accessCnt).arg(hitCnt).arg(tblChgCnt).arg(verChgCnt) 48 .arg(eventMap.size()).arg(pruneCnt).arg(prunedHitCnt); 32 49 } 33 50 34 static uint64_t construct_key(uint tsid, uint eventid, uint serviceid)51 static uint64_t construct_key(uint onid, uint tsid, uint serviceid, uint eventid) 35 52 { 36 return (((uint64_t) tsid << 48) | ((uint64_t) eventid<< 32) |37 ((uint64_t) serviceid << 16) );53 return (((uint64_t) onid << 48) | ((uint64_t) tsid << 32) | 54 ((uint64_t) serviceid << 16) | ((uint64_t) eventid )); 38 55 } 39 56 40 static uint64_t construct_sig(uint tableid, uint version, uint chksum)57 static uint64_t construct_sig(uint tableid, uint version, uint endtime) 41 58 { 42 59 return (((uint64_t) tableid << 40) | ((uint64_t) version << 32) | 43 ((uint64_t) chksum));60 ((uint64_t) endtime)); 44 61 } 45 62 46 63 static uint extract_table_id(uint64_t sig) … … 53 70 return (sig >> 32) & 0x1f; 54 71 } 55 72 56 bool EITCache::IsNewEIT(const uint tsid, const uint eventid, 57 const uint serviceid, const uint tableid, 58 const uint version, 59 const unsigned char * const /*eitdata*/, 60 const uint /*eitlength*/) 73 static uint extract_endtime(uint64_t sig) 61 74 { 75 return sig & 0xffffffff; 76 } 77 78 bool EITCache::IsNewEIT(const uint onid, const uint tsid, 79 const uint serviceid, const uint eventid, 80 const uint tableid, const uint version, 81 const uint endtime) 82 { 62 83 accessCnt++; 63 84 64 uint64_t key = construct_key(tsid, eventid, serviceid); 85 // don't readd pruned entries 86 if (endtime < lastPruneTime) 87 { 88 prunedHitCnt++; 89 return false; 90 } 91 92 uint64_t key = construct_key(onid, tsid, serviceid, eventid); 93 94 QMutexLocker locker(&eventMapLock); 65 95 key_map_t::const_iterator it = eventMap.find(key); 66 96 67 97 if (it != eventMap.end()) … … 87 117 } 88 118 } 89 119 90 eventMap[key] = construct_sig(tableid, version, 0 /*chksum*/);120 eventMap[key] = construct_sig(tableid, version, endtime); 91 121 92 122 return true; 93 123 } 94 124 125 uint EITCache::PruneOldEntries(uint timestamp) 126 { 127 QDateTime extime = QDateTime(); 128 extime.setTime_t(timestamp); 129 VERBOSE(VB_EIT, LOC + QString("Pruning all entries that ended before %1,") 130 .arg(extime.toString())); 131 132 QMutexLocker locker(&eventMapLock); 133 uint size = eventMap.size(); 134 135 key_map_t::iterator it = eventMap.begin(); 136 while (it != eventMap.end()) 137 { 138 if (extract_endtime(*it) < timestamp) 139 { 140 key_map_t::iterator tmp = it; 141 ++tmp; 142 eventMap.erase(it); 143 it = tmp; 144 } 145 else 146 ++it; 147 } 148 149 lastPruneTime = timestamp; 150 size -= eventMap.size(); 151 prunedHitCnt += size; 152 return size; 153 } 154 95 155 /* vim: set expandtab tabstop=4 shiftwidth=4: */ -
libs/libmythtv/eithelper.h
=== libs/libmythtv/eithelper.h ==================================================================
51 51 class EITHelper 52 52 { 53 53 public: 54 EITHelper( );54 EITHelper(EITCache *cache); 55 55 virtual ~EITHelper(); 56 56 57 57 uint GetListSize(void) const; -
libs/libmythtv/eitscanner.h
=== libs/libmythtv/eitscanner.h ==================================================================
17 17 class EITHelper; 18 18 class dvb_channel_t; 19 19 class ProgramMapTable; 20 class EITCache; 20 21 21 22 class EITSource 22 23 { … … 28 29 class EITScanner 29 30 { 30 31 public: 31 EITScanner( );32 EITScanner(EITCache *cache); 32 33 ~EITScanner() { TeardownAll(); } 33 34 34 35 void StartPassiveScan(ChannelBase*, EITSource*, bool ignore_source); 35 36 void StopPassiveScan(void); 36 37 38 #if 0 37 39 void StartActiveScan(TVRec*, uint max_seconds_per_source, 38 40 bool ignore_source); 39 41 40 42 void StopActiveScan(void); 43 #endif 41 44 42 45 private: 43 46 void TeardownAll(void); … … 56 59 57 60 TVRec *rec; 58 61 bool activeScan; 62 #if 0 59 63 QDateTime activeScanNextTrig; 60 64 uint activeScanTrigTime; 61 65 QStringList activeScanChannels; 62 66 QStringList::iterator activeScanNextChan; 67 #endif 63 68 64 69 bool ignore_source; 65 70 -
libs/libmythtv/tv_rec.cpp
=== libs/libmythtv/tv_rec.cpp ==================================================================
117 117 // Various components TVRec coordinates 118 118 : recorder(NULL), channel(NULL), signalMonitor(NULL), 119 119 scanner(NULL), dvbsiparser(NULL), dummyRecorder(NULL), 120 eitcache(NULL), 120 121 // Configuration variables from database 121 122 transcodeFirst(false), earlyCommFlag(false), runJobOnHostOnly(false), 122 123 audioSampleRateDB(0), overRecordSecNrml(0), overRecordSecCat(0), … … 151 152 bool init_run = false; 152 153 if (genOpt.cardtype == "DVB") 153 154 { 154 if (!scanner )155 scanner = new EITScanner( );155 if (!scanner && eitcache) 156 scanner = new EITScanner(eitcache); 156 157 157 158 #ifdef USING_DVB 158 159 channel = new DVBChannel(genOpt.videodev.toInt(), this); … … 726 727 // to avoid race condition with it's tuning requests. 727 728 if (HasFlags(kFlagEITScannerRunning)) 728 729 { 729 scanner->Stop ActiveScan();730 scanner->StopPassiveScan(); 730 731 ClearFlags(kFlagEITScannerRunning); 731 732 } 732 733 … … 770 771 eitScanStartTime = QDateTime::currentDateTime(); 771 772 if ((internalState == kState_None) && (genOpt.cardtype == "DVB")) 772 773 { 773 // Add some randomness to avoid all cards starting 774 // EIT scanning at nearly the same time. 774 // start the eit scanning only if the encoder is idle_start sec idle 775 775 uint idle_start = gContext->GetNumSetting("EITCrawIdleStart", 60); 776 uint timeout = idle_start + (random() % 59); 777 eitScanStartTime = eitScanStartTime.addSecs(timeout); 776 eitScanStartTime = eitScanStartTime.addSecs(idle_start); 778 777 } 779 778 else 780 779 eitScanStartTime = eitScanStartTime.addYears(1); … … 906 905 #ifdef USING_HDHOMERUN 907 906 HDHRChannel *hdhr_channel = GetHDHRChannel(); 908 907 HDHRRecorder *hdhr_recorder = GetHDHRRecorder(); 909 if (hdhr_channel && hdhr_recorder && !scanner )908 if (hdhr_channel && hdhr_recorder && !scanner && eitcache) 910 909 { 911 910 uint ignore = gContext->GetNumSetting("EITIgnoresSource", 0); 912 scanner = new EITScanner( );911 scanner = new EITScanner(eitcache); 913 912 scanner->StartPassiveScan(hdhr_channel, hdhr_recorder, ignore); 914 913 } 915 914 #endif // USING_HDHOMERUN … … 1246 1245 SetFlags(kFlagRunMainLoop); 1247 1246 ClearFlags(kFlagExitPlayer | kFlagFinishRecording); 1248 1247 1249 // Add some randomness to avoid all cards starting 1250 // EIT scanning at nearly the same time. 1248 // start the eit scanning only if the encoder is idle_start sec idle 1251 1249 uint idle_start = gContext->GetNumSetting("EITCrawIdleStart", 60); 1252 uint timeout = idle_start + (random() % 59); 1253 eitScanStartTime = QDateTime::currentDateTime().addSecs(timeout); 1250 eitScanStartTime = QDateTime::currentDateTime().addSecs(idle_start); 1254 1251 1255 1252 while (HasFlags(kFlagRunMainLoop)) 1256 1253 { … … 1380 1377 "for all sources on this card."); 1381 1378 eitScanStartTime = eitScanStartTime.addYears(1); 1382 1379 } 1380 /* 1383 1381 else 1384 1382 { 1385 1383 uint ttMin = gContext->GetNumSetting("EITTransportTimeout", 5); … … 1388 1386 SetFlags(kFlagEITScannerRunning); 1389 1387 eitScanStartTime = QDateTime::currentDateTime().addYears(1); 1390 1388 } 1389 */ 1391 1390 } 1392 1391 1393 1392 // We should be no more than a few thousand milliseconds, … … 3149 3148 VERBOSE(VB_RECORD, LOC + "SetChannel()" + " -- end"); 3150 3149 } 3151 3150 3151 /** \fn TVRec::StartEITScan(QString) 3152 * \brief Starts EIT scanning on the named channel and the current tuner. 3153 * 3154 * \param name channum of channel to scan on 3155 */ 3156 bool TVRec::StartEITScan(QString name) 3157 { 3158 // initialize eit scanner if needed 3159 if (!scanner && eitcache) 3160 scanner = new EITScanner(eitcache); 3161 3162 // Is this enough to guard against channel changes while recording? 3163 if (QDateTime::currentDateTime() > eitScanStartTime) 3164 { 3165 SetChannel(name, kFlagEITScan); 3166 //TODO: check for successful tuning 3167 return true; 3168 } 3169 VERBOSE(VB_EIT, LOC + QString("Now: %1 - start scan only after: %2") 3170 .arg(QDateTime::currentDateTime().toString()) 3171 .arg(eitScanStartTime.toString())); 3172 3173 return false; 3174 } 3175 3152 3176 /** \fn TVRec::GetNextProgram(int,QString&,QString&,QString&,QString&,QString&,QString&,QString&,QString&,QString&,QString&,QString&,QString&) 3153 3177 * \brief Returns information about the program that would be seen if we changed 3154 3178 * the channel using ChangeChannel(int) with "direction". … … 3540 3564 3541 3565 if (!(request.flags & kFlagEITScan) && HasFlags(kFlagEITScannerRunning)) 3542 3566 { 3543 scanner->Stop ActiveScan();3567 scanner->StopPassiveScan(); 3544 3568 ClearFlags(kFlagEITScannerRunning); 3545 3569 } 3546 3570 -
libs/libmythtv/eitscanner.cpp
=== libs/libmythtv/eitscanner.cpp ==================================================================
25 25 QDateTime EITScanner::resched_next_time = QDateTime::currentDateTime(); 26 26 const uint EITScanner::kMinRescheduleInterval = 150; 27 27 28 EITScanner::EITScanner( )29 : channel(NULL), eitSource(NULL), eitHelper(new EITHelper( )),28 EITScanner::EITScanner(EITCache *cache) 29 : channel(NULL), eitSource(NULL), eitHelper(new EITHelper(cache)), 30 30 exitThread(false), rec(NULL), activeScan(false) 31 31 { 32 32 QStringList langPref = iso639_get_language_list(); … … 41 41 42 42 void EITScanner::TeardownAll(void) 43 43 { 44 Stop ActiveScan();44 StopPassiveScan(); 45 45 if (!exitThread) 46 46 { 47 47 exitThread = true; … … 114 114 RescheduleRecordings(); 115 115 } 116 116 117 #if 0 117 118 if (activeScan && (QDateTime::currentDateTime() > activeScanNextTrig)) 118 119 { 119 120 // if there have been any new events, tell scheduler to run. … … 140 141 .addSecs(activeScanTrigTime); 141 142 activeScanNextChan++; 142 143 } 144 #endif 143 145 144 146 exitThreadCond.wait(200); // sleep up to 200 ms. 145 147 } … … 209 211 eitHelper->SetSourceID(0); 210 212 } 211 213 214 #if 0 212 215 void EITScanner::StartActiveScan(TVRec *_rec, uint max_seconds_per_source, 213 216 bool _ignore_source) 214 217 { … … 272 275 rec = NULL; 273 276 StopPassiveScan(); 274 277 } 278 #endif -
libs/libmythtv/tv_rec.h
=== libs/libmythtv/tv_rec.h ==================================================================
20 20 class QSocket; 21 21 class NuppelVideoRecorder; 22 22 class RingBuffer; 23 class EITCache; 23 24 class EITScanner; 24 25 class DVBSIParser; 25 26 class DummyDTVRecorder; … … 221 222 { SetChannel(QString("NextChannel %1").arg((int)dir)); } 222 223 void SetChannel(QString name, uint requestType = kFlagDetect); 223 224 225 bool StartEITScan(QString name); 226 224 227 int SetSignalMonitoringRate(int msec, int notifyFrontend = 1); 225 228 int ChangeColour(bool direction); 226 229 int ChangeContrast(bool direction); … … 254 257 void DVBGotPMT(void) 255 258 { QMutexLocker lock(&stateChangeLock); triggerEventLoop.wakeAll(); } 256 259 260 void SetEITCache(EITCache *cache) { eitcache = cache; } 261 257 262 public slots: 258 263 void SignalMonitorAllGood() { triggerEventLoop.wakeAll(); } 259 264 void deleteLater(void); … … 340 345 RecorderBase *recorder; 341 346 ChannelBase *channel; 342 347 SignalMonitor *signalMonitor; 348 EITCache *eitcache; 343 349 EITScanner *scanner; 344 350 DVBSIParser *dvbsiparser; 345 351 DummyDTVRecorder *dummyRecorder; -
libs/libmyth/mythcontext.h
=== libs/libmyth/mythcontext.h ==================================================================
229 229 * You must also update this value in 230 230 * mythplugins/mythweb/includes/mythbackend.php 231 231 */ 232 #define MYTH_PROTO_VERSION " 29"232 #define MYTH_PROTO_VERSION "30" 233 233 234 234 /** \class MythContext 235 235 * \brief This class contains the runtime context for MythTV. -
programs/mythbackend/encoderlink.h
=== programs/mythbackend/encoderlink.h ==================================================================
82 82 void ToggleChannelFavorite(void); 83 83 void ChangeChannel(int channeldirection); 84 84 void SetChannel(const QString &name); 85 bool StartEITScan(const QString chanid); 85 86 int ChangeContrast(bool direction); 86 87 int ChangeBrightness(bool direction); 87 88 int ChangeColour(bool direction); -
programs/mythbackend/playbacksock.cpp
=== programs/mythbackend/playbacksock.cpp ==================================================================
285 285 int ret = strlist[0].toInt(); 286 286 return ret; 287 287 } 288 289 bool PlaybackSock::StartEITScan(int capturecardnum, QString chanid) 290 { 291 QStringList strlist = QString("QUERY_REMOTEENCODER %1").arg(capturecardnum); 292 strlist << "START_EIT_SCAN"; 293 strlist << chanid; 294 295 SendReceiveStringList(strlist); 296 297 bool ret = strlist[0].toInt(); 298 return ret; 299 } 300 -
programs/mythbackend/mythbackend.pro
=== programs/mythbackend/mythbackend.pro ==================================================================
13 13 14 14 # Input 15 15 HEADERS += autoexpire.h encoderlink.h filetransfer.h httpstatus.h mainserver.h 16 HEADERS += playbacksock.h scheduler.h server.h housekeeper.h 16 HEADERS += playbacksock.h scheduler.h server.h housekeeper.h eitactivescanner.h 17 17 18 18 SOURCES += autoexpire.cpp encoderlink.cpp filetransfer.cpp httpstatus.cpp 19 19 SOURCES += main.cpp mainserver.cpp playbacksock.cpp scheduler.cpp server.cpp 20 SOURCES += housekeeper.cpp 20 SOURCES += housekeeper.cpp eitactivescanner.cpp 21 21 22 22 using_oss:DEFINES += USING_OSS 23 23 -
programs/mythbackend/mainserver.cpp
=== programs/mythbackend/mainserver.cpp ==================================================================
2767 2767 info->ToStringList(retlist); 2768 2768 delete info; 2769 2769 } 2770 else if (command == "START_EIT_SCAN") 2771 { 2772 retlist << QString::number((int)enc->StartEITScan(slist[2])); 2773 } 2770 2774 2771 2775 SendResponse(pbssock, retlist); 2772 2776 } -
programs/mythbackend/playbacksock.h
=== programs/mythbackend/playbacksock.h ==================================================================
60 60 const ProgramInfo *pginfo); 61 61 void RecordPending(int capturecardnum, const ProgramInfo *pginfo, int secsleft); 62 62 int SetSignalMonitoringRate(int capturecardnum, int rate, int notifyFrontend); 63 bool StartEITScan(int capturecardnum, QString chanid); 63 64 64 65 private: 65 66 bool SendReceiveStringList(QStringList &strlist); -
programs/mythbackend/main.cpp
=== programs/mythbackend/main.cpp ==================================================================
26 26 #include "encoderlink.h" 27 27 #include "remoteutil.h" 28 28 #include "housekeeper.h" 29 #include "eitactivescanner.h" 29 30 30 31 #include "libmyth/mythcontext.h" 31 32 #include "libmyth/mythdbcon.h" … … 42 43 QString lockfile_location; 43 44 HouseKeeper *housekeeping = NULL; 44 45 QString logfile = ""; 46 EITActiveScanner *eitscanner = NULL; 45 47 46 48 bool setupTVs(bool ismaster, bool &error) 47 49 { … … 595 597 else 596 598 jobqueue = new JobQueue(ismaster); 597 599 600 eitscanner = new EITActiveScanner(ismaster, &tvList); 598 601 VERBOSE(VB_IMPORTANT, QString("%1 version: %2 www.mythtv.org") 599 602 .arg(binname).arg(MYTH_BINARY_VERSION)); 600 603 -
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 14 EITActiveScanner::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 /* 21 void 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 */ 36 void *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 */ 46 void 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 while (!exitThread) 63 { 64 QDateTime now = QDateTime::currentDateTime(); 65 66 if (ismaster && (now > nextTriggerTime) && !cardList->isEmpty()) 67 { 68 VERBOSE(VB_EIT, eitCache->GetStatistics()); 69 if (nextCard == cardsSources.end()) 70 { 71 nextCard = cardsSources.begin(); 72 } 73 74 // find source with the highest priority 75 vector<uint>::iterator source = sources.begin(); 76 while (source != sources.end()) 77 { 78 if ((*nextCard).end() != find((*nextCard).begin(), 79 (*nextCard).end(), *source)) 80 break; 81 ++source; 82 } 83 if (source == sources.end()) 84 { 85 VERBOSE(VB_EIT, QString("Couldn't find source for card %1.") 86 .arg(nextCard.key())); 87 continue; 88 } 89 uint sid = *source; 90 int cardid = nextCard.key(); 91 92 93 if (!(*(nextChan[sid])).isEmpty() && 94 (*cardList)[cardid]->StartEITScan(*(nextChan[sid]))) 95 { 96 VERBOSE(VB_GENERAL, QString("DVB(%1): Now looking for EIT " 97 "data on multiplex of channel %2 " 98 "of source %3") 99 .arg(cardid).arg(*(nextChan[sid])).arg(sid)); 100 /* advace to the next channel and test for valid iterator. 101 needed to simplify selection of the source 102 with the highest priority. */ 103 nextChan[sid]++; 104 if (nextChan[sid] == channels[sid].end()) 105 { 106 nextChan[sid] = channels[sid].begin(); 107 sources.erase(source); 108 sources.push_back(sid); 109 //cerr << "Moved source " << sid << " to the back of the queue." << endl; 110 } 111 } 112 else 113 { 114 VERBOSE(VB_GENERAL, QString("Skipping card %1 in scan for EIT " 115 "data on multiplex of channel %2 " 116 "of source %3") 117 .arg(cardid).arg(*(nextChan[sid])).arg(sid)); 118 } 119 120 nextTriggerTime = QDateTime::currentDateTime().addSecs(triggerTime); 121 122 nextCard++; 123 } 124 125 // prune cache entries that ended more than kPruneCacheTimeOffset ago 126 if (now > nextPruneCacheTime) 127 { 128 uint prunedEntries = eitCache->PruneOldEntries(now 129 .addSecs(-kPruneCacheTimeOffset).toTime_t()); 130 nextPruneCacheTime = QDateTime::currentDateTime() 131 .addSecs(kPruneCacheTimeOffset); 132 133 VERBOSE(VB_EIT, eitCache->GetStatistics()); 134 VERBOSE(VB_EIT, QString("Pruned %1 entries from the eit cache") 135 .arg(prunedEntries)); 136 } 137 138 exitThreadCond.wait(1000); // sleep up to 1 second. 139 } 140 } 141 142 void EITActiveScanner::StartActiveScan() 143 { 144 if (!sources.size()) 145 { 146 // get all source ids with useeit == 1 147 MSqlQuery query(MSqlQuery::InitCon()); 148 query.prepare( 149 "SELECT DISTINCT channel.sourceid " 150 "FROM channel, videosource " 151 "WHERE videosource.sourceid = channel.sourceid AND " 152 " channel.mplexid IS NOT NULL AND " 153 " useonairguide = 1 AND " 154 " useeit = 1 " 155 "GROUP BY mplexid " 156 "ORDER BY channel.sourceid, atscsrcid, mplexid"); 157 158 if (!query.exec() || !query.isActive()) 159 { 160 MythContext::DBError("EITActiveScanner::StartActiveScan", query); 161 return; 162 } 163 164 while (query.next()) 165 sources.push_back(query.value(0).toUInt()); 166 167 // getting mapping from cardid to sourceid with useeit == 1 168 query.prepare( 169 "SELECT cardid, videosource.sourceid " 170 "FROM videosource,cardinput " 171 "WHERE videosource.sourceid = cardinput.sourceid AND " 172 " useeit = 1 " 173 "ORDER BY cardid"); 174 175 if (!query.exec() || !query.isActive()) 176 { 177 MythContext::DBError("EITActiveScanner::StartActiveScan", query); 178 return; 179 } 180 181 while (query.next()) 182 cardsSources[query.value(0).toInt()] 183 .push_back(query.value(1).toUInt()); 184 185 186 // get one channel with sourceid per mplexid 187 query.prepare( 188 "SELECT channel.sourceid, min(channum) " 189 "FROM channel, videosource " 190 "WHERE videosource.sourceid = channel.sourceid AND " 191 " channel.mplexid IS NOT NULL AND " 192 " useonairguide = 1 AND " 193 " useeit = 1 AND " 194 " channum != '' " 195 "GROUP BY mplexid " 196 "ORDER BY channel.sourceid, atscsrcid, mplexid"); 197 198 if (!query.exec() || !query.isActive()) 199 { 200 MythContext::DBError("EITScanner::StartActiveScan", query); 201 return; 202 } 203 204 while (query.next()) 205 { 206 VERBOSE(VB_EIT,QString("Adding channel %1 for source %2 " 207 "to scan list") 208 .arg(query.value(0).toString()) 209 .arg(query.value(1).toUInt())); 210 channels[query.value(0).toUInt()] 211 .push_back(query.value(1).toString()); 212 } 213 } 214 int number = 0; 215 for (vector<uint>::iterator it = sources.begin(); it != sources.end(); ++it) 216 { 217 nextChan[*it] = channels[*it].begin(); 218 number += channels[*it].size(); 219 } 220 221 VERBOSE(VB_EIT, 222 QString("StartActiveScan called with %1 multiplexes on %2 sources") 223 .arg(number).arg(sources.size())); 224 225 if (sources.size()) 226 { 227 uint scantime = gContext->GetNumSetting("EITTransportTimeout", 5) * 60; 228 uint idle_start = gContext->GetNumSetting("EITCrawIdleStart", 60); 229 230 nextTriggerTime = QDateTime::currentDateTime().addSecs(idle_start+5); 231 triggerTime = scantime / cardList->size(); 232 nextCard = cardsSources.begin(); 233 nextPruneCacheTime = QDateTime::currentDateTime() 234 .addSecs(kPruneCacheTimeOffset); 235 } 236 } -
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 21 class 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 nextTriggerTime; 41 uint triggerTime; 42 43 vector<uint> sources; 44 QMap<uint, QStringList> channels; 45 QMap<uint, QStringList::iterator> nextChan; 46 47 QMap<int, EncoderLink *> *cardList; 48 49 QMap<int, vector<uint> > cardsSources; 50 QMap<int, vector<uint> >::iterator nextCard; 51 52 bool ismaster; 53 54 QDateTime nextPruneCacheTime; 55 56 static const int kPruneCacheTimeOffset = 21600; // six hours 57 }; 58 59 #endif //EITACTIVESCANNER_H -
programs/mythbackend/encoderlink.cpp
Property changes on: programs/mythbackend/eitactivescanner.h ___________________________________________________________________ Name: svn:mime-type +text/cpp === programs/mythbackend/encoderlink.cpp ==================================================================
199 199 return retval; 200 200 } 201 201 202 /** \fn EncoderLink::StartEITScan(const QString) 203 * \brief Tells TVRec to scan for EIT on channel chanid. 204 * \param chanid Channel to scan 205 */ 206 bool EncoderLink::StartEITScan(const QString chanid) 207 { 208 if (local) 209 return tv->StartEITScan(chanid); 210 else if (sock) 211 { 212 return sock->StartEITScan(m_capturecardnum, chanid); 213 } 214 } 215 216 202 217 /** \fn EncoderLink::RecordPending(const ProgramInfo*, int) 203 218 * \brief Tells TVRec there is a pending recording "rec" in "secsleft" seconds. 204 219 * \param rec Recording to make.