MythTV  0.26-pre
dvbstreamdata.cpp
Go to the documentation of this file.
00001 // -*- Mode: c++ -*-
00002 // Copyright (c) 2003-2004, Daniel Thor Kristjansson
00003 #include <algorithm>
00004 using namespace std;
00005 
00006 #include "dvbstreamdata.h"
00007 #include "dvbtables.h"
00008 #include "premieretables.h"
00009 #include "eithelper.h"
00010 
00011 #define PREMIERE_ONID 133
00012 #define FREESAT_EIT_PID 3842
00013 #define MCA_ONID 6144
00014 #define MCA_EIT_TSID 136
00015 #define MCA_EIT_PID 1018
00016 
00017 // service_id is synonymous with the MPEG program number in the PMT.
00018 DVBStreamData::DVBStreamData(uint desired_netid,  uint desired_tsid,
00019                              int desired_program, bool cacheTables)
00020     : MPEGStreamData(desired_program, cacheTables),
00021       _desired_netid(desired_netid), _desired_tsid(desired_tsid),
00022       _dvb_eit_dishnet_long(false),
00023       _nit_version(-2), _nito_version(-2)
00024 {
00025     SetVersionNIT(-1,0);
00026     SetVersionNITo(-1,0);
00027     AddListeningPID(DVB_NIT_PID);
00028     AddListeningPID(DVB_SDT_PID);
00029     AddListeningPID(DVB_TDT_PID);
00030 }
00031 
00032 DVBStreamData::~DVBStreamData()
00033 {
00034     Reset(_desired_netid, _desired_tsid, _desired_program);
00035 
00036     QMutexLocker locker(&_listener_lock);
00037     _dvb_main_listeners.clear();
00038     _dvb_other_listeners.clear();
00039     _dvb_eit_listeners.clear();
00040     _dvb_has_eit.clear();
00041 }
00042 
00043 void DVBStreamData::SetDesiredService(uint netid, uint tsid, int serviceid)
00044 {
00045     bool reset = true;
00046 
00047     if (HasCachedAllSDT(tsid, true))
00048     {
00049         const sdt_ptr_t first_sdt = GetCachedSDT(tsid, 0, true);
00050         uint networkID = first_sdt->OriginalNetworkID();
00051         if (networkID == netid)
00052         {
00053             reset = false;
00054             _desired_netid = netid;
00055             _desired_tsid = tsid;
00056             uint last_section = first_sdt->LastSection();
00057             ProcessSDT(_desired_tsid, first_sdt);
00058             ReturnCachedTable(first_sdt);
00059             for (uint i = 1; i <= last_section; ++i)
00060             {
00061                 const sdt_ptr_t sdt = GetCachedSDT(_desired_tsid, i, true);
00062                 ProcessSDT(_desired_tsid, sdt);
00063                 ReturnCachedTable(sdt);
00064             }
00065             SetDesiredProgram(serviceid);
00066         }
00067     }
00068 
00069     if (reset)
00070         Reset(netid, tsid, serviceid);
00071 }
00072 
00073 
00078 bool DVBStreamData::IsRedundant(uint pid, const PSIPTable &psip) const
00079 {
00080     if (MPEGStreamData::IsRedundant(pid, psip))
00081         return true;
00082 
00083     const int table_id = psip.TableID();
00084     const int version  = psip.Version();
00085 
00086     if (TableID::NIT == table_id)
00087     {
00088         if (VersionNIT() != version)
00089             return false;
00090         return NITSectionSeen(psip.Section());
00091     }
00092 
00093     if (TableID::SDT == table_id)
00094     {
00095         if (VersionSDT(psip.TableIDExtension()) != version)
00096             return false;
00097         return SDTSectionSeen(psip.TableIDExtension(), psip.Section());
00098     }
00099 
00100     if (TableID::TDT == table_id)
00101         return false;
00102 
00103     if (TableID::BAT == table_id)
00104     {
00105         if (VersionBAT(psip.TableIDExtension()) != version)
00106             return false;
00107         return BATSectionSeen(psip.TableIDExtension(), psip.Section());
00108     }
00109 
00110     bool is_eit = false;
00111     if (DVB_EIT_PID == pid || FREESAT_EIT_PID == pid)
00112     {
00113         // Standard Now/Next Event Information Tables for this transport
00114         is_eit |= TableID::PF_EIT  == table_id;
00115         // Standard Future Event Information Tables for this transport
00116         is_eit |= (TableID::SC_EITbeg  <= table_id &&
00117                    TableID::SC_EITend  >= table_id);
00118     }
00119     if (is_eit)
00120     {
00121         uint service_id = psip.TableIDExtension();
00122         if (VersionEIT(table_id, service_id) != version)
00123             return false;
00124         return EITSectionSeen(table_id, service_id, psip.Section());
00125     }
00126 
00128     // Other transport tables
00129 
00130     if (TableID::NITo == table_id)
00131     {
00132         if (VersionNITo() != version)
00133             return false;
00134         return NIToSectionSeen(psip.Section());
00135     }
00136 
00137     if (TableID::SDTo == table_id)
00138     {
00139         if (VersionSDTo(psip.TableIDExtension()) != version)
00140             return false;
00141         return SDToSectionSeen(psip.TableIDExtension(), psip.Section());
00142     }
00143 
00144     if (DVB_EIT_PID == pid || FREESAT_EIT_PID == pid || MCA_EIT_PID == pid)
00145     {
00146         // Standard Now/Next Event Information Tables for other transport
00147         is_eit |= TableID::PF_EITo == table_id;
00148         // Standard Future Event Information Tables for other transports
00149         is_eit |= (TableID::SC_EITbego <= table_id &&
00150                    TableID::SC_EITendo >= table_id);
00151     }
00152     if (DVB_DNLONG_EIT_PID == pid || DVB_BVLONG_EIT_PID == pid)
00153     {
00154         // Dish Network and Bev Long Term Future Event Information
00155         // for all transports
00156         is_eit |= (TableID::DN_EITbego <= table_id &&
00157                    TableID::DN_EITendo >= table_id);
00158     }
00159     if (is_eit)
00160     {
00161         uint service_id = psip.TableIDExtension();
00162         if (VersionEIT(table_id, service_id) != version)
00163             return false;
00164         return EITSectionSeen(table_id, service_id, psip.Section());
00165     }
00166 
00167     if (((PREMIERE_EIT_DIREKT_PID == pid) || (PREMIERE_EIT_SPORT_PID == pid)) &&
00168         TableID::PREMIERE_CIT == table_id)
00169     {
00170         uint content_id = PremiereContentInformationTable(psip).ContentID();
00171         if (VersionCIT(content_id) != version)
00172             return false;
00173         return CITSectionSeen(content_id, psip.Section());
00174     }
00175 
00176     return false;
00177 }
00178 
00179 void DVBStreamData::Reset(uint desired_netid, uint desired_tsid,
00180                           int desired_serviceid)
00181 {
00182     MPEGStreamData::Reset(desired_serviceid);
00183 
00184     _desired_netid = desired_netid;
00185     _desired_tsid  = desired_tsid;
00186 
00187     SetVersionNIT(-1,0);
00188     _sdt_versions.clear();
00189     _sdt_section_seen.clear();
00190     _eit_version.clear();
00191     _eit_section_seen.clear();
00192     _cit_version.clear();
00193     _cit_section_seen.clear();
00194 
00195     SetVersionNITo(-1,0);
00196     _sdto_versions.clear();
00197     _sdto_section_seen.clear();
00198     _bat_versions.clear();
00199     _bat_section_seen.clear();
00200 
00201     {
00202         _cache_lock.lock();
00203 
00204         nit_cache_t::iterator nit = _cached_nit.begin();
00205         for (; nit != _cached_nit.end(); ++nit)
00206             DeleteCachedTable(*nit);
00207         _cached_nit.clear();
00208 
00209         sdt_cache_t::iterator sit = _cached_sdts.begin();
00210         for (; sit != _cached_sdts.end(); ++sit)
00211             DeleteCachedTable(*sit);
00212         _cached_sdts.clear();
00213 
00214         _cache_lock.unlock();
00215     }
00216     AddListeningPID(DVB_NIT_PID);
00217     AddListeningPID(DVB_SDT_PID);
00218     AddListeningPID(DVB_TDT_PID);
00219 }
00220 
00225 bool DVBStreamData::HandleTables(uint pid, const PSIPTable &psip)
00226 {
00227     if (MPEGStreamData::HandleTables(pid, psip))
00228         return true;
00229 
00230     if (IsRedundant(pid, psip))
00231         return true;
00232 
00233     switch (psip.TableID())
00234     {
00235         case TableID::NIT:
00236         {
00237             SetVersionNIT(psip.Version(), psip.LastSection());
00238             SetNITSectionSeen(psip.Section());
00239 
00240             if (_cache_tables)
00241             {
00242                 NetworkInformationTable *nit =
00243                     new NetworkInformationTable(psip);
00244                 CacheNIT(nit);
00245                 QMutexLocker locker(&_listener_lock);
00246                 for (uint i = 0; i < _dvb_main_listeners.size(); i++)
00247                     _dvb_main_listeners[i]->HandleNIT(nit);
00248             }
00249             else
00250             {
00251                 NetworkInformationTable nit(psip);
00252                 QMutexLocker locker(&_listener_lock);
00253                 for (uint i = 0; i < _dvb_main_listeners.size(); i++)
00254                     _dvb_main_listeners[i]->HandleNIT(&nit);
00255             }
00256 
00257             return true;
00258         }
00259         case TableID::SDT:
00260         {
00261             uint tsid = psip.TableIDExtension();
00262             SetVersionSDT(tsid, psip.Version(), psip.LastSection());
00263             SetSDTSectionSeen(tsid, psip.Section());
00264 
00265             if (_cache_tables)
00266             {
00267                 ServiceDescriptionTable *sdt =
00268                     new ServiceDescriptionTable(psip);
00269                 CacheSDT(sdt);
00270                 ProcessSDT(tsid, sdt);
00271             }
00272             else
00273             {
00274                 ServiceDescriptionTable sdt(psip);
00275                 ProcessSDT(tsid, &sdt);
00276             }
00277 
00278             return true;
00279         }
00280         case TableID::TDT:
00281         {
00282             TimeDateTable tdt(psip);
00283 
00284             UpdateTimeOffset(tdt.UTCUnix());
00285 
00286             QMutexLocker locker(&_listener_lock);
00287             for (uint i = 0; i < _dvb_main_listeners.size(); i++)
00288                 _dvb_main_listeners[i]->HandleTDT(&tdt);
00289 
00290             return true;
00291         }
00292         case TableID::NITo:
00293         {
00294             SetVersionNITo(psip.Version(), psip.LastSection());
00295             SetNIToSectionSeen(psip.Section());
00296             NetworkInformationTable nit(psip);
00297 
00298             QMutexLocker locker(&_listener_lock);
00299             for (uint i = 0; i < _dvb_other_listeners.size(); i++)
00300                 _dvb_other_listeners[i]->HandleNITo(&nit);
00301 
00302             return true;
00303         }
00304         case TableID::SDTo:
00305         {
00306             uint tsid = psip.TableIDExtension();
00307             SetVersionSDTo(tsid, psip.Version(), psip.LastSection());
00308             SetSDToSectionSeen(tsid, psip.Section());
00309             ServiceDescriptionTable sdt(psip);
00310 
00311             // some providers send the SDT for the current multiplex as SDTo
00312             // this routine changes the TableID to SDT and recalculates the CRC
00313             if (_desired_netid == sdt.OriginalNetworkID() &&
00314                 _desired_tsid  == tsid)
00315             {
00316                 ServiceDescriptionTable *sdta =
00317                     new ServiceDescriptionTable(psip);
00318                 if (!sdta->Mutate())
00319                 {
00320                     delete sdta;
00321                     return true;
00322                 }
00323                 if (_cache_tables)
00324                 {
00325                     CacheSDT(sdta);
00326                     ProcessSDT(tsid, sdta);
00327                 }
00328                 else
00329                 {
00330                     ProcessSDT(tsid, sdta);
00331                     delete sdta;
00332                 }
00333                 return true;
00334             }
00335 
00336             QMutexLocker locker(&_listener_lock);
00337             for (uint i = 0; i < _dvb_other_listeners.size(); i++)
00338                 _dvb_other_listeners[i]->HandleSDTo(tsid, &sdt);
00339 
00340             return true;
00341         }
00342         case TableID::BAT:
00343         {
00344             uint bid = psip.TableIDExtension();
00345             SetVersionBAT(bid, psip.Version(), psip.LastSection());
00346             SetBATSectionSeen(bid, psip.Section());
00347             BouquetAssociationTable bat(psip);
00348 
00349             QMutexLocker locker(&_listener_lock);
00350             for (uint i = 0; i < _dvb_other_listeners.size(); i++)
00351                 _dvb_other_listeners[i]->HandleBAT(&bat);
00352 
00353             return true;
00354         }
00355     }
00356 
00357     if ((DVB_EIT_PID == pid || DVB_DNLONG_EIT_PID == pid || FREESAT_EIT_PID == pid ||
00358         ((MCA_ONID == _desired_netid) && (MCA_EIT_TSID == _desired_tsid) &&
00359         (MCA_EIT_PID == pid)) || DVB_BVLONG_EIT_PID == pid) &&
00360 
00361         DVBEventInformationTable::IsEIT(psip.TableID()))
00362     {
00363         QMutexLocker locker(&_listener_lock);
00364         if (!_dvb_eit_listeners.size() && !_eit_helper)
00365             return true;
00366 
00367         uint service_id = psip.TableIDExtension();
00368         SetVersionEIT(psip.TableID(), service_id, psip.Version(),  psip.LastSection());
00369         SetEITSectionSeen(psip.TableID(), service_id, psip.Section());
00370 
00371         DVBEventInformationTable eit(psip);
00372         for (uint i = 0; i < _dvb_eit_listeners.size(); i++)
00373             _dvb_eit_listeners[i]->HandleEIT(&eit);
00374 
00375         if (_eit_helper)
00376             _eit_helper->AddEIT(&eit);
00377 
00378         return true;
00379     }
00380 
00381     if (_desired_netid == PREMIERE_ONID &&
00382         (PREMIERE_EIT_DIREKT_PID == pid || PREMIERE_EIT_SPORT_PID == pid) &&
00383         PremiereContentInformationTable::IsEIT(psip.TableID()))
00384     {
00385         QMutexLocker locker(&_listener_lock);
00386         if (!_dvb_eit_listeners.size() && !_eit_helper)
00387             return true;
00388 
00389         PremiereContentInformationTable cit(psip);
00390         SetVersionCIT(cit.ContentID(), cit.Version());
00391         SetCITSectionSeen(cit.ContentID(), cit.Section());
00392 
00393         for (uint i = 0; i < _dvb_eit_listeners.size(); i++)
00394             _dvb_eit_listeners[i]->HandleEIT(&cit);
00395 
00396         if (_eit_helper)
00397             _eit_helper->AddEIT(&cit);
00398 
00399         return true;
00400     }
00401 
00402     return false;
00403 }
00404 
00405 void DVBStreamData::ProcessSDT(uint tsid, const ServiceDescriptionTable *sdt)
00406 {
00407     QMutexLocker locker(&_listener_lock);
00408 
00409     for (uint i = 0; i < sdt->ServiceCount(); i++)
00410     {
00411         if (sdt->HasEITSchedule(i) || sdt->HasEITPresentFollowing(i))
00412             _dvb_has_eit[sdt->ServiceID(i)] = true;
00413     }
00414 
00415     for (uint i = 0; i < _dvb_main_listeners.size(); i++)
00416         _dvb_main_listeners[i]->HandleSDT(tsid, sdt);
00417 }
00418 
00419 bool DVBStreamData::HasEITPIDChanges(const uint_vec_t &in_use_pids) const
00420 {
00421     QMutexLocker locker(&_listener_lock);
00422     bool want_eit = (_eit_rate >= 0.5f) && HasAnyEIT();
00423     bool has_eit  = in_use_pids.size();
00424     return want_eit != has_eit;
00425 }
00426 
00427 bool DVBStreamData::GetEITPIDChanges(const uint_vec_t &cur_pids,
00428                                      uint_vec_t &add_pids,
00429                                      uint_vec_t &del_pids) const
00430 {
00431     QMutexLocker locker(&_listener_lock);
00432 
00433     if ((_eit_rate >= 0.5f) && HasAnyEIT())
00434     {
00435         if (find(cur_pids.begin(), cur_pids.end(),
00436                  (uint) DVB_EIT_PID) == cur_pids.end())
00437         {
00438             add_pids.push_back(DVB_EIT_PID);
00439         }
00440 
00441         if (_dvb_eit_dishnet_long &&
00442             find(cur_pids.begin(), cur_pids.end(),
00443                  (uint) DVB_DNLONG_EIT_PID) == cur_pids.end())
00444         {
00445             add_pids.push_back(DVB_DNLONG_EIT_PID);
00446         }
00447 
00448         if (_dvb_eit_dishnet_long &&
00449             find(cur_pids.begin(), cur_pids.end(),
00450                  (uint) DVB_BVLONG_EIT_PID) == cur_pids.end())
00451         {
00452             add_pids.push_back(DVB_BVLONG_EIT_PID);
00453         }
00454 
00455         if (_desired_netid == PREMIERE_ONID &&
00456             find(cur_pids.begin(), cur_pids.end(),
00457                  (uint) PREMIERE_EIT_DIREKT_PID) == cur_pids.end())
00458         {
00459             add_pids.push_back(PREMIERE_EIT_DIREKT_PID);
00460         }
00461 
00462         if (_desired_netid == PREMIERE_ONID &&
00463             find(cur_pids.begin(), cur_pids.end(),
00464                  (uint) PREMIERE_EIT_SPORT_PID) == cur_pids.end())
00465         {
00466             add_pids.push_back(PREMIERE_EIT_SPORT_PID);
00467         }
00468 
00469         if (find(cur_pids.begin(), cur_pids.end(),
00470                  (uint) FREESAT_EIT_PID) == cur_pids.end())
00471         {
00472             add_pids.push_back(FREESAT_EIT_PID);
00473         }
00474 
00475         if (MCA_ONID == _desired_netid && MCA_EIT_TSID == _desired_tsid &&
00476             find(cur_pids.begin(), cur_pids.end(),
00477                  (uint) MCA_EIT_PID) == cur_pids.end())
00478         {
00479             add_pids.push_back(MCA_EIT_PID);
00480         }
00481 
00482     }
00483     else
00484     {
00485         if (find(cur_pids.begin(), cur_pids.end(),
00486                  (uint) DVB_EIT_PID) != cur_pids.end())
00487         {
00488             del_pids.push_back(DVB_EIT_PID);
00489         }
00490 
00491         if (_dvb_eit_dishnet_long &&
00492             find(cur_pids.begin(), cur_pids.end(),
00493                  (uint) DVB_DNLONG_EIT_PID) != cur_pids.end())
00494         {
00495             del_pids.push_back(DVB_DNLONG_EIT_PID);
00496         }
00497 
00498         if (_dvb_eit_dishnet_long &&
00499             find(cur_pids.begin(), cur_pids.end(),
00500                  (uint) DVB_BVLONG_EIT_PID) != cur_pids.end())
00501         {
00502             del_pids.push_back(DVB_BVLONG_EIT_PID);
00503         }
00504 
00505         if (_desired_netid == PREMIERE_ONID &&
00506             find(cur_pids.begin(), cur_pids.end(),
00507                  (uint) PREMIERE_EIT_DIREKT_PID) != cur_pids.end())
00508         {
00509             del_pids.push_back(PREMIERE_EIT_DIREKT_PID);
00510         }
00511 
00512         if (_desired_netid == PREMIERE_ONID &&
00513             find(cur_pids.begin(), cur_pids.end(),
00514                  (uint) PREMIERE_EIT_SPORT_PID) != cur_pids.end())
00515         {
00516             del_pids.push_back(PREMIERE_EIT_SPORT_PID);
00517         }
00518 
00519         if (find(cur_pids.begin(), cur_pids.end(),
00520                  (uint) FREESAT_EIT_PID) == cur_pids.end())
00521         {
00522             del_pids.push_back(FREESAT_EIT_PID);
00523         }
00524 
00525         if (MCA_ONID == _desired_netid && MCA_EIT_TSID == _desired_tsid &&
00526             find(cur_pids.begin(), cur_pids.end(),
00527                  (uint) MCA_EIT_PID) != cur_pids.end())
00528         {
00529             del_pids.push_back(MCA_EIT_PID);
00530         }
00531     }
00532 
00533     return add_pids.size() || del_pids.size();
00534 }
00535 
00536 void DVBStreamData::SetNITSectionSeen(uint section)
00537 {
00538     _nit_section_seen[section>>3] |= bit_sel[section & 0x7];
00539 }
00540 
00541 bool DVBStreamData::NITSectionSeen(uint section) const
00542 {
00543     return (bool) (_nit_section_seen[section>>3] & bit_sel[section & 0x7]);
00544 }
00545 
00546 bool DVBStreamData::HasAllNITSections(void) const
00547 {
00548     for (uint i = 0; i < 32; i++)
00549         if (_nit_section_seen[i] != 0xff)
00550             return false;
00551     return true;
00552 }
00553 
00554 void DVBStreamData::SetNIToSectionSeen(uint section)
00555 {
00556     _nito_section_seen[section>>3] |= bit_sel[section & 0x7];
00557 }
00558 
00559 bool DVBStreamData::NIToSectionSeen(uint section) const
00560 {
00561     return (bool) (_nito_section_seen[section>>3] & bit_sel[section & 0x7]);
00562 }
00563 
00564 bool DVBStreamData::HasAllNIToSections(void) const
00565 {
00566     for (uint i = 0; i < 32; i++)
00567         if (_nito_section_seen[i] != 0xff)
00568             return false;
00569     return true;
00570 }
00571 
00572 void DVBStreamData::SetSDTSectionSeen(uint tsid, uint section)
00573 {
00574     sections_map_t::iterator it = _sdt_section_seen.find(tsid);
00575     if (it == _sdt_section_seen.end())
00576     {
00577         _sdt_section_seen[tsid].resize(32, 0);
00578         it = _sdt_section_seen.find(tsid);
00579     }
00580     (*it)[section>>3] |= bit_sel[section & 0x7];
00581 }
00582 
00583 bool DVBStreamData::SDTSectionSeen(uint tsid, uint section) const
00584 {
00585     sections_map_t::const_iterator it = _sdt_section_seen.find(tsid);
00586     if (it == _sdt_section_seen.end())
00587         return false;
00588     return (bool) ((*it)[section>>3] & bit_sel[section & 0x7]);
00589 }
00590 
00591 bool DVBStreamData::HasAllSDTSections(uint tsid) const
00592 {
00593     sections_map_t::const_iterator it = _sdt_section_seen.find(tsid);
00594     if (it == _sdt_section_seen.end())
00595         return false;
00596     for (uint i = 0; i < 32; i++)
00597         if ((*it)[i] != 0xff)
00598             return false;
00599     return true;
00600 }
00601 
00602 void DVBStreamData::SetSDToSectionSeen(uint tsid, uint section)
00603 {
00604     sections_map_t::iterator it = _sdto_section_seen.find(tsid);
00605     if (it == _sdto_section_seen.end())
00606     {
00607         _sdto_section_seen[tsid].resize(32, 0);
00608         it = _sdto_section_seen.find(tsid);
00609     }
00610     (*it)[section>>3] |= bit_sel[section & 0x7];
00611 }
00612 
00613 bool DVBStreamData::SDToSectionSeen(uint tsid, uint section) const
00614 {
00615     sections_map_t::const_iterator it = _sdto_section_seen.find(tsid);
00616     if (it == _sdto_section_seen.end())
00617         return false;
00618     return (bool) ((*it)[section>>3] & bit_sel[section & 0x7]);
00619 }
00620 
00621 bool DVBStreamData::HasAllSDToSections(uint tsid) const
00622 {
00623     sections_map_t::const_iterator it = _sdto_section_seen.find(tsid);
00624     if (it == _sdto_section_seen.end())
00625         return false;
00626     for (uint i = 0; i < 32; i++)
00627         if ((*it)[i] != 0xff)
00628             return false;
00629     return true;
00630 }
00631 
00632 void DVBStreamData::SetBATSectionSeen(uint bid, uint section)
00633 {
00634     sections_map_t::iterator it = _bat_section_seen.find(bid);
00635     if (it == _bat_section_seen.end())
00636     {
00637         _bat_section_seen[bid].resize(32, 0);
00638         it = _bat_section_seen.find(bid);
00639     }
00640     (*it)[section>>3] |= bit_sel[section & 0x7];
00641 }
00642 
00643 bool DVBStreamData::BATSectionSeen(uint bid, uint section) const
00644 {
00645     sections_map_t::const_iterator it = _bat_section_seen.find(bid);
00646     if (it == _bat_section_seen.end())
00647         return false;
00648     return (bool) ((*it)[section>>3] & bit_sel[section & 0x7]);
00649 }
00650 
00651 bool DVBStreamData::HasAllBATSections(uint bid) const
00652 {
00653     sections_map_t::const_iterator it = _bat_section_seen.find(bid);
00654     if (it == _bat_section_seen.end())
00655         return false;
00656     for (uint i = 0; i < 32; i++)
00657         if ((*it)[i] != 0xff)
00658             return false;
00659     return true;
00660 }
00661 
00662 void DVBStreamData::SetEITSectionSeen(uint tableid, uint serviceid,
00663                                       uint section)
00664 {
00665     uint key = (tableid<<16) | serviceid;
00666     sections_map_t::iterator it = _eit_section_seen.find(key);
00667     if (it == _eit_section_seen.end())
00668     {
00669         _eit_section_seen[key].resize(32, 0);
00670         it = _eit_section_seen.find(key);
00671     }
00672     (*it)[section>>3] |= bit_sel[section & 0x7];
00673 }
00674 
00675 bool DVBStreamData::EITSectionSeen(uint tableid, uint serviceid,
00676                                    uint section) const
00677 {
00678     uint key = (tableid<<16) | serviceid;
00679     sections_map_t::const_iterator it = _eit_section_seen.find(key);
00680     if (it == _eit_section_seen.end())
00681         return false;
00682     return (bool) ((*it)[section>>3] & bit_sel[section & 0x7]);
00683 }
00684 
00685 void DVBStreamData::SetCITSectionSeen(uint contentid, uint section)
00686 {
00687     sections_map_t::iterator it = _cit_section_seen.find(contentid);
00688     if (it == _cit_section_seen.end())
00689     {
00690         _cit_section_seen[contentid].resize(32, 0);
00691         it = _cit_section_seen.find(contentid);
00692     }
00693     (*it)[section>>3] |= bit_sel[section & 0x7];
00694 }
00695 
00696 bool DVBStreamData::CITSectionSeen(uint contentid, uint section) const
00697 {
00698     sections_map_t::const_iterator it = _cit_section_seen.find(contentid);
00699     if (it == _cit_section_seen.end())
00700         return false;
00701     return (bool) ((*it)[section>>3] & bit_sel[section & 0x7]);
00702 }
00703 
00704 bool DVBStreamData::HasCachedAnyNIT(bool current) const
00705 {
00706     QMutexLocker locker(&_cache_lock);
00707 
00708     if (!current)
00709         LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00710 
00711     return (bool)(_cached_nit.size());
00712 }
00713 
00714 bool DVBStreamData::HasCachedAllNIT(bool current) const
00715 {
00716     QMutexLocker locker(&_cache_lock);
00717 
00718     if (!current)
00719         LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00720 
00721     if (_cached_nit.empty())
00722         return false;
00723 
00724     uint last_section = (*_cached_nit.begin())->LastSection();
00725     if (!last_section)
00726         return true;
00727 
00728     for (uint i = 0; i <= last_section; i++)
00729         if (_cached_nit.find(i) == _cached_nit.end())
00730             return false;
00731 
00732     return true;
00733 }
00734 
00735 bool DVBStreamData::HasCachedAllSDT(uint tsid, bool current) const
00736 {
00737     QMutexLocker locker(&_cache_lock);
00738 
00739     if (!current)
00740         LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00741 
00742     sdt_cache_t::const_iterator it = _cached_sdts.find(tsid << 8);
00743     if (it == _cached_sdts.end())
00744         return false;
00745 
00746     uint last_section = (*it)->LastSection();
00747     if (!last_section)
00748         return true;
00749 
00750     for (uint i = 1; i <= last_section; i++)
00751         if (_cached_sdts.find((tsid << 8) | i) == _cached_sdts.end())
00752             return false;
00753 
00754     return true;
00755 }
00756 
00757 bool DVBStreamData::HasCachedAnySDT(uint tsid, bool current) const
00758 {
00759     QMutexLocker locker(&_cache_lock);
00760 
00761     if (!current)
00762         LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00763 
00764     for (uint i = 0; i <= 255; i++)
00765         if (_cached_sdts.find((tsid << 8) | i) != _cached_sdts.end())
00766             return true;
00767 
00768     return false;
00769 }
00770 
00771 bool DVBStreamData::HasCachedSDT(bool current) const
00772 {
00773     QMutexLocker locker(&_cache_lock);
00774 
00775     if (_cached_nit.empty())
00776         return false;
00777 
00778     nit_cache_t::const_iterator it = _cached_nit.begin();
00779     for (; it != _cached_nit.end(); ++it)
00780     {
00781         for (uint i = 0; i < (*it)->TransportStreamCount(); i++)
00782         {
00783             if (HasCachedAllSDT((*it)->TSID(i), current))
00784                 return true;
00785         }
00786     }
00787 
00788     return false;
00789 }
00790 
00791 bool DVBStreamData::HasCachedAnySDTs(bool current) const
00792 {
00793     QMutexLocker locker(&_cache_lock);
00794     return !_cached_sdts.empty();
00795 }
00796 
00797 bool DVBStreamData::HasCachedAllSDTs(bool current) const
00798 {
00799     QMutexLocker locker(&_cache_lock);
00800 
00801     if (_cached_nit.empty())
00802         return false;
00803 
00804     nit_cache_t::const_iterator it = _cached_nit.begin();
00805     for (; it != _cached_nit.end(); ++it)
00806     {
00807         if ((int)(*it)->TransportStreamCount() > _cached_sdts.size())
00808             return false;
00809 
00810         for (uint i = 0; i < (*it)->TransportStreamCount(); i++)
00811             if (!HasCachedAllSDT((*it)->TSID(i), current))
00812                 return false;
00813     }
00814 
00815     return true;
00816 }
00817 
00818 const nit_ptr_t DVBStreamData::GetCachedNIT(
00819     uint section_num, bool current) const
00820 {
00821     QMutexLocker locker(&_cache_lock);
00822 
00823     if (!current)
00824         LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00825 
00826     nit_ptr_t nit = NULL;
00827 
00828     nit_cache_t::const_iterator it = _cached_nit.find(section_num);
00829     if (it != _cached_nit.end())
00830         IncrementRefCnt(nit = *it);
00831 
00832     return nit;
00833 }
00834 
00835 const nit_vec_t DVBStreamData::GetCachedNIT(bool current) const
00836 {
00837     QMutexLocker locker(&_cache_lock);
00838 
00839     nit_vec_t nits;
00840 
00841     for (uint i = 0; i < 256; i++)
00842     {
00843         nit_ptr_t nit = GetCachedNIT(i, current);
00844         if (nit)
00845             nits.push_back(nit);
00846     }
00847 
00848     return nits;
00849 }
00850 
00851 const sdt_ptr_t DVBStreamData::GetCachedSDT(
00852     uint tsid, uint section_num, bool current) const
00853 {
00854     QMutexLocker locker(&_cache_lock);
00855 
00856     if (!current)
00857         LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00858 
00859     sdt_ptr_t sdt = NULL;
00860 
00861     uint key = (tsid << 8) | section_num;
00862     sdt_cache_t::const_iterator it = _cached_sdts.find(key);
00863     if (it != _cached_sdts.end())
00864         IncrementRefCnt(sdt = *it);
00865 
00866     return sdt;
00867 }
00868 
00869 const sdt_vec_t DVBStreamData::GetCachedSDTs(bool current) const
00870 {
00871     QMutexLocker locker(&_cache_lock);
00872 
00873     if (!current)
00874         LOG(VB_GENERAL, LOG_WARNING, "Currently we ignore \'current\' param");
00875 
00876     sdt_vec_t sdts;
00877 
00878     sdt_cache_t::const_iterator it = _cached_sdts.begin();
00879     for (; it != _cached_sdts.end(); ++it)
00880     {
00881         IncrementRefCnt(*it);
00882         sdts.push_back(*it);
00883     }
00884 
00885     return sdts;
00886 }
00887 
00888 void DVBStreamData::ReturnCachedSDTTables(sdt_vec_t &sdts) const
00889 {
00890     for (sdt_vec_t::iterator it = sdts.begin(); it != sdts.end(); ++it)
00891         ReturnCachedTable(*it);
00892     sdts.clear();
00893 }
00894 
00895 bool DVBStreamData::DeleteCachedTable(PSIPTable *psip) const
00896 {
00897     if (!psip)
00898         return false;
00899 
00900     uint tid = psip->TableIDExtension();
00901 
00902     QMutexLocker locker(&_cache_lock);
00903     if (_cached_ref_cnt[psip] > 0)
00904     {
00905         _cached_slated_for_deletion[psip] = 1;
00906         return false;
00907     }
00908     else if ((TableID::NIT == psip->TableID()) &&
00909              _cached_nit[psip->Section()])
00910     {
00911         _cached_nit[psip->Section()] = NULL;
00912         delete psip;
00913     }
00914     else if ((TableID::SDT == psip->TableID()) &&
00915              _cached_sdts[tid << 8 | psip->Section()])
00916     {
00917         _cached_sdts[tid << 8 | psip->Section()] = NULL;
00918         delete psip;
00919     }
00920     else
00921     {
00922         return MPEGStreamData::DeleteCachedTable(psip);
00923     }
00924     psip_refcnt_map_t::iterator it;
00925     it = _cached_slated_for_deletion.find(psip);
00926     if (it != _cached_slated_for_deletion.end())
00927         _cached_slated_for_deletion.erase(it);
00928 
00929     return true;
00930 }
00931 
00932 void DVBStreamData::CacheNIT(NetworkInformationTable *nit)
00933 {
00934     QMutexLocker locker(&_cache_lock);
00935 
00936     nit_cache_t::iterator it = _cached_nit.find(nit->Section());
00937     if (it != _cached_nit.end())
00938         DeleteCachedTable(*it);
00939 
00940     _cached_nit[nit->Section()] = nit;
00941 }
00942 
00943 void DVBStreamData::CacheSDT(ServiceDescriptionTable *sdt)
00944 {
00945     uint key = (sdt->TSID() << 8) | sdt->Section();
00946 
00947     QMutexLocker locker(&_cache_lock);
00948 
00949     sdt_cache_t::iterator it = _cached_sdts.find(key);
00950     if (it != _cached_sdts.end())
00951         DeleteCachedTable(*it);
00952 
00953     _cached_sdts[key] = sdt;
00954 }
00955 
00956 void DVBStreamData::AddDVBMainListener(DVBMainStreamListener *val)
00957 {
00958     QMutexLocker locker(&_listener_lock);
00959 
00960     dvb_main_listener_vec_t::iterator it = _dvb_main_listeners.begin();
00961     for (; it != _dvb_main_listeners.end(); ++it)
00962         if (((void*)val) == ((void*)*it))
00963             return;
00964 
00965     _dvb_main_listeners.push_back(val);
00966 }
00967 
00968 void DVBStreamData::RemoveDVBMainListener(DVBMainStreamListener *val)
00969 {
00970     QMutexLocker locker(&_listener_lock);
00971 
00972     dvb_main_listener_vec_t::iterator it = _dvb_main_listeners.begin();
00973     for (; it != _dvb_main_listeners.end(); ++it)
00974     {
00975         if (((void*)val) == ((void*)*it))
00976         {
00977             _dvb_main_listeners.erase(it);
00978             return;
00979         }
00980     }
00981 }
00982 
00983 void DVBStreamData::AddDVBOtherListener(DVBOtherStreamListener *val)
00984 {
00985     QMutexLocker locker(&_listener_lock);
00986 
00987     dvb_other_listener_vec_t::iterator it = _dvb_other_listeners.begin();
00988     for (; it != _dvb_other_listeners.end(); ++it)
00989         if (((void*)val) == ((void*)*it))
00990             return;
00991 
00992     _dvb_other_listeners.push_back(val);
00993 }
00994 
00995 void DVBStreamData::RemoveDVBOtherListener(DVBOtherStreamListener *val)
00996 {
00997     QMutexLocker locker(&_listener_lock);
00998 
00999     dvb_other_listener_vec_t::iterator it = _dvb_other_listeners.begin();
01000     for (; it != _dvb_other_listeners.end(); ++it)
01001     {
01002         if (((void*)val) == ((void*)*it))
01003         {
01004             _dvb_other_listeners.erase(it);
01005             return;
01006         }
01007     }
01008 }
01009 
01010 void DVBStreamData::AddDVBEITListener(DVBEITStreamListener *val)
01011 {
01012     QMutexLocker locker(&_listener_lock);
01013 
01014     dvb_eit_listener_vec_t::iterator it = _dvb_eit_listeners.begin();
01015     for (; it != _dvb_eit_listeners.end(); ++it)
01016         if (((void*)val) == ((void*)*it))
01017             return;
01018 
01019     _dvb_eit_listeners.push_back(val);
01020 }
01021 
01022 void DVBStreamData::RemoveDVBEITListener(DVBEITStreamListener *val)
01023 {
01024     QMutexLocker locker(&_listener_lock);
01025 
01026     dvb_eit_listener_vec_t::iterator it = _dvb_eit_listeners.begin();
01027     for (; it != _dvb_eit_listeners.end(); ++it)
01028     {
01029         if (((void*)val) == ((void*)*it))
01030         {
01031             _dvb_eit_listeners.erase(it);
01032             return;
01033         }
01034     }
01035 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends