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