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