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 desiredMajorChannel, int desiredMinorChannel)
123 {
124  _desired_major_channel = desiredMajorChannel;
125  _desired_minor_channel = desiredMinorChannel;
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  auto *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  {
247  auto *vct = new TerrestrialVirtualChannelTable(psip);
248  CacheTVCT(pid, vct);
249  ProcessTVCT(tsid, vct);
250  }
251  else
252  {
254  ProcessTVCT(tsid, &vct);
255  }
256  return true;
257  }
258  case TableID::CVCT:
259  {
260  uint tsid = psip.TableIDExtension();
261  SetVersionCVCT(tsid, version);
262  if (_cache_tables)
263  {
264  auto *vct = new CableVirtualChannelTable(psip);
265  CacheCVCT(pid, vct);
266  ProcessCVCT(tsid, vct);
267  }
268  else
269  {
270  CableVirtualChannelTable vct(psip);
271  ProcessCVCT(tsid, &vct);
272  }
273  return true;
274  }
275  case TableID::RRT:
276  {
277  uint region = psip.TableIDExtension();
278  SetVersionRRT(region, version);
279  RatingRegionTable rrt(psip);
280  QMutexLocker locker(&_listener_lock);
281  for (size_t i = 0; i < _atsc_aux_listeners.size(); i++)
282  _atsc_aux_listeners[i]->HandleRRT(&rrt);
283  return true;
284  }
285  case TableID::EIT:
286  {
287  QMutexLocker locker(&_listener_lock);
288  if (_atsc_eit_listeners.empty() && !_eit_helper)
289  return true;
290 
291  uint key = (pid<<16) | psip.TableIDExtension();
292  _eit_status.SetSectionSeen(key, version, psip.Section(), psip.LastSection());
293 
294  EventInformationTable eit(psip);
295  for (size_t i = 0; i < _atsc_eit_listeners.size(); i++)
296  _atsc_eit_listeners[i]->HandleEIT(pid, &eit);
297 
298  const uint mm = GetATSCMajorMinor(eit.SourceID());
299  if (mm && _eit_helper)
300  _eit_helper->AddEIT(mm >> 16, mm & 0xffff, &eit);
301 
302  return true;
303  }
304  case TableID::ETT:
305  {
306  ExtendedTextTable ett(psip);
307 
308  QMutexLocker locker(&_listener_lock);
309  for (size_t i = 0; i < _atsc_eit_listeners.size(); i++)
310  _atsc_eit_listeners[i]->HandleETT(pid, &ett);
311 
312  if (ett.IsEventETM() && _eit_helper) // Guide ETTs
313  {
314  const uint mm = GetATSCMajorMinor(ett.SourceID());
315  if (mm)
316  _eit_helper->AddETT(mm >> 16, mm & 0xffff, &ett);
317  }
318 
319  return true;
320  }
321  case TableID::STT:
322  {
323  SystemTimeTable stt(psip);
324 
325  UpdateTimeOffset(stt.UTCUnix());
326 
327  // only update internal offset if it changes
328  if (stt.GPSOffset() != _GPS_UTC_offset)
329  _GPS_UTC_offset = stt.GPSOffset();
330 
331  _listener_lock.lock();
332  for (size_t i = 0; i < _atsc_main_listeners.size(); i++)
333  _atsc_main_listeners[i]->HandleSTT(&stt);
334  _listener_lock.unlock();
335 
338 
339  return true;
340  }
341  case TableID::DCCT:
342  {
343  DirectedChannelChangeTable dcct(psip);
344 
345  QMutexLocker locker(&_listener_lock);
346  for (size_t i = 0; i < _atsc_aux_listeners.size(); i++)
347  _atsc_aux_listeners[i]->HandleDCCT(&dcct);
348 
349  return true;
350  }
351  case TableID::DCCSCT:
352  {
354 
355  QMutexLocker locker(&_listener_lock);
356  for (size_t i = 0; i < _atsc_aux_listeners.size(); i++)
357  _atsc_aux_listeners[i]->HandleDCCSCT(&dccsct);
358 
359  return true;
360  }
361 
362  // ATSC A/81 & SCTE 65 tables
363  case TableID::AEIT:
364  {
366 
367  QMutexLocker locker(&_listener_lock);
368  for (size_t i = 0; i < _atsc81_eit_listeners.size(); i++)
369  _atsc81_eit_listeners[i]->HandleAEIT(pid, &aeit);
370 
371  return true;
372  }
373  case TableID::AETT:
374  {
375  AggregateExtendedTextTable aett(psip);
376 
377  QMutexLocker locker(&_listener_lock);
378  for (size_t i = 0; i < _atsc81_eit_listeners.size(); i++)
379  _atsc81_eit_listeners[i]->HandleAETT(pid, &aett);
380 
381  return true;
382  }
383 
384  // SCTE 65 tables
385  case TableID::NITscte:
386  {
387  SCTENetworkInformationTable nit(psip);
388 
389  QMutexLocker locker(&_listener_lock);
390  for (size_t i = 0; i < _scte_main_listeners.size(); i++)
391  _scte_main_listeners[i]->HandleNIT(&nit);
392 
393  return true;
394  }
395  case TableID::NTT:
396  {
397  NetworkTextTable ntt(psip);
398 
399  QMutexLocker locker(&_listener_lock);
400  for (size_t i = 0; i < _scte_main_listeners.size(); i++)
401  _scte_main_listeners[i]->HandleNTT(&ntt);
402 
403  return true;
404  }
405  case TableID::SVCTscte:
406  {
407  ShortVirtualChannelTable svct(psip);
408 
409  QMutexLocker locker(&_listener_lock);
410  for (size_t i = 0; i < _scte_main_listeners.size(); i++)
411  _scte_main_listeners[i]->HandleSVCT(&svct);
412 
413  return true;
414  }
415  case TableID::STTscte:
416  {
417  SCTESystemTimeTable stt(psip);
418 
419  QMutexLocker locker(&_listener_lock);
420  for (size_t i = 0; i < _scte_main_listeners.size(); i++)
421  _scte_main_listeners[i]->HandleSTT(&stt);
422 
423  return true;
424  }
425 
426  // SCTE 57 table -- SCTE 65 standard supercedes this
427  case TableID::PIM:
428  {
430 
431  QMutexLocker locker(&_listener_lock);
432  for (size_t i = 0; i < _scte_main_listeners.size(); i++)
433  _scte_main_listeners[i]->HandlePIM(&pim);
434 
435  return true;
436  }
437  // SCTE 57 table -- SCTE 65 standard supercedes this
438  case TableID::PNM:
439  {
440  ProgramNameMessageTable pnm(psip);
441 
442  QMutexLocker locker(&_listener_lock);
443  for (size_t i = 0; i < _scte_main_listeners.size(); i++)
444  _scte_main_listeners[i]->HandlePNM(&pnm);
445 
446  return true;
447  }
448 
449  // SCTE 80
450  case TableID::ADET:
451  {
452  AggregateDataEventTable adet(psip);
453 
454  QMutexLocker locker(&_listener_lock);
455  for (size_t i = 0; i < _scte_main_listeners.size(); i++)
456  _scte_main_listeners[i]->HandleADET(&adet);
457 
458  return true;
459  }
460 
461  case TableID::NIT:
462  case TableID::NITo:
463  case TableID::SDT:
464  case TableID::SDTo:
465  case TableID::BAT:
466  case TableID::TDT:
467  case TableID::TOT:
468  case TableID::DVBCA_82:
469  case TableID::DVBCA_83:
470  {
471  // All DVB specific tables, not handled here
472  return false;
473  }
474 
475  default:
476  {
477  LOG(VB_RECORD, LOG_ERR, LOC +
478  QString("ATSCStreamData::HandleTables(): Unknown table 0x%1")
479  .arg(psip.TableID(),0,16));
480  break;
481  }
482  }
483  return false;
484 }
485 
486 bool ATSCStreamData::HasEITPIDChanges(const uint_vec_t &in_use_pids) const
487 {
488  QMutexLocker locker(&_listener_lock);
489  uint eit_count = (uint) round(_atsc_eit_pids.size() * _eit_rate);
490  uint ett_count = (uint) round(_atsc_ett_pids.size() * _eit_rate);
491  return (in_use_pids.size() != (eit_count + ett_count) || _atsc_eit_reset);
492 }
493 
495  uint_vec_t &add_pids,
496  uint_vec_t &del_pids) const
497 {
498  QMutexLocker locker(&_listener_lock);
499 
500  _atsc_eit_reset = false;
501 
502  uint eit_count = (uint) round(_atsc_eit_pids.size() * _eit_rate);
503  uint ett_count = (uint) round(_atsc_ett_pids.size() * _eit_rate);
504 
505 #if 0
506  LOG(VB_GENERAL, LOG_DEBUG, LOC + QString("eit size: %1, rate: %2, cnt: %3")
507  .arg(_atsc_eit_pids.size()).arg(_eit_rate).arg(eit_count));
508 #endif
509 
510  uint_vec_t add_pids_tmp;
511  atsc_eit_pid_map_t::const_iterator it = _atsc_eit_pids.begin();
512  for (uint i = 0; it != _atsc_eit_pids.end() && (i < eit_count); (++it),(i++))
513  add_pids_tmp.push_back(*it);
514 
515  atsc_ett_pid_map_t::const_iterator it2 = _atsc_ett_pids.begin();
516  for (uint i = 0; it2 != _atsc_ett_pids.end() && (i < ett_count); (++it2),(i++))
517  add_pids_tmp.push_back(*it2);
518 
519  uint_vec_t::const_iterator it3;
520  for (size_t i = 0; i < cur_pids.size(); i++)
521  {
522  it3 = find(add_pids_tmp.begin(), add_pids_tmp.end(), cur_pids[i]);
523  if (it3 == add_pids_tmp.end())
524  del_pids.push_back(cur_pids[i]);
525  }
526 
527  for (size_t i = 0; i < add_pids_tmp.size(); i++)
528  {
529  it3 = find(cur_pids.begin(), cur_pids.end(), add_pids_tmp[i]);
530  if (it3 == cur_pids.end())
531  add_pids.push_back(add_pids_tmp[i]);
532  }
533 
534  return !add_pids.empty() || !del_pids.empty();
535 }
536 
538 {
539  QMutexLocker locker(&_listener_lock);
540 
541  _atsc_eit_reset = true;
542  _atsc_eit_pids.clear();
543  _atsc_ett_pids.clear();
544 
545  for (uint i = 0 ; i < mgt->TableCount(); i++)
546  {
547  const int table_class = mgt->TableClass(i);
548  const uint pid = mgt->TablePID(i);
549 
550  if (table_class == TableClass::EIT)
551  {
552  const uint num = mgt->TableType(i) - 0x100;
553  _atsc_eit_pids[num] = pid;
554  }
555  else if (table_class == TableClass::ETTe)
556  {
557  const uint num = mgt->TableType(i) - 0x200;
558  _atsc_ett_pids[num] = pid;
559  }
560  }
561 
562  for (size_t i = 0; i < _atsc_main_listeners.size(); i++)
563  _atsc_main_listeners[i]->HandleMGT(mgt);
564 }
565 
567 {
568  for (size_t i = 0; i < _atsc_main_listeners.size(); i++)
569  _atsc_main_listeners[i]->HandleVCT(tsid, vct);
570 
572  for (uint i = 0; i < vct->ChannelCount() ; i++)
573  {
574  if (vct->IsHidden(i) && vct->IsHiddenInGuide(i))
575  {
576  LOG(VB_EIT, LOG_INFO, LOC +
577  QString("%1 chan %2-%3 is hidden in guide")
578  .arg(vct->ModulationMode(i) == 1 ? "NTSC" : "ATSC")
579  .arg(vct->MajorChannel(i))
580  .arg(vct->MinorChannel(i)));
581  continue;
582  }
583 
584  if (1 == vct->ModulationMode(i))
585  {
586  LOG(VB_EIT, LOG_INFO, LOC + QString("Ignoring NTSC chan %1-%2")
587  .arg(vct->MajorChannel(i))
588  .arg(vct->MinorChannel(i)));
589  continue;
590  }
591 
592  LOG(VB_EIT, LOG_INFO, LOC + QString("Adding Source #%1 ATSC chan %2-%3")
593  .arg(vct->SourceID(i))
594  .arg(vct->MajorChannel(i))
595  .arg(vct->MinorChannel(i)));
596 
598  vct->MajorChannel(i) << 16 | vct->MinorChannel(i);
599  }
600 }
601 
604 {
605  QMutexLocker locker(&_listener_lock);
606  ProcessVCT(tsid, vct);
607  for (size_t i = 0; i < _atsc_aux_listeners.size(); i++)
608  _atsc_aux_listeners[i]->HandleTVCT(tsid, vct);
609 }
610 
612  const CableVirtualChannelTable *vct)
613 {
614  QMutexLocker locker(&_listener_lock);
615  ProcessVCT(tsid, vct);
616  for (size_t i = 0; i < _atsc_aux_listeners.size(); i++)
617  _atsc_aux_listeners[i]->HandleCVCT(tsid, vct);
618 }
619 
621 {
622  if (!current)
623  LOG(VB_GENERAL, LOG_WARNING, LOC +
624  "Currently we ignore \'current\' param");
625 
626  return (bool)(_cached_mgt);
627 }
628 
630 {
631  bool hasit = false;
632 
633  {
634  tvct_vec_t tvct = GetCachedTVCTs();
635  for (size_t i = 0; i < tvct.size() && !hasit; i++)
636  {
637  if (tvct[i]->Find(major, minor) >= 0)
638  hasit |= HasProgram(tvct[i]->ProgramNumber(i));
639  }
641  }
642 
643  if (!hasit)
644  {
645  cvct_vec_t cvct = GetCachedCVCTs();
646  for (size_t i = 0; i < cvct.size() && !hasit; i++)
647  {
648  if (cvct[i]->Find(major, minor) >= 0)
649  hasit |= HasProgram(cvct[i]->ProgramNumber(i));
650  }
652  }
653 
654  return hasit;
655 }
656 
658 {
659  if (!current)
660  LOG(VB_GENERAL, LOG_WARNING, LOC +
661  "Currently we ignore \'current\' param");
662 
663  _cache_lock.lock();
664  tvct_cache_t::const_iterator it = _cached_tvcts.find(pid);
665  bool exists = (it != _cached_tvcts.end());
666  _cache_lock.unlock();
667 
668  return exists;
669 }
670 
672 {
673  if (!current)
674  LOG(VB_GENERAL, LOG_WARNING, LOC +
675  "Currently we ignore \'current\' param");
676 
677  _cache_lock.lock();
678  cvct_cache_t::const_iterator it = _cached_cvcts.find(pid);
679  bool exists = (it != _cached_cvcts.end());
680  _cache_lock.unlock();
681 
682  return exists;
683 }
684 
686 {
687  if (!current)
688  LOG(VB_GENERAL, LOG_WARNING, LOC +
689  "Currently we ignore \'current\' param");
690 
691  if (!_cached_mgt)
692  return false;
693 
694  _cache_lock.lock();
695  bool ret = true;
696  for (uint i = 0; ret && (i < _cached_mgt->TableCount()); ++i)
697  {
699  ret &= HasCachedTVCT(_cached_mgt->TablePID(i));
700  }
701  _cache_lock.unlock();
702 
703  return ret;
704 }
705 
707 {
708  if (!current)
709  LOG(VB_GENERAL, LOG_WARNING, LOC +
710  "Currently we ignore \'current\' param");
711 
712  if (!_cached_mgt)
713  return false;
714 
715  _cache_lock.lock();
716  bool ret = true;
717  for (uint i = 0; ret && (i < _cached_mgt->TableCount()); ++i)
718  {
720  ret &= HasCachedCVCT(_cached_mgt->TablePID(i));
721  }
722  _cache_lock.unlock();
723 
724  return ret;
725 }
726 
728 {
729  if (!current)
730  LOG(VB_GENERAL, LOG_WARNING, LOC +
731  "Currently we ignore \'current\' param");
732 
733  QMutexLocker locker(&_cache_lock);
734  return !_cached_tvcts.empty();
735 }
736 
738 {
739  if (!current)
740  LOG(VB_GENERAL, LOG_WARNING, LOC +
741  "Currently we ignore \'current\' param");
742 
743  QMutexLocker locker(&_cache_lock);
744  return !_cached_cvcts.empty();
745 }
746 
748 {
749  if (!current)
750  LOG(VB_GENERAL, LOG_WARNING, LOC +
751  "Currently we ignore \'current\' param");
752 
753  _cache_lock.lock();
754  const MasterGuideTable *mgt = _cached_mgt;
755  IncrementRefCnt(mgt);
756  _cache_lock.unlock();
757 
758  return mgt;
759 }
760 
762 {
763  if (!current)
764  LOG(VB_GENERAL, LOG_WARNING, LOC +
765  "Currently we ignore \'current\' param");
766 
767  tvct_ptr_t tvct = nullptr;
768 
769  _cache_lock.lock();
770  tvct_cache_t::const_iterator it = _cached_tvcts.find(pid);
771  if (it != _cached_tvcts.end())
772  IncrementRefCnt(tvct = *it);
773  _cache_lock.unlock();
774 
775  return tvct;
776 }
777 
779 {
780  if (!current)
781  LOG(VB_GENERAL, LOG_WARNING, LOC +
782  "Currently we ignore \'current\' param");
783 
784  cvct_ptr_t cvct = nullptr;
785 
786  _cache_lock.lock();
787  cvct_cache_t::const_iterator it = _cached_cvcts.find(pid);
788  if (it != _cached_cvcts.end())
789  IncrementRefCnt(cvct = *it);
790  _cache_lock.unlock();
791 
792  return cvct;
793 }
794 
796 {
797  if (!current)
798  LOG(VB_GENERAL, LOG_WARNING, LOC +
799  "Currently we ignore \'current\' param");
800 
801  vector<const TerrestrialVirtualChannelTable*> tvcts;
802 
803  _cache_lock.lock();
804  tvct_cache_t::const_iterator it = _cached_tvcts.begin();
805  for (; it != _cached_tvcts.end(); ++it)
806  {
807  TerrestrialVirtualChannelTable* tvct = *it;
808  IncrementRefCnt(tvct);
809  tvcts.push_back(tvct);
810  }
811  _cache_lock.unlock();
812 
813  return tvcts;
814 }
815 
817 {
818  if (!current)
819  LOG(VB_GENERAL, LOG_WARNING, LOC +
820  "Currently we ignore \'current\' param");
821 
822  vector<const CableVirtualChannelTable*> cvcts;
823 
824  _cache_lock.lock();
825  cvct_cache_t::const_iterator it = _cached_cvcts.begin();
826  for (; it != _cached_cvcts.end(); ++it)
827  {
828  CableVirtualChannelTable* cvct = *it;
829  IncrementRefCnt(cvct);
830  cvcts.push_back(cvct);
831  }
832  _cache_lock.unlock();
833 
834  return cvcts;
835 }
836 
838 {
839  QMutexLocker locker(&_cache_lock);
840 
842  _cached_mgt = mgt;
843 }
844 
846 {
847  QMutexLocker locker(&_cache_lock);
848 
850  _cached_tvcts[pid] = tvct;
851 }
852 
854 {
855  QMutexLocker locker(&_cache_lock);
856 
858  _cached_cvcts[pid] = cvct;
859 }
860 
862 {
863  if (!psip)
864  return false;
865 
866  QMutexLocker locker(&_cache_lock);
867  if (_cached_ref_cnt[psip] > 0)
868  {
869  _cached_slated_for_deletion[psip] = 1;
870  return false;
871  }
872  if (TableID::MGT == psip->TableID())
873  {
874  if (psip == _cached_mgt)
875  _cached_mgt = nullptr;
876  delete psip;
877  }
878  else if ((TableID::TVCT == psip->TableID()) &&
879  _cached_tvcts[psip->tsheader()->PID()])
880  {
881  _cached_tvcts[psip->tsheader()->PID()] = nullptr;
882  delete psip;
883  }
884  else if ((TableID::CVCT == psip->TableID()) &&
885  _cached_cvcts[psip->tsheader()->PID()])
886  {
887  _cached_cvcts[psip->tsheader()->PID()] = nullptr;
888  delete psip;
889  }
890  else
891  {
893  }
894  psip_refcnt_map_t::iterator it;
895  it = _cached_slated_for_deletion.find(psip);
896  if (it != _cached_slated_for_deletion.end())
897  _cached_slated_for_deletion.erase(it);
898 
899  return true;
900 }
901 
903 {
904  for (auto it = tvcts.begin(); it != tvcts.end(); ++it)
905  ReturnCachedTable(*it);
906  tvcts.clear();
907 }
908 
910 {
911  for (auto it = cvcts.begin(); it != cvcts.end(); ++it)
912  ReturnCachedTable(*it);
913  cvcts.clear();
914 }
915 
917 {
918  QMutexLocker locker(&_listener_lock);
919 
920  auto it = _atsc_main_listeners.begin();
921  for (; it != _atsc_main_listeners.end(); ++it)
922  if (((void*)val) == ((void*)*it))
923  return;
924 
925  _atsc_main_listeners.push_back(val);
926 }
927 
929 {
930  QMutexLocker locker(&_listener_lock);
931 
932  auto it = _atsc_main_listeners.begin();
933  for (; it != _atsc_main_listeners.end(); ++it)
934  {
935  if (((void*)val) == ((void*)*it))
936  {
937  _atsc_main_listeners.erase(it);
938  return;
939  }
940  }
941 }
942 
944 {
945  QMutexLocker locker(&_listener_lock);
946 
947  auto it = _scte_main_listeners.begin();
948  for (; it != _scte_main_listeners.end(); ++it)
949  if (((void*)val) == ((void*)*it))
950  return;
951 
952  _scte_main_listeners.push_back(val);
953 }
954 
956 {
957  QMutexLocker locker(&_listener_lock);
958 
959  auto it = _scte_main_listeners.begin();
960  for (; it != _scte_main_listeners.end(); ++it)
961  {
962  if (((void*)val) == ((void*)*it))
963  {
964  _scte_main_listeners.erase(it);
965  return;
966  }
967  }
968 }
969 
971 {
972  QMutexLocker locker(&_listener_lock);
973 
974  auto it = _atsc_aux_listeners.begin();
975  for (; it != _atsc_aux_listeners.end(); ++it)
976  if (((void*)val) == ((void*)*it))
977  return;
978 
979  _atsc_aux_listeners.push_back(val);
980 }
981 
983 {
984  QMutexLocker locker(&_listener_lock);
985 
986  auto it = _atsc_aux_listeners.begin();
987  for (; it != _atsc_aux_listeners.end(); ++it)
988  {
989  if (((void*)val) == ((void*)*it))
990  {
991  _atsc_aux_listeners.erase(it);
992  return;
993  }
994  }
995 }
996 
998 {
999  QMutexLocker locker(&_listener_lock);
1000 
1001  auto it = _atsc_eit_listeners.begin();
1002  for (; it != _atsc_eit_listeners.end(); ++it)
1003  if (((void*)val) == ((void*)*it))
1004  return;
1005 
1006  _atsc_eit_listeners.push_back(val);
1007 }
1008 
1010 {
1011  QMutexLocker locker(&_listener_lock);
1012 
1013  auto it = _atsc_eit_listeners.begin();
1014  for (; it != _atsc_eit_listeners.end(); ++it)
1015  {
1016  if (((void*)val) == ((void*)*it))
1017  {
1018  _atsc_eit_listeners.erase(it);
1019  return;
1020  }
1021  }
1022 }
1023 
1025 {
1026  QMutexLocker locker(&_listener_lock);
1027 
1028  auto it = _atsc81_eit_listeners.begin();
1029  for (; it != _atsc81_eit_listeners.end(); ++it)
1030  if (((void*)val) == ((void*)*it))
1031  return;
1032 
1033  _atsc81_eit_listeners.push_back(val);
1034 }
1035 
1037 {
1038  QMutexLocker locker(&_listener_lock);
1039 
1040  auto it = _atsc81_eit_listeners.begin();
1041  for (; it != _atsc81_eit_listeners.end(); ++it)
1042  {
1043  if (((void*)val) == ((void*)*it))
1044  {
1045  _atsc81_eit_listeners.erase(it);
1046  return;
1047  }
1048  }
1049 }
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:485
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)
Process PSIP packets.
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:141
virtual bool DeleteCachedTable(const PSIPTable *psip) const
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:180
#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
unsigned int uint
Definition: compat.h:140
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 *)
bool DeleteCachedTable(const PSIPTable *psip) const override
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
unsigned int PID(void) const
Definition: tspacket.h:71
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
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
void RemoveATSCEITListener(ATSCEITStreamListener *)
bool HandleTables(uint pid, const PSIPTable &psip) override
Process PSIP packets.
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
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
bool GetEITPIDChanges(const uint_vec_t &cur_pids, uint_vec_t &add_pids, uint_vec_t &del_pids) const override