00001 #include <unistd.h>
00002
00003 #include "dtvchannel.h"
00004 #include "dvbchannel.h"
00005 #include "dtvsignalmonitor.h"
00006 #include "scanstreamdata.h"
00007 #include "mpegtables.h"
00008 #include "atsctables.h"
00009 #include "dvbtables.h"
00010 #include "compat.h"
00011
00012 #undef DBG_SM
00013 #define DBG_SM(FUNC, MSG) VERBOSE(VB_CHANNEL, \
00014 "DTVSM("<<channel->GetDevice()<<")::"<<FUNC<<": "<<MSG);
00015
00016 #define LOC QString("DTVSM(%1): ").arg(channel->GetDevice())
00017 #define LOC_ERR QString("DTVSM(%1) Error: ").arg(channel->GetDevice())
00018
00023 DTVSignalMonitor::DTVSignalMonitor(int db_cardnum,
00024 DTVChannel *_channel,
00025 uint64_t wait_for_mask,
00026 const char *name)
00027 : SignalMonitor(db_cardnum, _channel, wait_for_mask, name),
00028 stream_data(NULL),
00029 seenPAT(tr("Seen")+" PAT", "seen_pat", 1, true, 0, 1, 0),
00030 seenPMT(tr("Seen")+" PMT", "seen_pmt", 1, true, 0, 1, 0),
00031 seenMGT(tr("Seen")+" MGT", "seen_mgt", 1, true, 0, 1, 0),
00032 seenVCT(tr("Seen")+" VCT", "seen_vct", 1, true, 0, 1, 0),
00033 seenNIT(tr("Seen")+" NIT", "seen_nit", 1, true, 0, 1, 0),
00034 seenSDT(tr("Seen")+" SDT", "seen_sdt", 1, true, 0, 1, 0),
00035 seenCrypt(tr("Seen")+" Crypt", "seen_crypt", 1, true, 0, 1, 0),
00036 matchingPAT(tr("Matching")+" PAT", "matching_pat", 1, true, 0, 1, 0),
00037 matchingPMT(tr("Matching")+" PMT", "matching_pmt", 1, true, 0, 1, 0),
00038 matchingMGT(tr("Matching")+" MGT", "matching_mgt", 1, true, 0, 1, 0),
00039 matchingVCT(tr("Matching")+" VCT", "matching_vct", 1, true, 0, 1, 0),
00040 matchingNIT(tr("Matching")+" NIT", "matching_nit", 1, true, 0, 1, 0),
00041 matchingSDT(tr("Matching")+" SDT", "matching_sdt", 1, true, 0, 1, 0),
00042 matchingCrypt(tr("Matching")+" Crypt", "matching_crypt",
00043 1, true, 0, 1, 0),
00044 majorChannel(-1), minorChannel(-1),
00045 networkID(0), transportID(0),
00046 detectedNetworkID(0), detectedTransportID(0),
00047 programNumber(-1),
00048 last_pat_crc(-1),
00049 error(""),
00050 ignore_encrypted(false)
00051 {
00052 }
00053
00054 DTVSignalMonitor::~DTVSignalMonitor()
00055 {
00056 SetStreamData(NULL);
00057 }
00058
00059 void DTVSignalMonitor::deleteLater(void)
00060 {
00061 SetStreamData(NULL);
00062 SignalMonitor::deleteLater();
00063 }
00064
00065 DTVChannel *DTVSignalMonitor::GetDTVChannel(void)
00066 {
00067 return dynamic_cast<DTVChannel*>(channel);
00068 }
00069
00070 QStringList DTVSignalMonitor::GetStatusList(bool kick)
00071 {
00072 QStringList list = SignalMonitor::GetStatusList(kick);
00073 QMutexLocker locker(&statusLock);
00074
00075 if (flags & kDTVSigMon_WaitForPAT)
00076 {
00077 list<<seenPAT.GetName()<<seenPAT.GetStatus();
00078 list<<matchingPAT.GetName()<<matchingPAT.GetStatus();
00079 }
00080 if (flags & kDTVSigMon_WaitForPMT)
00081 {
00082 #define DEBUG_PMT 1
00083 #if DEBUG_PMT
00084 static int seenGood = -1;
00085 static int matchingGood = -1;
00086 #endif
00087 list<<seenPMT.GetName()<<seenPMT.GetStatus();
00088 list<<matchingPMT.GetName()<<matchingPMT.GetStatus();
00089 #if DEBUG_PMT
00090 if ((seenGood != (int)seenPMT.IsGood()) ||
00091 (matchingGood != (int)matchingPMT.IsGood()))
00092 {
00093 DBG_SM("GetStatusList", "WaitForPMT seen("<<seenPMT.IsGood()
00094 <<") matching("<<matchingPMT.IsGood()<<")");
00095 seenGood = (int)seenPMT.IsGood();
00096 matchingGood = (int)matchingPMT.IsGood();
00097 }
00098 #endif
00099 }
00100
00101 if (flags & kDTVSigMon_WaitForMGT)
00102 {
00103 list<<seenMGT.GetName()<<seenMGT.GetStatus();
00104 list<<matchingMGT.GetName()<<matchingMGT.GetStatus();
00105 }
00106 if (flags & kDTVSigMon_WaitForVCT)
00107 {
00108 list<<seenVCT.GetName()<<seenVCT.GetStatus();
00109 list<<matchingVCT.GetName()<<matchingVCT.GetStatus();
00110 }
00111
00112 if (flags & kDTVSigMon_WaitForNIT)
00113 {
00114 list<<seenNIT.GetName()<<seenNIT.GetStatus();
00115 list<<matchingNIT.GetName()<<matchingNIT.GetStatus();
00116 }
00117 if (flags & kDTVSigMon_WaitForSDT)
00118 {
00119 list<<seenSDT.GetName()<<seenSDT.GetStatus();
00120 list<<matchingSDT.GetName()<<matchingSDT.GetStatus();
00121 }
00122 if (flags & kDTVSigMon_WaitForCrypt)
00123 {
00124 list<<seenCrypt.GetName()<<seenCrypt.GetStatus();
00125 list<<matchingCrypt.GetName()<<matchingCrypt.GetStatus();
00126 }
00127 if (error != "")
00128 {
00129 list<<"error"<<error;
00130 }
00131 return list;
00132 }
00133
00134 void DTVSignalMonitor::AddFlags(uint64_t _flags)
00135 {
00136 SignalMonitor::AddFlags(_flags);
00137 UpdateMonitorValues();
00138 }
00139
00140 void DTVSignalMonitor::RemoveFlags(uint64_t _flags)
00141 {
00142 SignalMonitor::RemoveFlags(_flags);
00143 UpdateMonitorValues();
00144 }
00145
00146 void DTVSignalMonitor::UpdateMonitorValues(void)
00147 {
00148 QMutexLocker locker(&statusLock);
00149 seenPAT.SetValue( (flags & kDTVSigMon_PATSeen) ? 1 : 0);
00150 seenPMT.SetValue( (flags & kDTVSigMon_PMTSeen) ? 1 : 0);
00151 seenMGT.SetValue( (flags & kDTVSigMon_MGTSeen) ? 1 : 0);
00152 seenVCT.SetValue( (flags & kDTVSigMon_VCTSeen) ? 1 : 0);
00153 seenNIT.SetValue( (flags & kDTVSigMon_NITSeen) ? 1 : 0);
00154 seenSDT.SetValue( (flags & kDTVSigMon_SDTSeen) ? 1 : 0);
00155 seenCrypt.SetValue( (flags & kDTVSigMon_CryptSeen)? 1 : 0);
00156 matchingPAT.SetValue((flags & kDTVSigMon_PATMatch) ? 1 : 0);
00157 matchingPMT.SetValue((flags & kDTVSigMon_PMTMatch) ? 1 : 0);
00158 matchingMGT.SetValue((flags & kDTVSigMon_MGTMatch) ? 1 : 0);
00159 matchingVCT.SetValue((flags & kDTVSigMon_VCTMatch) ? 1 : 0);
00160 matchingNIT.SetValue((flags & kDTVSigMon_NITMatch) ? 1 : 0);
00161 matchingSDT.SetValue((flags & kDTVSigMon_SDTMatch) ? 1 : 0);
00162 matchingCrypt.SetValue((flags & kDTVSigMon_CryptMatch) ? 1 : 0);
00163 }
00164
00165 void DTVSignalMonitor::UpdateListeningForEIT(void)
00166 {
00167 vector<uint> add_eit, del_eit;
00168
00169 if (GetStreamData()->HasEITPIDChanges(eit_pids) &&
00170 GetStreamData()->GetEITPIDChanges(eit_pids, add_eit, del_eit))
00171 {
00172 for (uint i = 0; i < del_eit.size(); i++)
00173 {
00174 uint_vec_t::iterator it;
00175 it = find(eit_pids.begin(), eit_pids.end(), del_eit[i]);
00176 if (it != eit_pids.end())
00177 eit_pids.erase(it);
00178 GetStreamData()->RemoveListeningPID(del_eit[i]);
00179 }
00180
00181 for (uint i = 0; i < add_eit.size(); i++)
00182 {
00183 eit_pids.push_back(add_eit[i]);
00184 GetStreamData()->AddListeningPID(add_eit[i]);
00185 }
00186 }
00187 }
00188
00189 void DTVSignalMonitor::SetChannel(int major, int minor)
00190 {
00191 DBG_SM(QString("SetChannel(%1, %2)").arg(major).arg(minor), "");
00192 last_pat_crc = -1;
00193 if (GetATSCStreamData() && (majorChannel != major || minorChannel != minor))
00194 {
00195 RemoveFlags(kDTVSigMon_PATSeen | kDTVSigMon_PATMatch |
00196 kDTVSigMon_PMTSeen | kDTVSigMon_PMTMatch |
00197 kDTVSigMon_VCTSeen | kDTVSigMon_VCTMatch |
00198 kDTVSigMon_CryptSeen | kDTVSigMon_CryptMatch);
00199 majorChannel = major;
00200 minorChannel = minor;
00201 GetATSCStreamData()->SetDesiredChannel(major, minor);
00202 AddFlags(kDTVSigMon_WaitForVCT | kDTVSigMon_WaitForPAT);
00203 }
00204 }
00205
00206 void DTVSignalMonitor::SetProgramNumber(int progNum)
00207 {
00208 DBG_SM(QString("SetProgramNumber(%1)").arg(progNum), "");
00209 last_pat_crc = -1;
00210 if (programNumber != progNum)
00211 {
00212 RemoveFlags(kDTVSigMon_PMTSeen | kDTVSigMon_PMTMatch |
00213 kDTVSigMon_CryptSeen | kDTVSigMon_CryptMatch);
00214 programNumber = progNum;
00215 if (GetStreamData())
00216 GetStreamData()->SetDesiredProgram(programNumber);
00217 AddFlags(kDTVSigMon_WaitForPMT);
00218 }
00219 }
00220
00221 void DTVSignalMonitor::SetDVBService(uint netid, uint tsid, int serviceid)
00222 {
00223 DBG_SM(QString("SetDVBService(transport_id: %1, network_id: %2, "
00224 "service_id: %3)").arg(tsid).arg(netid).arg(serviceid), "");
00225 last_pat_crc = -1;
00226
00227 if (netid == networkID && tsid == transportID &&
00228 serviceid == programNumber)
00229 {
00230 return;
00231 }
00232
00233 RemoveFlags(kDTVSigMon_PMTSeen | kDTVSigMon_PMTMatch |
00234 kDTVSigMon_SDTSeen | kDTVSigMon_SDTMatch |
00235 kDTVSigMon_CryptSeen | kDTVSigMon_CryptMatch);
00236
00237 transportID = tsid;
00238 networkID = netid;
00239 programNumber = serviceid;
00240
00241 if (GetDVBStreamData())
00242 {
00243 GetDVBStreamData()->SetDesiredService(netid, tsid, programNumber);
00244 AddFlags(kDTVSigMon_WaitForPMT | kDTVSigMon_WaitForSDT);
00245 GetDVBStreamData()->AddListeningPID(DVB_SDT_PID);
00246 }
00247 }
00248
00249 void DTVSignalMonitor::SetStreamData(MPEGStreamData *data)
00250 {
00251 if (stream_data)
00252 stream_data->RemoveMPEGListener(this);
00253
00254 ATSCStreamData *atsc = GetATSCStreamData();
00255 DVBStreamData *dvb = GetDVBStreamData();
00256 if (atsc)
00257 {
00258 atsc->RemoveATSCMainListener(this);
00259 atsc->RemoveATSCAuxListener(this);
00260 }
00261 if (dvb)
00262 dvb->RemoveDVBMainListener(this);
00263
00264 stream_data = data;
00265 if (!data)
00266 return;
00267
00268 data->AddMPEGListener(this);
00269
00270 atsc = GetATSCStreamData();
00271 dvb = GetDVBStreamData();
00272 if (atsc)
00273 {
00274 atsc->AddATSCMainListener(this);
00275 atsc->AddATSCAuxListener(this);
00276 }
00277 if (dvb)
00278 dvb->AddDVBMainListener(this);
00279 }
00280
00281
00282 void DTVSignalMonitor::HandlePAT(const ProgramAssociationTable *pat)
00283 {
00284 AddFlags(kDTVSigMon_PATSeen);
00285 int pmt_pid = pat->FindPID(programNumber);
00286 if (GetStreamData() && pmt_pid)
00287 {
00288 AddFlags(kDTVSigMon_PATMatch);
00289 GetStreamData()->AddListeningPID(pmt_pid);
00290 last_pat_crc = pat->CRC();
00291 return;
00292 }
00293
00294 if (programNumber >= 0)
00295 {
00296
00297
00298
00299
00300 uint tsid = pat->TransportStreamID();
00301 GetStreamData()->SetVersionPAT(tsid, -1,0);
00302
00303
00304 if (last_pat_crc != pat->CRC())
00305 {
00306 last_pat_crc = pat->CRC();
00307 QString errStr = QString("Program #%1 not found in PAT!")
00308 .arg(programNumber);
00309 VERBOSE(VB_IMPORTANT, errStr<<endl<<pat->toString());
00310 }
00311 if (pat->ProgramCount() == 1)
00312 {
00313 VERBOSE(VB_IMPORTANT, "But there is only one program "
00314 "in the PAT, so we'll just use it");
00315 SetProgramNumber(pat->ProgramNumber(0));
00316 AddFlags(kDTVSigMon_PATMatch);
00317 GetStreamData()->AddListeningPID(pat->ProgramPID(0));
00318 last_pat_crc = pat->CRC();
00319 }
00320 }
00321 }
00322
00323 void DTVSignalMonitor::HandlePMT(uint, const ProgramMapTable *pmt)
00324 {
00325 AddFlags(kDTVSigMon_PMTSeen);
00326
00327 if (programNumber < 0)
00328 return;
00329
00330 if (pmt->ProgramNumber() != (uint)programNumber)
00331 {
00332 VERBOSE(VB_IMPORTANT, LOC_ERR +
00333 QString("Wrong PMT; pmt->pn(%1) desired(%2)")
00334 .arg(pmt->ProgramNumber()).arg(programNumber));
00335 return;
00336 }
00337
00338 if (pmt->IsEncrypted())
00339 GetStreamData()->TestDecryption(pmt);
00340
00341
00342 uint hasAudio = 0;
00343 uint hasVideo = 0;
00344
00345 for (uint i = 0; i < pmt->StreamCount(); i++)
00346 {
00347 hasVideo += pmt->IsVideo(i, GetDTVChannel()->GetSIStandard());
00348 hasAudio += pmt->IsAudio(i, GetDTVChannel()->GetSIStandard());
00349 }
00350
00351 if ((hasVideo >= GetStreamData()->GetVideoStreamsRequired()) &&
00352 (hasAudio >= GetStreamData()->GetAudioStreamsRequired()))
00353 {
00354 if (pmt->IsEncrypted() && !ignore_encrypted)
00355 AddFlags(kDTVSigMon_WaitForCrypt);
00356
00357 AddFlags(kDTVSigMon_PMTMatch);
00358 }
00359 else
00360 {
00361 VERBOSE(VB_IMPORTANT, LOC_ERR +
00362 QString("We want %1 audio and %2 video streams")
00363 .arg(GetStreamData()->GetAudioStreamsRequired())
00364 .arg(GetStreamData()->GetVideoStreamsRequired()) +
00365 QString("\n\t\t\tBut have %1 audio and %2 video streams")
00366 .arg(hasAudio).arg(hasVideo));
00367 }
00368 }
00369
00370 void DTVSignalMonitor::HandleSTT(const SystemTimeTable*)
00371 {
00372 VERBOSE(VB_CHANNEL, LOC + "Time Offset: "<<GetStreamData()->TimeOffset());
00373 }
00374
00375 void DTVSignalMonitor::HandleMGT(const MasterGuideTable* mgt)
00376 {
00377 AddFlags(kDTVSigMon_MGTSeen);
00378
00379 if (!GetATSCStreamData())
00380 return;
00381
00382 for (uint i=0; i<mgt->TableCount(); i++)
00383 {
00384 if ((TableClass::TVCTc == mgt->TableClass(i)) ||
00385 (TableClass::CVCTc == mgt->TableClass(i)))
00386 {
00387 GetATSCStreamData()->AddListeningPID(mgt->TablePID(i));
00388 AddFlags(kDTVSigMon_MGTMatch);
00389 }
00390 }
00391 }
00392
00393 void DTVSignalMonitor::HandleTVCT(
00394 uint, const TerrestrialVirtualChannelTable* tvct)
00395 {
00396 AddFlags(kDTVSigMon_VCTSeen | kDTVSigMon_TVCTSeen);
00397 int idx = tvct->Find(majorChannel, minorChannel);
00398
00399 if (minorChannel < 0)
00400 return;
00401
00402 if (idx < 0)
00403 {
00404 VERBOSE(VB_IMPORTANT, "Could not find channel "
00405 <<majorChannel<<"_"<<minorChannel<<" in TVCT");
00406 VERBOSE(VB_IMPORTANT, endl<<tvct->toString());
00407 GetATSCStreamData()->SetVersionTVCT(tvct->TransportStreamID(),-1);
00408 return;
00409 }
00410
00411 DBG_SM("SetVCT()", QString("tvct->ProgramNumber(idx %1): prog num %2")
00412 .arg(idx).arg(tvct->ProgramNumber(idx)));
00413
00414 SetProgramNumber(tvct->ProgramNumber(idx));
00415 AddFlags(kDTVSigMon_VCTMatch | kDTVSigMon_TVCTMatch);
00416 }
00417
00418 void DTVSignalMonitor::HandleCVCT(uint, const CableVirtualChannelTable* cvct)
00419 {
00420 AddFlags(kDTVSigMon_VCTSeen | kDTVSigMon_CVCTSeen);
00421 int idx = cvct->Find(majorChannel, minorChannel);
00422
00423 if (idx < 0)
00424 {
00425 VERBOSE(VB_IMPORTANT, "Could not find channel "
00426 <<majorChannel<<"_"<<minorChannel<<" in CVCT");
00427 VERBOSE(VB_IMPORTANT, endl<<cvct->toString());
00428 GetATSCStreamData()->SetVersionCVCT(cvct->TransportStreamID(),-1);
00429 return;
00430 }
00431
00432 DBG_SM("SetVCT()", QString("cvct->ProgramNumber(idx %1): prog num %2")
00433 .arg(idx).arg(cvct->ProgramNumber(idx)));
00434
00435 SetProgramNumber(cvct->ProgramNumber(idx));
00436 AddFlags(kDTVSigMon_VCTMatch | kDTVSigMon_CVCTMatch);
00437 }
00438
00439 void DTVSignalMonitor::HandleTDT(const TimeDateTable*)
00440 {
00441 VERBOSE(VB_CHANNEL, LOC + "Time Offset: "<<GetStreamData()->TimeOffset());
00442 }
00443
00444 void DTVSignalMonitor::HandleNIT(const NetworkInformationTable *nit)
00445 {
00446 DBG_SM("SetNIT()", QString("net_id = %1").arg(nit->NetworkID()));
00447 AddFlags(kDTVSigMon_NITSeen);
00448 if (!GetDVBStreamData())
00449 return;
00450 }
00451
00452 void DTVSignalMonitor::HandleSDT(uint, const ServiceDescriptionTable *sdt)
00453 {
00454 AddFlags(kDTVSigMon_SDTSeen);
00455
00456 detectedNetworkID = sdt->OriginalNetworkID();
00457 detectedTransportID = sdt->TSID();
00458
00459 if (sdt->OriginalNetworkID() != networkID || sdt->TSID() != transportID)
00460 {
00461 GetDVBStreamData()->SetVersionSDT(sdt->TSID(), -1, 0);
00462 }
00463 else
00464 {
00465 DBG_SM("SetSDT()", QString("tsid = %1 orig_net_id = %2")
00466 .arg(sdt->TSID()).arg(sdt->OriginalNetworkID()));
00467 AddFlags(kDTVSigMon_SDTMatch);
00468 RemoveFlags(kDVBSigMon_WaitForPos);
00469 }
00470 }
00471
00472 void DTVSignalMonitor::HandleEncryptionStatus(uint, bool enc_status)
00473 {
00474 AddFlags(kDTVSigMon_CryptSeen);
00475 if (!enc_status)
00476 AddFlags(kDTVSigMon_CryptMatch);
00477 }
00478
00479 ATSCStreamData *DTVSignalMonitor::GetATSCStreamData()
00480 {
00481 return dynamic_cast<ATSCStreamData*>(stream_data);
00482 }
00483
00484 DVBStreamData *DTVSignalMonitor::GetDVBStreamData()
00485 {
00486 return dynamic_cast<DVBStreamData*>(stream_data);
00487 }
00488
00489 ScanStreamData *DTVSignalMonitor::GetScanStreamData()
00490 {
00491 return dynamic_cast<ScanStreamData*>(stream_data);
00492 }
00493
00494 const ATSCStreamData *DTVSignalMonitor::GetATSCStreamData() const
00495 {
00496 return dynamic_cast<const ATSCStreamData*>(stream_data);
00497 }
00498
00499 const DVBStreamData *DTVSignalMonitor::GetDVBStreamData() const
00500 {
00501 return dynamic_cast<const DVBStreamData*>(stream_data);
00502 }
00503
00504 const ScanStreamData *DTVSignalMonitor::GetScanStreamData() const
00505 {
00506 return dynamic_cast<const ScanStreamData*>(stream_data);
00507 }
00508
00509 bool DTVSignalMonitor::IsAllGood(void) const
00510 {
00511 QMutexLocker locker(&statusLock);
00512 if (!SignalMonitor::IsAllGood())
00513 return false;
00514 if ((flags & kDTVSigMon_WaitForPAT) && !matchingPAT.IsGood())
00515 return false;
00516 if ((flags & kDTVSigMon_WaitForPMT) && !matchingPMT.IsGood())
00517 return false;
00518 if ((flags & kDTVSigMon_WaitForMGT) && !matchingMGT.IsGood())
00519 return false;
00520 if ((flags & kDTVSigMon_WaitForVCT) && !matchingVCT.IsGood())
00521 return false;
00522 if ((flags & kDTVSigMon_WaitForNIT) && !matchingNIT.IsGood())
00523 return false;
00524 if ((flags & kDTVSigMon_WaitForSDT) && !matchingSDT.IsGood())
00525 return false;
00526 if ((flags & kDTVSigMon_WaitForCrypt) && !matchingCrypt.IsGood())
00527 return false;
00528
00529 return true;
00530 }
00531
00541 bool DTVSignalMonitor::WaitForLock(int timeout)
00542 {
00543 statusLock.lock();
00544 if (-1 == timeout)
00545 timeout = signalLock.GetTimeout();
00546 statusLock.unlock();
00547 if (timeout < 0)
00548 return false;
00549
00550 MythTimer t;
00551 t.start();
00552 while (t.elapsed()<timeout && running)
00553 {
00554 SignalMonitorList slist =
00555 SignalMonitorValue::Parse(GetStatusList());
00556 if (SignalMonitorValue::AllGood(slist))
00557 return true;
00558 usleep(250);
00559 }
00560
00561 return false;
00562 }