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)
|
| 133 | 133 | if (!(*activeScanNextChan).isEmpty()) |
| 134 | 134 | { |
| 135 | 135 | 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") |
| 140 | 141 | .arg(*activeScanNextChan)); |
| | 142 | } |
| 141 | 143 | } |
| 142 | 144 | |
| 143 | 145 | activeScanNextTrig = QDateTime::currentDateTime() |
| … |
… |
void EITScanner::StopPassiveScan(void)
|
| 216 | 218 | |
| 217 | 219 | eitHelper->WriteEITCache(); |
| 218 | 220 | eitHelper->SetSourceID(0); |
| | 221 | |
| | 222 | LOG(VB_EIT, LOG_INFO, LOC_ID + "Stopped passive scan."); |
| 219 | 223 | } |
| 220 | 224 | |
| 221 | 225 | void EITScanner::StartActiveScan(TVRec *_rec, uint max_seconds_per_source) |
| … |
… |
void EITScanner::StopActiveScan()
|
| 280 | 284 | activeScan = false; |
| 281 | 285 | rec = NULL; |
| 282 | 286 | StopPassiveScan(); |
| | 287 | |
| | 288 | LOG(VB_EIT, LOG_INFO, LOC_ID + "Stopped active scan."); |
| 283 | 289 | } |
diff --git a/mythtv/libs/libmythtv/tv_rec.cpp b/mythtv/libs/libmythtv/tv_rec.cpp
index 3d38c6d..9b53f5f 100644
|
a
|
b
|
|
| 36 | 36 | #include "tv_rec.h" |
| 37 | 37 | #include "mythmiscutil.h" |
| 38 | 38 | #include "osd.h" |
| | 39 | #include "cardutil.h" |
| 39 | 40 | |
| 40 | 41 | #define DEBUG_CHANNEL_PREFIX 0 /**< set to 1 to channel prefixing */ |
| 41 | 42 | |
| … |
… |
static QString load_profile(QString,void*,RecordingInfo*,RecordingProfile&);
|
| 52 | 53 | static int init_jobs(const RecordingInfo *rec, RecordingProfile &profile, |
| 53 | 54 | bool on_host, bool transcode_bfr_comm, bool on_line_comm); |
| 54 | 55 | static void apply_broken_dvb_driver_crc_hack(ChannelBase*, MPEGStreamData*); |
| 55 | | |
| | 56 | static int eit_start_rand(uint cardid, int eitTransportTimeout); |
| 56 | 57 | |
| 57 | 58 | /** \class TVRec |
| 58 | 59 | * \brief This is the coordinating class of the \ref recorder_subsystem. |
| … |
… |
bool TVRec::Init(void)
|
| 161 | 162 | gCoreContext->GetNumSetting("AutoTranscodeBeforeAutoCommflag", 0); |
| 162 | 163 | earlyCommFlag = gCoreContext->GetNumSetting("AutoCommflagWhileRecording", 0); |
| 163 | 164 | runJobOnHostOnly = gCoreContext->GetNumSetting("JobsRunOnRecordHost", 0); |
| 164 | | eitTransportTimeout=gCoreContext->GetNumSetting("EITTransportTimeout", 5) * 60; |
| | 165 | eitTransportTimeout = |
| | 166 | max(gCoreContext->GetNumSetting("EITTransportTimeout", 5) * 60, 6); |
| 165 | 167 | eitCrawlIdleStart = gCoreContext->GetNumSetting("EITCrawIdleStart", 60); |
| 166 | 168 | audioSampleRateDB = gCoreContext->GetNumSetting("AudioSampleRate"); |
| 167 | 169 | overRecordSecNrml = gCoreContext->GetNumSetting("RecordOverTime"); |
| … |
… |
void TVRec::HandleStateChange(void)
|
| 974 | 976 | |
| 975 | 977 | bool changed = false; |
| 976 | 978 | |
| | 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 | |
| 977 | 983 | QString transMsg = QString(" %1 to %2") |
| 978 | 984 | .arg(StateToString(nextState)) |
| 979 | 985 | .arg(StateToString(desiredNextState)); |
| … |
… |
void TVRec::HandleStateChange(void)
|
| 998 | 1004 | if (TRANSITION(kState_None, kState_WatchingLiveTV)) |
| 999 | 1005 | { |
| 1000 | 1006 | 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 | } |
| 1001 | 1016 | SET_NEXT(); |
| 1002 | 1017 | } |
| 1003 | 1018 | else if (TRANSITION(kState_WatchingLiveTV, kState_None)) |
| 1004 | 1019 | { |
| 1005 | 1020 | 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); |
| 1006 | 1047 | SET_NEXT(); |
| 1007 | 1048 | } |
| 1008 | 1049 | else if (TRANSITION(kState_WatchingLiveTV, kState_RecordingOnly)) |
| … |
… |
void TVRec::HandleStateChange(void)
|
| 1015 | 1058 | { |
| 1016 | 1059 | SetPseudoLiveTVRecording(NULL); |
| 1017 | 1060 | 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 | } |
| 1018 | 1070 | SET_NEXT(); |
| 1019 | 1071 | } |
| 1020 | 1072 | else if (TRANSITION(kState_RecordingOnly, kState_None)) |
| … |
… |
void TVRec::HandleStateChange(void)
|
| 1022 | 1074 | tuningRequests.enqueue( |
| 1023 | 1075 | TuningRequest(kFlagCloseRec|kFlagKillRingBuffer| |
| 1024 | 1076 | (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); |
| 1025 | 1103 | SET_NEXT(); |
| 1026 | 1104 | } |
| 1027 | 1105 | |
| … |
… |
void TVRec::HandleStateChange(void)
|
| 1034 | 1114 | |
| 1035 | 1115 | eitScanStartTime = QDateTime::currentDateTime(); |
| 1036 | 1116 | if (scanner && (internalState == kState_None)) |
| 1037 | | eitScanStartTime = eitScanStartTime.addSecs(eitCrawlIdleStart); |
| | 1117 | { |
| | 1118 | eitScanStartTime = eitScanStartTime.addSecs( |
| | 1119 | eitCrawlIdleStart + eit_start_rand(cardid, eitTransportTimeout)); |
| | 1120 | } |
| 1038 | 1121 | else |
| 1039 | 1122 | eitScanStartTime = eitScanStartTime.addYears(1); |
| 1040 | 1123 | } |
| … |
… |
void TVRec::CloseChannel(void)
|
| 1130 | 1213 | CardUtil::IsV4L(genOpt.cardtype))) |
| 1131 | 1214 | { |
| 1132 | 1215 | channel->Close(); |
| | 1216 | LOG(VB_GENERAL, LOG_INFO, LOC + QString("Close Card %1") |
| | 1217 | .arg(CardUtil::ProbeDVBFrontendName(CardUtil::GetVideoDevice(cardid))) ); |
| | 1218 | // GetDeviceLabel(cardid)) |
| 1133 | 1219 | } |
| 1134 | 1220 | } |
| 1135 | 1221 | |
| … |
… |
static int no_capturecards(uint cardid)
|
| 1213 | 1299 | return -1; |
| 1214 | 1300 | } |
| 1215 | 1301 | |
| | 1302 | static 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 | |
| 1216 | 1315 | /// \brief Event handling method, contains event loop. |
| 1217 | 1316 | void TVRec::run(void) |
| 1218 | 1317 | { |
| … |
… |
void TVRec::run(void)
|
| 1227 | 1326 | (dvbOpt.dvb_eitscan || get_use_eit(cardid))) |
| 1228 | 1327 | { |
| 1229 | 1328 | 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)); |
| 1241 | 1331 | } |
| 1242 | 1332 | else |
| 1243 | 1333 | eitScanStartTime = eitScanStartTime.addYears(1); |
| … |
… |
void TVRec::run(void)
|
| 1370 | 1460 | } |
| 1371 | 1461 | |
| 1372 | 1462 | if (scanner && channel && |
| 1373 | | QDateTime::currentDateTime() > eitScanStartTime) |
| | 1463 | QDateTime::currentDateTime() > eitScanStartTime && |
| | 1464 | !HasFlags(kFlagEITScanPaused)) |
| 1374 | 1465 | { |
| 1375 | 1466 | if (!dvbOpt.dvb_eitscan) |
| 1376 | 1467 | { |
| … |
… |
void TVRec::run(void)
|
| 1392 | 1483 | } |
| 1393 | 1484 | } |
| 1394 | 1485 | |
| | 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 | |
| 1395 | 1495 | // We should be no more than a few thousand milliseconds, |
| 1396 | 1496 | // as the end recording code does not have a trigger... |
| 1397 | 1497 | // NOTE: If you change anything here, make sure that |
| … |
… |
void TVRec::SetChannel(QString name, uint requestType)
|
| 3052 | 3152 | // Clear the RingBuffer reset flag, in case we wait for a reset below |
| 3053 | 3153 | ClearFlags(kFlagRingBufferReady); |
| 3054 | 3154 | |
| | 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 | |
| 3055 | 3165 | // Actually add the tuning request to the queue, and |
| 3056 | 3166 | // then wait for it to start tuning |
| 3057 | 3167 | tuningRequests.enqueue(TuningRequest(requestType, name)); |
| … |
… |
void TVRec::SetChannel(QString name, uint requestType)
|
| 3066 | 3176 | LOG(VB_CHANNEL, LOG_INFO, LOC + QString("SetChannel(%1) -- end").arg(name)); |
| 3067 | 3177 | } |
| 3068 | 3178 | |
| | 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 | */ |
| | 3186 | bool 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 | |
| 3069 | 3208 | void TVRec::GetNextProgram(BrowseDirection direction, |
| 3070 | 3209 | QString &title, QString &subtitle, |
| 3071 | 3210 | QString &desc, QString &category, |
| … |
… |
QString TVRec::FlagToString(uint f)
|
| 4204 | 4343 | msg += "Errored,"; |
| 4205 | 4344 | if (kFlagCancelNextRecording & f) |
| 4206 | 4345 | msg += "CancelNextRecording,"; |
| | 4346 | if (kFlagEITScanPaused & f) |
| | 4347 | msg += "EITScanPaused,"; |
| 4207 | 4348 | |
| 4208 | 4349 | // Tuning flags |
| 4209 | 4350 | if ((kFlagRec & f) == kFlagRec) |
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
|
| 156 | 156 | void FinishRecording(void) { SetFlags(kFlagFinishRecording); } |
| 157 | 157 | /// \brief Tells TVRec that the frontend's TV class is ready for messages. |
| 158 | 158 | void FrontendReady(void) { SetFlags(kFlagFrontendReady); } |
| | 159 | void PauseEITActiveScan(void) { SetFlags(kFlagEITScanPaused); } |
| | 160 | void RestartEITActiveScan(void) { ClearFlags(kFlagEITScanPaused); } |
| 159 | 161 | void CancelNextRecording(bool cancel); |
| 160 | 162 | ProgramInfo *GetRecording(void); |
| 161 | 163 | |
| … |
… |
class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable
|
| 198 | 200 | void ChangeChannel(ChannelChangeDirection dir) |
| 199 | 201 | { SetChannel(QString("NextChannel %1").arg((int)dir)); } |
| 200 | 202 | void SetChannel(QString name, uint requestType = kFlagDetect); |
| | 203 | bool QueueEITChannelChange(const QString &name); |
| 201 | 204 | |
| 202 | 205 | int SetSignalMonitoringRate(int msec, int notifyFrontend = 1); |
| 203 | 206 | int GetPictureAttribute(PictureAttribute attr); |
| … |
… |
class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable
|
| 409 | 412 | static const uint kFlagFinishRecording = 0x00000008; |
| 410 | 413 | static const uint kFlagErrored = 0x00000010; |
| 411 | 414 | static const uint kFlagCancelNextRecording = 0x00000020; |
| | 415 | static const uint kFlagEITScanPaused = 0x00000040; |
| 412 | 416 | |
| 413 | 417 | // Tuning flags |
| 414 | 418 | /// final result desired is LiveTV recording |
| … |
… |
class MTV_PUBLIC TVRec : public SignalMonitorListener, public QRunnable
|
| 432 | 436 | |
| 433 | 437 | // Waiting stuff |
| 434 | 438 | static const uint kFlagWaitingForRecPause = 0x00100000; |
| 435 | | static const uint kFlagWaitingForSignal = 0x00200000; |
| | 439 | static const uint kFlagWaitingForSignal = 0x00200000; |
| 436 | 440 | static const uint kFlagNeedToStartRecorder = 0x00800000; |
| 437 | 441 | static const uint kFlagPendingActions = 0x00F00000; |
| 438 | 442 | |
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)
|
| 192 | 192 | } |
| 193 | 193 | else |
| 194 | 194 | { |
| 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"); |
| 197 | 197 | delete tv; |
| 198 | 198 | } |
| 199 | 199 | } |