|
MythTV
0.26-pre
|
00001 // -*- Mode: c++ -*- 00002 // Copyright (c) 2003-2004, Daniel Thor Kristjansson 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; // retransmit ETT's we've seen 00179 00180 if (TableID::STT == table_id) 00181 return false; // each SystemTimeTable matters 00182 00183 if (TableID::STTscte == table_id) 00184 return false; // each SCTESystemTimeTable matters 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; // ignore these messages.. 00204 00205 if (TableID::PNM == table_id) 00206 return true; // ignore these messages.. 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 // Decode any table we know about 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) // Guide ETTs 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 // only update internal offset if it changes 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 // ATSC A/81 & SCTE 65 tables 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 // SCTE 65 tables 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 // SCTE 57 table -- SCTE 65 standard supercedes this 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 // SCTE 57 table -- SCTE 65 standard supercedes this 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 // SCTE 80 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 // All DVB specific tables, not handled here 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 }
1.7.6.1