MythTV  master
dvbstreamdata.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 // Copyright (c) 2003-2004, Daniel Thor Kristjansson
3 #include <algorithm>
4 using namespace std;
5 
6 #include <QSharedPointer>
7 #include "dvbstreamdata.h"
8 #include "dvbtables.h"
9 #include "premieretables.h"
10 #include "eithelper.h"
11 
12 #define PREMIERE_ONID 133
13 #define FREESAT_EIT_PID 3842
14 #define MCA_ONID 6144
15 #define MCA_EIT_TSID 136
16 #define MCA_EIT_PID 1018
17 
18 #define LOC QString("DVBStream[%1]: ").arg(_cardid)
19 
20 // service_id is synonymous with the MPEG program number in the PMT.
21 DVBStreamData::DVBStreamData(uint desired_netid, uint desired_tsid,
22  int desired_program, int cardnum, bool cacheTables)
23  : MPEGStreamData(desired_program, cardnum, cacheTables),
24  _desired_netid(desired_netid), _desired_tsid(desired_tsid),
25  _dvb_real_network_id(-1), _dvb_eit_dishnet_long(false)
26 {
27  _nit_status.SetVersion(-1,0);
32 }
33 
35 {
37 
38  QMutexLocker locker(&_listener_lock);
39  _dvb_main_listeners.clear();
40  _dvb_other_listeners.clear();
41  _dvb_eit_listeners.clear();
42  _dvb_has_eit.clear();
43 }
44 
45 void DVBStreamData::SetDesiredService(uint netid, uint tsid, int serviceid)
46 {
47  bool reset = true;
48 
49  if (HasCachedAllSDT(tsid, true))
50  {
51  sdt_const_ptr_t first_sdt = GetCachedSDT(tsid, 0, true);
52  uint networkID = first_sdt->OriginalNetworkID();
53  if (networkID == netid)
54  {
55  reset = false;
56  _desired_netid = netid;
57  _desired_tsid = tsid;
58  uint last_section = first_sdt->LastSection();
59  ProcessSDT(_desired_tsid, first_sdt);
60  ReturnCachedTable(first_sdt);
61  for (uint i = 1; i <= last_section; ++i)
62  {
65  ReturnCachedTable(sdt);
66  }
67  SetDesiredProgram(serviceid);
68  }
69  }
70 
71  if (reset)
72  Reset(netid, tsid, serviceid);
73 }
74 
75 
80 bool DVBStreamData::IsRedundant(uint pid, const PSIPTable &psip) const
81 {
82  if (MPEGStreamData::IsRedundant(pid, psip))
83  return true;
84 
85  const int table_id = psip.TableID();
86  const int version = psip.Version();
87 
88  if (TableID::NIT == table_id)
89  {
90  return _nit_status.IsSectionSeen(version, psip.Section());
91  }
92 
93  if (TableID::SDT == table_id)
94  {
96  }
97 
98  if (TableID::TDT == table_id)
99  return false;
100 
101  if (TableID::BAT == table_id)
102  {
103  return _bat_status.IsSectionSeen(psip.TableIDExtension(), version, psip.Section());
104  }
105 
106  bool is_eit = false;
107  if (DVB_EIT_PID == pid || FREESAT_EIT_PID == pid)
108  {
109  // Standard Now/Next Event Information Tables for this transport
110  is_eit |= TableID::PF_EIT == table_id;
111  // Standard Future Event Information Tables for this transport
112  is_eit |= (TableID::SC_EITbeg <= table_id &&
113  TableID::SC_EITend >= table_id);
114  }
115  if (is_eit)
116  {
117  uint service_id = psip.TableIDExtension();
118  uint key = (table_id<<16) | service_id;
119  return _eit_status.IsSectionSeen(key, version, psip.Section());
120  }
121 
123  // Other transport tables
124 
125  if (TableID::NITo == table_id)
126  {
127  return _nito_status.IsSectionSeen(version, psip.Section());
128  }
129 
130  if (TableID::SDTo == table_id)
131  {
133  }
134 
135  if (DVB_EIT_PID == pid || FREESAT_EIT_PID == pid || MCA_EIT_PID == pid)
136  {
137  // Standard Now/Next Event Information Tables for other transport
138  is_eit |= TableID::PF_EITo == table_id;
139  // Standard Future Event Information Tables for other transports
140  is_eit |= (TableID::SC_EITbego <= table_id &&
141  TableID::SC_EITendo >= table_id);
142  }
143  if (DVB_DNLONG_EIT_PID == pid || DVB_BVLONG_EIT_PID == pid)
144  {
145  // Dish Network and Bev Long Term Future Event Information
146  // for all transports
147  is_eit |= (TableID::DN_EITbego <= table_id &&
148  TableID::DN_EITendo >= table_id);
149  }
150  if (is_eit)
151  {
152  uint service_id = psip.TableIDExtension();
153  uint key = (table_id<<16) | service_id;
154  return _eit_status.IsSectionSeen(key, version, psip.Section());
155  }
156 
157  if (((PREMIERE_EIT_DIREKT_PID == pid) || (PREMIERE_EIT_SPORT_PID == pid)) &&
158  TableID::PREMIERE_CIT == table_id)
159  {
160  uint content_id = PremiereContentInformationTable(psip).ContentID();
161  return _cit_status.IsSectionSeen(content_id, version, psip.Section());
162  }
163 
164  return false;
165 }
166 
167 void DVBStreamData::Reset(uint desired_netid, uint desired_tsid,
168  int desired_serviceid)
169 {
170  MPEGStreamData::Reset(desired_serviceid);
171 
172  _desired_netid = desired_netid;
173  _desired_tsid = desired_tsid;
174 
175  _nit_status.SetVersion(-1,0);
176  _sdt_status.clear();
177  _eit_status.clear();
178  _cit_status.clear();
179 
180  _nito_status.SetVersion(-1,0);
181  _sdto_status.clear();
182  _bat_status.clear();
183 
184  {
185  _cache_lock.lock();
186 
187  nit_cache_t::iterator nit = _cached_nit.begin();
188  for (; nit != _cached_nit.end(); ++nit)
189  DeleteCachedTable(*nit);
190  _cached_nit.clear();
191 
192  sdt_cache_t::iterator sit = _cached_sdts.begin();
193  for (; sit != _cached_sdts.end(); ++sit)
194  DeleteCachedTable(*sit);
195  _cached_sdts.clear();
196 
197  _cache_lock.unlock();
198  }
202 }
203 
209 {
210  if (MPEGStreamData::HandleTables(pid, psip))
211  return true;
212 
213  if (IsRedundant(pid, psip))
214  return true;
215 
216  switch (psip.TableID())
217  {
218  case TableID::NIT:
219  {
221  {
223  if (!nit->Mutate())
224  {
225  delete nit;
226  return true;
227  }
228  bool retval = HandleTables(pid, *nit);
229  delete nit;
230  return retval;
231  }
232 
233  _nit_status.SetSectionSeen(psip.Version(), psip.Section(),
234  psip.LastSection());
235 
236  if (_cache_tables)
237  {
239  new NetworkInformationTable(psip);
240  CacheNIT(nit);
241  QMutexLocker locker(&_listener_lock);
242  for (size_t i = 0; i < _dvb_main_listeners.size(); i++)
243  _dvb_main_listeners[i]->HandleNIT(nit);
244  }
245  else
246  {
247  NetworkInformationTable nit(psip);
248  QMutexLocker locker(&_listener_lock);
249  for (size_t i = 0; i < _dvb_main_listeners.size(); i++)
250  _dvb_main_listeners[i]->HandleNIT(&nit);
251  }
252 
253  return true;
254  }
255  case TableID::SDT:
256  {
257  uint tsid = psip.TableIDExtension();
258  _sdt_status.SetSectionSeen(tsid, psip.Version(), psip.Section(),
259  psip.LastSection());
260 
261  if (_cache_tables)
262  {
264  new ServiceDescriptionTable(psip);
265  CacheSDT(sdt);
266  ProcessSDT(tsid, sdt);
267  }
268  else
269  {
270  ServiceDescriptionTable sdt(psip);
271  ProcessSDT(tsid, &sdt);
272  }
273 
274  return true;
275  }
276  case TableID::TDT:
277  {
278  TimeDateTable tdt(psip);
279 
280  UpdateTimeOffset(tdt.UTCUnix());
281 
282  QMutexLocker locker(&_listener_lock);
283  for (size_t i = 0; i < _dvb_main_listeners.size(); i++)
284  _dvb_main_listeners[i]->HandleTDT(&tdt);
285 
286  return true;
287  }
288  case TableID::NITo:
289  {
291  {
293  if (!nit->Mutate())
294  {
295  delete nit;
296  return true;
297  }
298  bool retval = HandleTables(pid, *nit);
299  delete nit;
300  return retval;
301  }
302 
304  psip.LastSection());
305  NetworkInformationTable nit(psip);
306 
307  QMutexLocker locker(&_listener_lock);
308  for (size_t i = 0; i < _dvb_other_listeners.size(); i++)
309  _dvb_other_listeners[i]->HandleNITo(&nit);
310 
311  return true;
312  }
313  case TableID::SDTo:
314  {
315  uint tsid = psip.TableIDExtension();
316  _sdto_status.SetSectionSeen(tsid, psip.Version(), psip.Section(),
317  psip.LastSection());
318  ServiceDescriptionTable sdt(psip);
319 
320  // some providers send the SDT for the current multiplex as SDTo
321  // this routine changes the TableID to SDT and recalculates the CRC
322  if (_desired_netid == sdt.OriginalNetworkID() &&
323  _desired_tsid == tsid)
324  {
326  new ServiceDescriptionTable(psip);
327  if (!sdta->Mutate())
328  {
329  delete sdta;
330  return true;
331  }
332  if (_cache_tables)
333  {
334  CacheSDT(sdta);
335  ProcessSDT(tsid, sdta);
336  }
337  else
338  {
339  ProcessSDT(tsid, sdta);
340  delete sdta;
341  }
342  return true;
343  }
344 
345  QMutexLocker locker(&_listener_lock);
346  for (size_t i = 0; i < _dvb_other_listeners.size(); i++)
347  _dvb_other_listeners[i]->HandleSDTo(tsid, &sdt);
348 
349  return true;
350  }
351  case TableID::BAT:
352  {
353  uint bid = psip.TableIDExtension();
354  _bat_status.SetSectionSeen(bid, psip.Version(), psip.Section(),
355  psip.LastSection());
356  BouquetAssociationTable bat(psip);
357 
358  QMutexLocker locker(&_listener_lock);
359  for (size_t i = 0; i < _dvb_other_listeners.size(); i++)
360  _dvb_other_listeners[i]->HandleBAT(&bat);
361 
362  return true;
363  }
364  }
365 
366  if ((DVB_EIT_PID == pid || DVB_DNLONG_EIT_PID == pid || FREESAT_EIT_PID == pid ||
368  (MCA_EIT_PID == pid)) || DVB_BVLONG_EIT_PID == pid) &&
369 
371  {
372  QMutexLocker locker(&_listener_lock);
373  if (_dvb_eit_listeners.empty() && !_eit_helper)
374  return true;
375 
376  uint service_id = psip.TableIDExtension();
377  uint key = (psip.TableID()<<16) | service_id;
378  _eit_status.SetSectionSeen(key, psip.Version(), psip.Section(),
379  psip.LastSection());
380 
381  DVBEventInformationTable eit(psip);
382  for (size_t i = 0; i < _dvb_eit_listeners.size(); i++)
383  _dvb_eit_listeners[i]->HandleEIT(&eit);
384 
385  if (_eit_helper)
386  _eit_helper->AddEIT(&eit);
387 
388  return true;
389  }
390 
391  if (_desired_netid == PREMIERE_ONID &&
392  (PREMIERE_EIT_DIREKT_PID == pid || PREMIERE_EIT_SPORT_PID == pid) &&
394  {
395  QMutexLocker locker(&_listener_lock);
396  if (_dvb_eit_listeners.empty() && !_eit_helper)
397  return true;
398 
400  _cit_status.SetSectionSeen(cit.ContentID(), psip.Version(), psip.Section(), psip.LastSection());
401 
402  for (size_t i = 0; i < _dvb_eit_listeners.size(); i++)
403  _dvb_eit_listeners[i]->HandleEIT(&cit);
404 
405  if (_eit_helper)
406  _eit_helper->AddEIT(&cit);
407 
408  return true;
409  }
410 
411  return false;
412 }
413 
415 {
416  QMutexLocker locker(&_listener_lock);
417 
418  for (uint i = 0; i < sdt->ServiceCount(); i++)
419  {
420  /*
421  * FIXME always signal EIT presence. We filter later. To many
422  * networks set these flags wrong.
423  * This allows the user to simply set useonairguide on a
424  * channel manually.
425  */
426 #if 0
427  if (sdt->HasEITSchedule(i) || sdt->HasEITPresentFollowing(i))
428 #endif
429  _dvb_has_eit[sdt->ServiceID(i)] = true;
430  }
431 
432  for (size_t i = 0; i < _dvb_main_listeners.size(); i++)
433  _dvb_main_listeners[i]->HandleSDT(tsid, sdt);
434 }
435 
436 bool DVBStreamData::HasEITPIDChanges(const uint_vec_t &in_use_pids) const
437 {
438  QMutexLocker locker(&_listener_lock);
439  bool want_eit = (_eit_rate >= 0.5F) && HasAnyEIT();
440  bool has_eit = !in_use_pids.empty();
441  return want_eit != has_eit;
442 }
443 
445  uint_vec_t &add_pids,
446  uint_vec_t &del_pids) const
447 {
448  QMutexLocker locker(&_listener_lock);
449 
450  if ((_eit_rate >= 0.5F) && HasAnyEIT())
451  {
452  if (find(cur_pids.begin(), cur_pids.end(),
453  (uint) DVB_EIT_PID) == cur_pids.end())
454  {
455  add_pids.push_back(DVB_EIT_PID);
456  }
457 
458  if (_dvb_eit_dishnet_long &&
459  find(cur_pids.begin(), cur_pids.end(),
460  (uint) DVB_DNLONG_EIT_PID) == cur_pids.end())
461  {
462  add_pids.push_back(DVB_DNLONG_EIT_PID);
463  }
464 
465  if (_dvb_eit_dishnet_long &&
466  find(cur_pids.begin(), cur_pids.end(),
467  (uint) DVB_BVLONG_EIT_PID) == cur_pids.end())
468  {
469  add_pids.push_back(DVB_BVLONG_EIT_PID);
470  }
471 
472  if (_desired_netid == PREMIERE_ONID &&
473  find(cur_pids.begin(), cur_pids.end(),
474  (uint) PREMIERE_EIT_DIREKT_PID) == cur_pids.end())
475  {
476  add_pids.push_back(PREMIERE_EIT_DIREKT_PID);
477  }
478 
479  if (_desired_netid == PREMIERE_ONID &&
480  find(cur_pids.begin(), cur_pids.end(),
481  (uint) PREMIERE_EIT_SPORT_PID) == cur_pids.end())
482  {
483  add_pids.push_back(PREMIERE_EIT_SPORT_PID);
484  }
485 
486  if (find(cur_pids.begin(), cur_pids.end(),
487  (uint) FREESAT_EIT_PID) == cur_pids.end())
488  {
489  add_pids.push_back(FREESAT_EIT_PID);
490  }
491 
493  find(cur_pids.begin(), cur_pids.end(),
494  (uint) MCA_EIT_PID) == cur_pids.end())
495  {
496  add_pids.push_back(MCA_EIT_PID);
497  }
498 
499  }
500  else
501  {
502  if (find(cur_pids.begin(), cur_pids.end(),
503  (uint) DVB_EIT_PID) != cur_pids.end())
504  {
505  del_pids.push_back(DVB_EIT_PID);
506  }
507 
508  if (_dvb_eit_dishnet_long &&
509  find(cur_pids.begin(), cur_pids.end(),
510  (uint) DVB_DNLONG_EIT_PID) != cur_pids.end())
511  {
512  del_pids.push_back(DVB_DNLONG_EIT_PID);
513  }
514 
515  if (_dvb_eit_dishnet_long &&
516  find(cur_pids.begin(), cur_pids.end(),
517  (uint) DVB_BVLONG_EIT_PID) != cur_pids.end())
518  {
519  del_pids.push_back(DVB_BVLONG_EIT_PID);
520  }
521 
522  if (_desired_netid == PREMIERE_ONID &&
523  find(cur_pids.begin(), cur_pids.end(),
524  (uint) PREMIERE_EIT_DIREKT_PID) != cur_pids.end())
525  {
526  del_pids.push_back(PREMIERE_EIT_DIREKT_PID);
527  }
528 
529  if (_desired_netid == PREMIERE_ONID &&
530  find(cur_pids.begin(), cur_pids.end(),
531  (uint) PREMIERE_EIT_SPORT_PID) != cur_pids.end())
532  {
533  del_pids.push_back(PREMIERE_EIT_SPORT_PID);
534  }
535 
536  if (find(cur_pids.begin(), cur_pids.end(),
537  (uint) FREESAT_EIT_PID) != cur_pids.end())
538  {
539  del_pids.push_back(FREESAT_EIT_PID);
540  }
541 
543  find(cur_pids.begin(), cur_pids.end(),
544  (uint) MCA_EIT_PID) != cur_pids.end())
545  {
546  del_pids.push_back(MCA_EIT_PID);
547  }
548  }
549 
550  return !add_pids.empty() || !del_pids.empty();
551 }
552 
554 {
555  return _nit_status.HasAllSections();
556 }
557 
559 {
560  return _nito_status.HasAllSections();
561 }
562 
564 {
565  return _sdt_status.HasAllSections(tsid);
566 }
567 
569 {
570  return _sdto_status.HasAllSections(tsid);
571 }
572 
574 {
575  return _bat_status.HasAllSections(bid);
576 }
577 
579 {
580  QMutexLocker locker(&_cache_lock);
581 
582  if (!current)
583  LOG(VB_GENERAL, LOG_WARNING, LOC +
584  "Currently we ignore \'current\' param");
585 
586  return (bool)(_cached_nit.size());
587 }
588 
590 {
591  QMutexLocker locker(&_cache_lock);
592 
593  if (!current)
594  LOG(VB_GENERAL, LOG_WARNING, LOC +
595  "Currently we ignore \'current\' param");
596 
597  if (_cached_nit.empty())
598  return false;
599 
600  uint last_section = (*_cached_nit.begin())->LastSection();
601  if (!last_section)
602  return true;
603 
604  for (uint i = 0; i <= last_section; i++)
605  if (_cached_nit.find(i) == _cached_nit.end())
606  return false;
607 
608  return true;
609 }
610 
612 {
613  QMutexLocker locker(&_cache_lock);
614 
615  if (!current)
616  LOG(VB_GENERAL, LOG_WARNING, LOC +
617  "Currently we ignore \'current\' param");
618 
619  sdt_cache_t::const_iterator it = _cached_sdts.find(tsid << 8);
620  if (it == _cached_sdts.end())
621  return false;
622 
623  uint last_section = (*it)->LastSection();
624  if (!last_section)
625  return true;
626 
627  for (uint i = 1; i <= last_section; i++)
628  if (_cached_sdts.find((tsid << 8) | i) == _cached_sdts.end())
629  return false;
630 
631  return true;
632 }
633 
635 {
636  QMutexLocker locker(&_cache_lock);
637 
638  if (!current)
639  LOG(VB_GENERAL, LOG_WARNING, LOC +
640  "Currently we ignore \'current\' param");
641 
642  for (uint i = 0; i <= 255; i++)
643  if (_cached_sdts.find((tsid << 8) | i) != _cached_sdts.end())
644  return true;
645 
646  return false;
647 }
648 
650 {
651  QMutexLocker locker(&_cache_lock);
652 
653  if (_cached_nit.empty())
654  return false;
655 
656  nit_cache_t::const_iterator it = _cached_nit.begin();
657  for (; it != _cached_nit.end(); ++it)
658  {
659  for (uint i = 0; i < (*it)->TransportStreamCount(); i++)
660  {
661  if (HasCachedAllSDT((*it)->TSID(i), current))
662  return true;
663  }
664  }
665 
666  return false;
667 }
668 
669 bool DVBStreamData::HasCachedAnySDTs(bool /*current*/) const
670 {
671  QMutexLocker locker(&_cache_lock);
672  return !_cached_sdts.empty();
673 }
674 
676 {
677  QMutexLocker locker(&_cache_lock);
678 
679  if (_cached_nit.empty())
680  return false;
681 
682  nit_cache_t::const_iterator it = _cached_nit.begin();
683  for (; it != _cached_nit.end(); ++it)
684  {
685  if ((int)(*it)->TransportStreamCount() > _cached_sdts.size())
686  return false;
687 
688  for (uint i = 0; i < (*it)->TransportStreamCount(); i++)
689  if (!HasCachedAllSDT((*it)->TSID(i), current))
690  return false;
691  }
692 
693  return true;
694 }
695 
697  uint section_num, bool current) const
698 {
699  QMutexLocker locker(&_cache_lock);
700 
701  if (!current)
702  LOG(VB_GENERAL, LOG_WARNING, LOC +
703  "Currently we ignore \'current\' param");
704 
705  nit_ptr_t nit = nullptr;
706 
707  nit_cache_t::const_iterator it = _cached_nit.find(section_num);
708  if (it != _cached_nit.end())
709  IncrementRefCnt(nit = *it);
710 
711  return nit;
712 }
713 
715 {
716  QMutexLocker locker(&_cache_lock);
717 
718  nit_vec_t nits;
719 
720  for (uint i = 0; i < 256; i++)
721  {
723  if (nit)
724  nits.push_back(nit);
725  }
726 
727  return nits;
728 }
729 
731  uint tsid, uint section_num, bool current) const
732 {
733  QMutexLocker locker(&_cache_lock);
734 
735  if (!current)
736  LOG(VB_GENERAL, LOG_WARNING, LOC +
737  "Currently we ignore \'current\' param");
738 
739  sdt_ptr_t sdt = nullptr;
740 
741  uint key = (tsid << 8) | section_num;
742  sdt_cache_t::const_iterator it = _cached_sdts.find(key);
743  if (it != _cached_sdts.end())
744  IncrementRefCnt(sdt = *it);
745 
746  return sdt;
747 }
748 
750 {
751  QMutexLocker locker(&_cache_lock);
752 
753  if (!current)
754  LOG(VB_GENERAL, LOG_WARNING, LOC +
755  "Currently we ignore \'current\' param");
756 
757  sdt_vec_t sdts;
758  sdt_const_ptr_t sdt = GetCachedSDT(tsid, 0);
759 
760  if (sdt)
761  {
762  uint lastSection = sdt->LastSection();
763 
764  sdts.push_back(sdt);
765 
766  for (uint section = 1; section <= lastSection; section++)
767  {
768  sdt = GetCachedSDT(tsid, section);
769 
770  if (sdt)
771  sdts.push_back(sdt);
772  }
773  }
774 
775  return sdts;
776 }
777 
779 {
780  QMutexLocker locker(&_cache_lock);
781 
782  if (!current)
783  LOG(VB_GENERAL, LOG_WARNING, LOC +
784  "Currently we ignore \'current\' param");
785 
786  sdt_vec_t sdts;
787 
788  sdt_cache_t::const_iterator it = _cached_sdts.begin();
789  for (; it != _cached_sdts.end(); ++it)
790  {
791  IncrementRefCnt(*it);
792  sdts.push_back(*it);
793  }
794 
795  return sdts;
796 }
797 
799 {
800  for (sdt_vec_t::iterator it = sdts.begin(); it != sdts.end(); ++it)
801  ReturnCachedTable(*it);
802  sdts.clear();
803 }
804 
806 {
807  if (!psip)
808  return false;
809 
810  uint tid = psip->TableIDExtension();
811 
812  QMutexLocker locker(&_cache_lock);
813  if (_cached_ref_cnt[psip] > 0)
814  {
815  _cached_slated_for_deletion[psip] = 1;
816  return false;
817  }
818  if ((TableID::NIT == psip->TableID()) &&
819  _cached_nit[psip->Section()])
820  {
821  _cached_nit[psip->Section()] = nullptr;
822  delete psip;
823  }
824  else if ((TableID::SDT == psip->TableID()) &&
825  _cached_sdts[tid << 8 | psip->Section()])
826  {
827  _cached_sdts[tid << 8 | psip->Section()] = nullptr;
828  delete psip;
829  }
830  else
831  {
833  }
834  psip_refcnt_map_t::iterator it;
835  it = _cached_slated_for_deletion.find(psip);
836  if (it != _cached_slated_for_deletion.end())
837  _cached_slated_for_deletion.erase(it);
838 
839  return true;
840 }
841 
843 {
844  QMutexLocker locker(&_cache_lock);
845 
846  nit_cache_t::iterator it = _cached_nit.find(nit->Section());
847  if (it != _cached_nit.end())
848  DeleteCachedTable(*it);
849 
850  _cached_nit[nit->Section()] = nit;
851 }
852 
854 {
855  uint key = (sdt->TSID() << 8) | sdt->Section();
856 
857  QMutexLocker locker(&_cache_lock);
858 
859  sdt_cache_t::iterator it = _cached_sdts.find(key);
860  if (it != _cached_sdts.end())
861  DeleteCachedTable(*it);
862 
863  _cached_sdts[key] = sdt;
864 }
865 
867 {
868  QMutexLocker locker(&_listener_lock);
869 
870  dvb_main_listener_vec_t::iterator it = _dvb_main_listeners.begin();
871  for (; it != _dvb_main_listeners.end(); ++it)
872  if (((void*)val) == ((void*)*it))
873  return;
874 
875  _dvb_main_listeners.push_back(val);
876 }
877 
879 {
880  QMutexLocker locker(&_listener_lock);
881 
882  dvb_main_listener_vec_t::iterator it = _dvb_main_listeners.begin();
883  for (; it != _dvb_main_listeners.end(); ++it)
884  {
885  if (((void*)val) == ((void*)*it))
886  {
887  _dvb_main_listeners.erase(it);
888  return;
889  }
890  }
891 }
892 
894 {
895  QMutexLocker locker(&_listener_lock);
896 
897  dvb_other_listener_vec_t::iterator it = _dvb_other_listeners.begin();
898  for (; it != _dvb_other_listeners.end(); ++it)
899  if (((void*)val) == ((void*)*it))
900  return;
901 
902  _dvb_other_listeners.push_back(val);
903 }
904 
906 {
907  QMutexLocker locker(&_listener_lock);
908 
909  dvb_other_listener_vec_t::iterator it = _dvb_other_listeners.begin();
910  for (; it != _dvb_other_listeners.end(); ++it)
911  {
912  if (((void*)val) == ((void*)*it))
913  {
914  _dvb_other_listeners.erase(it);
915  return;
916  }
917  }
918 }
919 
921 {
922  QMutexLocker locker(&_listener_lock);
923 
924  dvb_eit_listener_vec_t::iterator it = _dvb_eit_listeners.begin();
925  for (; it != _dvb_eit_listeners.end(); ++it)
926  if (((void*)val) == ((void*)*it))
927  return;
928 
929  _dvb_eit_listeners.push_back(val);
930 }
931 
933 {
934  QMutexLocker locker(&_listener_lock);
935 
936  dvb_eit_listener_vec_t::iterator it = _dvb_eit_listeners.begin();
937  for (; it != _dvb_eit_listeners.end(); ++it)
938  {
939  if (((void*)val) == ((void*)*it))
940  {
941  _dvb_eit_listeners.erase(it);
942  return;
943  }
944  }
945 }
bool IsSectionSeen(uint32_t key, int32_t version, uint32_t section) const
Definition: tablestatus.cpp:73
bool HasCachedAnyNIT(bool current=true) const
uint Version(void) const
Definition: mpegtables.h:503
bool Mutate(void)
mutates a SDTo into a SDTa (vice versa) and recalculates the CRC
Definition: dvbtables.cpp:176
virtual void Reset(void)
bool HasAnyEIT(void) const
bool HasAllSections() const
Definition: tablestatus.cpp:49
bool HasEITPresentFollowing(uint i) const
Definition: dvbtables.h:146
bool HasAllSDTSections(uint tsid) const
virtual void ReturnCachedTable(const PSIPTable *psip) const
virtual bool IsRedundant(uint pid, const PSIPTable &) const
Returns true if table already seen.
TableStatus _nito_status
void SetSectionSeen(int32_t version, uint32_t section, uint32_t last_section, uint32_t segment_last_section=0xffff)
Definition: tablestatus.cpp:30
sdt_vec_t GetCachedSDTSections(uint tsid, bool current=true) const
This table tells the decoder on which PIDs to find A/V data.
Definition: dvbtables.h:101
uint TableIDExtension(void) const
Definition: mpegtables.h:496
#define LOC
time_t UTCUnix(void) const
Definition: dvbtables.h:393
dvb_eit_listener_vec_t _dvb_eit_listeners
uint ServiceID(uint i) const
service_id 16 0.0+p
Definition: dvbtables.h:141
#define MCA_EIT_TSID
static pid_list_t::iterator find(const PIDInfoMap &map, pid_list_t &list, pid_list_t::iterator begin, pid_list_t::iterator end, bool find_open)
uint _desired_netid
DVB table monitoring.
uint LastSection(void) const
Definition: mpegtables.h:515
#define MCA_ONID
This table gives the current DVB stream time.
Definition: dvbtables.h:373
bool Mutate(void)
mutates a NITo into a NITa (vice versa) and recalculates the CRC
Definition: dvbtables.cpp:85
virtual ~DVBStreamData()
ServiceDescriptionTable const * sdt_const_ptr_t
Definition: dvbstreamdata.h:16
TableStatusMap _sdt_status
virtual bool HandleTables(uint pid, const PSIPTable &psip)
Assembles PSIP packets and processes them.
unsigned int uint
Definition: compat.h:140
dvb_other_listener_vec_t _dvb_other_listeners
#define MCA_EIT_PID
uint TSID() const
transport_stream_id 16 3.0 0x0000
Definition: dvbtables.h:129
psip_refcnt_map_t _cached_ref_cnt
void CacheNIT(NetworkInformationTable *)
DVBStreamData(uint desired_netid, uint desired_tsid, int desired_program, int cardnum, bool cacheTables=false)
bool HasAllSDToSections(uint tsid) const
#define PREMIERE_ONID
void AddEIT(uint atsc_major, uint atsc_minor, const EventInformationTable *eit)
Definition: eithelper.cpp:145
bool HasCachedAllNIT(bool current=true) const
uint Section(void) const
Definition: mpegtables.h:512
static bool IsEIT(uint table_id)
Definition: dvbtables.cpp:253
void SetSectionSeen(uint32_t key, int32_t version, uint32_t section, uint32_t last_section, uint32_t segment_last_section=0xffff)
Definition: tablestatus.cpp:65
TableStatusMap _eit_status
void AddDVBMainListener(DVBMainStreamListener *)
int _dvb_real_network_id
bool HandleTables(uint pid, const PSIPTable &) override
Assembles PSIP packets and processes them.
NetworkInformationTable const * nit_const_ptr_t
Definition: dvbstreamdata.h:11
bool HasAllNIToSections(void) const
bool IsSectionSeen(int32_t version, uint32_t section) const
Definition: tablestatus.cpp:41
uint OriginalNetworkID() const
original_network_id 16 8.0
Definition: dvbtables.h:132
A PSIP table is a variant of a PES packet containing an MPEG, ATSC or DVB table.
Definition: mpegtables.h:371
bool HasEITPIDChanges(const uint_vec_t &in_use_pids) const override
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
void CacheSDT(ServiceDescriptionTable *)
bool HasCachedAnySDT(uint tsid, bool current=true) const
bool HasAllNITSections(void) const
bool HasCachedSDT(bool current=true) const
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
void SetDesiredProgram(int p)
bool DeleteCachedTable(PSIPTable *psip) const override
sdt_cache_t _cached_sdts
TableStatusMap _sdto_status
uint ServiceCount() const
Number of services.
Definition: dvbtables.h:136
void ProcessSDT(uint tsid, const ServiceDescriptionTable *)
psip_refcnt_map_t _cached_slated_for_deletion
TableStatusMap _bat_status
bool HasAllSections(uint32_t key) const
Definition: tablestatus.cpp:81
sdt_const_ptr_t GetCachedSDT(uint tsid, uint section_num, bool current=true) const
bool HasCachedAllSDTs(bool current=true) const
void RemoveDVBEITListener(DVBEITStreamListener *)
sdt_vec_t GetCachedSDTs(bool current=true) const
void ReturnCachedSDTTables(sdt_vec_t &) const
bool HasEITSchedule(uint i) const
Definition: dvbtables.h:144
vector< const NetworkInformationTable * > nit_vec_t
Definition: dvbstreamdata.h:12
bool GetEITPIDChanges(const uint_vec_t &cur_pids, uint_vec_t &add_pids, uint_vec_t &del_pids) const override
void UpdateTimeOffset(uint64_t si_utc_time)
void IncrementRefCnt(const PSIPTable *psip) const
TableStatusMap _cit_status
nit_cache_t _cached_nit
vector< uint > uint_vec_t
void AddDVBEITListener(DVBEITStreamListener *)
dvb_main_listener_vec_t _dvb_main_listeners
virtual void AddListeningPID(uint pid, PIDPriority priority=kPIDPriorityNormal)
EITHelper * _eit_helper
uint TableID(void) const
Definition: mpegtables.h:479
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
bool HasCachedAllSDT(uint tsid, bool current=true) const
nit_const_ptr_t GetCachedNIT(uint section_num, bool current=true) const
static bool IsEIT(uint table_id)
void RemoveDVBOtherListener(DVBOtherStreamListener *)
void Reset(void) override
Definition: dvbstreamdata.h:35
void RemoveDVBMainListener(DVBMainStreamListener *)
virtual bool DeleteCachedTable(PSIPTable *psip) const
#define FREESAT_EIT_PID
bool HasAllBATSections(uint bid) const
bool _dvb_eit_dishnet_long
Decode DishNet's long-term DVB EIT.
Tells what channels can be found on each transponder for one bouquet (a bunch of channels from one pr...
Definition: dvbtables.h:179
void AddDVBOtherListener(DVBOtherStreamListener *)
bool HasCachedAnySDTs(bool current=true) const
TableStatus _nit_status
vector< const ServiceDescriptionTable * > sdt_vec_t
Definition: dvbstreamdata.h:17
dvb_has_eit_t _dvb_has_eit
Tell us if the DVB service has EIT.
void SetDesiredService(uint netid, uint tsid, int serviceid)
This table tells the decoder on which PIDs to find other tables.
Definition: dvbtables.h:21
void SetVersion(int32_t version, uint32_t last_section)
Definition: tablestatus.cpp:21
bool IsRedundant(uint pid, const PSIPTable &) const override
Returns true if table already seen.
Encapsulates data about MPEG stream and emits events for each table.