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; }
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; }