Example #1
0
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");
	}
}