示例#1
0
void CPatParser::OnTsPacket(byte* tsPacket)
{
  m_packetsReceived++;

  if (m_packetsReceived > m_packetsToSkip)
  {
    for (int i=0; i < (int)m_pmtParsers.size(); ++i)
    {
      CPmtParser* parser = m_pmtParsers[i];
      parser->OnTsPacket(tsPacket);
    }
    CSectionDecoder::OnTsPacket(tsPacket);
  }

  if (m_iState==Parsing && m_pCallback!=NULL)
  {
    for (int i=0; i < (int)m_pmtParsers.size(); ++i)
    {
      CPmtParser* parser = m_pmtParsers[i];
      if (true == parser->IsReady()) 
      {
        CChannelInfo info;
        if (GetChannel(i, info))
        {
          m_iState=Idle;

          info.PatVersion = m_iPatTableVersion;
          m_pCallback->OnNewChannel(info);
          m_iState = Parsing;
          return;
        }
      }
    }
  }
}
示例#2
0
void CPatParser::OnNewSection(CSection& section)
{
  if (section.table_id != 0)
    return;

  try
  {
    //int section_syntax_indicator = (section.Data[1]>>7) & 1;
    //int transport_stream_id = section.table_id_extension;

    if (section.version_number != m_iPatTableVersion)
    {
      XBMC->Log(LOG_DEBUG, "PatParser: new pat table %d->%d", m_iPatTableVersion, section.version_number); //was commented out
      CleanUp();
      m_iPatTableVersion = section.version_number;
      m_iState = Parsing;
    }
    //XBMC->Log(LOG_DEBUG, "DecodePat  %d section:%d lastsection:%d sectionlen:%d",
    //            version_number,section_number,last_section_number,section_length);

    int loop = (section.section_length - 9) / 4;
    for(int i=0; i < loop; i++)
    {
      int offset = (8 +(i * 4));
      int pmtPid = ((section.Data[offset+2] & 0x1F)<<8) + section.Data[offset+3];
      if (pmtPid < 0x10 || pmtPid >=0x1fff) 
      {
        //invalid pmt pid
        return;
      }

      bool found=false;
      for (int idx=0; idx < (int)m_pmtParsers.size(); idx++)
      {
        CPmtParser* pmtParser = m_pmtParsers[idx];
        if (pmtParser->GetPid() == pmtPid)
        {
          found=true;
          break;
        }
      }
      if (!found && pmtPid>=0x10)
      {
        CPmtParser* pmtParser = new CPmtParser();
        pmtParser->SetPid(pmtPid);
        //pmtParser->SetPmtCallBack(this);
        m_pmtParsers.push_back( pmtParser );
        XBMC->Log(LOG_DEBUG, "PatParser:  add pmt# %d pid: %x",m_pmtParsers.size(), pmtPid);
      }
    }
  }
  catch (...)
  {
    XBMC->Log(LOG_DEBUG, "Exception in PatParser");
  }
}
示例#3
0
int CPatParser::Count()
{
  int count = m_pmtParsers.size();

  if (count == 0)
    return 0;

  for (int i=0; i < (int)m_pmtParsers.size(); ++i)
  {
    CPmtParser* parser = m_pmtParsers[i];
    if (true == parser->IsReady())
    {
      return count;
    }
  }
  return 0;
}
示例#4
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");
	}
}