11#include < fcntl.h>
2+ #include < algorithm>
23#include < lib/dvb/idvb.h>
34#include < dvbsi++/descriptor_tag.h>
45#include < dvbsi++/service_descriptor.h>
910#include < dvbsi++/logical_channel_descriptor.h>
1011#include < dvbsi++/cable_delivery_system_descriptor.h>
1112#include < dvbsi++/ca_identifier_descriptor.h>
13+ #include < dvbsi++/ca_descriptor.h>
1214#include < dvbsi++/registration_descriptor.h>
1315#include < dvbsi++/extension_descriptor.h>
1416#include < dvbsi++/frequency_list_descriptor.h>
@@ -472,6 +474,11 @@ void eDVBScan::PMTready(int err)
472474 bool have_audio = false ;
473475 bool have_video = false ;
474476 unsigned short pcrpid = 0xFFFF ;
477+ unsigned short videopid = 0xFFFF ;
478+ unsigned short audiopid = 0xFFFF ;
479+ eDVBService::cacheID audioCacheId = eDVBService::cMPEGAPID;
480+ int videotype = -1 ; // -1 = MPEG2 (default)
481+ CAID_LIST caids;
475482 std::vector<ProgramMapSection*>::const_iterator i;
476483
477484 for (i = m_PMT->getSections ().begin (); i != m_PMT->getSections ().end (); ++i)
@@ -485,28 +492,61 @@ void eDVBScan::PMTready(int err)
485492 for (es = pmt.getEsInfo ()->begin (); es != pmt.getEsInfo ()->end (); ++es)
486493 {
487494 int isaudio = 0 , isvideo = 0 , is_scrambled = 0 , forced_audio = 0 , forced_video = 0 ;
495+ eDVBService::cacheID currentAudioCacheId = eDVBService::cMPEGAPID;
496+ int currentVideoType = -1 ; // -1 = MPEG2 (default)
488497 switch ((*es)->getType ())
489498 {
490499 case 0x1b : // AVC Video Stream (MPEG4 H264)
500+ isvideo = 1 ;
501+ forced_video = 1 ;
502+ currentVideoType = 1 ; // MPEG4_H264
503+ break ;
491504 case 0x24 : // H265 HEVC
505+ isvideo = 1 ;
506+ forced_video = 1 ;
507+ currentVideoType = 7 ; // H265_HEVC
508+ break ;
492509 case 0x10 : // MPEG 4 Part 2
510+ isvideo = 1 ;
511+ forced_video = 1 ;
512+ currentVideoType = 4 ; // MPEG4_Part2
513+ break ;
493514 case 0x01 : // MPEG 1 video
515+ isvideo = 1 ;
516+ forced_video = 1 ;
517+ currentVideoType = 5 ; // MPEG1
518+ break ;
494519 case 0x02 : // MPEG 2 video
495520 isvideo = 1 ;
496521 forced_video = 1 ;
497- [[fallthrough]];
522+ currentVideoType = -1 ; // MPEG2 (default, stored as -1)
523+ break ;
498524 case 0x03 : // MPEG 1 audio
499525 case 0x04 : // MPEG 2 audio
526+ if (!isvideo)
527+ {
528+ forced_audio = 1 ;
529+ isaudio = 1 ;
530+ currentAudioCacheId = eDVBService::cMPEGAPID;
531+ }
532+ [[fallthrough]];
500533 case 0x0f : // MPEG 2 AAC
501534 case 0x11 : // MPEG 4 AAC
502- if (!isvideo)
535+ if (!isvideo && !forced_audio )
503536 {
504537 forced_audio = 1 ;
505538 isaudio = 1 ;
539+ currentAudioCacheId = eDVBService::cAACAPID;
506540 }
507541 [[fallthrough]];
508542 case 0x06 : // PES Private
509- case 0x81 : // user private
543+ case 0x81 : // user private - often AC3
544+ if ((*es)->getType () == 0x81 && !forced_audio)
545+ {
546+ isaudio = 1 ;
547+ currentAudioCacheId = eDVBService::cAC3PID;
548+ }
549+ [[fallthrough]];
510550 case 0xEA : // TS_PSI_ST_SMPTE_VC1
511551 for (DescriptorConstIterator desc = (*es)->getDescriptors ()->begin ();
512552 desc != (*es)->getDescriptors ()->end (); ++desc)
@@ -521,10 +561,24 @@ void eDVBScan::PMTready(int err)
521561 case 0x1C : // TS_PSI_DT_MPEG4_Audio
522562 case 0x2B : // TS_PSI_DT_MPEG2_AAC
523563 case AAC_DESCRIPTOR:
564+ isaudio = 1 ;
565+ currentAudioCacheId = eDVBService::cAACAPID;
566+ break ;
524567 case AC3_DESCRIPTOR:
568+ isaudio = 1 ;
569+ currentAudioCacheId = eDVBService::cAC3PID;
570+ break ;
571+ case ENHANCED_AC3_DESCRIPTOR:
572+ isaudio = 1 ;
573+ currentAudioCacheId = eDVBService::cDDPPID;
574+ break ;
525575 case DTS_DESCRIPTOR:
576+ isaudio = 1 ;
577+ currentAudioCacheId = eDVBService::cDTSPID;
578+ break ;
526579 case AUDIO_STREAM_DESCRIPTOR:
527580 isaudio = 1 ;
581+ currentAudioCacheId = eDVBService::cMPEGAPID;
528582 break ;
529583 case 0x28 : // TS_PSI_DT_AVC
530584 case 0x1B : // TS_PSI_DT_MPEG4_Video
@@ -537,9 +591,16 @@ void eDVBScan::PMTready(int err)
537591 switch (d->getFormatIdentifier ())
538592 {
539593 case 0x44545331 ... 0x44545333 : // DTS1/DTS2/DTS3
594+ isaudio = 1 ;
595+ currentAudioCacheId = eDVBService::cDTSPID;
596+ break ;
540597 case 0x41432d33 : // == 'AC-3'
598+ isaudio = 1 ;
599+ currentAudioCacheId = eDVBService::cAC3PID;
600+ break ;
541601 case 0x42535344 : // == 'BSSD' (LPCM)
542602 isaudio = 1 ;
603+ currentAudioCacheId = eDVBService::cLPCMPID;
543604 break ;
544605 case 0x56432d31 : // == 'VC-1'
545606 isvideo = 1 ;
@@ -554,16 +615,36 @@ void eDVBScan::PMTready(int err)
554615 }
555616 }
556617 if (tag == CA_DESCRIPTOR)
618+ {
557619 is_scrambled = 1 ;
620+ CaDescriptor *ca = (CaDescriptor*)(*desc);
621+ uint16_t caid = ca->getCaSystemId ();
622+ if (caid != 0 && std::find (caids.begin (), caids.end (), caid) == caids.end ())
623+ caids.push_back (caid);
624+ }
558625 }
559626 [[fallthrough]];
560627 default :
561628 break ;
562629 }
563630 if (isvideo)
631+ {
564632 have_video = true ;
633+ if (videopid == 0xFFFF )
634+ {
635+ videopid = (*es)->getPid ();
636+ videotype = currentVideoType;
637+ }
638+ }
565639 else if (isaudio)
640+ {
566641 have_audio = true ;
642+ if (audiopid == 0xFFFF )
643+ {
644+ audiopid = (*es)->getPid ();
645+ audioCacheId = currentAudioCacheId;
646+ }
647+ }
567648 else
568649 continue ;
569650 if (is_scrambled)
@@ -573,16 +654,30 @@ void eDVBScan::PMTready(int err)
573654 desc != pmt.getDescriptors ()->end (); ++desc)
574655 {
575656 if ((*desc)->getTag () == CA_DESCRIPTOR)
657+ {
576658 scrambled = true ;
659+ CaDescriptor *ca = (CaDescriptor*)(*desc);
660+ uint16_t caid = ca->getCaSystemId ();
661+ if (caid != 0 && std::find (caids.begin (), caids.end (), caid) == caids.end ())
662+ caids.push_back (caid);
663+ }
577664 }
578665 }
579666 m_pmt_in_progress->second .scrambled = scrambled;
667+ m_pmt_in_progress->second .pcrPid = pcrpid;
668+ m_pmt_in_progress->second .videoPid = videopid;
669+ m_pmt_in_progress->second .audioPid = audiopid;
670+ m_pmt_in_progress->second .audioCacheId = audioCacheId;
671+ m_pmt_in_progress->second .videoType = videotype;
672+ m_pmt_in_progress->second .caids = caids;
580673 if ( have_video )
581674 m_pmt_in_progress->second .serviceType = 1 ;
582675 else if ( have_audio )
583676 m_pmt_in_progress->second .serviceType = 2 ;
584677 else
585678 m_pmt_in_progress->second .serviceType = 100 ;
679+ SCAN_eDebug (" [eDVBScan] SID %04x: vpid=%04x (vtype=%d) apid=%04x (cacheId=%d) pcrpid=%04x caids=%d" ,
680+ m_pmt_in_progress->first , videopid, videotype, audiopid, audioCacheId, pcrpid, (int )caids.size ());
586681 }
587682 if (err == -1 ) // timeout or removed by sdt
588683 m_pmts_to_read.erase (m_pmt_in_progress++);
@@ -1242,6 +1337,20 @@ void eDVBScan::channelDone()
12421337 m_last_service = i.first ;
12431338 m_event (evtNewService);
12441339 }
1340+
1341+ /* store cached PIDs from PMT - use service from m_new_services (may exist from SDT) */
1342+ ePtr<eDVBService> target = i.first ->second ;
1343+ if (m_pmt_in_progress->second .videoPid != 0xFFFF )
1344+ target->setCacheEntry (eDVBService::cVPID, m_pmt_in_progress->second .videoPid );
1345+ if (m_pmt_in_progress->second .audioPid != 0xFFFF )
1346+ target->setCacheEntry (m_pmt_in_progress->second .audioCacheId , m_pmt_in_progress->second .audioPid );
1347+ if (m_pmt_in_progress->second .pcrPid != 0xFFFF )
1348+ target->setCacheEntry (eDVBService::cPCRPID, m_pmt_in_progress->second .pcrPid );
1349+ target->setCacheEntry (eDVBService::cPMTPID, m_pmt_in_progress->second .pmtPid );
1350+
1351+ /* store CAIDs from PMT */
1352+ if (!m_pmt_in_progress->second .caids .empty ())
1353+ target->m_ca = m_pmt_in_progress->second .caids ;
12451354 }
12461355 else
12471356 SCAN_eDebug (" [eDVBScan] dont add... is scrambled!" );
@@ -1554,6 +1663,31 @@ void eDVBScan::insertInto(iDVBChannelList *db, bool backgroundscanresult)
15541663 }
15551664 if (service->second ->m_ca .size ())
15561665 dvb_service->m_ca = service->second ->m_ca ;
1666+
1667+ /* update cached PIDs from scan if the new service has them */
1668+ int vpid = service->second ->getCacheEntry (eDVBService::cVPID);
1669+ if (vpid != -1 )
1670+ dvb_service->setCacheEntry (eDVBService::cVPID, vpid);
1671+ int vtype = service->second ->getCacheEntry (eDVBService::cVTYPE);
1672+ if (vtype != -1 )
1673+ dvb_service->setCacheEntry (eDVBService::cVTYPE, vtype);
1674+ /* copy audio PID with correct audio type */
1675+ for (int j = 0 ; j < eDVBService::nAudioCacheTags; ++j)
1676+ {
1677+ int apid = service->second ->getCacheEntry (eDVBService::audioCacheTags[j]);
1678+ if (apid != -1 )
1679+ {
1680+ dvb_service->setCacheEntry (eDVBService::audioCacheTags[j], apid);
1681+ break ;
1682+ }
1683+ }
1684+ int pcrpid = service->second ->getCacheEntry (eDVBService::cPCRPID);
1685+ if (pcrpid != -1 )
1686+ dvb_service->setCacheEntry (eDVBService::cPCRPID, pcrpid);
1687+ int pmtpid = service->second ->getCacheEntry (eDVBService::cPMTPID);
1688+ if (pmtpid != -1 )
1689+ dvb_service->setCacheEntry (eDVBService::cPMTPID, pmtpid);
1690+
15571691 if (!backgroundscanresult) // do not remove new found flags when this is the result of a 'background scan'
15581692 dvb_service->m_flags &= ~eDVBService::dxNewFound;
15591693 }
@@ -1655,6 +1789,21 @@ RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescription
16551789 ref.set (chid);
16561790 ref.setServiceID (service_id);
16571791
1792+ /* copy cached PIDs and CAIDs from PMT if available (only if PMT was already processed) */
1793+ if (it != m_pmts_to_read.end () && it->second .videoPid != 0xFFFF )
1794+ {
1795+ service->setCacheEntry (eDVBService::cVPID, it->second .videoPid );
1796+ if (it->second .videoType != -1 ) // only set if not MPEG2 (default)
1797+ service->setCacheEntry (eDVBService::cVTYPE, it->second .videoType );
1798+ if (it->second .audioPid != 0xFFFF )
1799+ service->setCacheEntry (it->second .audioCacheId , it->second .audioPid );
1800+ if (it->second .pcrPid != 0xFFFF )
1801+ service->setCacheEntry (eDVBService::cPCRPID, it->second .pcrPid );
1802+ service->setCacheEntry (eDVBService::cPMTPID, it->second .pmtPid );
1803+ if (!it->second .caids .empty ())
1804+ service->m_ca = it->second .caids ;
1805+ }
1806+
16581807 for (DescriptorConstIterator desc = (*s)->getDescriptors ()->begin ();
16591808 desc != (*s)->getDescriptors ()->end (); ++desc)
16601809 {
@@ -1704,7 +1853,9 @@ RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescription
17041853 for (CaSystemIdList::const_iterator i (caids.begin ()); i != caids.end (); ++i)
17051854 {
17061855 SCAN_eDebugNoNewLine (" %04x" , *i);
1707- service->m_ca .push_front (*i);
1856+ /* avoid duplicates - CAIDs may already be set from PMT */
1857+ if (std::find (service->m_ca .begin (), service->m_ca .end (), *i) == service->m_ca .end ())
1858+ service->m_ca .push_front (*i);
17081859 }
17091860 SCAN_eDebugNoNewLine (" \n " );
17101861 break ;
@@ -1738,7 +1889,8 @@ RESULT eDVBScan::processSDT(eDVBNamespace dvbnamespace, const ServiceDescription
17381889 }
17391890 if (m_pmt_running && m_pmt_in_progress->first == service_id)
17401891 m_abort_current_pmt = true ;
1741- else
1892+ else if (it != m_pmts_to_read.end () && (it->second .videoPid != 0xFFFF || it->second .audioPid != 0xFFFF ))
1893+ /* only erase if PMT was already processed (has video or audio), otherwise channelDone() needs it */
17421894 m_pmts_to_read.erase (service_id);
17431895 }
17441896
@@ -1770,6 +1922,8 @@ RESULT eDVBScan::processVCT(eDVBNamespace dvbnamespace, const VirtualChannelTabl
17701922 }
17711923 SCAN_eDebugNoNewLine (" \n " );
17721924
1925+ std::map<unsigned short , struct service >::iterator it = m_pmts_to_read.find (service_id);
1926+
17731927 if (!(m_flags & scanOnlyFree) || !is_crypted)
17741928 {
17751929 char number[32 ];
@@ -1803,6 +1957,22 @@ RESULT eDVBScan::processVCT(eDVBNamespace dvbnamespace, const VirtualChannelTabl
18031957 ref.setServiceID (service_id);
18041958 ref.setServiceType (servicetype);
18051959 ref.setSourceID (source_id);
1960+
1961+ /* copy cached PIDs and CAIDs from PMT if available (only if PMT was already processed) */
1962+ if (it != m_pmts_to_read.end () && it->second .videoPid != 0xFFFF )
1963+ {
1964+ service->setCacheEntry (eDVBService::cVPID, it->second .videoPid );
1965+ if (it->second .videoType != -1 ) // only set if not MPEG2 (default)
1966+ service->setCacheEntry (eDVBService::cVTYPE, it->second .videoType );
1967+ if (it->second .audioPid != 0xFFFF )
1968+ service->setCacheEntry (it->second .audioCacheId , it->second .audioPid );
1969+ if (it->second .pcrPid != 0xFFFF )
1970+ service->setCacheEntry (eDVBService::cPCRPID, it->second .pcrPid );
1971+ service->setCacheEntry (eDVBService::cPMTPID, it->second .pmtPid );
1972+ if (!it->second .caids .empty ())
1973+ service->m_ca = it->second .caids ;
1974+ }
1975+
18061976 service->m_service_name = (*s)->getName ();
18071977 /* strip trailing spaces */
18081978 service->m_service_name = service->m_service_name .erase (service->m_service_name .find_last_not_of (" " ) + 1 );
@@ -1845,7 +2015,8 @@ RESULT eDVBScan::processVCT(eDVBNamespace dvbnamespace, const VirtualChannelTabl
18452015 }
18462016 if (m_pmt_running && m_pmt_in_progress->first == service_id)
18472017 m_abort_current_pmt = true ;
1848- else
2018+ else if (it != m_pmts_to_read.end () && (it->second .videoPid != 0xFFFF || it->second .audioPid != 0xFFFF ))
2019+ /* only erase if PMT was already processed (has video or audio), otherwise channelDone() needs it */
18492020 m_pmts_to_read.erase (service_id);
18502021 }
18512022
0 commit comments