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);
116 }
117 
118 void ATSCStreamData::Reset(int desiredMajorChannel, int desiredMinorChannel)
119 {
120  m_desiredMajorChannel = desiredMajorChannel;
121  m_desiredMinorChannel = desiredMinorChannel;
122 
124  m_mgtVersion = -1;
125  m_tvctVersion.clear();
126  m_cvctVersion.clear();
127  m_eitStatus.clear();
128 
129  m_sourceIdToAtscMajMin.clear();
130  m_atscEitPids.clear();
131  m_atscEttPids.clear();
132 
133  {
134  QMutexLocker locker(&m_cacheLock);
135 
137  m_cachedMgt = nullptr;
138 
139  foreach (auto & cached, m_cachedTvcts)
140  DeleteCachedTable(cached);
141  m_cachedTvcts.clear();
142 
143  foreach (auto & cached, m_cachedCvcts)
144  DeleteCachedTable(cached);
145  m_cachedCvcts.clear();
146  }
147 
149 }
150 
158 bool ATSCStreamData::IsRedundant(uint pid, const PSIPTable &psip) const
159 {
160  if (MPEGStreamData::IsRedundant(pid, psip))
161  return true;
162 
163  const int table_id = psip.TableID();
164  const int version = psip.Version();
165 
166  if (TableID::EIT == table_id)
167  {
168  uint key = (pid<<16) | psip.TableIDExtension();
169  return m_eitStatus.IsSectionSeen(key, version, psip.Section());
170  }
171 
172  if (TableID::ETT == table_id)
173  return false; // retransmit ETT's we've seen
174 
175  if (TableID::STT == table_id)
176  return false; // each SystemTimeTable matters
177 
178  if (TableID::STTscte == table_id)
179  return false; // each SCTESystemTimeTable matters
180 
181  if (TableID::MGT == table_id)
182  return VersionMGT() == version;
183 
184  if (TableID::TVCT == table_id)
185  {
186  return VersionTVCT(psip.TableIDExtension()) == version;
187  }
188 
189  if (TableID::CVCT == table_id)
190  {
191  return VersionCVCT(psip.TableIDExtension()) == version;
192  }
193 
194  if (TableID::RRT == table_id)
195  return VersionRRT(psip.TableIDExtension()) == version;
196 
197  if (TableID::PIM == table_id)
198  return true; // ignore these messages..
199 
200  if (TableID::PNM == table_id)
201  return true; // ignore these messages..
202 
203  return false;
204 }
205 
207 {
208  if (MPEGStreamData::HandleTables(pid, psip))
209  return true;
210 
211  if (IsRedundant(pid, psip))
212  return true;
213 
214  const int version = psip.Version();
215 
216  // Decode any table we know about
217  switch (psip.TableID())
218  {
219  case TableID::MGT:
220  {
222  if (m_cacheTables)
223  {
224  auto *mgt = new MasterGuideTable(psip);
225  CacheMGT(mgt);
226  ProcessMGT(mgt);
227  }
228  else
229  {
230  MasterGuideTable mgt(psip);
231  ProcessMGT(&mgt);
232  }
233  return true;
234  }
235  case TableID::TVCT:
236  {
237  uint tsid = psip.TableIDExtension();
238  SetVersionTVCT(tsid, version);
239  if (m_cacheTables)
240  {
241  auto *vct = new TerrestrialVirtualChannelTable(psip);
242  CacheTVCT(pid, vct);
243  ProcessTVCT(tsid, vct);
244  }
245  else
246  {
248  ProcessTVCT(tsid, &vct);
249  }
250  return true;
251  }
252  case TableID::CVCT:
253  {
254  uint tsid = psip.TableIDExtension();
255  SetVersionCVCT(tsid, version);
256  if (m_cacheTables)
257  {
258  auto *vct = new CableVirtualChannelTable(psip);
259  CacheCVCT(pid, vct);
260  ProcessCVCT(tsid, vct);
261  }
262  else
263  {
264  CableVirtualChannelTable vct(psip);
265  ProcessCVCT(tsid, &vct);
266  }
267  return true;
268  }
269  case TableID::RRT:
270  {
271  uint region = psip.TableIDExtension();
272  SetVersionRRT(region, version);
273  RatingRegionTable rrt(psip);
274  QMutexLocker locker(&m_listenerLock);
275  for (auto & listener : m_atscAuxListeners)
276  listener->HandleRRT(&rrt);
277  return true;
278  }
279  case TableID::EIT:
280  {
281  QMutexLocker locker(&m_listenerLock);
282  if (m_atscEitListeners.empty() && !m_eitHelper)
283  return true;
284 
285  uint key = (pid<<16) | psip.TableIDExtension();
286  m_eitStatus.SetSectionSeen(key, version, psip.Section(), psip.LastSection());
287 
288  EventInformationTable eit(psip);
289  for (auto & listener : m_atscEitListeners)
290  listener->HandleEIT(pid, &eit);
291 
292  const uint mm = GetATSCMajorMinor(eit.SourceID());
293  if (mm && m_eitHelper)
294  m_eitHelper->AddEIT(mm >> 16, mm & 0xffff, &eit);
295 
296  return true;
297  }
298  case TableID::ETT:
299  {
300  ExtendedTextTable ett(psip);
301 
302  QMutexLocker locker(&m_listenerLock);
303  for (auto & listener : m_atscEitListeners)
304  listener->HandleETT(pid, &ett);
305 
306  if (ett.IsEventETM() && m_eitHelper) // Guide ETTs
307  {
308  const uint mm = GetATSCMajorMinor(ett.SourceID());
309  if (mm)
310  m_eitHelper->AddETT(mm >> 16, mm & 0xffff, &ett);
311  }
312 
313  return true;
314  }
315  case TableID::STT:
316  {
317  SystemTimeTable stt(psip);
318 
319  UpdateTimeOffset(stt.UTCUnix());
320 
321  // only update internal offset if it changes
322  if (stt.GPSOffset() != m_gpsUtcOffset)
323  m_gpsUtcOffset = stt.GPSOffset();
324 
325  m_listenerLock.lock();
326  for (auto & listener : m_atscMainListeners)
327  listener->HandleSTT(&stt);
328  m_listenerLock.unlock();
329 
332 
333  return true;
334  }
335  case TableID::DCCT:
336  {
337  DirectedChannelChangeTable dcct(psip);
338 
339  QMutexLocker locker(&m_listenerLock);
340  for (auto & listener : m_atscAuxListeners)
341  listener->HandleDCCT(&dcct);
342 
343  return true;
344  }
345  case TableID::DCCSCT:
346  {
348 
349  QMutexLocker locker(&m_listenerLock);
350  for (auto & listener : m_atscAuxListeners)
351  listener->HandleDCCSCT(&dccsct);
352 
353  return true;
354  }
355 
356  // ATSC A/81 & SCTE 65 tables
357  case TableID::AEIT:
358  {
360 
361  QMutexLocker locker(&m_listenerLock);
362  for (auto & listener : m_atsc81EitListeners)
363  listener->HandleAEIT(pid, &aeit);
364 
365  return true;
366  }
367  case TableID::AETT:
368  {
369  AggregateExtendedTextTable aett(psip);
370 
371  QMutexLocker locker(&m_listenerLock);
372  for (auto & listener : m_atsc81EitListeners)
373  listener->HandleAETT(pid, &aett);
374 
375  return true;
376  }
377 
378  // SCTE 65 tables
379  case TableID::NITscte:
380  {
381  SCTENetworkInformationTable nit(psip);
382 
383  QMutexLocker locker(&m_listenerLock);
384  for (auto & listener : m_scteMainlisteners)
385  listener->HandleNIT(&nit);
386 
387  return true;
388  }
389  case TableID::NTT:
390  {
391  NetworkTextTable ntt(psip);
392 
393  QMutexLocker locker(&m_listenerLock);
394  for (auto & listener : m_scteMainlisteners)
395  listener->HandleNTT(&ntt);
396 
397  return true;
398  }
399  case TableID::SVCTscte:
400  {
401  ShortVirtualChannelTable svct(psip);
402 
403  QMutexLocker locker(&m_listenerLock);
404  for (auto & listener : m_scteMainlisteners)
405  listener->HandleSVCT(&svct);
406 
407  return true;
408  }
409  case TableID::STTscte:
410  {
411  SCTESystemTimeTable stt(psip);
412 
413  QMutexLocker locker(&m_listenerLock);
414  for (auto & listener : m_scteMainlisteners)
415  listener->HandleSTT(&stt);
416 
417  return true;
418  }
419 
420  // SCTE 57 table -- SCTE 65 standard supercedes this
421  case TableID::PIM:
422  {
424 
425  QMutexLocker locker(&m_listenerLock);
426  for (auto & listener : m_scteMainlisteners)
427  listener->HandlePIM(&pim);
428 
429  return true;
430  }
431  // SCTE 57 table -- SCTE 65 standard supercedes this
432  case TableID::PNM:
433  {
434  ProgramNameMessageTable pnm(psip);
435 
436  QMutexLocker locker(&m_listenerLock);
437  for (auto & listener : m_scteMainlisteners)
438  listener->HandlePNM(&pnm);
439 
440  return true;
441  }
442 
443  // SCTE 80
444  case TableID::ADET:
445  {
446  AggregateDataEventTable adet(psip);
447 
448  QMutexLocker locker(&m_listenerLock);
449  for (auto & listener : m_scteMainlisteners)
450  listener->HandleADET(&adet);
451 
452  return true;
453  }
454 
455  case TableID::NIT:
456  case TableID::NITo:
457  case TableID::SDT:
458  case TableID::SDTo:
459  case TableID::BAT:
460  case TableID::TDT:
461  case TableID::TOT:
462  case TableID::DVBCA_82:
463  case TableID::DVBCA_83:
464  {
465  // All DVB specific tables, not handled here
466  return false;
467  }
468 
469  default:
470  {
471  LOG(VB_RECORD, LOG_ERR, LOC +
472  QString("ATSCStreamData::HandleTables(): Unknown table 0x%1")
473  .arg(psip.TableID(),0,16));
474  break;
475  }
476  }
477  return false;
478 }
479 
480 bool ATSCStreamData::HasEITPIDChanges(const uint_vec_t &in_use_pids) const
481 {
482  QMutexLocker locker(&m_listenerLock);
483  uint eit_count = (uint) round(m_atscEitPids.size() * m_eitRate);
484  uint ett_count = (uint) round(m_atscEttPids.size() * m_eitRate);
485  return (in_use_pids.size() != (eit_count + ett_count) || m_atscEitReset);
486 }
487 
489  uint_vec_t &add_pids,
490  uint_vec_t &del_pids) const
491 {
492  QMutexLocker locker(&m_listenerLock);
493 
494  m_atscEitReset = false;
495 
496  uint eit_count = (uint) round(m_atscEitPids.size() * m_eitRate);
497  uint ett_count = (uint) round(m_atscEttPids.size() * m_eitRate);
498 
499 #if 0
500  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("eit size: %1, rate: %2, cnt: %3")
501  .arg(m_atscEitPids.size()).arg(m_eitRate).arg(eit_count));
502 #endif
503 
504  uint_vec_t add_pids_tmp;
505  atsc_eit_pid_map_t::const_iterator it = m_atscEitPids.begin();
506  for (uint i = 0; it != m_atscEitPids.end() && (i < eit_count); (++it),(i++))
507  add_pids_tmp.push_back(*it);
508 
509  atsc_ett_pid_map_t::const_iterator it2 = m_atscEttPids.begin();
510  for (uint i = 0; it2 != m_atscEttPids.end() && (i < ett_count); (++it2),(i++))
511  add_pids_tmp.push_back(*it2);
512 
513  uint_vec_t::const_iterator it3;
514  for (uint pid : cur_pids)
515  {
516  it3 = find(add_pids_tmp.begin(), add_pids_tmp.end(), pid);
517  if (it3 == add_pids_tmp.end())
518  del_pids.push_back(pid);
519  }
520 
521  for (uint pid : add_pids_tmp)
522  {
523  it3 = find(cur_pids.begin(), cur_pids.end(), pid);
524  if (it3 == cur_pids.end())
525  add_pids.push_back(pid);
526  }
527 
528  return !add_pids.empty() || !del_pids.empty();
529 }
530 
532 {
533  QMutexLocker locker(&m_listenerLock);
534 
535  m_atscEitReset = true;
536  m_atscEitPids.clear();
537  m_atscEttPids.clear();
538 
539  for (uint i = 0 ; i < mgt->TableCount(); i++)
540  {
541  const int table_class = mgt->TableClass(i);
542  const uint pid = mgt->TablePID(i);
543 
544  if (table_class == TableClass::EIT)
545  {
546  const uint num = mgt->TableType(i) - 0x100;
547  m_atscEitPids[num] = pid;
548  }
549  else if (table_class == TableClass::ETTe)
550  {
551  const uint num = mgt->TableType(i) - 0x200;
552  m_atscEttPids[num] = pid;
553  }
554  }
555 
556  for (auto & listener : m_atscMainListeners)
557  listener->HandleMGT(mgt);
558 }
559 
561 {
562  for (auto & listener : m_atscMainListeners)
563  listener->HandleVCT(tsid, vct);
564 
565  m_sourceIdToAtscMajMin.clear();
566  for (uint i = 0; i < vct->ChannelCount() ; i++)
567  {
568  if (vct->IsHidden(i) && vct->IsHiddenInGuide(i))
569  {
570  LOG(VB_EIT, LOG_INFO, LOC +
571  QString("%1 chan %2-%3 is hidden in guide")
572  .arg(vct->ModulationMode(i) == 1 ? "NTSC" : "ATSC")
573  .arg(vct->MajorChannel(i))
574  .arg(vct->MinorChannel(i)));
575  continue;
576  }
577 
578  if (1 == vct->ModulationMode(i))
579  {
580  LOG(VB_EIT, LOG_INFO, LOC + QString("Ignoring NTSC chan %1-%2")
581  .arg(vct->MajorChannel(i))
582  .arg(vct->MinorChannel(i)));
583  continue;
584  }
585 
586  LOG(VB_EIT, LOG_INFO, LOC + QString("Adding Source #%1 ATSC chan %2-%3")
587  .arg(vct->SourceID(i))
588  .arg(vct->MajorChannel(i))
589  .arg(vct->MinorChannel(i)));
590 
592  vct->MajorChannel(i) << 16 | vct->MinorChannel(i);
593  }
594 }
595 
598 {
599  QMutexLocker locker(&m_listenerLock);
600  ProcessVCT(tsid, vct);
601  for (auto & listener : m_atscAuxListeners)
602  listener->HandleTVCT(tsid, vct);
603 }
604 
606  const CableVirtualChannelTable *vct)
607 {
608  QMutexLocker locker(&m_listenerLock);
609  ProcessVCT(tsid, vct);
610  for (auto & listener : m_atscAuxListeners)
611  listener->HandleCVCT(tsid, vct);
612 }
613 
615 {
616  if (!current)
617  LOG(VB_GENERAL, LOG_WARNING, LOC +
618  "Currently we ignore \'current\' param");
619 
620  return (bool)(m_cachedMgt);
621 }
622 
624 {
625  bool hasit = false;
626 
627  {
628  tvct_vec_t tvct = GetCachedTVCTs();
629  for (size_t i = 0; i < tvct.size() && !hasit; i++)
630  {
631  if (tvct[i]->Find(major, minor) >= 0)
632  hasit |= HasProgram(tvct[i]->ProgramNumber(i));
633  }
635  }
636 
637  if (!hasit)
638  {
639  cvct_vec_t cvct = GetCachedCVCTs();
640  for (size_t i = 0; i < cvct.size() && !hasit; i++)
641  {
642  if (cvct[i]->Find(major, minor) >= 0)
643  hasit |= HasProgram(cvct[i]->ProgramNumber(i));
644  }
646  }
647 
648  return hasit;
649 }
650 
652 {
653  if (!current)
654  LOG(VB_GENERAL, LOG_WARNING, LOC +
655  "Currently we ignore \'current\' param");
656 
657  m_cacheLock.lock();
658  tvct_cache_t::const_iterator it = m_cachedTvcts.find(pid);
659  bool exists = (it != m_cachedTvcts.end());
660  m_cacheLock.unlock();
661 
662  return exists;
663 }
664 
666 {
667  if (!current)
668  LOG(VB_GENERAL, LOG_WARNING, LOC +
669  "Currently we ignore \'current\' param");
670 
671  m_cacheLock.lock();
672  cvct_cache_t::const_iterator it = m_cachedCvcts.find(pid);
673  bool exists = (it != m_cachedCvcts.end());
674  m_cacheLock.unlock();
675 
676  return exists;
677 }
678 
680 {
681  if (!current)
682  LOG(VB_GENERAL, LOG_WARNING, LOC +
683  "Currently we ignore \'current\' param");
684 
685  if (!m_cachedMgt)
686  return false;
687 
688  m_cacheLock.lock();
689  bool ret = true;
690  for (uint i = 0; ret && (i < m_cachedMgt->TableCount()); ++i)
691  {
693  ret &= HasCachedTVCT(m_cachedMgt->TablePID(i));
694  }
695  m_cacheLock.unlock();
696 
697  return ret;
698 }
699 
701 {
702  if (!current)
703  LOG(VB_GENERAL, LOG_WARNING, LOC +
704  "Currently we ignore \'current\' param");
705 
706  if (!m_cachedMgt)
707  return false;
708 
709  m_cacheLock.lock();
710  bool ret = true;
711  for (uint i = 0; ret && (i < m_cachedMgt->TableCount()); ++i)
712  {
714  ret &= HasCachedCVCT(m_cachedMgt->TablePID(i));
715  }
716  m_cacheLock.unlock();
717 
718  return ret;
719 }
720 
722 {
723  if (!current)
724  LOG(VB_GENERAL, LOG_WARNING, LOC +
725  "Currently we ignore \'current\' param");
726 
727  QMutexLocker locker(&m_cacheLock);
728  return !m_cachedTvcts.empty();
729 }
730 
732 {
733  if (!current)
734  LOG(VB_GENERAL, LOG_WARNING, LOC +
735  "Currently we ignore \'current\' param");
736 
737  QMutexLocker locker(&m_cacheLock);
738  return !m_cachedCvcts.empty();
739 }
740 
742 {
743  if (!current)
744  LOG(VB_GENERAL, LOG_WARNING, LOC +
745  "Currently we ignore \'current\' param");
746 
747  m_cacheLock.lock();
748  const MasterGuideTable *mgt = m_cachedMgt;
749  IncrementRefCnt(mgt);
750  m_cacheLock.unlock();
751 
752  return mgt;
753 }
754 
756 {
757  if (!current)
758  LOG(VB_GENERAL, LOG_WARNING, LOC +
759  "Currently we ignore \'current\' param");
760 
761  tvct_ptr_t tvct = nullptr;
762 
763  m_cacheLock.lock();
764  tvct_cache_t::const_iterator it = m_cachedTvcts.find(pid);
765  if (it != m_cachedTvcts.end())
766  IncrementRefCnt(tvct = *it);
767  m_cacheLock.unlock();
768 
769  return tvct;
770 }
771 
773 {
774  if (!current)
775  LOG(VB_GENERAL, LOG_WARNING, LOC +
776  "Currently we ignore \'current\' param");
777 
778  cvct_ptr_t cvct = nullptr;
779 
780  m_cacheLock.lock();
781  cvct_cache_t::const_iterator it = m_cachedCvcts.find(pid);
782  if (it != m_cachedCvcts.end())
783  IncrementRefCnt(cvct = *it);
784  m_cacheLock.unlock();
785 
786  return cvct;
787 }
788 
790 {
791  if (!current)
792  LOG(VB_GENERAL, LOG_WARNING, LOC +
793  "Currently we ignore \'current\' param");
794 
795  vector<const TerrestrialVirtualChannelTable*> tvcts;
796 
797  m_cacheLock.lock();
798  tvct_cache_t::const_iterator it = m_cachedTvcts.begin();
799  for (; it != m_cachedTvcts.end(); ++it)
800  {
801  TerrestrialVirtualChannelTable* tvct = *it;
802  IncrementRefCnt(tvct);
803  tvcts.push_back(tvct);
804  }
805  m_cacheLock.unlock();
806 
807  return tvcts;
808 }
809 
811 {
812  if (!current)
813  LOG(VB_GENERAL, LOG_WARNING, LOC +
814  "Currently we ignore \'current\' param");
815 
816  vector<const CableVirtualChannelTable*> cvcts;
817 
818  m_cacheLock.lock();
819  foreach (auto cvct, m_cachedCvcts)
820  {
821  IncrementRefCnt(cvct);
822  cvcts.push_back(cvct);
823  }
824  m_cacheLock.unlock();
825 
826  return cvcts;
827 }
828 
830 {
831  QMutexLocker locker(&m_cacheLock);
832 
834  m_cachedMgt = mgt;
835 }
836 
838 {
839  QMutexLocker locker(&m_cacheLock);
840 
842  m_cachedTvcts[pid] = tvct;
843 }
844 
846 {
847  QMutexLocker locker(&m_cacheLock);
848 
850  m_cachedCvcts[pid] = cvct;
851 }
852 
854 {
855  if (!psip)
856  return false;
857 
858  QMutexLocker locker(&m_cacheLock);
859  if (m_cachedRefCnt[psip] > 0)
860  {
861  m_cachedSlatedForDeletion[psip] = 1;
862  return false;
863  }
864  if (TableID::MGT == psip->TableID())
865  {
866  if (psip == m_cachedMgt)
867  m_cachedMgt = nullptr;
868  delete psip;
869  }
870  else if ((TableID::TVCT == psip->TableID()) &&
871  m_cachedTvcts[psip->tsheader()->PID()])
872  {
873  m_cachedTvcts[psip->tsheader()->PID()] = nullptr;
874  delete psip;
875  }
876  else if ((TableID::CVCT == psip->TableID()) &&
877  m_cachedCvcts[psip->tsheader()->PID()])
878  {
879  m_cachedCvcts[psip->tsheader()->PID()] = nullptr;
880  delete psip;
881  }
882  else
883  {
885  }
886  psip_refcnt_map_t::iterator it;
887  it = m_cachedSlatedForDeletion.find(psip);
888  if (it != m_cachedSlatedForDeletion.end())
889  m_cachedSlatedForDeletion.erase(it);
890 
891  return true;
892 }
893 
895 {
896  for (auto & tvct : tvcts)
897  ReturnCachedTable(tvct);
898  tvcts.clear();
899 }
900 
902 {
903  for (auto & cvct : cvcts)
904  ReturnCachedTable(cvct);
905  cvcts.clear();
906 }
907 
909 {
910  QMutexLocker locker(&m_listenerLock);
911 
912  for (auto & listener : m_atscMainListeners)
913  if (((void*)val) == ((void*)listener))
914  return;
915 
916  m_atscMainListeners.push_back(val);
917 }
918 
920 {
921  QMutexLocker locker(&m_listenerLock);
922 
923  for (auto it = m_atscMainListeners.begin(); it != m_atscMainListeners.end(); ++it)
924  {
925  if (((void*)val) == ((void*)*it))
926  {
927  m_atscMainListeners.erase(it);
928  return;
929  }
930  }
931 }
932 
934 {
935  QMutexLocker locker(&m_listenerLock);
936 
937  for (auto & listener : m_scteMainlisteners)
938  if (((void*)val) == ((void*)listener))
939  return;
940 
941  m_scteMainlisteners.push_back(val);
942 }
943 
945 {
946  QMutexLocker locker(&m_listenerLock);
947 
948  for (auto it = m_scteMainlisteners.begin(); it != m_scteMainlisteners.end(); ++it)
949  {
950  if (((void*)val) == ((void*)*it))
951  {
952  m_scteMainlisteners.erase(it);
953  return;
954  }
955  }
956 }
957 
959 {
960  QMutexLocker locker(&m_listenerLock);
961 
962  for (auto & listener : m_atscAuxListeners)
963  if (((void*)val) == ((void*)listener))
964  return;
965 
966  m_atscAuxListeners.push_back(val);
967 }
968 
970 {
971  QMutexLocker locker(&m_listenerLock);
972 
973  for (auto it = m_atscAuxListeners.begin(); it != m_atscAuxListeners.end(); ++it)
974  {
975  if (((void*)val) == ((void*)*it))
976  {
977  m_atscAuxListeners.erase(it);
978  return;
979  }
980  }
981 }
982 
984 {
985  QMutexLocker locker(&m_listenerLock);
986 
987  for (auto & listener : m_atscEitListeners)
988  if (((void*)val) == ((void*)listener))
989  return;
990 
991  m_atscEitListeners.push_back(val);
992 }
993 
995 {
996  QMutexLocker locker(&m_listenerLock);
997 
998  for (auto it = m_atscEitListeners.begin(); it != m_atscEitListeners.end(); ++it)
999  {
1000  if (((void*)val) == ((void*)*it))
1001  {
1002  m_atscEitListeners.erase(it);
1003  return;
1004  }
1005  }
1006 }
1007 
1009 {
1010  QMutexLocker locker(&m_listenerLock);
1011 
1012  for (auto & listener : m_atsc81EitListeners)
1013  if (((void*)val) == ((void*)listener))
1014  return;
1015 
1016  m_atsc81EitListeners.push_back(val);
1017 }
1018 
1020 {
1021  QMutexLocker locker(&m_listenerLock);
1022 
1023  for (auto it = m_atsc81EitListeners.begin(); it != m_atsc81EitListeners.end(); ++it)
1024  {
1025  if (((void*)val) == ((void*)*it))
1026  {
1027  m_atsc81EitListeners.erase(it);
1028  return;
1029  }
1030  }
1031 }
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:65
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
#define LOG(_MASK_, _LEVEL_, _STRING_)
Definition: mythlogging.h:41
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