bool CPatParser::GetChannel(int index, CChannelInfo& info) { static CChannelInfo unknownChannel; if (index < 0 || index > Count()) { return false; } CPmtParser* parser = m_pmtParsers[index]; if (false == parser->IsReady()) { return false; } info.PidTable = parser->GetPidInfo(); m_iState = Idle; return true; }
void CPmtGrabber::OnNewSection(CSection& section) { try { // if only service ID given, lookup from PAT if (GetPid() == 0) // PID 0 is the PAT, so look for matching PMT { int PMTPid=m_patgrab.PATRequest(section, m_iServiceId); if (PMTPid>0) { SetPmtPid(PMTPid,m_iServiceId); SetPid(PMTPid); } else { LogDebug("PMT Pid wasn't found on the PAT. Channel may have moved, try a new channel scan."); } } if (section.table_id!=2) return; CEnterCriticalSection enter(m_section); if (section.section_length<0 || section.section_length>=MAX_SECTION_LENGTH) return; long serviceId = section.table_id_extension; if (m_iPmtVersion<0) LogDebug("pmtgrabber: got pmt %x sid:%x",GetPid(), serviceId); if (serviceId != m_iServiceId) { LogDebug("pmtgrabber: serviceid mismatch %x != %x",serviceId,m_iServiceId); return; } m_iPmtLength=section.section_length; // copy pmt data for passing it to tvserver memcpy(m_pmtData,section.Data,m_iPmtLength); // compare the current section data with the previous one if (memcmp(section.Data, m_pmtPrevSection.Data, m_iPmtLength)!=0) { bool pidsChanged = false; CPmtParser prevPmtParser; CPmtParser currPmtParser; prevPmtParser.SetPid(GetPid()); prevPmtParser.DecodePmtPidTable(m_pmtPrevSection); currPmtParser.SetPid(GetPid()); // Check if failed - if corrupted it can crash tv service after the callback if(!currPmtParser.DecodePmtPidTable(section)) { LogDebug("CPmtGrabber::OnNewSection() - Error decoding PMT from new section, bad signal?"); return; } if (!(prevPmtParser.GetPidInfo() == currPmtParser.GetPidInfo())) { LogDebug("pmtgrabber: PMT pids changed from:"); prevPmtParser.GetPidInfo().LogPIDs(); LogDebug("pmtgrabber: PMT pids changed to:"); currPmtParser.GetPidInfo().LogPIDs(); pidsChanged = true; } m_pmtPrevSection=section; // do a callback each time the version number changes. this also allows switching for "regional channels" if (m_pCallback!=NULL && m_iPmtVersion != section.version_number) { LogDebug("pmtgrabber: got new pmt version:%x %x, service_id:%x", section.version_number, m_iPmtVersion, serviceId); // if the pids are different, then a callback is required. if (pidsChanged) { LogDebug("pmtgrabber: do callback pid %x",GetPid()); m_pCallback->OnPMTReceived(GetPid()); } // otherwise no need to callback, i.e. if _only_ version number changes regulary... else { LogDebug("pmtgrabber: NO callback done because a/v pids still the same."); } } } m_iPmtVersion=section.version_number; } catch(...) { LogDebug("CPmtGrabber::OnNewSection exception"); } }