MythTV  master
atscstreamdata.cpp
Go to the documentation of this file.
1 // -*- Mode: c++ -*-
2 // Copyright (c) 2003-2004, Daniel Thor Kristjansson
3 
4 #include <cmath>
5 
6 #include <algorithm>
7 using namespace std;
8 
9 #include "atscstreamdata.h"
10 #include "atsctables.h"
11 #include "sctetables.h"
12 #include "ringbuffer.h"
13 #include "eithelper.h"
14 
15 #define LOC QString("ATSCStream[%1]: ").arg(_cardid)
16 
35 ATSCStreamData::ATSCStreamData(int desiredMajorChannel,
36  int desiredMinorChannel,
37  int cardnum, bool cacheTables)
38  : MPEGStreamData(-1, cardnum, cacheTables),
39  _GPS_UTC_offset(GPS_LEAP_SECONDS),
40  _atsc_eit_reset(false),
41  _mgt_version(-1),
42  _cached_mgt(nullptr),
43  _desired_major_channel(desiredMajorChannel),
44  _desired_minor_channel(desiredMinorChannel)
45 {
48 }
49 
51 {
52  Reset(-1,-1);
53 
54  QMutexLocker locker(&_listener_lock);
55  _atsc_main_listeners.clear();
56  _atsc_aux_listeners.clear();
57  _atsc_eit_listeners.clear();
58 
59  _scte_main_listeners.clear();
60  _atsc81_eit_listeners.clear();
61 }
62 
64 {
65  bool reset = true;
66  const MasterGuideTable *mgt = GetCachedMGT();
67  tvct_vec_t tvcts = GetCachedTVCTs();
68  cvct_vec_t cvcts = GetCachedCVCTs();
69 
70  if (mgt && (!tvcts.empty() || !cvcts.empty()))
71  {
72  const TerrestrialVirtualChannelTable *tvct = nullptr;
73  const CableVirtualChannelTable *cvct = nullptr;
74  int chan_idx = -1;
75  for (uint i = 0; (i < tvcts.size()) && (chan_idx < 0); i++)
76  {
77  tvct = tvcts[i];
78  chan_idx = tvcts[i]->Find(major, minor);
79  }
80  for (uint i = (chan_idx < 0) ? 0 : cvcts.size();
81  (i < cvcts.size()) && (chan_idx < 0); i++)
82  {
83  cvct = cvcts[i];
84  chan_idx = cvcts[i]->Find(major, minor);
85  }
86 
87  if (chan_idx >= 0)
88  {
89  _desired_major_channel = major;
91 
92  ProcessMGT(mgt);
93 
94  if (cvct)
95  {
96  ProcessCVCT(cvct->TransportStreamID(), cvct);
97  SetDesiredProgram(cvct->ProgramNumber(chan_idx));
98  }
99  else if (tvct)
100  {
101  ProcessTVCT(tvct->TransportStreamID(), tvct);
102  SetDesiredProgram(tvct->ProgramNumber(chan_idx));
103  }
104  reset = false;
105  }
106  }
107 
108  ReturnCachedTable(mgt);
109  ReturnCachedTVCTTables(tvcts);
110  ReturnCachedCVCTTables(cvcts);
111 
112  if (reset)
113  Reset(major, minor);
114 }
115 
116 void ATSCStreamData::Reset(int desiredProgram)
117 {
118  MPEGStreamData::Reset(desiredProgram);
120 }
121 
122 void ATSCStreamData::Reset(int major, int minor)
123 {
124  _desired_major_channel = major;
126 
128  _mgt_version = -1;
129  _tvct_version.clear();
130  _cvct_version.clear();
131  _eit_status.clear();
132 
134  _atsc_eit_pids.clear();
135  _atsc_ett_pids.clear();
136 
137  {
138  QMutexLocker locker(&_cache_lock);
139 
141  _cached_mgt = nullptr;
142 
143  tvct_cache_t::iterator tit = _cached_tvcts.begin();
144  for (; tit != _cached_tvcts.end(); ++tit)
145  DeleteCachedTable(*tit);
146  _cached_tvcts.clear();
147 
148  cvct_cache_t::iterator cit = _cached_cvcts.begin();
149  for (; cit != _cached_cvcts.end(); ++cit)
150  DeleteCachedTable(*cit);
151  _cached_cvcts.clear();
152  }
153 
155 }
156 
164 bool ATSCStreamData::IsRedundant(uint pid, const PSIPTable &psip) const
165 {
166  if (MPEGStreamData::IsRedundant(pid, psip))
167  return true;
168 
169  const int table_id = psip.TableID();
170  const int version = psip.Version();
171 
172  if (TableID::EIT == table_id)
173  {
174  uint key = (pid<<16) | psip.TableIDExtension();
175  return _eit_status.IsSectionSeen(key, version, psip.Section());
176  }
177 
178  if (TableID::ETT == table_id)
179  return false; // retransmit ETT's we've seen
180 
181  if (TableID::STT == table_id)
182  return false; // each SystemTimeTable matters
183 
184  if (TableID::STTscte == table_id)
185  return false; // each SCTESystemTimeTable matters
186 
187  if (TableID::MGT == table_id)
188  return VersionMGT() == version;
189 
190  if (TableID::TVCT == table_id)
191  {
192  return VersionTVCT(psip.TableIDExtension()) == version;
193  }
194 
195  if (TableID::CVCT == table_id)
196  {
197  return VersionCVCT(psip.TableIDExtension()) == version;
198  }
199 
200  if (TableID::RRT == table_id)
201  return VersionRRT(psip.TableIDExtension()) == version;
202 
203  if (TableID::PIM == table_id)
204  return true; // ignore these messages..
205 
206  if (TableID::PNM == table_id)
207  return true; // ignore these messages..
208 
209  return false;
210 }
211 
213 {
214  if (MPEGStreamData::HandleTables(pid, psip))
215  return true;
216 
217  if (IsRedundant(pid, psip))
218  return true;
219 
220  const int version = psip.Version();
221 
222  // Decode any table we know about
223  switch (psip.TableID())
224  {
225  case TableID::MGT:
226  {
228  if (_cache_tables)
229  {
230  MasterGuideTable *mgt = new MasterGuideTable(psip);
231  CacheMGT(mgt);
232  ProcessMGT(mgt);
233  }
234  else
235  {
236  MasterGuideTable mgt(psip);
237  ProcessMGT(&mgt);
238  }
239  return true;
240  }
241  case TableID::TVCT:
242  {
243  uint tsid = psip.TableIDExtension();
244  SetVersionTVCT(tsid, version);
245  if (_cache_tables)
246  {
249  CacheTVCT(pid, vct);
250  ProcessTVCT(tsid, vct);
251  }
252  else
253  {
255  ProcessTVCT(tsid, &vct);
256  }
257  return true;
258  }
259  case TableID::CVCT:
260  {
261  uint tsid = psip.TableIDExtension();
262  SetVersionCVCT(tsid, version);
263  if (_cache_tables)
264  {
266  new CableVirtualChannelTable(psip);
267  CacheCVCT(pid, vct);
268  ProcessCVCT(tsid, vct);
269  }
270  else
271  {
272  CableVirtualChannelTable vct(psip);
273  ProcessCVCT(tsid, &vct);
274  }
275  return true;
276  }
277  case TableID::RRT:
278  {
279  uint region = psip.TableIDExtension();
280  SetVersionRRT(region, version);
281  RatingRegionTable rrt(psip);
282  QMutexLocker locker(&_listener_lock);
283  for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
284  _atsc_aux_listeners[i]->HandleRRT(&rrt);
285  return true;
286  }
287  case TableID::EIT:
288  {
289  QMutexLocker locker(&_listener_lock);
290  if (!_atsc_eit_listeners.size() && !_eit_helper)
291  return true;
292 
293  uint key = (pid<<16) | psip.TableIDExtension();
294  _eit_status.SetSectionSeen(key, version, psip.Section(), psip.LastSection());
295 
296  EventInformationTable eit(psip);
297  for (uint i = 0; i < _atsc_eit_listeners.size(); i++)
298  _atsc_eit_listeners[i]->HandleEIT(pid, &eit);
299 
300  const uint mm = GetATSCMajorMinor(eit.SourceID());
301  if (mm && _eit_helper)
302  _eit_helper->AddEIT(mm >> 16, mm & 0xffff, &eit);
303 
304  return true;
305  }
306  case TableID::ETT:
307  {
308  ExtendedTextTable ett(psip);
309 
310  QMutexLocker locker(&_listener_lock);
311  for (uint i = 0; i < _atsc_eit_listeners.size(); i++)
312  _atsc_eit_listeners[i]->HandleETT(pid, &ett);
313 
314  if (ett.IsEventETM() && _eit_helper) // Guide ETTs
315  {
316  const uint mm = GetATSCMajorMinor(ett.SourceID());
317  if (mm)
318  _eit_helper->AddETT(mm >> 16, mm & 0xffff, &ett);
319  }
320 
321  return true;
322  }
323  case TableID::STT:
324  {
325  SystemTimeTable stt(psip);
326 
327  UpdateTimeOffset(stt.UTCUnix());
328 
329  // only update internal offset if it changes
330  if (stt.GPSOffset() != _GPS_UTC_offset)
331  _GPS_UTC_offset = stt.GPSOffset();
332 
333  _listener_lock.lock();
334  for (uint i = 0; i < _atsc_main_listeners.size(); i++)
335  _atsc_main_listeners[i]->HandleSTT(&stt);
336  _listener_lock.unlock();
337 
340 
341  return true;
342  }
343  case TableID::DCCT:
344  {
345  DirectedChannelChangeTable dcct(psip);
346 
347  QMutexLocker locker(&_listener_lock);
348  for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
349  _atsc_aux_listeners[i]->HandleDCCT(&dcct);
350 
351  return true;
352  }
353  case TableID::DCCSCT:
354  {
356 
357  QMutexLocker locker(&_listener_lock);
358  for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
359  _atsc_aux_listeners[i]->HandleDCCSCT(&dccsct);
360 
361  return true;
362  }
363 
364  // ATSC A/81 & SCTE 65 tables
365  case TableID::AEIT:
366  {
368 
369  QMutexLocker locker(&_listener_lock);
370  for (uint i = 0; i < _atsc81_eit_listeners.size(); i++)
371  _atsc81_eit_listeners[i]->HandleAEIT(pid, &aeit);
372 
373  return true;
374  }
375  case TableID::AETT:
376  {
377  AggregateExtendedTextTable aett(psip);
378 
379  QMutexLocker locker(&_listener_lock);
380  for (uint i = 0; i < _atsc81_eit_listeners.size(); i++)
381  _atsc81_eit_listeners[i]->HandleAETT(pid, &aett);
382 
383  return true;
384  }
385 
386  // SCTE 65 tables
387  case TableID::NITscte:
388  {
389  SCTENetworkInformationTable nit(psip);
390 
391  QMutexLocker locker(&_listener_lock);
392  for (uint i = 0; i < _scte_main_listeners.size(); i++)
393  _scte_main_listeners[i]->HandleNIT(&nit);
394 
395  return true;
396  }
397  case TableID::NTT:
398  {
399  NetworkTextTable ntt(psip);
400 
401  QMutexLocker locker(&_listener_lock);
402  for (uint i = 0; i < _scte_main_listeners.size(); i++)
403  _scte_main_listeners[i]->HandleNTT(&ntt);
404 
405  return true;
406  }
407  case TableID::SVCTscte:
408  {
409  ShortVirtualChannelTable svct(psip);
410 
411  QMutexLocker locker(&_listener_lock);
412  for (uint i = 0; i < _scte_main_listeners.size(); i++)
413  _scte_main_listeners[i]->HandleSVCT(&svct);
414 
415  return true;
416  }
417  case TableID::STTscte:
418  {
419  SCTESystemTimeTable stt(psip);
420 
421  QMutexLocker locker(&_listener_lock);
422  for (uint i = 0; i < _scte_main_listeners.size(); i++)
423  _scte_main_listeners[i]->HandleSTT(&stt);
424 
425  return true;
426  }
427 
428  // SCTE 57 table -- SCTE 65 standard supercedes this
429  case TableID::PIM:
430  {
432 
433  QMutexLocker locker(&_listener_lock);
434  for (uint i = 0; i < _scte_main_listeners.size(); i++)
435  _scte_main_listeners[i]->HandlePIM(&pim);
436 
437  return true;
438  }
439  // SCTE 57 table -- SCTE 65 standard supercedes this
440  case TableID::PNM:
441  {
442  ProgramNameMessageTable pnm(psip);
443 
444  QMutexLocker locker(&_listener_lock);
445  for (uint i = 0; i < _scte_main_listeners.size(); i++)
446  _scte_main_listeners[i]->HandlePNM(&pnm);
447 
448  return true;
449  }
450 
451  // SCTE 80
452  case TableID::ADET:
453  {
454  AggregateDataEventTable adet(psip);
455 
456  QMutexLocker locker(&_listener_lock);
457  for (uint i = 0; i < _scte_main_listeners.size(); i++)
458  _scte_main_listeners[i]->HandleADET(&adet);
459 
460  return true;
461  }
462 
463  case TableID::NIT:
464  case TableID::NITo:
465  case TableID::SDT:
466  case TableID::SDTo:
467  case TableID::BAT:
468  case TableID::TDT:
469  case TableID::TOT:
470  case TableID::DVBCA_82:
471  case TableID::DVBCA_83:
472  {
473  // All DVB specific tables, not handled here
474  return false;
475  }
476 
477  default:
478  {
479  LOG(VB_RECORD, LOG_ERR, LOC +
480  QString("ATSCStreamData::HandleTables(): Unknown table 0x%1")
481  .arg(psip.TableID(),0,16));
482  break;
483  }
484  }
485  return false;
486 }
487 
488 bool ATSCStreamData::HasEITPIDChanges(const uint_vec_t &in_use_pids) const
489 {
490  QMutexLocker locker(&_listener_lock);
491  uint eit_count = (uint) round(_atsc_eit_pids.size() * _eit_rate);
492  uint ett_count = (uint) round(_atsc_ett_pids.size() * _eit_rate);
493  return (in_use_pids.size() != (eit_count + ett_count) || _atsc_eit_reset);
494 }
495 
497  uint_vec_t &add_pids,
498  uint_vec_t &del_pids) const
499 {
500  QMutexLocker locker(&_listener_lock);
501 
502  _atsc_eit_reset = false;
503 
504  uint eit_count = (uint) round(_atsc_eit_pids.size() * _eit_rate);
505  uint ett_count = (uint) round(_atsc_ett_pids.size() * _eit_rate);
506  uint i;
507 
508 #if 0
509  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("eit size: %1, rate: %2, cnt: %3")
510  .arg(_atsc_eit_pids.size()).arg(_eit_rate).arg(eit_count));
511 #endif
512 
513  uint_vec_t add_pids_tmp;
514  atsc_eit_pid_map_t::const_iterator it = _atsc_eit_pids.begin();
515  for (i = 0; it != _atsc_eit_pids.end() && (i < eit_count); (++it),(i++))
516  add_pids_tmp.push_back(*it);
517 
518  atsc_ett_pid_map_t::const_iterator it2 = _atsc_ett_pids.begin();
519  for (i = 0; it2 != _atsc_ett_pids.end() && (i < ett_count); (++it2),(i++))
520  add_pids_tmp.push_back(*it2);
521 
522  uint_vec_t::const_iterator it3;
523  for (i = 0; i < cur_pids.size(); i++)
524  {
525  it3 = find(add_pids_tmp.begin(), add_pids_tmp.end(), cur_pids[i]);
526  if (it3 == add_pids_tmp.end())
527  del_pids.push_back(cur_pids[i]);
528  }
529 
530  for (i = 0; i < add_pids_tmp.size(); i++)
531  {
532  it3 = find(cur_pids.begin(), cur_pids.end(), add_pids_tmp[i]);
533  if (it3 == cur_pids.end())
534  add_pids.push_back(add_pids_tmp[i]);
535  }
536 
537  return add_pids.size() || del_pids.size();
538 }
539 
541 {
542  QMutexLocker locker(&_listener_lock);
543 
544  _atsc_eit_reset = true;
545  _atsc_eit_pids.clear();
546  _atsc_ett_pids.clear();
547 
548  for (uint i = 0 ; i < mgt->TableCount(); i++)
549  {
550  const int table_class = mgt->TableClass(i);
551  const uint pid = mgt->TablePID(i);
552 
553  if (table_class == TableClass::EIT)
554  {
555  const uint num = mgt->TableType(i) - 0x100;
556  _atsc_eit_pids[num] = pid;
557  }
558  else if (table_class == TableClass::ETTe)
559  {
560  const uint num = mgt->TableType(i) - 0x200;
561  _atsc_ett_pids[num] = pid;
562  }
563  }
564 
565  for (uint i = 0; i < _atsc_main_listeners.size(); i++)
566  _atsc_main_listeners[i]->HandleMGT(mgt);
567 }
568 
570 {
571  for (uint i = 0; i < _atsc_main_listeners.size(); i++)
572  _atsc_main_listeners[i]->HandleVCT(tsid, vct);
573 
575  for (uint i = 0; i < vct->ChannelCount() ; i++)
576  {
577  if (vct->IsHidden(i) && vct->IsHiddenInGuide(i))
578  {
579  LOG(VB_EIT, LOG_INFO, LOC +
580  QString("%1 chan %2-%3 is hidden in guide")
581  .arg(vct->ModulationMode(i) == 1 ? "NTSC" : "ATSC")
582  .arg(vct->MajorChannel(i))
583  .arg(vct->MinorChannel(i)));
584  continue;
585  }
586 
587  if (1 == vct->ModulationMode(i))
588  {
589  LOG(VB_EIT, LOG_INFO, LOC + QString("Ignoring NTSC chan %1-%2")
590  .arg(vct->MajorChannel(i))
591  .arg(vct->MinorChannel(i)));
592  continue;
593  }
594 
595  LOG(VB_EIT, LOG_INFO, LOC + QString("Adding Source #%1 ATSC chan %2-%3")
596  .arg(vct->SourceID(i))
597  .arg(vct->MajorChannel(i))
598  .arg(vct->MinorChannel(i)));
599 
601  vct->MajorChannel(i) << 16 | vct->MinorChannel(i);
602  }
603 }
604 
607 {
608  QMutexLocker locker(&_listener_lock);
609  ProcessVCT(tsid, vct);
610  for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
611  _atsc_aux_listeners[i]->HandleTVCT(tsid, vct);
612 }
613 
615  const CableVirtualChannelTable *vct)
616 {
617  QMutexLocker locker(&_listener_lock);
618  ProcessVCT(tsid, vct);
619  for (uint i = 0; i < _atsc_aux_listeners.size(); i++)
620  _atsc_aux_listeners[i]->HandleCVCT(tsid, vct);
621 }
622 
624 {
625  if (!current)
626  LOG(VB_GENERAL, LOG_WARNING, LOC +
627  "Currently we ignore \'current\' param");
628 
629  return (bool)(_cached_mgt);
630 }
631 
633 {
634  bool hasit = false;
635 
636  {
637  tvct_vec_t tvct = GetCachedTVCTs();
638  for (uint i = 0; i < tvct.size() && !hasit; i++)
639  {
640  if (tvct[i]->Find(major, minor) >= 0)
641  hasit |= HasProgram(tvct[i]->ProgramNumber(i));
642  }
644  }
645 
646  if (!hasit)
647  {
648  cvct_vec_t cvct = GetCachedCVCTs();
649  for (uint i = 0; i < cvct.size() && !hasit; i++)
650  {
651  if (cvct[i]->Find(major, minor) >= 0)
652  hasit |= HasProgram(cvct[i]->ProgramNumber(i));
653  }
655  }
656 
657  return hasit;
658 }
659 
661 {
662  if (!current)
663  LOG(VB_GENERAL, LOG_WARNING, LOC +
664  "Currently we ignore \'current\' param");
665 
666  _cache_lock.lock();
667  tvct_cache_t::const_iterator it = _cached_tvcts.find(pid);
668  bool exists = (it != _cached_tvcts.end());
669  _cache_lock.unlock();
670 
671  return exists;
672 }
673 
675 {
676  if (!current)
677  LOG(VB_GENERAL, LOG_WARNING, LOC +
678  "Currently we ignore \'current\' param");
679 
680  _cache_lock.lock();
681  cvct_cache_t::const_iterator it = _cached_cvcts.find(pid);
682  bool exists = (it != _cached_cvcts.end());
683  _cache_lock.unlock();
684 
685  return exists;
686 }
687 
689 {
690  if (!current)
691  LOG(VB_GENERAL, LOG_WARNING, LOC +
692  "Currently we ignore \'current\' param");
693 
694  if (!_cached_mgt)
695  return false;
696 
697  _cache_lock.lock();
698  bool ret = true;
699  for (uint i = 0; ret && (i < _cached_mgt->TableCount()); ++i)
700  {
702  ret &= HasCachedTVCT(_cached_mgt->TablePID(i));
703  }
704  _cache_lock.unlock();
705 
706  return ret;
707 }
708 
710 {
711  if (!current)
712  LOG(VB_GENERAL, LOG_WARNING, LOC +
713  "Currently we ignore \'current\' param");
714 
715  if (!_cached_mgt)
716  return false;
717 
718  _cache_lock.lock();
719  bool ret = true;
720  for (uint i = 0; ret && (i < _cached_mgt->TableCount()); ++i)
721  {
723  ret &= HasCachedCVCT(_cached_mgt->TablePID(i));
724  }
725  _cache_lock.unlock();
726 
727  return ret;
728 }
729 
731 {
732  if (!current)
733  LOG(VB_GENERAL, LOG_WARNING, LOC +
734  "Currently we ignore \'current\' param");
735 
736  QMutexLocker locker(&_cache_lock);
737  return !_cached_tvcts.empty();
738 }
739 
741 {
742  if (!current)
743  LOG(VB_GENERAL, LOG_WARNING, LOC +
744  "Currently we ignore \'current\' param");
745 
746  QMutexLocker locker(&_cache_lock);
747  return !_cached_cvcts.empty();
748 }
749 
751 {
752  if (!current)
753  LOG(VB_GENERAL, LOG_WARNING, LOC +
754  "Currently we ignore \'current\' param");
755 
756  _cache_lock.lock();
757  const MasterGuideTable *mgt = _cached_mgt;
758  IncrementRefCnt(mgt);
759  _cache_lock.unlock();
760 
761  return mgt;
762 }
763 
765 {
766  if (!current)
767  LOG(VB_GENERAL, LOG_WARNING, LOC +
768  "Currently we ignore \'current\' param");
769 
770  tvct_ptr_t tvct = nullptr;
771 
772  _cache_lock.lock();
773  tvct_cache_t::const_iterator it = _cached_tvcts.find(pid);
774  if (it != _cached_tvcts.end())
775  IncrementRefCnt(tvct = *it);
776  _cache_lock.unlock();
777 
778  return tvct;
779 }
780 
782 {
783  if (!current)
784  LOG(VB_GENERAL, LOG_WARNING, LOC +
785  "Currently we ignore \'current\' param");
786 
787  cvct_ptr_t cvct = nullptr;
788 
789  _cache_lock.lock();
790  cvct_cache_t::const_iterator it = _cached_cvcts.find(pid);
791  if (it != _cached_cvcts.end())
792  IncrementRefCnt(cvct = *it);
793  _cache_lock.unlock();
794 
795  return cvct;
796 }
797 
799 {
800  if (!current)
801  LOG(VB_GENERAL, LOG_WARNING, LOC +
802  "Currently we ignore \'current\' param");
803 
804  vector<const TerrestrialVirtualChannelTable*> tvcts;
805 
806  _cache_lock.lock();
807  tvct_cache_t::const_iterator it = _cached_tvcts.begin();
808  for (; it != _cached_tvcts.end(); ++it)
809  {
810  TerrestrialVirtualChannelTable* tvct = *it;
811  IncrementRefCnt(tvct);
812  tvcts.push_back(tvct);
813  }
814  _cache_lock.unlock();
815 
816  return tvcts;
817 }
818 
820 {
821  if (!current)
822  LOG(VB_GENERAL, LOG_WARNING, LOC +
823  "Currently we ignore \'current\' param");
824 
825  vector<const CableVirtualChannelTable*> cvcts;
826 
827  _cache_lock.lock();
828  cvct_cache_t::const_iterator it = _cached_cvcts.begin();
829  for (; it != _cached_cvcts.end(); ++it)
830  {
831  CableVirtualChannelTable* cvct = *it;
832  IncrementRefCnt(cvct);
833  cvcts.push_back(cvct);
834  }
835  _cache_lock.unlock();
836 
837  return cvcts;
838 }
839 
841 {
842  QMutexLocker locker(&_cache_lock);
843 
845  _cached_mgt = mgt;
846 }
847 
849 {
850  QMutexLocker locker(&_cache_lock);
851 
853  _cached_tvcts[pid] = tvct;
854 }
855 
857 {
858  QMutexLocker locker(&_cache_lock);
859 
861  _cached_cvcts[pid] = cvct;
862 }
863 
865 {
866  if (!psip)
867  return false;
868 
869  QMutexLocker locker(&_cache_lock);
870  if (_cached_ref_cnt[psip] > 0)
871  {
872  _cached_slated_for_deletion[psip] = 1;
873  return false;
874  }
875  else if (TableID::MGT == psip->TableID())
876  {
877  if (psip == _cached_mgt)
878  _cached_mgt = nullptr;
879  delete psip;
880  }
881  else if ((TableID::TVCT == psip->TableID()) &&
882  _cached_tvcts[psip->tsheader()->PID()])
883  {
884  _cached_tvcts[psip->tsheader()->PID()] = nullptr;
885  delete psip;
886  }
887  else if ((TableID::CVCT == psip->TableID()) &&
888  _cached_cvcts[psip->tsheader()->PID()])
889  {
890  _cached_cvcts[psip->tsheader()->PID()] = nullptr;
891  delete psip;
892  }
893  else
894  {
896  }
897  psip_refcnt_map_t::iterator it;
898  it = _cached_slated_for_deletion.find(psip);
899  if (it != _cached_slated_for_deletion.end())
900  _cached_slated_for_deletion.erase(it);
901 
902  return true;
903 }
904 
906 {
907  for (tvct_vec_t::iterator it = tvcts.begin(); it != tvcts.end(); ++it)
908  ReturnCachedTable(*it);
909  tvcts.clear();
910 }
911 
913 {
914  for (cvct_vec_t::iterator it = cvcts.begin(); it != cvcts.end(); ++it)
915  ReturnCachedTable(*it);
916  cvcts.clear();
917 }
918 
920 {
921  QMutexLocker locker(&_listener_lock);
922 
923  atsc_main_listener_vec_t::iterator it = _atsc_main_listeners.begin();
924  for (; it != _atsc_main_listeners.end(); ++it)
925  if (((void*)val) == ((void*)*it))
926  return;
927 
928  _atsc_main_listeners.push_back(val);
929 }
930 
932 {
933  QMutexLocker locker(&_listener_lock);
934 
935  atsc_main_listener_vec_t::iterator it = _atsc_main_listeners.begin();
936  for (; it != _atsc_main_listeners.end(); ++it)
937  {
938  if (((void*)val) == ((void*)*it))
939  {
940  _atsc_main_listeners.erase(it);
941  return;
942  }
943  }
944 }
945 
947 {
948  QMutexLocker locker(&_listener_lock);
949 
950  scte_main_listener_vec_t::iterator it = _scte_main_listeners.begin();
951  for (; it != _scte_main_listeners.end(); ++it)
952  if (((void*)val) == ((void*)*it))
953  return;
954 
955  _scte_main_listeners.push_back(val);
956 }
957 
959 {
960  QMutexLocker locker(&_listener_lock);
961 
962  scte_main_listener_vec_t::iterator it = _scte_main_listeners.begin();
963  for (; it != _scte_main_listeners.end(); ++it)
964  {
965  if (((void*)val) == ((void*)*it))
966  {
967  _scte_main_listeners.erase(it);
968  return;
969  }
970  }
971 }
972 
974 {
975  QMutexLocker locker(&_listener_lock);
976 
977  atsc_aux_listener_vec_t::iterator it = _atsc_aux_listeners.begin();
978  for (; it != _atsc_aux_listeners.end(); ++it)
979  if (((void*)val) == ((void*)*it))
980  return;
981 
982  _atsc_aux_listeners.push_back(val);
983 }
984 
986 {
987  QMutexLocker locker(&_listener_lock);
988 
989  atsc_aux_listener_vec_t::iterator it = _atsc_aux_listeners.begin();
990  for (; it != _atsc_aux_listeners.end(); ++it)
991  {
992  if (((void*)val) == ((void*)*it))
993  {
994  _atsc_aux_listeners.erase(it);
995  return;
996  }
997  }
998 }
999 
1001 {
1002  QMutexLocker locker(&_listener_lock);
1003 
1004  atsc_eit_listener_vec_t::iterator it = _atsc_eit_listeners.begin();
1005  for (; it != _atsc_eit_listeners.end(); ++it)
1006  if (((void*)val) == ((void*)*it))
1007  return;
1008 
1009  _atsc_eit_listeners.push_back(val);
1010 }
1011 
1013 {
1014  QMutexLocker locker(&_listener_lock);
1015 
1016  atsc_eit_listener_vec_t::iterator it = _atsc_eit_listeners.begin();
1017  for (; it != _atsc_eit_listeners.end(); ++it)
1018  {
1019  if (((void*)val) == ((void*)*it))
1020  {
1021  _atsc_eit_listeners.erase(it);
1022  return;
1023  }
1024  }
1025 }
1026 
1028 {
1029  QMutexLocker locker(&_listener_lock);
1030 
1031  atsc81_eit_listener_vec_t::iterator it = _atsc81_eit_listeners.begin();
1032  for (; it != _atsc81_eit_listeners.end(); ++it)
1033  if (((void*)val) == ((void*)*it))
1034  return;
1035 
1036  _atsc81_eit_listeners.push_back(val);
1037 }
1038 
1040 {
1041  QMutexLocker locker(&_listener_lock);
1042 
1043  atsc81_eit_listener_vec_t::iterator it = _atsc81_eit_listeners.begin();
1044  for (; it != _atsc81_eit_listeners.end(); ++it)
1045  {
1046  if (((void*)val) == ((void*)*it))
1047  {
1048  _atsc81_eit_listeners.erase(it);
1049  return;
1050  }
1051  }
1052 }
QMap< uint, uint > _sourceid_to_atsc_maj_min
bool IsSectionSeen(uint32_t key, int32_t version, uint32_t section) const
Definition: tablestatus.cpp:73
No one has had time to decode this table yet...
Definition: atsctables.h:781
const TSHeader * tsheader() const
Definition: pespacket.h:89
uint Version(void) const
Definition: mpegtables.h:503
virtual void Reset(void)
void RemoveATSC81EITListener(ATSC81EITStreamListener *)
int VersionTVCT(uint tsid) const
void SetVersionRRT(uint region, int version)
bool IsRedundant(uint, const PSIPTable &) const override
Returns true if table already seen.
SCTE 65 & ATSC/81 0xD7.
Definition: atsctables.h:818
uint MajorChannel(uint i) const
Definition: atsctables.h:245
bool HasCachedAllCVCTs(bool current=true) const
virtual void ReturnCachedTable(const PSIPTable *psip) const
virtual bool IsRedundant(uint pid, const PSIPTable &) const
Returns true if table already seen.
uint MinorChannel(uint i) const
Definition: atsctables.h:250
int Find(int major, int minor) const
Definition: atsctables.cpp:487
uint TableIDExtension(void) const
Definition: mpegtables.h:496
ExtendedTextTable contain additional text not contained in EventInformationTables.
Definition: atsctables.h:625
#define round(x)
Definition: mythplayer.cpp:65
void CacheCVCT(uint pid, CableVirtualChannelTable *)
void SetGPSOffset(uint _gps_offset)
Definition: eithelper.h:103
void SetVersionCVCT(uint tsid, int version)
int VersionMGT() const
cvct_vec_t GetCachedCVCTs(bool current=true) const
atsc_aux_listener_vec_t _atsc_aux_listeners
#define GPS_LEAP_SECONDS
Leap seconds as of June 30th, 2012.
Definition: mpegtables.h:31
uint TableCount() const
Definition: atsctables.h:114
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 ProgramNumber(uint i) const
Definition: atsctables.h:267
atsc_ett_pid_map_t _atsc_ett_pids
uint GetGPSOffset(void) const
Definition: eithelper.h:100
uint LastSection(void) const
Definition: mpegtables.h:515
bool HasCachedAnyTVCTs(bool current=true) const
bool HasCachedMGT(bool current=true) const
void SetVersionTVCT(uint tsid, int version)
virtual bool HandleTables(uint pid, const PSIPTable &psip)
Assembles PSIP packets and processes them.
unsigned int uint
Definition: compat.h:140
psip_refcnt_map_t _cached_ref_cnt
uint SourceID() const
Definition: atsctables.h:550
void ProcessVCT(uint tsid, const VirtualChannelTable *)
uint ModulationMode(uint i) const
Definition: atsctables.h:255
QMap< uint, int > _cvct_version
virtual ~ATSCStreamData()
void AddATSCAuxListener(ATSCAuxStreamListener *)
void AddEIT(uint atsc_major, uint atsc_minor, const EventInformationTable *eit)
Definition: eithelper.cpp:145
uint Section(void) const
Definition: mpegtables.h:512
bool HasCachedAnyCVCTs(bool current=true) const
atsc_eit_listener_vec_t _atsc_eit_listeners
tvct_cache_t _cached_tvcts
Overall structure.
int TableClass(uint i) const
Definition: atsctables.cpp:25
void CacheTVCT(uint pid, TerrestrialVirtualChannelTable *)
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
bool IsHidden(uint i) const
Definition: atsctables.h:282
QMap< uint, int > _tvct_version
A PSIP table is a variant of a PES packet containing an MPEG, ATSC or DVB table.
Definition: mpegtables.h:371
bool HasProgram(uint progNum) const
void ProcessMGT(const MasterGuideTable *)
VERBOSE_PREAMBLE false
Definition: verbosedefs.h:85
This table contains information about the cable channels transmitted on this multiplex.
Definition: atsctables.h:415
void ProcessTVCT(uint tsid, const TerrestrialVirtualChannelTable *)
No one has had time to decode this table yet...
Definition: atsctables.h:748
bool IsHiddenInGuide(uint i) const
Definition: atsctables.h:288
uint ChannelCount() const
Definition: atsctables.h:221
cvct_const_ptr_t GetCachedCVCT(uint pid, bool current=true) const
bool HasCachedCVCT(uint pid, bool current=true) const
No one has had time to decode this table yet...
Definition: atsctables.h:764
QDateTime current(bool stripped)
Returns current Date and Time in UTC.
Definition: mythdate.cpp:10
void SetDesiredProgram(int p)
MasterGuideTable * _cached_mgt
uint TablePID(uint i) const
Definition: atsctables.h:128
bool HasCachedTVCT(uint pid, bool current=true) const
void AddETT(uint atsc_major, uint atsc_minor, const ExtendedTextTable *ett)
Definition: eithelper.cpp:190
#define minor(X)
Definition: compat.h:138
void RemoveATSCAuxListener(ATSCAuxStreamListener *)
psip_refcnt_map_t _cached_slated_for_deletion
vector< const CableVirtualChannelTable * > cvct_vec_t
bool HasChannel(uint major, uint minor) const
void AddATSCEITListener(ATSCEITStreamListener *)
void AddATSC81EITListener(ATSC81EITStreamListener *)
vector< const TerrestrialVirtualChannelTable * > tvct_vec_t
void RemoveSCTEMainListener(SCTEMainStreamListener *)
void AddATSCMainListener(ATSCMainStreamListener *)
void SetDesiredChannel(int major, int minor)
EventInformationTables contain program titles, start times, and channel information.
Definition: atsctables.h:521
void UpdateTimeOffset(uint64_t si_utc_time)
void IncrementRefCnt(const PSIPTable *psip) const
vector< uint > uint_vec_t
void RemoveATSCMainListener(ATSCMainStreamListener *)
const MasterGuideTable * GetCachedMGT(bool current=true) const
virtual void AddListeningPID(uint pid, PIDPriority priority=kPIDPriorityNormal)
EITHelper * _eit_helper
atsc_main_listener_vec_t _atsc_main_listeners
uint TableID(void) const
Definition: mpegtables.h:479
bool IsEventETM(void) const
Definition: atsctables.h:660
uint SourceID(uint i) const
Definition: atsctables.h:300
int VersionCVCT(uint tsid) const
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
This table tells the decoder on which PIDs to find other tables, and their sizes and each table's cur...
Definition: atsctables.h:74
atsc_eit_pid_map_t _atsc_eit_pids
atsc81_eit_listener_vec_t _atsc81_eit_listeners
uint GPSOffset(void) const
Current UTC to GPS time offset in seconds.
void ReturnCachedCVCTTables(cvct_vec_t &) const
#define LOC
TerrestrialVirtualChannelTable const * tvct_const_ptr_t
tvct_vec_t GetCachedTVCTs(bool current=true) const
virtual bool DeleteCachedTable(PSIPTable *psip) const
void SetVersionMGT(int version)
time_t UTCUnix(void) const
Definition: atsctables.h:725
TableStatusMap _eit_status
void ProcessCVCT(uint tsid, const CableVirtualChannelTable *)
This table contains information about the channels transmitted on this multiplex.
Definition: atsctables.h:189
bool HasCachedAllTVCTs(bool current=true) const
uint GetATSCMajorMinor(uint eit_sourceid) const
uint TableType(uint i) const
Definition: atsctables.h:120
int VersionRRT(uint region) const
bool GetEITPIDChanges(const uint_vec_t &in_use_pid, uint_vec_t &pids_to_add, uint_vec_t &pids_to_del) const override
bool DeleteCachedTable(PSIPTable *psip) const override
void RemoveATSCEITListener(ATSCEITStreamListener *)
bool HandleTables(uint pid, const PSIPTable &psip) override
Assembles PSIP packets and processes them.
CableVirtualChannelTable const * cvct_const_ptr_t
uint GPSOffset() const
Definition: atsctables.h:729
bool HasEITPIDChanges(const uint_vec_t &in_use_pid) const override
This table contains the GPS time at the time of transmission.
Definition: atsctables.h:683
SCTE 65 & ATSC/81 0xD6.
Definition: atsctables.h:798
This table contains the GPS time at the time of transmission.
Definition: sctetables.h:568
This table contains information about the terrestrial channels transmitted on this multiplex.
Definition: atsctables.h:346
cvct_cache_t _cached_cvcts
unsigned int PID() const
Definition: tspacket.h:67
void ReturnCachedTVCTTables(tvct_vec_t &) const
uint TransportStreamID() const
Definition: atsctables.h:218
tvct_const_ptr_t GetCachedTVCT(uint pid, bool current=true) const
void AddSCTEMainListener(SCTEMainStreamListener *)
Encapsulates data about MPEG stream and emits events for each table.
scte_main_listener_vec_t _scte_main_listeners
uint SourceID(void) const
Definition: atsctables.h:661
void CacheMGT(MasterGuideTable *)
ATSCStreamData(int desiredMajorChannel, int desiredMinorChannel, int cardnum, bool cacheTables=false)
Initializes ATSCStreamData.
void Reset(void) override