Ticket #7923: ca-key-patch-2.diff
File ca-key-patch-2.diff, 15.0 KB (added by , 14 years ago) |
---|
-
mpegstreamdata.cpp
21 21 22 22 //#define DEBUG_MPEG_RADIO // uncomment to strip video streams from TS stream 23 23 24 // Defined: CA pids are added to the PMT 25 // Undefined: CA pids are added as listening pids only 26 // Undefined option is cleaner and seems to work. Also has the benefit 27 // of not requiring the CAT to be cached before handling the PMT 28 // so it won't break if there is no CAT. 29 //#define ADD_CA_TO_PMT 30 24 31 void init_sections(sections_t §, uint last_section) 25 32 { 26 33 static const unsigned char init_bits[8] = … … 86 93 memset(_si_time_offsets, 0, sizeof(_si_time_offsets)); 87 94 88 95 AddListeningPID(MPEG_PAT_PID); 96 AddListeningPID(MPEG_CAT_PID); 89 97 } 90 98 91 99 MPEGStreamData::~MPEGStreamData() … … 209 217 for (; it2 != _cached_pmts.end(); ++it2) 210 218 DeleteCachedTable(*it2); 211 219 _cached_pmts.clear(); 220 221 cat_cache_t::iterator it3 = _cached_cats.begin(); 222 for (; it3 != _cached_cats.end(); ++it3) 223 DeleteCachedTable(*it3); 224 _cached_cats.clear(); 212 225 } 213 226 214 227 ResetDecryptionMonitoringState(); 215 228 216 229 AddListeningPID(MPEG_PAT_PID); 230 AddListeningPID(MPEG_CAT_PID); 217 231 } 218 232 219 233 void MPEGStreamData::DeletePartialPES(uint pid) … … 505 519 VERBOSE(VB_RECORD, "no PAT yet..."); 506 520 return false; // no way to properly rewrite pids without PAT 507 521 } 522 #ifdef ADD_CA_TO_PMT 523 if (!HasCachedAnyCAT()) 524 { 525 VERBOSE(VB_RECORD, "no CAT yet..."); 526 return false; 527 } 528 #endif 508 529 pmt.Parse(); 509 530 510 531 uint programNumber = 1; // MPEG Program Number … … 517 538 518 539 if (!_strip_pmt_descriptors) 519 540 { 541 #ifdef ADD_CA_TO_PMT 542 /* 543 Do not exclude the CA descriptors or we break AU (auto update). 544 This is especially noticable on the Optus C1 Aurora service 545 where all AU data is in a separate PID. 546 */ 547 gdesc = MPEGDescriptor::Parse(pmt.ProgramInfo(), pmt.ProgramInfoLength()); 548 549 /* looks like we also need to bring in the PIDs listed in the 550 CAT (Conditional Access Table). The program keys in the PIDs 551 referenced in the PMT seem to be changed daily, and the ones 552 in the CAT are changed weekly. 553 */ 554 cat_vec_t cats = GetCachedCATs(); 555 VERBOSE(VB_RECORD, QString("Adding CA PIDS from %1 CAT tables").arg(cats.size())); 556 for (uint i = 0; i < cats.size(); i++) 557 { 558 desc_list_t cdesc = MPEGDescriptor::ParseOnlyInclude( 559 cats[i]->Descriptors(), cats[i]->DescriptorsLength(), 560 DescriptorID::conditional_access); 561 if (cdesc.size()) 562 gdesc.insert(gdesc.end(), cdesc.begin(), cdesc.end()); 563 } 564 #else 520 565 gdesc = MPEGDescriptor::ParseAndExclude( 521 566 pmt.ProgramInfo(), pmt.ProgramInfoLength(), 522 567 DescriptorID::conditional_access); 568 #endif 523 569 524 570 // If there is no caption descriptor in PMT, copy any caption 525 571 // descriptor found in VCT to global descriptors... … … 618 664 return false; 619 665 } 620 666 667 #ifndef ADD_CA_TO_PMT 668 desc_list_t cdesc = MPEGDescriptor::ParseOnlyInclude( 669 pmt.ProgramInfo(), pmt.ProgramInfoLength(), 670 DescriptorID::conditional_access); 671 672 VERBOSE(VB_RECORD, QString("Adding %1 CA pids from PMT").arg(cdesc.size())); 673 for (uint i = 0; i < cdesc.size(); i++) 674 { 675 ConditionalAccessDescriptor cad(cdesc[i]); 676 VERBOSE(VB_RECORD, QString("CA PID from PMT:%1").arg(cad.PID())); 677 AddListeningPID(cad.PID()); 678 } 679 #endif 680 621 681 _pids_audio.clear(); 622 682 for (uint i = 0; i < audioPIDs.size(); i++) 623 683 AddAudioPID(audioPIDs[i]); … … 679 739 } 680 740 681 741 if (TableID::CAT == table_id) 682 return false; 742 { 743 if (VersionCAT(psip.TableIDExtension()) != version) 744 return false; 745 return CATSectionSeen(psip.TableIDExtension(), psip.Section()); 746 } 683 747 684 748 if (TableID::PMT == table_id) 685 749 { … … 720 784 } 721 785 case TableID::CAT: 722 786 { 787 uint tsid = psip.TableIDExtension(); 788 SetVersionCAT(tsid, version, psip.LastSection()); 789 SetCATSectionSeen(tsid, psip.Section()); 790 723 791 ConditionalAccessTable cat(psip); 724 792 725 _listener_lock.lock(); 726 for (uint i = 0; i < _mpeg_listeners.size(); i++) 727 _mpeg_listeners[i]->HandleCAT(&cat); 728 _listener_lock.unlock(); 793 if (_cache_tables) 794 CacheCAT(&cat); 729 795 796 ProcessCAT(&cat); 797 730 798 return true; 731 799 } 732 800 case TableID::PMT: … … 798 866 } 799 867 } 800 868 869 870 void MPEGStreamData::ProcessCAT(const ConditionalAccessTable *cat) 871 { 872 _listener_lock.lock(); 873 for (uint i = 0; i < _mpeg_listeners.size(); i++) 874 _mpeg_listeners[i]->HandleCAT(cat); 875 _listener_lock.unlock(); 876 877 #ifndef ADD_CA_TO_PMT 878 desc_list_t cdesc = MPEGDescriptor::ParseOnlyInclude( 879 cat->Descriptors(), cat->DescriptorsLength(), 880 DescriptorID::conditional_access); 881 882 VERBOSE(VB_RECORD, QString("Adding %1 CA pids from CAT").arg(cdesc.size())); 883 for (uint i = 0; i < cdesc.size(); i++) 884 { 885 ConditionalAccessDescriptor cad(cdesc[i]); 886 VERBOSE(VB_RECORD, QString("CA PID from CAT:%1").arg(cad.PID())); 887 AddListeningPID(cad.PID()); 888 } 889 #endif 890 } 891 801 892 void MPEGStreamData::ProcessPMT(const ProgramMapTable *pmt) 802 893 { 803 894 _listener_lock.lock(); … … 967 1058 { 968 1059 bool ok = !tspacket.TransportError(); 969 1060 1061 VERBOSE(VB_RECORD, tspacket.toString()); 1062 970 1063 if (IsEncryptionTestPID(tspacket.PID())) 971 1064 { 972 1065 ProcessEncryptedPacket(tspacket); … … 1146 1239 return true; 1147 1240 } 1148 1241 1242 void MPEGStreamData::SetCATSectionSeen(uint tsid, uint section) 1243 { 1244 sections_map_t::iterator it = _cat_section_seen.find(tsid); 1245 if (it == _cat_section_seen.end()) 1246 { 1247 _cat_section_seen[tsid].resize(32, 0); 1248 it = _cat_section_seen.find(tsid); 1249 } 1250 (*it)[section>>3] |= bit_sel[section & 0x7]; 1251 } 1252 1253 bool MPEGStreamData::CATSectionSeen(uint tsid, uint section) const 1254 { 1255 sections_map_t::const_iterator it = _cat_section_seen.find(tsid); 1256 if (it == _cat_section_seen.end()) 1257 return false; 1258 return (bool) ((*it)[section>>3] & bit_sel[section & 0x7]); 1259 } 1260 1261 bool MPEGStreamData::HasAllCATSections(uint tsid) const 1262 { 1263 sections_map_t::const_iterator it = _cat_section_seen.find(tsid); 1264 if (it == _cat_section_seen.end()) 1265 return false; 1266 for (uint i = 0; i < 32; i++) 1267 if ((*it)[i] != 0xff) 1268 return false; 1269 return true; 1270 } 1271 1149 1272 void MPEGStreamData::SetPMTSectionSeen(uint prog_num, uint section) 1150 1273 { 1151 1274 sections_map_t::iterator it = _pmt_section_seen.find(prog_num); … … 1221 1344 return _cached_pats.size(); 1222 1345 } 1223 1346 1347 bool MPEGStreamData::HasCachedAllCAT(uint tsid) const 1348 { 1349 QMutexLocker locker(&_cache_lock); 1350 1351 cat_cache_t::const_iterator it = _cached_cats.find(tsid << 8); 1352 if (it == _cached_cats.end()) 1353 return false; 1354 1355 uint last_section = (*it)->LastSection(); 1356 if (!last_section) 1357 return true; 1358 1359 for (uint i = 1; i <= last_section; i++) 1360 if (_cached_cats.find((tsid << 8) | i) == _cached_cats.end()) 1361 return false; 1362 1363 return true; 1364 } 1365 1366 bool MPEGStreamData::HasCachedAnyCAT(uint tsid) const 1367 { 1368 QMutexLocker locker(&_cache_lock); 1369 1370 for (uint i = 0; i <= 255; i++) 1371 if (_cached_cats.find((tsid << 8) | i) != _cached_cats.end()) 1372 return true; 1373 1374 return false; 1375 } 1376 1377 bool MPEGStreamData::HasCachedAnyCAT(void) const 1378 { 1379 QMutexLocker locker(&_cache_lock); 1380 return _cached_cats.size(); 1381 } 1382 1224 1383 bool MPEGStreamData::HasCachedAllPMT(uint pnum) const 1225 1384 { 1226 1385 QMutexLocker locker(&_cache_lock); … … 1324 1483 return pats; 1325 1484 } 1326 1485 1486 const cat_ptr_t MPEGStreamData::GetCachedCAT( 1487 uint tsid, uint section_num) const 1488 { 1489 QMutexLocker locker(&_cache_lock); 1490 ConditionalAccessTable *cat = NULL; 1491 1492 uint key = (tsid << 8) | section_num; 1493 cat_cache_t::const_iterator it = _cached_cats.find(key); 1494 if (it != _cached_cats.end()) 1495 IncrementRefCnt(cat = *it); 1496 1497 return cat; 1498 } 1499 1500 cat_vec_t MPEGStreamData::GetCachedCATs(uint tsid) const 1501 { 1502 QMutexLocker locker(&_cache_lock); 1503 cat_vec_t cats; 1504 1505 for (uint i=0; i < 256; i++) 1506 { 1507 ConditionalAccessTable *cat = GetCachedCAT(tsid, i); 1508 if (cat) 1509 cats.push_back(cat); 1510 } 1511 1512 return cats; 1513 } 1514 1515 cat_vec_t MPEGStreamData::GetCachedCATs(void) const 1516 { 1517 QMutexLocker locker(&_cache_lock); 1518 cat_vec_t cats; 1519 1520 cat_cache_t::const_iterator it = _cached_cats.begin(); 1521 for (; it != _cached_cats.end(); ++it) 1522 { 1523 ConditionalAccessTable* cat = *it; 1524 IncrementRefCnt(cat); 1525 cats.push_back(cat); 1526 } 1527 1528 return cats; 1529 } 1530 1327 1531 const pmt_ptr_t MPEGStreamData::GetCachedPMT( 1328 1532 uint program_num, uint section_num) const 1329 1533 { … … 1401 1605 pats.clear(); 1402 1606 } 1403 1607 1608 void MPEGStreamData::ReturnCachedCATTables(cat_vec_t &cats) const 1609 { 1610 for (cat_vec_t::iterator it = cats.begin(); it != cats.end(); ++it) 1611 ReturnCachedTable(*it); 1612 cats.clear(); 1613 } 1614 1615 void MPEGStreamData::ReturnCachedCATTables(cat_map_t &cats) const 1616 { 1617 for (cat_map_t::iterator it = cats.begin(); it != cats.end(); ++it) 1618 ReturnCachedCATTables(*it); 1619 cats.clear(); 1620 } 1621 1404 1622 void MPEGStreamData::ReturnCachedPMTTables(pmt_vec_t &pmts) const 1405 1623 { 1406 1624 for (pmt_vec_t::iterator it = pmts.begin(); it != pmts.end(); ++it) … … 1440 1658 _cached_pats[(tid << 8) | psip->Section()] = NULL; 1441 1659 delete psip; 1442 1660 } 1661 else if (TableID::CAT == psip->TableID() && 1662 (_cached_cats[(tid << 8) | psip->Section()] == psip)) 1663 { 1664 _cached_cats[(tid << 8) | psip->Section()] = NULL; 1665 delete psip; 1666 } 1443 1667 else if ((TableID::PMT == psip->TableID()) && 1444 1668 (_cached_pmts[(tid << 8) | psip->Section()] == psip)) 1445 1669 { … … 1473 1697 _cached_pats[key] = pat; 1474 1698 } 1475 1699 1700 void MPEGStreamData::CacheCAT(const ConditionalAccessTable *_cat) 1701 { 1702 ConditionalAccessTable *cat = new ConditionalAccessTable(*_cat); 1703 uint key = (_cat->TableIDExtension() << 8) | _cat->Section(); 1704 1705 QMutexLocker locker(&_cache_lock); 1706 1707 cat_cache_t::iterator it = _cached_cats.find(key); 1708 if (it != _cached_cats.end()) 1709 DeleteCachedTable(*it); 1710 1711 _cached_cats[key] = cat; 1712 } 1713 1476 1714 void MPEGStreamData::CachePMT(const ProgramMapTable *_pmt) 1477 1715 { 1478 1716 ProgramMapTable *pmt = new ProgramMapTable(*_pmt); -
mpegstreamdata.h
33 33 typedef QMap<uint, pat_vec_t> pat_map_t; 34 34 typedef QMap<uint, ProgramAssociationTable*> pat_cache_t; 35 35 36 typedef ConditionalAccessTable* cat_ptr_t; 37 typedef vector<const ConditionalAccessTable*> cat_vec_t; 38 typedef QMap<uint, cat_vec_t> cat_map_t; 39 typedef QMap<uint, ConditionalAccessTable*> cat_cache_t; 40 36 41 typedef ProgramMapTable* pmt_ptr_t; 37 42 typedef vector<const ProgramMapTable*> pmt_vec_t; 38 43 typedef QMap<uint, pmt_vec_t> pmt_map_t; … … 169 174 return *it; 170 175 } 171 176 177 void SetVersionCAT(uint tsid, int version, uint last_section) 178 { 179 if (VersionCAT(tsid) == version) 180 return; 181 _cat_version[tsid] = version; 182 init_sections(_cat_section_seen[tsid], last_section); 183 } 184 int VersionCAT(uint tsid) const 185 { 186 const QMap<uint, int>::const_iterator it = _cat_version.find(tsid); 187 if (it == _cat_version.end()) 188 return -1; 189 return *it; 190 } 191 172 192 void SetVersionPMT(uint program_num, int version, uint last_section) 173 193 { 174 194 if (VersionPMT(program_num) == version) … … 189 209 bool PATSectionSeen( uint tsid, uint section) const; 190 210 bool HasAllPATSections(uint tsid) const; 191 211 212 void SetCATSectionSeen(uint tsid, uint section); 213 bool CATSectionSeen( uint tsid, uint section) const; 214 bool HasAllCATSections(uint tsid) const; 215 192 216 void SetPMTSectionSeen(uint prog_num, uint section); 193 217 bool PMTSectionSeen( uint prog_num, uint section) const; 194 218 bool HasAllPMTSections(uint prog_num) const; … … 200 224 bool HasCachedAnyPAT(uint tsid) const; 201 225 bool HasCachedAnyPAT(void) const; 202 226 227 bool HasCachedAllCAT(uint tsid) const; 228 bool HasCachedAnyCAT(uint tsid) const; 229 bool HasCachedAnyCAT(void) const; 230 203 231 bool HasCachedAllPMT(uint program_num) const; 204 232 bool HasCachedAnyPMT(uint program_num) const; 205 233 bool HasCachedAllPMTs(void) const; … … 210 238 pat_vec_t GetCachedPATs(void) const; 211 239 pat_map_t GetCachedPATMap(void) const; 212 240 241 const cat_ptr_t GetCachedCAT(uint tsid, uint section_num) const; 242 cat_vec_t GetCachedCATs(uint tsid) const; 243 cat_vec_t GetCachedCATs(void) const; 244 cat_map_t GetCachedCATMap(void) const; 245 213 246 const pmt_ptr_t GetCachedPMT(uint program_num, uint section_num) const; 214 247 pmt_vec_t GetCachedPMTs(void) const; 215 248 pmt_map_t GetCachedPMTMap(void) const; … … 217 250 virtual void ReturnCachedTable(const PSIPTable *psip) const; 218 251 virtual void ReturnCachedPATTables(pat_vec_t&) const; 219 252 virtual void ReturnCachedPATTables(pat_map_t&) const; 253 virtual void ReturnCachedCATTables(cat_vec_t&) const; 254 virtual void ReturnCachedCATTables(cat_map_t&) const; 220 255 virtual void ReturnCachedPMTTables(pmt_vec_t&) const; 221 256 virtual void ReturnCachedPMTTables(pmt_map_t&) const; 222 257 … … 297 332 { _partial_pes_packet_cache.remove(pid); } 298 333 void DeletePartialPES(uint pid); 299 334 void ProcessPAT(const ProgramAssociationTable *pat); 335 void ProcessCAT(const ConditionalAccessTable *pat); 300 336 void ProcessPMT(const ProgramMapTable *pmt); 301 337 void ProcessEncryptedPacket(const TSPacket&); 302 338 … … 308 344 void IncrementRefCnt(const PSIPTable *psip) const; 309 345 virtual bool DeleteCachedTable(PSIPTable *psip) const; 310 346 void CachePAT(const ProgramAssociationTable *pat); 347 void CacheCAT(const ConditionalAccessTable *pat); 311 348 void CachePMT(const ProgramMapTable *pmt); 312 349 313 350 protected: … … 348 385 349 386 // Table versions 350 387 QMap<uint, int> _pat_version; 388 QMap<uint, int> _cat_version; 351 389 QMap<uint, int> _pmt_version; 352 390 353 391 sections_map_t _pat_section_seen; 392 sections_map_t _cat_section_seen; 354 393 sections_map_t _pmt_section_seen; 355 394 356 395 // PSIP construction … … 360 399 bool _cache_tables; 361 400 mutable QMutex _cache_lock; 362 401 mutable pat_cache_t _cached_pats; 402 mutable cat_cache_t _cached_cats; 363 403 mutable pmt_cache_t _cached_pmts; 364 404 mutable psip_refcnt_map_t _cached_ref_cnt; 365 405 mutable psip_refcnt_map_t _cached_slated_for_deletion;