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