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[%1]: ").arg(_cardid)
00016
00032 ATSCStreamData::ATSCStreamData(int desiredMajorChannel,
00033 int desiredMinorChannel,
00034 int cardnum, bool cacheTables)
00035 : MPEGStreamData(-1, cardnum, 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, LOC +
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, LOC + 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, LOC +
00601 QString("%1 chan %2-%3 is hidden in guide")
00602 .arg(vct->ModulationMode(i) == 1 ? "NTSC" : "ATSC")
00603 .arg(vct->MajorChannel(i))
00604 .arg(vct->MinorChannel(i)));
00605 continue;
00606 }
00607
00608 if (1 == vct->ModulationMode(i))
00609 {
00610 LOG(VB_EIT, LOG_INFO, LOC + QString("Ignoring NTSC chan %1-%2")
00611 .arg(vct->MajorChannel(i))
00612 .arg(vct->MinorChannel(i)));
00613 continue;
00614 }
00615
00616 LOG(VB_EIT, LOG_INFO, LOC + QString("Adding Source #%1 ATSC chan %2-%3")
00617 .arg(vct->SourceID(i))
00618 .arg(vct->MajorChannel(i))
00619 .arg(vct->MinorChannel(i)));
00620
00621 _sourceid_to_atsc_maj_min[vct->SourceID(i)] =
00622 vct->MajorChannel(i) << 16 | vct->MinorChannel(i);
00623 }
00624 }
00625
00626 void ATSCStreamData::ProcessTVCT(uint tsid,
00627 const TerrestrialVirtualChannelTable *vct)
00628 {
00629 QMutexLocker locker(&_listener_lock);
00630 ProcessVCT(tsid, vct);
00631 for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
00632 _atsc_aux_listeners[i]->HandleTVCT(tsid, vct);
00633 }
00634
00635 void ATSCStreamData::ProcessCVCT(uint tsid,
00636 const CableVirtualChannelTable *vct)
00637 {
00638 QMutexLocker locker(&_listener_lock);
00639 ProcessVCT(tsid, vct);
00640 for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
00641 _atsc_aux_listeners[i]->HandleCVCT(tsid, vct);
00642 }
00643
00644 bool ATSCStreamData::HasCachedMGT(bool current) const
00645 {
00646 if (!current)
00647 LOG(VB_GENERAL, LOG_WARNING, LOC +
00648 "Currently we ignore \'current\' param");
00649
00650 return (bool)(_cached_mgt);
00651 }
00652
00653 bool ATSCStreamData::HasChannel(uint major, uint minor) const
00654 {
00655 bool hasit = false;
00656
00657 {
00658 tvct_vec_t tvct = GetCachedTVCTs();
00659 for (uint i = 0; i < tvct.size() && !hasit; i++)
00660 {
00661 if (tvct[i]->Find(major, minor) >= 0)
00662 hasit |= HasProgram(tvct[i]->ProgramNumber(i));
00663 }
00664 ReturnCachedTVCTTables(tvct);
00665 }
00666
00667 if (!hasit)
00668 {
00669 cvct_vec_t cvct = GetCachedCVCTs();
00670 for (uint i = 0; i < cvct.size() && !hasit; i++)
00671 {
00672 if (cvct[i]->Find(major, minor) >= 0)
00673 hasit |= HasProgram(cvct[i]->ProgramNumber(i));
00674 }
00675 ReturnCachedCVCTTables(cvct);
00676 }
00677
00678 return hasit;
00679 }
00680
00681 bool ATSCStreamData::HasCachedTVCT(uint pid, bool current) const
00682 {
00683 if (!current)
00684 LOG(VB_GENERAL, LOG_WARNING, LOC +
00685 "Currently we ignore \'current\' param");
00686
00687 _cache_lock.lock();
00688 tvct_cache_t::const_iterator it = _cached_tvcts.find(pid);
00689 bool exists = (it != _cached_tvcts.end());
00690 _cache_lock.unlock();
00691
00692 return exists;
00693 }
00694
00695 bool ATSCStreamData::HasCachedCVCT(uint pid, bool current) const
00696 {
00697 if (!current)
00698 LOG(VB_GENERAL, LOG_WARNING, LOC +
00699 "Currently we ignore \'current\' param");
00700
00701 _cache_lock.lock();
00702 cvct_cache_t::const_iterator it = _cached_cvcts.find(pid);
00703 bool exists = (it != _cached_cvcts.end());
00704 _cache_lock.unlock();
00705
00706 return exists;
00707 }
00708
00709 bool ATSCStreamData::HasCachedAllTVCTs(bool current) const
00710 {
00711 if (!current)
00712 LOG(VB_GENERAL, LOG_WARNING, LOC +
00713 "Currently we ignore \'current\' param");
00714
00715 if (!_cached_mgt)
00716 return false;
00717
00718 _cache_lock.lock();
00719 bool ret = true;
00720 for (uint i = 0; ret && (i < _cached_mgt->TableCount()); ++i)
00721 {
00722 if (TableClass::TVCTc == _cached_mgt->TableClass(i))
00723 ret &= HasCachedTVCT(_cached_mgt->TablePID(i));
00724 }
00725 _cache_lock.unlock();
00726
00727 return ret;
00728 }
00729
00730 bool ATSCStreamData::HasCachedAllCVCTs(bool current) const
00731 {
00732 if (!current)
00733 LOG(VB_GENERAL, LOG_WARNING, LOC +
00734 "Currently we ignore \'current\' param");
00735
00736 if (!_cached_mgt)
00737 return false;
00738
00739 _cache_lock.lock();
00740 bool ret = true;
00741 for (uint i = 0; ret && (i < _cached_mgt->TableCount()); ++i)
00742 {
00743 if (TableClass::CVCTc == _cached_mgt->TableClass(i))
00744 ret &= HasCachedCVCT(_cached_mgt->TablePID(i));
00745 }
00746 _cache_lock.unlock();
00747
00748 return ret;
00749 }
00750
00751 bool ATSCStreamData::HasCachedAnyTVCTs(bool current) const
00752 {
00753 if (!current)
00754 LOG(VB_GENERAL, LOG_WARNING, LOC +
00755 "Currently we ignore \'current\' param");
00756
00757 QMutexLocker locker(&_cache_lock);
00758 return !_cached_tvcts.empty();
00759 }
00760
00761 bool ATSCStreamData::HasCachedAnyCVCTs(bool current) const
00762 {
00763 if (!current)
00764 LOG(VB_GENERAL, LOG_WARNING, LOC +
00765 "Currently we ignore \'current\' param");
00766
00767 QMutexLocker locker(&_cache_lock);
00768 return !_cached_cvcts.empty();
00769 }
00770
00771 const MasterGuideTable *ATSCStreamData::GetCachedMGT(bool current) const
00772 {
00773 if (!current)
00774 LOG(VB_GENERAL, LOG_WARNING, LOC +
00775 "Currently we ignore \'current\' param");
00776
00777 _cache_lock.lock();
00778 const MasterGuideTable *mgt = _cached_mgt;
00779 IncrementRefCnt(mgt);
00780 _cache_lock.unlock();
00781
00782 return mgt;
00783 }
00784
00785 tvct_const_ptr_t ATSCStreamData::GetCachedTVCT(uint pid, bool current) const
00786 {
00787 if (!current)
00788 LOG(VB_GENERAL, LOG_WARNING, LOC +
00789 "Currently we ignore \'current\' param");
00790
00791 tvct_ptr_t tvct = NULL;
00792
00793 _cache_lock.lock();
00794 tvct_cache_t::const_iterator it = _cached_tvcts.find(pid);
00795 if (it != _cached_tvcts.end())
00796 IncrementRefCnt(tvct = *it);
00797 _cache_lock.unlock();
00798
00799 return tvct;
00800 }
00801
00802 cvct_const_ptr_t ATSCStreamData::GetCachedCVCT(uint pid, bool current) const
00803 {
00804 if (!current)
00805 LOG(VB_GENERAL, LOG_WARNING, LOC +
00806 "Currently we ignore \'current\' param");
00807
00808 cvct_ptr_t cvct = NULL;
00809
00810 _cache_lock.lock();
00811 cvct_cache_t::const_iterator it = _cached_cvcts.find(pid);
00812 if (it != _cached_cvcts.end())
00813 IncrementRefCnt(cvct = *it);
00814 _cache_lock.unlock();
00815
00816 return cvct;
00817 }
00818
00819 tvct_vec_t ATSCStreamData::GetCachedTVCTs(bool current) const
00820 {
00821 if (!current)
00822 LOG(VB_GENERAL, LOG_WARNING, LOC +
00823 "Currently we ignore \'current\' param");
00824
00825 vector<const TerrestrialVirtualChannelTable*> tvcts;
00826
00827 _cache_lock.lock();
00828 tvct_cache_t::const_iterator it = _cached_tvcts.begin();
00829 for (; it != _cached_tvcts.end(); ++it)
00830 {
00831 TerrestrialVirtualChannelTable* tvct = *it;
00832 IncrementRefCnt(tvct);
00833 tvcts.push_back(tvct);
00834 }
00835 _cache_lock.unlock();
00836
00837 return tvcts;
00838 }
00839
00840 cvct_vec_t ATSCStreamData::GetCachedCVCTs(bool current) const
00841 {
00842 if (!current)
00843 LOG(VB_GENERAL, LOG_WARNING, LOC +
00844 "Currently we ignore \'current\' param");
00845
00846 vector<const CableVirtualChannelTable*> cvcts;
00847
00848 _cache_lock.lock();
00849 cvct_cache_t::const_iterator it = _cached_cvcts.begin();
00850 for (; it != _cached_cvcts.end(); ++it)
00851 {
00852 CableVirtualChannelTable* cvct = *it;
00853 IncrementRefCnt(cvct);
00854 cvcts.push_back(cvct);
00855 }
00856 _cache_lock.unlock();
00857
00858 return cvcts;
00859 }
00860
00861 void ATSCStreamData::CacheMGT(MasterGuideTable *mgt)
00862 {
00863 QMutexLocker locker(&_cache_lock);
00864
00865 DeleteCachedTable(_cached_mgt);
00866 _cached_mgt = mgt;
00867 }
00868
00869 void ATSCStreamData::CacheTVCT(uint pid, TerrestrialVirtualChannelTable* tvct)
00870 {
00871 QMutexLocker locker(&_cache_lock);
00872
00873 DeleteCachedTable(_cached_tvcts[pid]);
00874 _cached_tvcts[pid] = tvct;
00875 }
00876
00877 void ATSCStreamData::CacheCVCT(uint pid, CableVirtualChannelTable* cvct)
00878 {
00879 QMutexLocker locker(&_cache_lock);
00880
00881 DeleteCachedTable(_cached_cvcts[pid]);
00882 _cached_cvcts[pid] = cvct;
00883 }
00884
00885 bool ATSCStreamData::DeleteCachedTable(PSIPTable *psip) const
00886 {
00887 if (!psip)
00888 return false;
00889
00890 QMutexLocker locker(&_cache_lock);
00891 if (_cached_ref_cnt[psip] > 0)
00892 {
00893 _cached_slated_for_deletion[psip] = 1;
00894 return false;
00895 }
00896 else if (TableID::MGT == psip->TableID())
00897 {
00898 if (psip == _cached_mgt)
00899 _cached_mgt = NULL;
00900 delete psip;
00901 }
00902 else if ((TableID::TVCT == psip->TableID()) &&
00903 _cached_tvcts[psip->tsheader()->PID()])
00904 {
00905 _cached_tvcts[psip->tsheader()->PID()] = NULL;
00906 delete psip;
00907 }
00908 else if ((TableID::CVCT == psip->TableID()) &&
00909 _cached_cvcts[psip->tsheader()->PID()])
00910 {
00911 _cached_cvcts[psip->tsheader()->PID()] = NULL;
00912 delete psip;
00913 }
00914 else
00915 {
00916 return MPEGStreamData::DeleteCachedTable(psip);
00917 }
00918 psip_refcnt_map_t::iterator it;
00919 it = _cached_slated_for_deletion.find(psip);
00920 if (it != _cached_slated_for_deletion.end())
00921 _cached_slated_for_deletion.erase(it);
00922
00923 return true;
00924 }
00925
00926 void ATSCStreamData::ReturnCachedTVCTTables(tvct_vec_t &tvcts) const
00927 {
00928 for (tvct_vec_t::iterator it = tvcts.begin(); it != tvcts.end(); ++it)
00929 ReturnCachedTable(*it);
00930 tvcts.clear();
00931 }
00932
00933 void ATSCStreamData::ReturnCachedCVCTTables(cvct_vec_t &cvcts) const
00934 {
00935 for (cvct_vec_t::iterator it = cvcts.begin(); it != cvcts.end(); ++it)
00936 ReturnCachedTable(*it);
00937 cvcts.clear();
00938 }
00939
00940 void ATSCStreamData::AddATSCMainListener(ATSCMainStreamListener *val)
00941 {
00942 QMutexLocker locker(&_listener_lock);
00943
00944 atsc_main_listener_vec_t::iterator it = _atsc_main_listeners.begin();
00945 for (; it != _atsc_main_listeners.end(); ++it)
00946 if (((void*)val) == ((void*)*it))
00947 return;
00948
00949 _atsc_main_listeners.push_back(val);
00950 }
00951
00952 void ATSCStreamData::RemoveATSCMainListener(ATSCMainStreamListener *val)
00953 {
00954 QMutexLocker locker(&_listener_lock);
00955
00956 atsc_main_listener_vec_t::iterator it = _atsc_main_listeners.begin();
00957 for (; it != _atsc_main_listeners.end(); ++it)
00958 {
00959 if (((void*)val) == ((void*)*it))
00960 {
00961 _atsc_main_listeners.erase(it);
00962 return;
00963 }
00964 }
00965 }
00966
00967 void ATSCStreamData::AddSCTEMainListener(SCTEMainStreamListener *val)
00968 {
00969 QMutexLocker locker(&_listener_lock);
00970
00971 scte_main_listener_vec_t::iterator it = _scte_main_listeners.begin();
00972 for (; it != _scte_main_listeners.end(); ++it)
00973 if (((void*)val) == ((void*)*it))
00974 return;
00975
00976 _scte_main_listeners.push_back(val);
00977 }
00978
00979 void ATSCStreamData::RemoveSCTEMainListener(SCTEMainStreamListener *val)
00980 {
00981 QMutexLocker locker(&_listener_lock);
00982
00983 scte_main_listener_vec_t::iterator it = _scte_main_listeners.begin();
00984 for (; it != _scte_main_listeners.end(); ++it)
00985 {
00986 if (((void*)val) == ((void*)*it))
00987 {
00988 _scte_main_listeners.erase(it);
00989 return;
00990 }
00991 }
00992 }
00993
00994 void ATSCStreamData::AddATSCAuxListener(ATSCAuxStreamListener *val)
00995 {
00996 QMutexLocker locker(&_listener_lock);
00997
00998 atsc_aux_listener_vec_t::iterator it = _atsc_aux_listeners.begin();
00999 for (; it != _atsc_aux_listeners.end(); ++it)
01000 if (((void*)val) == ((void*)*it))
01001 return;
01002
01003 _atsc_aux_listeners.push_back(val);
01004 }
01005
01006 void ATSCStreamData::RemoveATSCAuxListener(ATSCAuxStreamListener *val)
01007 {
01008 QMutexLocker locker(&_listener_lock);
01009
01010 atsc_aux_listener_vec_t::iterator it = _atsc_aux_listeners.begin();
01011 for (; it != _atsc_aux_listeners.end(); ++it)
01012 {
01013 if (((void*)val) == ((void*)*it))
01014 {
01015 _atsc_aux_listeners.erase(it);
01016 return;
01017 }
01018 }
01019 }
01020
01021 void ATSCStreamData::AddATSCEITListener(ATSCEITStreamListener *val)
01022 {
01023 QMutexLocker locker(&_listener_lock);
01024
01025 atsc_eit_listener_vec_t::iterator it = _atsc_eit_listeners.begin();
01026 for (; it != _atsc_eit_listeners.end(); ++it)
01027 if (((void*)val) == ((void*)*it))
01028 return;
01029
01030 _atsc_eit_listeners.push_back(val);
01031 }
01032
01033 void ATSCStreamData::RemoveATSCEITListener(ATSCEITStreamListener *val)
01034 {
01035 QMutexLocker locker(&_listener_lock);
01036
01037 atsc_eit_listener_vec_t::iterator it = _atsc_eit_listeners.begin();
01038 for (; it != _atsc_eit_listeners.end(); ++it)
01039 {
01040 if (((void*)val) == ((void*)*it))
01041 {
01042 _atsc_eit_listeners.erase(it);
01043 return;
01044 }
01045 }
01046 }
01047
01048 void ATSCStreamData::AddATSC81EITListener(ATSC81EITStreamListener *val)
01049 {
01050 QMutexLocker locker(&_listener_lock);
01051
01052 atsc81_eit_listener_vec_t::iterator it = _atsc81_eit_listeners.begin();
01053 for (; it != _atsc81_eit_listeners.end(); ++it)
01054 if (((void*)val) == ((void*)*it))
01055 return;
01056
01057 _atsc81_eit_listeners.push_back(val);
01058 }
01059
01060 void ATSCStreamData::RemoveATSC81EITListener(ATSC81EITStreamListener *val)
01061 {
01062 QMutexLocker locker(&_listener_lock);
01063
01064 atsc81_eit_listener_vec_t::iterator it = _atsc81_eit_listeners.begin();
01065 for (; it != _atsc81_eit_listeners.end(); ++it)
01066 {
01067 if (((void*)val) == ((void*)*it))
01068 {
01069 _atsc81_eit_listeners.erase(it);
01070 return;
01071 }
01072 }
01073 }