MythTV  0.26-pre
atscstreamdata.cpp
Go to the documentation of this file.
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 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends