00001
00002
00003
00004 #include <cmath>
00005
00006 #include <algorithm>
00007 using namespace std;
00008
00009 #include "atscstreamdata.h"
00010 #include "atsctables.h"
00011 #include "sctetables.h"
00012 #include "ringbuffer.h"
00013 #include "eithelper.h"
00014
00015 #define LOC QString("ATSCStream: ")
00016
00032 ATSCStreamData::ATSCStreamData(int desiredMajorChannel,
00033 int desiredMinorChannel,
00034 bool cacheTables)
00035 : MPEGStreamData(-1, cacheTables),
00036 _GPS_UTC_offset(GPS_LEAP_SECONDS),
00037 _atsc_eit_reset(false),
00038 _mgt_version(-1),
00039 _cached_mgt(NULL),
00040 _desired_major_channel(desiredMajorChannel),
00041 _desired_minor_channel(desiredMinorChannel)
00042 {
00043 AddListeningPID(ATSC_PSIP_PID);
00044 AddListeningPID(SCTE_PSIP_PID);
00045 }
00046
00047 ATSCStreamData::~ATSCStreamData()
00048 {
00049 Reset(-1,-1);
00050
00051 QMutexLocker locker(&_listener_lock);
00052 _atsc_main_listeners.clear();
00053 _atsc_aux_listeners.clear();
00054 _atsc_eit_listeners.clear();
00055
00056 _scte_main_listeners.clear();
00057 _atsc81_eit_listeners.clear();
00058 }
00059
00060 void ATSCStreamData::SetDesiredChannel(int major, int minor)
00061 {
00062 bool reset = true;
00063 const MasterGuideTable *mgt = GetCachedMGT();
00064 tvct_vec_t tvcts = GetCachedTVCTs();
00065 cvct_vec_t cvcts = GetCachedCVCTs();
00066
00067 if (mgt && (!tvcts.empty() || !cvcts.empty()))
00068 {
00069 const TerrestrialVirtualChannelTable *tvct = NULL;
00070 const CableVirtualChannelTable *cvct = NULL;
00071 int chan_idx = -1;
00072 for (uint i = 0; (i < tvcts.size()) && (chan_idx < 0); i++)
00073 {
00074 tvct = tvcts[i];
00075 chan_idx = tvcts[i]->Find(major, minor);
00076 }
00077 for (uint i = (chan_idx < 0) ? 0 : cvcts.size();
00078 (i < cvcts.size()) && (chan_idx < 0); i++)
00079 {
00080 cvct = cvcts[i];
00081 chan_idx = cvcts[i]->Find(major, minor);
00082 }
00083
00084 if (chan_idx >= 0)
00085 {
00086 _desired_major_channel = major;
00087 _desired_minor_channel = minor;
00088
00089 ProcessMGT(mgt);
00090
00091 if (cvct)
00092 {
00093 ProcessCVCT(cvct->TransportStreamID(), cvct);
00094 SetDesiredProgram(cvct->ProgramNumber(chan_idx));
00095 }
00096 else if (tvct)
00097 {
00098 ProcessTVCT(tvct->TransportStreamID(), tvct);
00099 SetDesiredProgram(tvct->ProgramNumber(chan_idx));
00100 }
00101 reset = false;
00102 }
00103 }
00104
00105 ReturnCachedTable(mgt);
00106 ReturnCachedTVCTTables(tvcts);
00107 ReturnCachedCVCTTables(cvcts);
00108
00109 if (reset)
00110 Reset(major, minor);
00111 }
00112
00113 void ATSCStreamData::Reset(int desiredProgram)
00114 {
00115 MPEGStreamData::Reset(desiredProgram);
00116 AddListeningPID(ATSC_PSIP_PID);
00117 }
00118
00119 void ATSCStreamData::Reset(int major, int minor)
00120 {
00121 _desired_major_channel = major;
00122 _desired_minor_channel = minor;
00123
00124 MPEGStreamData::Reset(-1);
00125 _mgt_version = -1;
00126 _tvct_version.clear();
00127 _cvct_version.clear();
00128 _eit_version.clear();
00129 _eit_section_seen.clear();
00130
00131 _sourceid_to_atsc_maj_min.clear();
00132 _atsc_eit_pids.clear();
00133 _atsc_ett_pids.clear();
00134
00135 {
00136 QMutexLocker locker(&_cache_lock);
00137
00138 DeleteCachedTable(_cached_mgt);
00139 _cached_mgt = NULL;
00140
00141 tvct_cache_t::iterator tit = _cached_tvcts.begin();
00142 for (; tit != _cached_tvcts.end(); ++tit)
00143 DeleteCachedTable(*tit);
00144 _cached_tvcts.clear();
00145
00146 cvct_cache_t::iterator cit = _cached_cvcts.begin();
00147 for (; cit != _cached_cvcts.end(); ++cit)
00148 DeleteCachedTable(*cit);
00149 _cached_cvcts.clear();
00150 }
00151
00152 AddListeningPID(ATSC_PSIP_PID);
00153 }
00154
00162 bool ATSCStreamData::IsRedundant(uint pid, const PSIPTable &psip) const
00163 {
00164 if (MPEGStreamData::IsRedundant(pid, psip))
00165 return true;
00166
00167 const int table_id = psip.TableID();
00168 const int version = psip.Version();
00169
00170 if (TableID::EIT == table_id)
00171 {
00172 if (VersionEIT(pid, psip.TableIDExtension()) != version)
00173 return false;
00174 return EITSectionSeen(pid, psip.TableIDExtension(), psip.Section());
00175 }
00176
00177 if (TableID::ETT == table_id)
00178 return false;
00179
00180 if (TableID::STT == table_id)
00181 return false;
00182
00183 if (TableID::STTscte == table_id)
00184 return false;
00185
00186 if (TableID::MGT == table_id)
00187 return VersionMGT() == version;
00188
00189 if (TableID::TVCT == table_id)
00190 {
00191 return VersionTVCT(psip.TableIDExtension()) == version;
00192 }
00193
00194 if (TableID::CVCT == table_id)
00195 {
00196 return VersionCVCT(psip.TableIDExtension()) == version;
00197 }
00198
00199 if (TableID::RRT == table_id)
00200 return VersionRRT(psip.TableIDExtension()) == version;
00201
00202 if (TableID::PIM == table_id)
00203 return true;
00204
00205 if (TableID::PNM == table_id)
00206 return true;
00207
00208 return false;
00209 }
00210
00211 bool ATSCStreamData::HandleTables(uint pid, const PSIPTable &psip)
00212 {
00213 if (MPEGStreamData::HandleTables(pid, psip))
00214 return true;
00215
00216 if (IsRedundant(pid, psip))
00217 return true;
00218
00219 const int version = psip.Version();
00220
00221
00222 switch (psip.TableID())
00223 {
00224 case TableID::MGT:
00225 {
00226 SetVersionMGT(version);
00227 if (_cache_tables)
00228 {
00229 MasterGuideTable *mgt = new MasterGuideTable(psip);
00230 CacheMGT(mgt);
00231 ProcessMGT(mgt);
00232 }
00233 else
00234 {
00235 MasterGuideTable mgt(psip);
00236 ProcessMGT(&mgt);
00237 }
00238 return true;
00239 }
00240 case TableID::TVCT:
00241 {
00242 uint tsid = psip.TableIDExtension();
00243 SetVersionTVCT(tsid, version);
00244 if (_cache_tables)
00245 {
00246 TerrestrialVirtualChannelTable *vct =
00247 new TerrestrialVirtualChannelTable(psip);
00248 CacheTVCT(pid, vct);
00249 ProcessTVCT(tsid, vct);
00250 }
00251 else
00252 {
00253 TerrestrialVirtualChannelTable vct(psip);
00254 ProcessTVCT(tsid, &vct);
00255 }
00256 return true;
00257 }
00258 case TableID::CVCT:
00259 {
00260 uint tsid = psip.TableIDExtension();
00261 SetVersionCVCT(tsid, version);
00262 if (_cache_tables)
00263 {
00264 CableVirtualChannelTable *vct =
00265 new CableVirtualChannelTable(psip);
00266 CacheCVCT(pid, vct);
00267 ProcessCVCT(tsid, vct);
00268 }
00269 else
00270 {
00271 CableVirtualChannelTable vct(psip);
00272 ProcessCVCT(tsid, &vct);
00273 }
00274 return true;
00275 }
00276 case TableID::RRT:
00277 {
00278 uint region = psip.TableIDExtension();
00279 SetVersionRRT(region, version);
00280 RatingRegionTable rrt(psip);
00281 QMutexLocker locker(&_listener_lock);
00282 for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
00283 _atsc_aux_listeners[i]->HandleRRT(&rrt);
00284 return true;
00285 }
00286 case TableID::EIT:
00287 {
00288 QMutexLocker locker(&_listener_lock);
00289 if (!_atsc_eit_listeners.size() && !_eit_helper)
00290 return true;
00291
00292 if (VersionEIT(pid, psip.TableIDExtension()) != version)
00293 SetVersionEIT(pid, psip.TableIDExtension(), version);
00294 SetEITSectionSeen(pid, psip.TableIDExtension(), psip.Section());
00295
00296 EventInformationTable eit(psip);
00297 for (uint i = 0; i < _atsc_eit_listeners.size(); i++)
00298 _atsc_eit_listeners[i]->HandleEIT(pid, &eit);
00299
00300 const uint mm = GetATSCMajorMinor(eit.SourceID());
00301 if (mm && _eit_helper)
00302 _eit_helper->AddEIT(mm >> 16, mm & 0xffff, &eit);
00303
00304 return true;
00305 }
00306 case TableID::ETT:
00307 {
00308 ExtendedTextTable ett(psip);
00309
00310 QMutexLocker locker(&_listener_lock);
00311 for (uint i = 0; i < _atsc_eit_listeners.size(); i++)
00312 _atsc_eit_listeners[i]->HandleETT(pid, &ett);
00313
00314 if (ett.IsEventETM() && _eit_helper)
00315 {
00316 const uint mm = GetATSCMajorMinor(ett.SourceID());
00317 if (mm)
00318 _eit_helper->AddETT(mm >> 16, mm & 0xffff, &ett);
00319 }
00320
00321 return true;
00322 }
00323 case TableID::STT:
00324 {
00325 SystemTimeTable stt(psip);
00326
00327 UpdateTimeOffset(stt.UTCUnix());
00328
00329
00330 if (stt.GPSOffset() != _GPS_UTC_offset)
00331 _GPS_UTC_offset = stt.GPSOffset();
00332
00333 _listener_lock.lock();
00334 for (uint i = 0; i < _atsc_main_listeners.size(); i++)
00335 _atsc_main_listeners[i]->HandleSTT(&stt);
00336 _listener_lock.unlock();
00337
00338 if (_eit_helper && GPSOffset() != _eit_helper->GetGPSOffset())
00339 _eit_helper->SetGPSOffset(GPSOffset());
00340
00341 return true;
00342 }
00343 case TableID::DCCT:
00344 {
00345 DirectedChannelChangeTable dcct(psip);
00346
00347 QMutexLocker locker(&_listener_lock);
00348 for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
00349 _atsc_aux_listeners[i]->HandleDCCT(&dcct);
00350
00351 return true;
00352 }
00353 case TableID::DCCSCT:
00354 {
00355 DirectedChannelChangeSelectionCodeTable dccsct(psip);
00356
00357 QMutexLocker locker(&_listener_lock);
00358 for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
00359 _atsc_aux_listeners[i]->HandleDCCSCT(&dccsct);
00360
00361 return true;
00362 }
00363
00364
00365 case TableID::AEIT:
00366 {
00367 AggregateEventInformationTable aeit(psip);
00368
00369 QMutexLocker locker(&_listener_lock);
00370 for (uint i = 0; i < _atsc81_eit_listeners.size(); i++)
00371 _atsc81_eit_listeners[i]->HandleAEIT(pid, &aeit);
00372
00373 return true;
00374 }
00375 case TableID::AETT:
00376 {
00377 AggregateExtendedTextTable aett(psip);
00378
00379 QMutexLocker locker(&_listener_lock);
00380 for (uint i = 0; i < _atsc81_eit_listeners.size(); i++)
00381 _atsc81_eit_listeners[i]->HandleAETT(pid, &aett);
00382
00383 return true;
00384 }
00385
00386
00387 case TableID::NITscte:
00388 {
00389 SCTENetworkInformationTable nit(psip);
00390
00391 QMutexLocker locker(&_listener_lock);
00392 for (uint i = 0; i < _scte_main_listeners.size(); i++)
00393 _scte_main_listeners[i]->HandleNIT(&nit);
00394
00395 return true;
00396 }
00397 case TableID::NTT:
00398 {
00399 NetworkTextTable ntt(psip);
00400
00401 QMutexLocker locker(&_listener_lock);
00402 for (uint i = 0; i < _scte_main_listeners.size(); i++)
00403 _scte_main_listeners[i]->HandleNTT(&ntt);
00404
00405 return true;
00406 }
00407 case TableID::SVCTscte:
00408 {
00409 ShortVirtualChannelTable svct(psip);
00410
00411 QMutexLocker locker(&_listener_lock);
00412 for (uint i = 0; i < _scte_main_listeners.size(); i++)
00413 _scte_main_listeners[i]->HandleSVCT(&svct);
00414
00415 return true;
00416 }
00417 case TableID::STTscte:
00418 {
00419 SCTESystemTimeTable stt(psip);
00420
00421 QMutexLocker locker(&_listener_lock);
00422 for (uint i = 0; i < _scte_main_listeners.size(); i++)
00423 _scte_main_listeners[i]->HandleSTT(&stt);
00424
00425 return true;
00426 }
00427
00428
00429 case TableID::PIM:
00430 {
00431 ProgramInformationMessageTable pim(psip);
00432
00433 QMutexLocker locker(&_listener_lock);
00434 for (uint i = 0; i < _scte_main_listeners.size(); i++)
00435 _scte_main_listeners[i]->HandlePIM(&pim);
00436
00437 return true;
00438 }
00439
00440 case TableID::PNM:
00441 {
00442 ProgramNameMessageTable pnm(psip);
00443
00444 QMutexLocker locker(&_listener_lock);
00445 for (uint i = 0; i < _scte_main_listeners.size(); i++)
00446 _scte_main_listeners[i]->HandlePNM(&pnm);
00447
00448 return true;
00449 }
00450
00451
00452 case TableID::ADET:
00453 {
00454 AggregateDataEventTable adet(psip);
00455
00456 QMutexLocker locker(&_listener_lock);
00457 for (uint i = 0; i < _scte_main_listeners.size(); i++)
00458 _scte_main_listeners[i]->HandleADET(&adet);
00459
00460 return true;
00461 }
00462
00463 case TableID::NIT:
00464 case TableID::NITo:
00465 case TableID::SDT:
00466 case TableID::SDTo:
00467 case TableID::BAT:
00468 case TableID::TDT:
00469 case TableID::TOT:
00470 {
00471
00472 return false;
00473 }
00474
00475 default:
00476 {
00477 LOG(VB_RECORD, LOG_ERR,
00478 QString("ATSCStreamData::HandleTables(): Unknown table 0x%1")
00479 .arg(psip.TableID(),0,16));
00480 break;
00481 }
00482 }
00483 return false;
00484 }
00485
00486 void ATSCStreamData::SetEITSectionSeen(uint pid, uint atsc_source_id,
00487 uint section)
00488 {
00489 uint key = (pid<<16) | atsc_source_id;
00490 sections_map_t::iterator it = _eit_section_seen.find(key);
00491 if (it == _eit_section_seen.end())
00492 {
00493 _eit_section_seen[key].resize(32, 0);
00494 it = _eit_section_seen.find(key);
00495 }
00496 (*it)[section>>3] |= bit_sel[section & 0x7];
00497 }
00498
00499 bool ATSCStreamData::EITSectionSeen(uint pid, uint atsc_source_id,
00500 uint section) const
00501 {
00502 uint key = (pid<<16) | atsc_source_id;
00503 sections_map_t::const_iterator it = _eit_section_seen.find(key);
00504 if (it == _eit_section_seen.end())
00505 return false;
00506 return (bool) ((*it)[section>>3] & bit_sel[section & 0x7]);
00507 }
00508
00509 bool ATSCStreamData::HasEITPIDChanges(const uint_vec_t &in_use_pids) const
00510 {
00511 QMutexLocker locker(&_listener_lock);
00512 uint eit_count = (uint) round(_atsc_eit_pids.size() * _eit_rate);
00513 uint ett_count = (uint) round(_atsc_ett_pids.size() * _eit_rate);
00514 return (in_use_pids.size() != (eit_count + ett_count) || _atsc_eit_reset);
00515 }
00516
00517 bool ATSCStreamData::GetEITPIDChanges(const uint_vec_t &cur_pids,
00518 uint_vec_t &add_pids,
00519 uint_vec_t &del_pids) const
00520 {
00521 QMutexLocker locker(&_listener_lock);
00522
00523 _atsc_eit_reset = false;
00524
00525 uint eit_count = (uint) round(_atsc_eit_pids.size() * _eit_rate);
00526 uint ett_count = (uint) round(_atsc_ett_pids.size() * _eit_rate);
00527 uint i;
00528
00529 #if 0
00530 LOG(VB_GENERAL, LOG_DEBUG, QString("eit size: %1, rate: %2, cnt: %3")
00531 .arg(_atsc_eit_pids.size()).arg(_eit_rate).arg(eit_count));
00532 #endif
00533
00534 uint_vec_t add_pids_tmp;
00535 atsc_eit_pid_map_t::const_iterator it = _atsc_eit_pids.begin();
00536 for (i = 0; it != _atsc_eit_pids.end() && (i < eit_count); (++it),(i++))
00537 add_pids_tmp.push_back(*it);
00538
00539 atsc_ett_pid_map_t::const_iterator it2 = _atsc_ett_pids.begin();
00540 for (i = 0; it2 != _atsc_ett_pids.end() && (i < ett_count); (++it2),(i++))
00541 add_pids_tmp.push_back(*it2);
00542
00543 uint_vec_t::const_iterator it3;
00544 for (i = 0; i < cur_pids.size(); i++)
00545 {
00546 it3 = find(add_pids_tmp.begin(), add_pids_tmp.end(), cur_pids[i]);
00547 if (it3 == add_pids_tmp.end())
00548 del_pids.push_back(cur_pids[i]);
00549 }
00550
00551 for (i = 0; i < add_pids_tmp.size(); i++)
00552 {
00553 it3 = find(cur_pids.begin(), cur_pids.end(), add_pids_tmp[i]);
00554 if (it3 == cur_pids.end())
00555 add_pids.push_back(add_pids_tmp[i]);
00556 }
00557
00558 return add_pids.size() || del_pids.size();
00559 }
00560
00561 void ATSCStreamData::ProcessMGT(const MasterGuideTable *mgt)
00562 {
00563 QMutexLocker locker(&_listener_lock);
00564
00565 _atsc_eit_reset = true;
00566 _atsc_eit_pids.clear();
00567 _atsc_ett_pids.clear();
00568
00569 for (uint i = 0 ; i < mgt->TableCount(); i++)
00570 {
00571 const int table_class = mgt->TableClass(i);
00572 const uint pid = mgt->TablePID(i);
00573
00574 if (table_class == TableClass::EIT)
00575 {
00576 const uint num = mgt->TableType(i) - 0x100;
00577 _atsc_eit_pids[num] = pid;
00578 }
00579 else if (table_class == TableClass::ETTe)
00580 {
00581 const uint num = mgt->TableType(i) - 0x200;
00582 _atsc_ett_pids[num] = pid;
00583 }
00584 }
00585
00586 for (uint i = 0; i < _atsc_main_listeners.size(); i++)
00587 _atsc_main_listeners[i]->HandleMGT(mgt);
00588 }
00589
00590 void ATSCStreamData::ProcessVCT(uint tsid, const VirtualChannelTable *vct)
00591 {
00592 for (uint i = 0; i < _atsc_main_listeners.size(); i++)
00593 _atsc_main_listeners[i]->HandleVCT(tsid, vct);
00594
00595 _sourceid_to_atsc_maj_min.clear();
00596 for (uint i = 0; i < vct->ChannelCount() ; i++)
00597 {
00598 if (vct->IsHidden(i) && vct->IsHiddenInGuide(i))
00599 {
00600 LOG(VB_EIT, LOG_INFO, QString("%1 chan %2-%3 is hidden in guide")
00601 .arg(vct->ModulationMode(i) == 1 ? "NTSC" : "ATSC")
00602 .arg(vct->MajorChannel(i))
00603 .arg(vct->MinorChannel(i)));
00604 continue;
00605 }
00606
00607 if (1 == vct->ModulationMode(i))
00608 {
00609 LOG(VB_EIT, LOG_INFO, QString("Ignoring NTSC chan %1-%2")
00610 .arg(vct->MajorChannel(i))
00611 .arg(vct->MinorChannel(i)));
00612 continue;
00613 }
00614
00615 LOG(VB_EIT, LOG_INFO, QString("Adding Source #%1 ATSC chan %2-%3")
00616 .arg(vct->SourceID(i))
00617 .arg(vct->MajorChannel(i))
00618 .arg(vct->MinorChannel(i)));
00619
00620 _sourceid_to_atsc_maj_min[vct->SourceID(i)] =
00621 vct->MajorChannel(i) << 16 | vct->MinorChannel(i);
00622 }
00623 }
00624
00625 void ATSCStreamData::ProcessTVCT(uint tsid,
00626 const TerrestrialVirtualChannelTable *vct)
00627 {
00628 QMutexLocker locker(&_listener_lock);
00629 ProcessVCT(tsid, vct);
00630 for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
00631 _atsc_aux_listeners[i]->HandleTVCT(tsid, vct);
00632 }
00633
00634 void ATSCStreamData::ProcessCVCT(uint tsid,
00635 const CableVirtualChannelTable *vct)
00636 {
00637 QMutexLocker locker(&_listener_lock);
00638 ProcessVCT(tsid, vct);
00639 for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
00640 _atsc_aux_listeners[i]->HandleCVCT(tsid, vct);
00641 }
00642
00643 bool ATSCStreamData::HasCachedMGT(bool current) const
00644 {
00645 if (!current)
00646 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00647
00648 return (bool)(_cached_mgt);
00649 }
00650
00651 bool ATSCStreamData::HasChannel(uint major, uint minor) const
00652 {
00653 bool hasit = false;
00654
00655 {
00656 tvct_vec_t tvct = GetCachedTVCTs();
00657 for (uint i = 0; i < tvct.size() && !hasit; i++)
00658 {
00659 if (tvct[i]->Find(major, minor) >= 0)
00660 hasit |= HasProgram(tvct[i]->ProgramNumber(i));
00661 }
00662 ReturnCachedTVCTTables(tvct);
00663 }
00664
00665 if (!hasit)
00666 {
00667 cvct_vec_t cvct = GetCachedCVCTs();
00668 for (uint i = 0; i < cvct.size() && !hasit; i++)
00669 {
00670 if (cvct[i]->Find(major, minor) >= 0)
00671 hasit |= HasProgram(cvct[i]->ProgramNumber(i));
00672 }
00673 ReturnCachedCVCTTables(cvct);
00674 }
00675
00676 return hasit;
00677 }
00678
00679 bool ATSCStreamData::HasCachedTVCT(uint pid, bool current) const
00680 {
00681 if (!current)
00682 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00683
00684 _cache_lock.lock();
00685 tvct_cache_t::const_iterator it = _cached_tvcts.find(pid);
00686 bool exists = (it != _cached_tvcts.end());
00687 _cache_lock.unlock();
00688
00689 return exists;
00690 }
00691
00692 bool ATSCStreamData::HasCachedCVCT(uint pid, bool current) const
00693 {
00694 if (!current)
00695 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00696
00697 _cache_lock.lock();
00698 cvct_cache_t::const_iterator it = _cached_cvcts.find(pid);
00699 bool exists = (it != _cached_cvcts.end());
00700 _cache_lock.unlock();
00701
00702 return exists;
00703 }
00704
00705 bool ATSCStreamData::HasCachedAllTVCTs(bool current) const
00706 {
00707 if (!current)
00708 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00709
00710 if (!_cached_mgt)
00711 return false;
00712
00713 _cache_lock.lock();
00714 bool ret = true;
00715 for (uint i = 0; ret && (i < _cached_mgt->TableCount()); ++i)
00716 {
00717 if (TableClass::TVCTc == _cached_mgt->TableClass(i))
00718 ret &= HasCachedTVCT(_cached_mgt->TablePID(i));
00719 }
00720 _cache_lock.unlock();
00721
00722 return ret;
00723 }
00724
00725 bool ATSCStreamData::HasCachedAllCVCTs(bool current) const
00726 {
00727 if (!current)
00728 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00729
00730 if (!_cached_mgt)
00731 return false;
00732
00733 _cache_lock.lock();
00734 bool ret = true;
00735 for (uint i = 0; ret && (i < _cached_mgt->TableCount()); ++i)
00736 {
00737 if (TableClass::CVCTc == _cached_mgt->TableClass(i))
00738 ret &= HasCachedCVCT(_cached_mgt->TablePID(i));
00739 }
00740 _cache_lock.unlock();
00741
00742 return ret;
00743 }
00744
00745 bool ATSCStreamData::HasCachedAnyTVCTs(bool current) const
00746 {
00747 if (!current)
00748 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00749
00750 QMutexLocker locker(&_cache_lock);
00751 return !_cached_tvcts.empty();
00752 }
00753
00754 bool ATSCStreamData::HasCachedAnyCVCTs(bool current) const
00755 {
00756 if (!current)
00757 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00758
00759 QMutexLocker locker(&_cache_lock);
00760 return !_cached_cvcts.empty();
00761 }
00762
00763 const MasterGuideTable *ATSCStreamData::GetCachedMGT(bool current) const
00764 {
00765 if (!current)
00766 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00767
00768 _cache_lock.lock();
00769 const MasterGuideTable *mgt = _cached_mgt;
00770 IncrementRefCnt(mgt);
00771 _cache_lock.unlock();
00772
00773 return mgt;
00774 }
00775
00776 const tvct_ptr_t ATSCStreamData::GetCachedTVCT(uint pid, bool current) const
00777 {
00778 if (!current)
00779 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00780
00781 TerrestrialVirtualChannelTable *tvct = NULL;
00782
00783 _cache_lock.lock();
00784 tvct_cache_t::const_iterator it = _cached_tvcts.find(pid);
00785 if (it != _cached_tvcts.end())
00786 IncrementRefCnt(tvct = *it);
00787 _cache_lock.unlock();
00788
00789 return tvct;
00790 }
00791
00792 const cvct_ptr_t ATSCStreamData::GetCachedCVCT(uint pid, bool current) const
00793 {
00794 if (!current)
00795 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00796
00797 CableVirtualChannelTable *cvct = NULL;
00798
00799 _cache_lock.lock();
00800 cvct_cache_t::const_iterator it = _cached_cvcts.find(pid);
00801 if (it != _cached_cvcts.end())
00802 IncrementRefCnt(cvct = *it);
00803 _cache_lock.unlock();
00804
00805 return cvct;
00806 }
00807
00808 tvct_vec_t ATSCStreamData::GetCachedTVCTs(bool current) const
00809 {
00810 if (!current)
00811 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00812
00813 vector<const TerrestrialVirtualChannelTable*> tvcts;
00814
00815 _cache_lock.lock();
00816 tvct_cache_t::const_iterator it = _cached_tvcts.begin();
00817 for (; it != _cached_tvcts.end(); ++it)
00818 {
00819 TerrestrialVirtualChannelTable* tvct = *it;
00820 IncrementRefCnt(tvct);
00821 tvcts.push_back(tvct);
00822 }
00823 _cache_lock.unlock();
00824
00825 return tvcts;
00826 }
00827
00828 cvct_vec_t ATSCStreamData::GetCachedCVCTs(bool current) const
00829 {
00830 if (!current)
00831 LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00832
00833 vector<const CableVirtualChannelTable*> cvcts;
00834
00835 _cache_lock.lock();
00836 cvct_cache_t::const_iterator it = _cached_cvcts.begin();
00837 for (; it != _cached_cvcts.end(); ++it)
00838 {
00839 CableVirtualChannelTable* cvct = *it;
00840 IncrementRefCnt(cvct);
00841 cvcts.push_back(cvct);
00842 }
00843 _cache_lock.unlock();
00844
00845 return cvcts;
00846 }
00847
00848 void ATSCStreamData::CacheMGT(MasterGuideTable *mgt)
00849 {
00850 QMutexLocker locker(&_cache_lock);
00851
00852 DeleteCachedTable(_cached_mgt);
00853 _cached_mgt = mgt;
00854 }
00855
00856 void ATSCStreamData::CacheTVCT(uint pid, TerrestrialVirtualChannelTable* tvct)
00857 {
00858 QMutexLocker locker(&_cache_lock);
00859
00860 DeleteCachedTable(_cached_tvcts[pid]);
00861 _cached_tvcts[pid] = tvct;
00862 }
00863
00864 void ATSCStreamData::CacheCVCT(uint pid, CableVirtualChannelTable* cvct)
00865 {
00866 QMutexLocker locker(&_cache_lock);
00867
00868 DeleteCachedTable(_cached_cvcts[pid]);
00869 _cached_cvcts[pid] = cvct;
00870 }
00871
00872 bool ATSCStreamData::DeleteCachedTable(PSIPTable *psip) const
00873 {
00874 if (!psip)
00875 return false;
00876
00877 QMutexLocker locker(&_cache_lock);
00878 if (_cached_ref_cnt[psip] > 0)
00879 {
00880 _cached_slated_for_deletion[psip] = 1;
00881 return false;
00882 }
00883 else if (TableID::MGT == psip->TableID())
00884 {
00885 if (psip == _cached_mgt)
00886 _cached_mgt = NULL;
00887 delete psip;
00888 }
00889 else if ((TableID::TVCT == psip->TableID()) &&
00890 _cached_tvcts[psip->tsheader()->PID()])
00891 {
00892 _cached_tvcts[psip->tsheader()->PID()] = NULL;
00893 delete psip;
00894 }
00895 else if ((TableID::CVCT == psip->TableID()) &&
00896 _cached_cvcts[psip->tsheader()->PID()])
00897 {
00898 _cached_cvcts[psip->tsheader()->PID()] = NULL;
00899 delete psip;
00900 }
00901 else
00902 {
00903 return MPEGStreamData::DeleteCachedTable(psip);
00904 }
00905 psip_refcnt_map_t::iterator it;
00906 it = _cached_slated_for_deletion.find(psip);
00907 if (it != _cached_slated_for_deletion.end())
00908 _cached_slated_for_deletion.erase(it);
00909
00910 return true;
00911 }
00912
00913 void ATSCStreamData::ReturnCachedTVCTTables(tvct_vec_t &tvcts) const
00914 {
00915 for (tvct_vec_t::iterator it = tvcts.begin(); it != tvcts.end(); ++it)
00916 ReturnCachedTable(*it);
00917 tvcts.clear();
00918 }
00919
00920 void ATSCStreamData::ReturnCachedCVCTTables(cvct_vec_t &cvcts) const
00921 {
00922 for (cvct_vec_t::iterator it = cvcts.begin(); it != cvcts.end(); ++it)
00923 ReturnCachedTable(*it);
00924 cvcts.clear();
00925 }
00926
00927 void ATSCStreamData::AddATSCMainListener(ATSCMainStreamListener *val)
00928 {
00929 QMutexLocker locker(&_listener_lock);
00930
00931 atsc_main_listener_vec_t::iterator it = _atsc_main_listeners.begin();
00932 for (; it != _atsc_main_listeners.end(); ++it)
00933 if (((void*)val) == ((void*)*it))
00934 return;
00935
00936 _atsc_main_listeners.push_back(val);
00937 }
00938
00939 void ATSCStreamData::RemoveATSCMainListener(ATSCMainStreamListener *val)
00940 {
00941 QMutexLocker locker(&_listener_lock);
00942
00943 atsc_main_listener_vec_t::iterator it = _atsc_main_listeners.begin();
00944 for (; it != _atsc_main_listeners.end(); ++it)
00945 {
00946 if (((void*)val) == ((void*)*it))
00947 {
00948 _atsc_main_listeners.erase(it);
00949 return;
00950 }
00951 }
00952 }
00953
00954 void ATSCStreamData::AddSCTEMainListener(SCTEMainStreamListener *val)
00955 {
00956 QMutexLocker locker(&_listener_lock);
00957
00958 scte_main_listener_vec_t::iterator it = _scte_main_listeners.begin();
00959 for (; it != _scte_main_listeners.end(); ++it)
00960 if (((void*)val) == ((void*)*it))
00961 return;
00962
00963 _scte_main_listeners.push_back(val);
00964 }
00965
00966 void ATSCStreamData::RemoveSCTEMainListener(SCTEMainStreamListener *val)
00967 {
00968 QMutexLocker locker(&_listener_lock);
00969
00970 scte_main_listener_vec_t::iterator it = _scte_main_listeners.begin();
00971 for (; it != _scte_main_listeners.end(); ++it)
00972 {
00973 if (((void*)val) == ((void*)*it))
00974 {
00975 _scte_main_listeners.erase(it);
00976 return;
00977 }
00978 }
00979 }
00980
00981 void ATSCStreamData::AddATSCAuxListener(ATSCAuxStreamListener *val)
00982 {
00983 QMutexLocker locker(&_listener_lock);
00984
00985 atsc_aux_listener_vec_t::iterator it = _atsc_aux_listeners.begin();
00986 for (; it != _atsc_aux_listeners.end(); ++it)
00987 if (((void*)val) == ((void*)*it))
00988 return;
00989
00990 _atsc_aux_listeners.push_back(val);
00991 }
00992
00993 void ATSCStreamData::RemoveATSCAuxListener(ATSCAuxStreamListener *val)
00994 {
00995 QMutexLocker locker(&_listener_lock);
00996
00997 atsc_aux_listener_vec_t::iterator it = _atsc_aux_listeners.begin();
00998 for (; it != _atsc_aux_listeners.end(); ++it)
00999 {
01000 if (((void*)val) == ((void*)*it))
01001 {
01002 _atsc_aux_listeners.erase(it);
01003 return;
01004 }
01005 }
01006 }
01007
01008 void ATSCStreamData::AddATSCEITListener(ATSCEITStreamListener *val)
01009 {
01010 QMutexLocker locker(&_listener_lock);
01011
01012 atsc_eit_listener_vec_t::iterator it = _atsc_eit_listeners.begin();
01013 for (; it != _atsc_eit_listeners.end(); ++it)
01014 if (((void*)val) == ((void*)*it))
01015 return;
01016
01017 _atsc_eit_listeners.push_back(val);
01018 }
01019
01020 void ATSCStreamData::RemoveATSCEITListener(ATSCEITStreamListener *val)
01021 {
01022 QMutexLocker locker(&_listener_lock);
01023
01024 atsc_eit_listener_vec_t::iterator it = _atsc_eit_listeners.begin();
01025 for (; it != _atsc_eit_listeners.end(); ++it)
01026 {
01027 if (((void*)val) == ((void*)*it))
01028 {
01029 _atsc_eit_listeners.erase(it);
01030 return;
01031 }
01032 }
01033 }
01034
01035 void ATSCStreamData::AddATSC81EITListener(ATSC81EITStreamListener *val)
01036 {
01037 QMutexLocker locker(&_listener_lock);
01038
01039 atsc81_eit_listener_vec_t::iterator it = _atsc81_eit_listeners.begin();
01040 for (; it != _atsc81_eit_listeners.end(); ++it)
01041 if (((void*)val) == ((void*)*it))
01042 return;
01043
01044 _atsc81_eit_listeners.push_back(val);
01045 }
01046
01047 void ATSCStreamData::RemoveATSC81EITListener(ATSC81EITStreamListener *val)
01048 {
01049 QMutexLocker locker(&_listener_lock);
01050
01051 atsc81_eit_listener_vec_t::iterator it = _atsc81_eit_listeners.begin();
01052 for (; it != _atsc81_eit_listeners.end(); ++it)
01053 {
01054 if (((void*)val) == ((void*)*it))
01055 {
01056 _atsc81_eit_listeners.erase(it);
01057 return;
01058 }
01059 }
01060 }