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  bat_cache_t::iterator bat = _cached_bats.begin();
198  for (; bat != _cached_bats.end(); ++bat)
199  DeleteCachedTable(*bat);
200  _cached_bats.clear();
201 
202  _cache_lock.unlock();
203  }
207 }
208 
214 {
215  if (MPEGStreamData::HandleTables(pid, psip))
216  return true;
217 
218  if (IsRedundant(pid, psip))
219  return true;
220 
221  switch (psip.TableID())
222  {
223  case TableID::NIT:
224  {
226  {
228  if (!nit->Mutate())
229  {
230  delete nit;
231  return true;
232  }
233  bool retval = HandleTables(pid, *nit);
234  delete nit;
235  return retval;
236  }
237 
238  _nit_status.SetSectionSeen(psip.Version(), psip.Section(),
239  psip.LastSection());
240 
241  if (_cache_tables)
242  {
244  new NetworkInformationTable(psip);
245  CacheNIT(nit);
246  QMutexLocker locker(&_listener_lock);
247  for (size_t i = 0; i < _dvb_main_listeners.size(); i++)
248  _dvb_main_listeners[i]->HandleNIT(nit);
249  }
250  else
251  {
252  NetworkInformationTable nit(psip);
253  QMutexLocker locker(&_listener_lock);
254  for (size_t i = 0; i < _dvb_main_listeners.size(); i++)
255  _dvb_main_listeners[i]->HandleNIT(&nit);
256  }
257 
258  return true;
259  }
260  case TableID::SDT:
261  {
262  uint tsid = psip.TableIDExtension();
263  _sdt_status.SetSectionSeen(tsid, psip.Version(), psip.Section(),
264  psip.LastSection());
265 
266  if (_cache_tables)
267  {
269  new ServiceDescriptionTable(psip);
270  CacheSDT(sdt);
271  ProcessSDT(tsid, sdt);
272  }
273  else
274  {
275  ServiceDescriptionTable sdt(psip);
276  ProcessSDT(tsid, &sdt);
277  }
278 
279  return true;
280  }
281  case TableID::TDT:
282  {
283  TimeDateTable tdt(psip);
284 
285  UpdateTimeOffset(tdt.UTCUnix());
286 
287  QMutexLocker locker(&_listener_lock);
288  for (size_t i = 0; i < _dvb_main_listeners.size(); i++)
289  _dvb_main_listeners[i]->HandleTDT(&tdt);
290 
291  return true;
292  }
293  case TableID::NITo:
294  {
296  {
298  if (!nit->Mutate())
299  {
300  delete nit;
301  return true;
302  }
303  bool retval = HandleTables(pid, *nit);
304  delete nit;
305  return retval;
306  }
307 
309  psip.LastSection());
310  NetworkInformationTable nit(psip);
311 
312  QMutexLocker locker(&_listener_lock);
313  for (size_t i = 0; i < _dvb_other_listeners.size(); i++)
314  _dvb_other_listeners[i]->HandleNITo(&nit);
315 
316  return true;
317  }
318  case TableID::SDTo:
319  {
320  uint tsid = psip.TableIDExtension();
321  _sdto_status.SetSectionSeen(tsid, psip.Version(), psip.Section(),
322  psip.LastSection());
323  ServiceDescriptionTable sdt(psip);
324 
325  // some providers send the SDT for the current multiplex as SDTo
326  // this routine changes the TableID to SDT and recalculates the CRC
327  if (_desired_netid == sdt.OriginalNetworkID() &&
328  _desired_tsid == tsid)
329  {
331  new ServiceDescriptionTable(psip);
332  if (!sdta->Mutate())
333  {
334  delete sdta;
335  return true;
336  }
337  if (_cache_tables)
338  {
339  CacheSDT(sdta);
340  ProcessSDT(tsid, sdta);
341  }
342  else
343  {
344  ProcessSDT(tsid, sdta);
345  delete sdta;
346  }
347  return true;
348  }
349 
350  QMutexLocker locker(&_listener_lock);
351  for (size_t i = 0; i < _dvb_other_listeners.size(); i++)
352  _dvb_other_listeners[i]->HandleSDTo(tsid, &sdt);
353 
354  return true;
355  }
356  case TableID::BAT:
357  {
358  uint bouquet_id = psip.TableIDExtension();
359  _bat_status.SetSectionSeen(bouquet_id, psip.Version(), psip.Section(),
360  psip.LastSection());
361 
362  if (_cache_tables)
363  {
365  new BouquetAssociationTable(psip);
366  CacheBAT(bat);
367  QMutexLocker locker(&_listener_lock);
368  for (size_t i = 0; i < _dvb_other_listeners.size(); i++)
369  _dvb_other_listeners[i]->HandleBAT(bat);
370  }
371  else
372  {
373  BouquetAssociationTable bat(psip);
374  QMutexLocker locker(&_listener_lock);
375  for (size_t i = 0; i < _dvb_other_listeners.size(); i++)
376  _dvb_other_listeners[i]->HandleBAT(&bat);
377  }
378 
379  return true;
380  }
381  }
382 
383  if ((DVB_EIT_PID == pid || DVB_DNLONG_EIT_PID == pid || FREESAT_EIT_PID == pid ||
385  (MCA_EIT_PID == pid)) || DVB_BVLONG_EIT_PID == pid) &&
386 
388  {
389  QMutexLocker locker(&_listener_lock);
390  if (_dvb_eit_listeners.empty() && !_eit_helper)
391  return true;
392 
393  uint service_id = psip.TableIDExtension();
394  uint key = (psip.TableID()<<16) | service_id;
395  _eit_status.SetSectionSeen(key, psip.Version(), psip.Section(),
396  psip.LastSection());
397 
398  DVBEventInformationTable eit(psip);
399  for (size_t i = 0; i < _dvb_eit_listeners.size(); i++)
400  _dvb_eit_listeners[i]->HandleEIT(&eit);
401 
402  if (_eit_helper)
403  _eit_helper->AddEIT(&eit);
404 
405  return true;
406  }
407 
408  if (_desired_netid == PREMIERE_ONID &&
409  (PREMIERE_EIT_DIREKT_PID == pid || PREMIERE_EIT_SPORT_PID == pid) &&
411  {
412  QMutexLocker locker(&_listener_lock);
413  if (_dvb_eit_listeners.empty() && !_eit_helper)
414  return true;
415 
417  _cit_status.SetSectionSeen(cit.ContentID(), psip.Version(), psip.Section(), psip.LastSection());
418 
419  for (size_t i = 0; i < _dvb_eit_listeners.size(); i++)
420  _dvb_eit_listeners[i]->HandleEIT(&cit);
421 
422  if (_eit_helper)
423  _eit_helper->AddEIT(&cit);
424 
425  return true;
426  }
427 
428  return false;
429 }
430 
432 {
433  QMutexLocker locker(&_listener_lock);
434 
435  for (uint i = 0; i < sdt->ServiceCount(); i++)
436  {
437  /*
438  * FIXME always signal EIT presence. We filter later. To many
439  * networks set these flags wrong.
440  * This allows the user to simply set useonairguide on a
441  * channel manually.
442  */
443 #if 0
444  if (sdt->HasEITSchedule(i) || sdt->HasEITPresentFollowing(i))
445 #endif
446  _dvb_has_eit[sdt->ServiceID(i)] = true;
447  }
448 
449  for (size_t i = 0; i < _dvb_main_listeners.size(); i++)
450  _dvb_main_listeners[i]->HandleSDT(tsid, sdt);
451 }
452 
453 bool DVBStreamData::HasEITPIDChanges(const uint_vec_t &in_use_pids) const
454 {
455  QMutexLocker locker(&_listener_lock);
456  bool want_eit = (_eit_rate >= 0.5F) && HasAnyEIT();
457  bool has_eit = !in_use_pids.empty();
458  return want_eit != has_eit;
459 }
460 
462  uint_vec_t &add_pids,
463  uint_vec_t &del_pids) const
464 {
465  QMutexLocker locker(&_listener_lock);
466 
467  if ((_eit_rate >= 0.5F) && HasAnyEIT())
468  {
469  if (find(cur_pids.begin(), cur_pids.end(),
470  (uint) DVB_EIT_PID) == cur_pids.end())
471  {
472  add_pids.push_back(DVB_EIT_PID);
473  }
474 
475  if (_dvb_eit_dishnet_long &&
476  find(cur_pids.begin(), cur_pids.end(),
477  (uint) DVB_DNLONG_EIT_PID) == cur_pids.end())
478  {
479  add_pids.push_back(DVB_DNLONG_EIT_PID);
480  }
481 
482  if (_dvb_eit_dishnet_long &&
483  find(cur_pids.begin(), cur_pids.end(),
484  (uint) DVB_BVLONG_EIT_PID) == cur_pids.end())
485  {
486  add_pids.push_back(DVB_BVLONG_EIT_PID);
487  }
488 
489  if (_desired_netid == PREMIERE_ONID &&
490  find(cur_pids.begin(), cur_pids.end(),
491  (uint) PREMIERE_EIT_DIREKT_PID) == cur_pids.end())
492  {
493  add_pids.push_back(PREMIERE_EIT_DIREKT_PID);
494  }
495 
496  if (_desired_netid == PREMIERE_ONID &&
497  find(cur_pids.begin(), cur_pids.end(),
498  (uint) PREMIERE_EIT_SPORT_PID) == cur_pids.end())
499  {
500  add_pids.push_back(PREMIERE_EIT_SPORT_PID);
501  }
502 
503  if (find(cur_pids.begin(), cur_pids.end(),
504  (uint) FREESAT_EIT_PID) == cur_pids.end())
505  {
506  add_pids.push_back(FREESAT_EIT_PID);
507  }
508 
510  find(cur_pids.begin(), cur_pids.end(),
511  (uint) MCA_EIT_PID) == cur_pids.end())
512  {
513  add_pids.push_back(MCA_EIT_PID);
514  }
515 
516  }
517  else
518  {
519  if (find(cur_pids.begin(), cur_pids.end(),
520  (uint) DVB_EIT_PID) != cur_pids.end())
521  {
522  del_pids.push_back(DVB_EIT_PID);
523  }
524 
525  if (_dvb_eit_dishnet_long &&
526  find(cur_pids.begin(), cur_pids.end(),
527  (uint) DVB_DNLONG_EIT_PID) != cur_pids.end())
528  {
529  del_pids.push_back(DVB_DNLONG_EIT_PID);
530  }
531 
532  if (_dvb_eit_dishnet_long &&
533  find(cur_pids.begin(), cur_pids.end(),
534  (uint) DVB_BVLONG_EIT_PID) != cur_pids.end())
535  {
536  del_pids.push_back(DVB_BVLONG_EIT_PID);
537  }
538 
539  if (_desired_netid == PREMIERE_ONID &&
540  find(cur_pids.begin(), cur_pids.end(),
541  (uint) PREMIERE_EIT_DIREKT_PID) != cur_pids.end())
542  {
543  del_pids.push_back(PREMIERE_EIT_DIREKT_PID);
544  }
545 
546  if (_desired_netid == PREMIERE_ONID &&
547  find(cur_pids.begin(), cur_pids.end(),
548  (uint) PREMIERE_EIT_SPORT_PID) != cur_pids.end())
549  {
550  del_pids.push_back(PREMIERE_EIT_SPORT_PID);
551  }
552 
553  if (find(cur_pids.begin(), cur_pids.end(),
554  (uint) FREESAT_EIT_PID) != cur_pids.end())
555  {
556  del_pids.push_back(FREESAT_EIT_PID);
557  }
558 
560  find(cur_pids.begin(), cur_pids.end(),
561  (uint) MCA_EIT_PID) != cur_pids.end())
562  {
563  del_pids.push_back(MCA_EIT_PID);
564  }
565  }
566 
567  return !add_pids.empty() || !del_pids.empty();
568 }
569 
571 {
572  return _nit_status.HasAllSections();
573 }
574 
576 {
577  return _nito_status.HasAllSections();
578 }
579 
581 {
582  return _sdt_status.HasAllSections(tsid);
583 }
584 
586 {
587  return _sdto_status.HasAllSections(tsid);
588 }
589 
591 {
592  return _bat_status.HasAllSections(bid);
593 }
594 
596 {
597  QMutexLocker locker(&_cache_lock);
598 
599  if (!current)
600  LOG(VB_GENERAL, LOG_WARNING, LOC +
601  "Currently we ignore \'current\' param");
602 
603  return (bool)(_cached_nit.size());
604 }
605 
607 {
608  QMutexLocker locker(&_cache_lock);
609 
610  if (!current)
611  LOG(VB_GENERAL, LOG_WARNING, LOC +
612  "Currently we ignore \'current\' param");
613 
614  if (_cached_nit.empty())
615  return false;
616 
617  uint last_section = (*_cached_nit.begin())->LastSection();
618  if (!last_section)
619  return true;
620 
621  for (uint i = 0; i <= last_section; i++)
622  if (_cached_nit.find(i) == _cached_nit.end())
623  return false;
624 
625  return true;
626 }
627 
629 {
630  QMutexLocker locker(&_cache_lock);
631 
632  if (!current)
633  LOG(VB_GENERAL, LOG_WARNING, LOC +
634  "Currently we ignore \'current\' param");
635 
636  for (uint i = 0; i <= 255; i++)
637  if (_cached_bats.find((batid << 8) | i) != _cached_bats.end())
638  return true;
639 
640  return false;
641 }
642 
644 {
645  QMutexLocker locker(&_cache_lock);
646 
647  if (!current)
648  LOG(VB_GENERAL, LOG_WARNING, LOC +
649  "Currently we ignore \'current\' param");
650 
651  bat_cache_t::const_iterator it = _cached_bats.find(batid << 8);
652  if (it == _cached_bats.end())
653  return false;
654 
655  uint last_section = (*it)->LastSection();
656  if (!last_section)
657  return true;
658 
659  for (uint i = 1; i <= last_section; i++)
660  if (_cached_bats.find((batid << 8) | i) == _cached_bats.end())
661  return false;
662 
663  return true;
664 }
665 
666 bool DVBStreamData::HasCachedAnyBATs(bool /*current*/) const
667 {
668  QMutexLocker locker(&_cache_lock);
669  return !_cached_bats.empty();
670 }
671 
673 {
674  QMutexLocker locker(&_cache_lock);
675 
676  if (_cached_bats.empty())
677  return false;
678 
679  bat_cache_t::const_iterator it = _cached_bats.begin();
680  for (; it != _cached_bats.end(); ++it)
681  {
682  if (!HasCachedAllBAT(it.key() >> 8, current))
683  return false;
684  }
685 
686  return true;
687 }
688 
690 {
691  QMutexLocker locker(&_cache_lock);
692 
693  if (!current)
694  LOG(VB_GENERAL, LOG_WARNING, LOC +
695  "Currently we ignore \'current\' param");
696 
697  sdt_cache_t::const_iterator it = _cached_sdts.find(tsid << 8);
698  if (it == _cached_sdts.end())
699  return false;
700 
701  uint last_section = (*it)->LastSection();
702  if (!last_section)
703  return true;
704 
705  for (uint i = 1; i <= last_section; i++)
706  if (_cached_sdts.find((tsid << 8) | i) == _cached_sdts.end())
707  return false;
708 
709  return true;
710 }
711 
713 {
714  QMutexLocker locker(&_cache_lock);
715 
716  if (!current)
717  LOG(VB_GENERAL, LOG_WARNING, LOC +
718  "Currently we ignore \'current\' param");
719 
720  for (uint i = 0; i <= 255; i++)
721  if (_cached_sdts.find((tsid << 8) | i) != _cached_sdts.end())
722  return true;
723 
724  return false;
725 }
726 
728 {
729  QMutexLocker locker(&_cache_lock);
730 
731  if (_cached_nit.empty())
732  return false;
733 
734  nit_cache_t::const_iterator it = _cached_nit.begin();
735  for (; it != _cached_nit.end(); ++it)
736  {
737  for (uint i = 0; i < (*it)->TransportStreamCount(); i++)
738  {
739  if (HasCachedAllSDT((*it)->TSID(i), current))
740  return true;
741  }
742  }
743 
744  return false;
745 }
746 
747 bool DVBStreamData::HasCachedAnySDTs(bool /*current*/) const
748 {
749  QMutexLocker locker(&_cache_lock);
750  return !_cached_sdts.empty();
751 }
752 
754 {
755  QMutexLocker locker(&_cache_lock);
756 
757  if (_cached_nit.empty())
758  return false;
759 
760  nit_cache_t::const_iterator it = _cached_nit.begin();
761  for (; it != _cached_nit.end(); ++it)
762  {
763  if ((int)(*it)->TransportStreamCount() > _cached_sdts.size())
764  return false;
765 
766  for (uint i = 0; i < (*it)->TransportStreamCount(); i++)
767  if (!HasCachedAllSDT((*it)->TSID(i), current))
768  return false;
769  }
770 
771  return true;
772 }
773 
775  uint section_num, bool current) const
776 {
777  QMutexLocker locker(&_cache_lock);
778 
779  if (!current)
780  LOG(VB_GENERAL, LOG_WARNING, LOC +
781  "Currently we ignore \'current\' param");
782 
783  nit_ptr_t nit = nullptr;
784 
785  nit_cache_t::const_iterator it = _cached_nit.find(section_num);
786  if (it != _cached_nit.end())
787  IncrementRefCnt(nit = *it);
788 
789  return nit;
790 }
791 
793 {
794  QMutexLocker locker(&_cache_lock);
795 
796  nit_vec_t nits;
797 
798  for (uint i = 0; i < 256; i++)
799  {
801  if (nit)
802  nits.push_back(nit);
803  }
804 
805  return nits;
806 }
807 
809  uint batid, uint section_num, bool current) const
810 {
811  QMutexLocker locker(&_cache_lock);
812 
813  if (!current)
814  LOG(VB_GENERAL, LOG_WARNING, LOC +
815  "Currently we ignore \'current\' param");
816 
817  bat_ptr_t bat = nullptr;
818 
819  uint key = (batid << 8) | section_num;
820  bat_cache_t::const_iterator it = _cached_bats.find(key);
821  if (it != _cached_bats.end())
822  IncrementRefCnt(bat = *it);
823 
824  return bat;
825 }
826 
828 {
829  QMutexLocker locker(&_cache_lock);
830 
831  if (!current)
832  LOG(VB_GENERAL, LOG_WARNING, LOC +
833  "Currently we ignore \'current\' param");
834 
835  bat_vec_t bats;
836 
837  bat_cache_t::const_iterator it = _cached_bats.begin();
838  for (; it != _cached_bats.end(); ++it)
839  {
840  IncrementRefCnt(*it);
841  bats.push_back(*it);
842  }
843 
844  return bats;
845 }
846 
848  uint tsid, uint section_num, bool current) const
849 {
850  QMutexLocker locker(&_cache_lock);
851 
852  if (!current)
853  LOG(VB_GENERAL, LOG_WARNING, LOC +
854  "Currently we ignore \'current\' param");
855 
856  sdt_ptr_t sdt = nullptr;
857 
858  uint key = (tsid << 8) | section_num;
859  sdt_cache_t::const_iterator it = _cached_sdts.find(key);
860  if (it != _cached_sdts.end())
861  IncrementRefCnt(sdt = *it);
862 
863  return sdt;
864 }
865 
867 {
868  QMutexLocker locker(&_cache_lock);
869 
870  if (!current)
871  LOG(VB_GENERAL, LOG_WARNING, LOC +
872  "Currently we ignore \'current\' param");
873 
874  sdt_vec_t sdts;
875  sdt_const_ptr_t sdt = GetCachedSDT(tsid, 0);
876 
877  if (sdt)
878  {
879  uint lastSection = sdt->LastSection();
880 
881  sdts.push_back(sdt);
882 
883  for (uint section = 1; section <= lastSection; section++)
884  {
885  sdt = GetCachedSDT(tsid, section);
886 
887  if (sdt)
888  sdts.push_back(sdt);
889  }
890  }
891 
892  return sdts;
893 }
894 
896 {
897  QMutexLocker locker(&_cache_lock);
898 
899  if (!current)
900  LOG(VB_GENERAL, LOG_WARNING, LOC +
901  "Currently we ignore \'current\' param");
902 
903  sdt_vec_t sdts;
904 
905  sdt_cache_t::const_iterator it = _cached_sdts.begin();
906  for (; it != _cached_sdts.end(); ++it)
907  {
908  IncrementRefCnt(*it);
909  sdts.push_back(*it);
910  }
911 
912  return sdts;
913 }
914 
916 {
917  for (sdt_vec_t::iterator it = sdts.begin(); it != sdts.end(); ++it)
918  ReturnCachedTable(*it);
919  sdts.clear();
920 }
921 
923 {
924  if (!psip)
925  return false;
926 
927  uint tid = psip->TableIDExtension(); // For SDTs
928  uint bid = psip->TableIDExtension(); // For BATs
929 
930  QMutexLocker locker(&_cache_lock);
931  if (_cached_ref_cnt[psip] > 0)
932  {
933  _cached_slated_for_deletion[psip] = 1;
934  return false;
935  }
936  if ((TableID::NIT == psip->TableID()) &&
937  _cached_nit[psip->Section()])
938  {
939  _cached_nit[psip->Section()] = nullptr;
940  delete psip;
941  }
942  else if ((TableID::SDT == psip->TableID()) &&
943  _cached_sdts[tid << 8 | psip->Section()])
944  {
945  _cached_sdts[tid << 8 | psip->Section()] = nullptr;
946  delete psip;
947  }
948  else if ((TableID::BAT == psip->TableID()) &&
949  _cached_bats[bid << 8 | psip->Section()])
950  {
951  _cached_bats[bid << 8 | psip->Section()] = nullptr;
952  delete psip;
953  }
954  else
955  {
957  }
958  psip_refcnt_map_t::iterator it;
959  it = _cached_slated_for_deletion.find(psip);
960  if (it != _cached_slated_for_deletion.end())
961  _cached_slated_for_deletion.erase(it);
962 
963  return true;
964 }
965 
967 {
968  QMutexLocker locker(&_cache_lock);
969 
970  nit_cache_t::iterator it = _cached_nit.find(nit->Section());
971  if (it != _cached_nit.end())
972  DeleteCachedTable(*it);
973 
974  _cached_nit[nit->Section()] = nit;
975 }
976 
978 {
979  uint key = (bat->BouquetID() << 8) | bat->Section();
980 
981  QMutexLocker locker(&_cache_lock);
982 
983  bat_cache_t::iterator it = _cached_bats.find(key);
984  if (it != _cached_bats.end())
985  DeleteCachedTable(*it);
986 
987  _cached_bats[key] = bat;
988 }
989 
991 {
992  uint key = (sdt->TSID() << 8) | sdt->Section();
993 
994  QMutexLocker locker(&_cache_lock);
995 
996  sdt_cache_t::iterator it = _cached_sdts.find(key);
997  if (it != _cached_sdts.end())
998  DeleteCachedTable(*it);
999 
1000  _cached_sdts[key] = sdt;
1001 }
1002 
1004 {
1005  QMutexLocker locker(&_listener_lock);
1006 
1007  dvb_main_listener_vec_t::iterator it = _dvb_main_listeners.begin();
1008  for (; it != _dvb_main_listeners.end(); ++it)
1009  if (((void*)val) == ((void*)*it))
1010  return;
1011 
1012  _dvb_main_listeners.push_back(val);
1013 }
1014 
1016 {
1017  QMutexLocker locker(&_listener_lock);
1018 
1019  dvb_main_listener_vec_t::iterator it = _dvb_main_listeners.begin();
1020  for (; it != _dvb_main_listeners.end(); ++it)
1021  {
1022  if (((void*)val) == ((void*)*it))
1023  {
1024  _dvb_main_listeners.erase(it);
1025  return;
1026  }
1027  }
1028 }
1029 
1031 {
1032  QMutexLocker locker(&_listener_lock);
1033 
1034  dvb_other_listener_vec_t::iterator it = _dvb_other_listeners.begin();
1035  for (; it != _dvb_other_listeners.end(); ++it)
1036  if (((void*)val) == ((void*)*it))
1037  return;
1038 
1039  _dvb_other_listeners.push_back(val);
1040 }
1041 
1043 {
1044  QMutexLocker locker(&_listener_lock);
1045 
1046  dvb_other_listener_vec_t::iterator it = _dvb_other_listeners.begin();
1047  for (; it != _dvb_other_listeners.end(); ++it)
1048  {
1049  if (((void*)val) == ((void*)*it))
1050  {
1051  _dvb_other_listeners.erase(it);
1052  return;
1053  }
1054  }
1055 }
1056 
1058 {
1059  QMutexLocker locker(&_listener_lock);
1060 
1061  dvb_eit_listener_vec_t::iterator it = _dvb_eit_listeners.begin();
1062  for (; it != _dvb_eit_listeners.end(); ++it)
1063  if (((void*)val) == ((void*)*it))
1064  return;
1065 
1066  _dvb_eit_listeners.push_back(val);
1067 }
1068 
1070 {
1071  QMutexLocker locker(&_listener_lock);
1072 
1073  dvb_eit_listener_vec_t::iterator it = _dvb_eit_listeners.begin();
1074  for (; it != _dvb_eit_listeners.end(); ++it)
1075  {
1076  if (((void*)val) == ((void*)*it))
1077  {
1078  _dvb_eit_listeners.erase(it);
1079  return;
1080  }
1081  }
1082 }
bool IsSectionSeen(uint32_t key, int32_t version, uint32_t section) const
Definition: tablestatus.cpp:73
uint BouquetID() const
Definition: dvbtables.h:195
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:177
virtual void Reset(void)
bool HasAnyEIT(void) const
bool HasAllSections() const
Definition: tablestatus.cpp:49
bool HasEITPresentFollowing(uint i) const
Definition: dvbtables.h:146
BouquetAssociationTable const * bat_const_ptr_t
Definition: dvbstreamdata.h:22
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
bool HasCachedAnyBAT(uint batid, bool current=true) const
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
bat_const_ptr_t GetCachedBAT(uint batid, uint section_num, bool current=true) const
bat_cache_t _cached_bats
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:144
bool HasCachedAllNIT(bool current=true) const
uint Section(void) const
Definition: mpegtables.h:512
static bool IsEIT(uint table_id)
Definition: dvbtables.cpp:254
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 *)
vector< const BouquetAssociationTable * > bat_vec_t
Definition: dvbstreamdata.h:23
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
bat_vec_t GetCachedBATs(bool current=true) const
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
bool HasCachedAllBAT(uint batid, bool current=true) const
bool HasCachedAllBATs(bool current=true) const
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
bool HasCachedAnyBATs(bool current=true) const
#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:40
void RemoveDVBMainListener(DVBMainStreamListener *)
void CacheBAT(BouquetAssociationTable *)
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.