bool cVNSIChannelFilter::PassFilter(const cChannel &channel)
{
  cMutexLock lock(&m_Mutex);

  if(channel.GroupSep())
    return true;

  if (!IsWhitelist(channel))
    return false;

  std::vector<int>::iterator it;
  if (IsRadio(&channel))
  {
    it = std::find(m_channelsRadio.begin(), m_channelsRadio.end(), CreateChannelUID(&channel));
    if(it!=m_channelsRadio.end())
      return false;
  }
  else
  {
    it = std::find(m_channelsVideo.begin(), m_channelsVideo.end(), CreateChannelUID(&channel));
    if(it!=m_channelsVideo.end())
      return false;
  }

  return true;
}
Example #2
0
cLiveStreamer::cLiveStreamer(cXVDRClient* parent, const cChannel *channel, int priority)
 : cThread("cLiveStreamer stream processor")
 , cRingBufferLinear(MEGABYTE(10), TS_SIZE * 2, true)
 , cReceiver(NULL, priority)
 , m_scanTimeout(10)
 , m_parent(parent)
{
  m_Device          = NULL;
  m_Queue           = NULL;
  m_startup         = true;
  m_SignalLost      = false;
  m_LangStreamType  = cStreamInfo::stMPEG2AUDIO;
  m_LanguageIndex   = -1;
  m_uid             = CreateChannelUID(channel);
  m_ready           = false;
  m_protocolVersion = XVDR_PROTOCOLVERSION;
  m_waitforiframe   = false;
  m_PatFilter       = NULL;


  m_requestStreamChange = false;

  if(m_scanTimeout == 0)
    m_scanTimeout = XVDRServerConfig.stream_timeout;

  // create send queue
  m_Queue = new cLiveQueue(m_parent->GetSocket());
  m_Queue->Start();

  SetTimeouts(0, 10);
  Start();
}
Example #3
0
void cLiveStreamer::ChannelChange(const cChannel* channel) {
  cMutexLock lock(&m_FilterMutex);

  if(CreateChannelUID(channel) != m_uid || !Running()) {
    return;
  }

  INFOLOG("ChannelChange()");

  SwitchChannel(channel);
}
Example #4
0
void cLivePatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
{
  if (Pid == 0x00 && Tid == 0x00)
  {
    SI::PAT pat(Data, false);
    if (!pat.CheckCRCAndParse())
      return;

    SI::PAT::Association assoc;
    for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); )
    {
      if (!assoc.isNITPid())
      {
    	XVDRChannels.Lock(false);
        const cChannel *Channel =  XVDRChannels.Get()->GetByServiceID(Source(), Transponder(), assoc.getServiceId());

        if (Channel && (Channel == m_Channel))
        {
          int prevPmtPid = m_pmtPid;
          if (0 != (m_pmtPid = assoc.getPid()))
          {
            m_pmtSid = assoc.getServiceId();
            if (m_pmtPid != prevPmtPid)
            {
              Add(m_pmtPid, 0x02);
              m_pmtVersion = -1;
            }
            XVDRChannels.Unlock();
            return;
          }
        }

        XVDRChannels.Unlock();
      }
    }
  }
  else if (Pid == m_pmtPid && Tid == SI::TableIdPMT && Source() && Transponder())
  {
    SI::PMT pmt(Data, false);
    if (!pmt.CheckCRCAndParse() || pmt.getServiceId() != m_pmtSid)
      return;

    if (m_pmtVersion != -1)
    {
      if (m_pmtVersion != pmt.getVersionNumber())
      {
        cFilter::Del(m_pmtPid, 0x02);
        m_pmtPid = 0; // this triggers PAT scan
      }
      return;
    }
    m_pmtVersion = pmt.getVersionNumber();

    // get cached channel data
    if(m_ChannelCache.size() == 0)
      m_ChannelCache = cChannelCache::GetFromCache(CreateChannelUID(m_Channel));

    // get all streams and check if there are new (currently unknown) streams
    SI::PMT::Stream stream;
    cChannelCache cache;
    for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); )
    {
      cStreamInfo info;
      if (GetStreamInfo(stream, info) && cache.size() < MAXRECEIVEPIDS) {
        info.SetContent();
        cache.AddStream(info);
      }
    }

    // no new streams found -> exit
    if (m_ChannelCache.ismetaof(cache))
      return;

    m_Streamer->m_FilterMutex.Lock();

    // create new stream demuxers
    m_Streamer->Detach();
    cache.CreateDemuxers(m_Streamer);

    m_Streamer->m_ready = false;
    INFOLOG("Currently unknown new streams found, requesting stream change");

    m_Streamer->RequestStreamChange();

    // write changed data back to the cache
    m_ChannelCache = cache;
    cChannelCache::AddToCache(CreateChannelUID(m_Channel), m_ChannelCache);

    // try to attach receiver
    int c = 0;
    for(; c < 3 && !m_Streamer->Attach(); c++) {
      INFOLOG("Unable to attach receiver, retrying ...");
      usleep(100 * 1000);
    }

    // unable to attach receiver
    if(c == 3) {
      ERRORLOG("failed to attach receiver, sending detach ...");
      m_Streamer->sendDetach();
    }

    m_Streamer->m_FilterMutex.Unlock();
  }
}
Example #5
0
void cLivePatFilter::Process(u_short Pid, u_char Tid, const u_char *Data, int Length)
{
  if (Pid == 0x00 && Tid == 0x00)
  {
    SI::PAT pat(Data, false);
    if (!pat.CheckCRCAndParse())
      return;

    SI::PAT::Association assoc;
    for (SI::Loop::Iterator it; pat.associationLoop.getNext(assoc, it); )
    {
      if (!assoc.isNITPid())
      {
        const cChannel *Channel =  Channels.GetByServiceID(Source(), Transponder(), assoc.getServiceId());
        if (Channel && (Channel == m_Channel))
        {
          int prevPmtPid = m_pmtPid;
          if (0 != (m_pmtPid = assoc.getPid()))
          {
            m_pmtSid = assoc.getServiceId();
            if (m_pmtPid != prevPmtPid)
            {
              Add(m_pmtPid, 0x02);
              m_pmtVersion = -1;
            }
            return;
          }
        }
      }
    }
  }
  else if (Pid == m_pmtPid && Tid == SI::TableIdPMT && Source() && Transponder())
  {
    SI::PMT pmt(Data, false);
    if (!pmt.CheckCRCAndParse() || pmt.getServiceId() != m_pmtSid)
      return;

    if (m_pmtVersion != -1)
    {
      if (m_pmtVersion != pmt.getVersionNumber())
      {
        cFilter::Del(m_pmtPid, 0x02);
        m_pmtPid = 0; // this triggers PAT scan
      }
      return;
    }
    m_pmtVersion = pmt.getVersionNumber();

    // get cached channel data
    if(m_ChannelCache.size() == 0)
      m_ChannelCache = cChannelCache::GetFromCache(CreateChannelUID(m_Channel));

    // get all streams and check if there are new (currently unknown) streams
    SI::PMT::Stream stream;
    cChannelCache cache;
    for (SI::Loop::Iterator it; pmt.streamLoop.getNext(stream, it); )
    {
      struct StreamInfo info;
      if (GetStreamInfo(stream, info) && cache.size() < MAXRECEIVEPIDS)
        cache.AddStream(info);
    }

    // no new streams found -> exit
    if (cache == m_ChannelCache)
      return;

    m_Streamer->m_FilterMutex.Lock();

    // create new stream demuxers
    cache.CreateDemuxers(m_Streamer);

    INFOLOG("Currently unknown new streams found, requesting stream change");

    // write changed data back to the cache
    m_ChannelCache = cache;
    cChannelCache::AddToCache(CreateChannelUID(m_Channel), m_ChannelCache);

    m_Streamer->RequestStreamChange();
    m_Streamer->m_FilterMutex.Unlock();
  }
}
Example #6
0
int cLiveStreamer::SwitchChannel(const cChannel *channel)
{
  if (channel == NULL) {
    return XVDR_RET_ERROR;
  }

  if(m_PatFilter != NULL && m_Device != NULL) {
    m_Device->Detach(m_PatFilter);
    delete m_PatFilter;
    m_PatFilter = NULL;
  }

  if(IsAttached()) {
    Detach();
  }

  // check if any device is able to decrypt the channel - code taken from VDR
  int NumUsableSlots = 0;

  if (channel->Ca() >= CA_ENCRYPTED_MIN) {
    for (cCamSlot *CamSlot = CamSlots.First(); CamSlot; CamSlot = CamSlots.Next(CamSlot)) {
      if (CamSlot->ModuleStatus() == msReady) {
        if (CamSlot->ProvidesCa(channel->Caids())) {
          if (!ChannelCamRelations.CamChecked(channel->GetChannelID(), CamSlot->SlotNumber())) {
            NumUsableSlots++;
          }
       }
      }
    }
    if (!NumUsableSlots) {
      return XVDR_RET_ENCRYPTED;
    }
  }

  // get device for this channel
  {
    cMutexLock lock(&m_DeviceMutex);
    m_Device = cDevice::GetDevice(channel, LIVEPRIORITY, false);
  }

  if (m_Device == NULL)
  {
    // return status "recording running" if there is an active timer
    time_t now = time(NULL);

    for (cTimer *ti = Timers.First(); ti; ti = Timers.Next(ti)) {
      if (ti->Recording() && ti->Matches(now)) {
        return XVDR_RET_RECRUNNING;
      }
    }

    return XVDR_RET_DATALOCKED;
  }

  INFOLOG("Found available device %d", m_Device->DeviceNumber() + 1);

  if (!m_Device->SwitchChannel(channel, false))
  {
    ERRORLOG("Can't switch to channel %i - %s", channel->Number(), channel->Name());
    return XVDR_RET_ERROR;
  }

  // get cached demuxer data
  cChannelCache cache = cChannelCache::GetFromCache(m_uid);

  // channel not found in cache -> add it from vdr
  if(cache.size() == 0) {
    INFOLOG("adding channel to cache");
    cChannelCache::AddToCache(channel);
    cache = cChannelCache::GetFromCache(m_uid);
  }

  // channel already in cache
  else {
    INFOLOG("Channel information found in cache");
  }

  // recheck cache item
  if(cache.size() != 0) {
    INFOLOG("Creating demuxers");
    cache.CreateDemuxers(this);
  }

  RequestStreamChange();

  INFOLOG("Successfully switched to channel %i - %s", channel->Number(), channel->Name());

  if(m_waitforiframe) {
    INFOLOG("Will wait for first I-Frame ...");
  }

  // clear cached data
  Clear();
  m_Queue->Cleanup();

  m_uid = CreateChannelUID(channel);

  if(!Attach()) {
    INFOLOG("Unable to attach receiver !");
    return XVDR_RET_DATALOCKED;
  }

  INFOLOG("Starting PAT scanner");
  m_PatFilter = new cLivePatFilter(this);
  m_PatFilter->SetChannel(channel);
  m_Device->AttachFilter(m_PatFilter);

  INFOLOG("done switching.");
  return XVDR_RET_OK;
}
Example #7
0
int cLiveStreamer::StreamChannel(const cChannel *channel, int sock, bool waitforiframe)
{
  if (channel == NULL)
  {
    ERRORLOG("Starting streaming of channel without valid channel");
    return XVDR_RET_ERROR;
  }

  m_uid = CreateChannelUID(channel);
  m_waitforiframe = waitforiframe;

  if(m_waitforiframe) {
    INFOLOG("Will wait for first I-Frame ...");
  }

  // check if any device is able to decrypt the channel - code taken from VDR
  int NumUsableSlots = 0;

  if (channel->Ca() >= CA_ENCRYPTED_MIN) {
    for (cCamSlot *CamSlot = CamSlots.First(); CamSlot; CamSlot = CamSlots.Next(CamSlot)) {
      if (CamSlot->ModuleStatus() == msReady) {
        if (CamSlot->ProvidesCa(channel->Caids())) {
          if (!ChannelCamRelations.CamChecked(channel->GetChannelID(), CamSlot->SlotNumber())) {
            NumUsableSlots++;
          }
       }
      }
    }
    if (!NumUsableSlots) {
      ERRORLOG("Unable to decrypt channel %i - %s", channel->Number(), channel->Name());
      return XVDR_RET_ENCRYPTED;
    }
  }

  // get device for this channel
  m_Device = cDevice::GetDevice(channel, LIVEPRIORITY, true);

  // try a bit harder if we can't find a device
  if(m_Device == NULL)
    m_Device = cDevice::GetDevice(channel, LIVEPRIORITY, false);

  INFOLOG("--------------------------------------");
  INFOLOG("Channel streaming request: %i - %s", channel->Number(), channel->Name());

  if (m_Device == NULL)
  {
    ERRORLOG("Can't get device for channel %i - %s", channel->Number(), channel->Name());

    // return status "recording running" if there is an active timer
    time_t now = time(NULL);
    if(Timers.GetMatch(now) != NULL)
      return XVDR_RET_RECRUNNING;

    return XVDR_RET_DATALOCKED;
  }

  INFOLOG("Found available device %d", m_Device->DeviceNumber() + 1);

  if (!m_Device->SwitchChannel(channel, false))
  {
    ERRORLOG("Can't switch to channel %i - %s", channel->Number(), channel->Name());
    return XVDR_RET_ERROR;
  }

  // create send queue
  if (m_Queue == NULL)
  {
    m_Queue = new cLiveQueue(sock);
    m_Queue->Start();
  }

  m_PatFilter = new cLivePatFilter(this, channel);

  // get cached demuxer data
  cChannelCache cache = cChannelCache::GetFromCache(m_uid);

  // channel not found in cache -> add it from vdr
  if(cache.size() == 0) {
    INFOLOG("adding channel to cache");
    cChannelCache::AddToCache(channel);
    cache = cChannelCache::GetFromCache(m_uid);
  }

  // channel already in cache
  else {
    INFOLOG("Channel information found in cache");
  }

  // recheck cache item
  if(cache.size() != 0) {
    INFOLOG("Creating demuxers");
    cache.CreateDemuxers(this);
  }

  if(!Attach()) {
    INFOLOG("Unable to attach receiver !");
    return XVDR_RET_DATALOCKED;
  }

  RequestStreamChange();

  DEBUGLOG("Starting PAT scanner");
  m_Device->AttachFilter(m_PatFilter);

  INFOLOG("Successfully switched to channel %i - %s", channel->Number(), channel->Name());

  Start();

  return XVDR_RET_OK;
}