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