#include <lib/dvb/sec.h>
#include <lib/dvb/specs.h>
+#include <lib/dvb/fbc.h>
+#include <lib/dvb/fcc.h>
+
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
+#include <fstream>
DEFINE_REF(eDVBRegisteredFrontend);
DEFINE_REF(eDVBRegisteredDemux);
eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
{
m_fe->dec_use();
+ if (m_fe->m_frontend->is_FBCTuner())
+ {
+ eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
+ if (fbcmng)
+ {
+ fbcmng->unLink(m_fe);
+ }
+ }
}
DEFINE_REF(eDVBAllocatedDemux);
num_adapter++;
}
+ setUsbTuner();
+
int fd = open("/proc/stb/info/model", O_RDONLY);
char tmp[255];
int rd = fd >= 0 ? read(fd, tmp, 255) : 0;
eDVBCAService::registerChannelCallback(this);
+ m_fbc_mng = new eFBCTunerManager(this);
+
CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
}
{
struct stat s;
char filename[128];
-#if HAVE_DVB_API_VERSION < 3
- sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
-#else
sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
-#endif
if (stat(filename, &s))
break;
eDVBFrontend *fe;
{
struct stat s;
char filename[128];
-#if HAVE_DVB_API_VERSION < 3
- sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
-#else
sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
-#endif
if (stat(filename, &s))
break;
ePtr<eDVBDemux> demux;
{
struct stat s;
char filename[128];
-#if HAVE_DVB_API_VERSION < 3
- sprintf(filename, "/dev/dvb/card%d", nr);
-#else
sprintf(filename, "/dev/dvb/adapter%d", nr);
-#endif
if (!stat(filename, &s))
return 1;
return 0;
ePtr<eDVBFrontend> frontend;
if (!adapter->getFrontend(frontend, i))
{
- int frontendType=0;
- frontend->getFrontendType(frontendType);
eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
m_frontend.push_back(new_fe);
frontend->setSEC(m_sec);
// we must link all dvb-t frontends ( for active antenna voltage )
- if (frontendType == iDVBFrontend::feTerrestrial)
+ if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
{
if (prev_dvbt_frontend)
{
ePtr<eDVBFrontend> frontend;
if (!adapter->getFrontend(frontend, i, true))
{
- int frontendType=0;
- frontend->getFrontendType(frontendType);
eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
// CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
m_simulate_frontend.push_back(new_fe);
frontend->setSEC(m_sec);
// we must link all dvb-t frontends ( for active antenna voltage )
- if (frontendType == iDVBFrontend::feTerrestrial)
+ if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
{
if (prev_dvbt_frontend)
{
}
+void eDVBResourceManager::setUsbTuner()
+{
+ std::ifstream in("/proc/bus/nim_sockets");
+ std::string line;
+
+ int res = -1;
+ int fe_idx = -1;
+ int usbtuner_idx[8] = {0};
+ int usbtuner_count = 0;
+
+ if (in.is_open())
+ {
+ while(!in.eof())
+ {
+ getline(in, line);
+ if ((res = sscanf(line.c_str(), "NIM Socket %d:", &fe_idx)) == 1)
+ continue;
+
+ if ((fe_idx != -1) && (line.find("\tName: ") == 0) && (line.find("VTUNER") != -1))
+ usbtuner_idx[usbtuner_count++] = fe_idx;
+ }
+ in.close();
+ }
+
+ if (usbtuner_count)
+ {
+ for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_frontend.begin()); it != m_frontend.end(); ++it)
+ {
+ int slotid = it->m_frontend->getSlotID();
+ for (int i=0; i < usbtuner_count ; i++)
+ {
+ if (slotid == usbtuner_idx[i])
+ {
+ it->m_frontend->setUSBTuner(true);
+ break;
+ }
+ }
+ }
+ for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_simulate_frontend.begin()); it != m_simulate_frontend.end(); ++it)
+ {
+ int slotid = it->m_frontend->getSlotID();
+ for (int i=0; i < usbtuner_count ; i++)
+ {
+ if (slotid == usbtuner_idx[i])
+ {
+ it->m_frontend->setUSBTuner(true);
+ break;
+ }
+ }
+ }
+ }
+}
+
PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
{
if (!PyList_Check(list))
Py_RETURN_NONE;
}
+bool eDVBResourceManager::frontendIsCompatible(int index, const char *type)
+{
+ for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
+ {
+ if (i->m_frontend->getSlotID() == index)
+ {
+ if (!strcmp(type, "DVB-S2"))
+ {
+ return i->m_frontend->supportsDeliverySystem(SYS_DVBS2, false);
+ }
+ else if (!strcmp(type, "DVB-S"))
+ {
+ return i->m_frontend->supportsDeliverySystem(SYS_DVBS, false);
+ }
+ else if (!strcmp(type, "DVB-T2"))
+ {
+ return i->m_frontend->supportsDeliverySystem(SYS_DVBT2, false);
+ }
+ else if (!strcmp(type, "DVB-T"))
+ {
+ return i->m_frontend->supportsDeliverySystem(SYS_DVBT, false);
+ }
+ else if (!strcmp(type, "DVB-C"))
+ {
+#if defined SYS_DVBC_ANNEX_A
+ return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_A, false);
+#else
+ return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_AC, false);
+#endif
+ }
+ }
+ }
+ return false;
+}
+
+void eDVBResourceManager::setFrontendType(int index, const char *type)
+{
+ eDebug("[eDVBResourceManager::setFrontendType] index : %d, type : %s", index, type);
+
+ for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
+ {
+ if (i->m_frontend->getSlotID() == index)
+ {
+ std::vector<fe_delivery_system_t> whitelist;
+ if (!strcmp(type, "DVB-S2") || !strcmp(type, "DVB-S"))
+ {
+ whitelist.push_back(SYS_DVBS);
+ whitelist.push_back(SYS_DVBS2);
+ }
+ else if (!strcmp(type, "DVB-T2") || !strcmp(type, "DVB-T"))
+ {
+ whitelist.push_back(SYS_DVBT);
+ whitelist.push_back(SYS_DVBT2);
+ }
+ else if (!strcmp(type, "DVB-C"))
+ {
+#if defined SYS_DVBC_ANNEX_A
+ whitelist.push_back(SYS_DVBC_ANNEX_A);
+#else
+ whitelist.push_back(SYS_DVBC_ANNEX_AC);
+#endif
+ }
+ i->m_frontend->setDeliverySystemWhitelist(whitelist);
+ break;
+ }
+ }
+}
+
RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
{
eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
- ePtr<eDVBRegisteredFrontend> best;
+ eDVBRegisteredFrontend *best = NULL;
int bestval = 0;
int foundone = 0;
+ int check_fbc_leaf_linkable = 0;
+ int current_fbc_setid = -1;
+ eDVBRegisteredFrontend *fbc_fe = NULL;
+ eDVBRegisteredFrontend *best_fbc_fe = NULL;
+
for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
{
- int c = i->m_frontend->isCompatibleWith(feparm);
+ int c = 0;
+ fbc_fe = NULL;
+ if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
+ {
+ int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
+ if (fbc_setid != current_fbc_setid)
+ {
+ current_fbc_setid = fbc_setid;
+ check_fbc_leaf_linkable = 0;
+ }
+
+ if (!check_fbc_leaf_linkable)
+ {
+ c = m_fbc_mng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
+ check_fbc_leaf_linkable = 1;
+ eDebug("[eDVBResourceManager::allocateFrontend] m_fbc_mng->isCompatibleWith slotid : %p (%d), fbc_fe : %p (%d), score : %d", (eDVBRegisteredFrontend *)*i, i->m_frontend->getSlotID(), fbc_fe, fbc_fe?fbc_fe->m_frontend->getSlotID():-1, c);
+ }
+ }
+ else
+ {
+ c = i->m_frontend->isCompatibleWith(feparm);
+ }
if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
foundone = 1;
if (!i->m_inuse)
{
-// eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
+ eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
if (c > bestval)
{
bestval = c;
- best = i;
+ best = *i;
+ best_fbc_fe = fbc_fe;
}
}
-// else
-// eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
+ else
+ {
+ eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
+ }
+
+ eDVBRegisteredFrontend *tmp = *i;
}
if (best)
{
+ if (best_fbc_fe)
+ {
+ m_fbc_mng->addLink(best, best_fbc_fe, simulate);
+ }
+
fe = new eDVBAllocatedFrontend(best);
return 0;
}
if (!simulate) \
eDebug(x); \
} while(0)
-// else \
-// { \
-// eDebugNoNewLine("SIMULATE:"); \
-// eDebug(x); \
-// } \
-
RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
{
eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
ePtr<eDVBRegisteredFrontend> best;
int bestval = 0;
+ int check_fbc_leaf_linkable = 0;
+ int current_fbc_setid = -1;
for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
+ {
if (!i->m_inuse)
{
- int c = i->m_frontend->isCompatibleWith(feparm);
+ int c = 0;
+ if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
+ {
+ int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
+ if (fbc_setid != current_fbc_setid)
+ {
+ current_fbc_setid = fbc_setid;
+ check_fbc_leaf_linkable = 0;
+ }
+
+ if (!check_fbc_leaf_linkable)
+ {
+ eDVBRegisteredFrontend *dummy;
+ c = m_fbc_mng->isCompatibleWith(feparm, *i, dummy, simulate);
+ check_fbc_leaf_linkable = 1;
+ }
+ }
+ else
+ {
+ c = i->m_frontend->isCompatibleWith(feparm);
+ }
if (c > bestval)
bestval = c;
}
+ }
return bestval;
}
int *decremented_cached_channel_fe_usecount=NULL,
*decremented_fe_usecount=NULL;
+ /* check FCC channels */
+ std::vector<int*> fcc_decremented_fe_usecounts;
+ std::map<eDVBChannelID, int> fcc_chids;
+ int apply_to_ignore = 0;
+ if (!eFCCServiceManager::getFCCChannelID(fcc_chids))
+ {
+ for (std::map<eDVBChannelID, int>::iterator i(fcc_chids.begin()); i != fcc_chids.end(); ++i)
+ {
+ //eDebug("[eDVBResourceManager::canAllocateChannel] FCC NS : %08x, TSID : %04x, ONID : %04x", i->first.dvbnamespace.get(), i->first.transport_stream_id.get(), i->first.original_network_id.get());
+ if (ignore == i->first)
+ {
+ apply_to_ignore = i->second;
+ continue;
+ }
+ for (std::list<active_channel>::iterator ii(active_channels.begin()); ii != active_channels.end(); ++ii)
+ {
+ eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
+ if (ii->m_channel_id == i->first)
+ {
+ eDVBChannel *channel = (eDVBChannel*) &(*ii->m_channel);
+
+ int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
+ check_usecount += i->second * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
+ //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
+ if (channel->getUseCount() == check_usecount)
+ {
+ ePtr<iDVBFrontend> fe;
+ if (!ii->m_channel->getFrontend(fe))
+ {
+ for (eSmartPtrList<eDVBRegisteredFrontend>::iterator iii(frontends.begin()); iii != frontends.end(); ++iii)
+ {
+ if ( &(*fe) == &(*iii->m_frontend) )
+ {
+ //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : decrease fcc fe use_count! feid : %d (%d -> %d)", iii->m_frontend->getSlotID(), iii->m_inuse, iii->m_inuse-1);
+ --iii->m_inuse;
+ int *tmp_decremented_fe_usecount = &iii->m_inuse;
+ fcc_decremented_fe_usecounts.push_back(tmp_decremented_fe_usecount);
+ if (channel == &(*m_cached_channel))
+ decremented_cached_channel_fe_usecount = tmp_decremented_fe_usecount;
+ break;
+ }
+ }
+ }
+ }
+ break;
+ }
+ }
+ }
+ }
+
for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
{
eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
// another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
// so we must check here if usecount is 3 (when the channel is equal to the cached channel)
// or 2 when the cached channel is not equal to the compared channel
- if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
+ int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
+ check_usecount += (apply_to_ignore+1) * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
+ //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
+ if (channel->getUseCount() == check_usecount) // channel only used once..(except fcc)
{
ePtr<iDVBFrontend> fe;
if (!i->m_channel->getFrontend(fe))
{
if ( &(*fe) == &(*ii->m_frontend) )
{
+ //eDebug("[eDVBResourceManager::canAllocateChannel] ignore : decrease fcc fe use_count! feid : %d (%d -> %d)", ii->m_frontend->getSlotID(), ii->m_inuse, ii->m_inuse-1);
--ii->m_inuse;
decremented_fe_usecount = &ii->m_inuse;
if (channel == &(*m_cached_channel))
++(*decremented_fe_usecount);
if (decremented_cached_channel_fe_usecount)
++(*decremented_cached_channel_fe_usecount);
+ if (fcc_decremented_fe_usecounts.size())
+ {
+ for (std::vector<int*>::iterator i(fcc_decremented_fe_usecounts.begin()); i != fcc_decremented_fe_usecounts.end(); ++i)
+ {
+ //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : increase fcc fe use_count!");
+ ++(**i);
+ }
+ }
return ret;
}
eDebug("SOF");
m_event(this, evtSOF);
break;
+ case eFilePushThread::evtUser+3: /* limit space */
+ eDebug("Too large file");
+ m_event(this, evtFailed+3);
+ break;
}
}
m_pvr_thread = 0;
}
- if (!source->valid())
+ if (!source->valid() && !source->isStream())
{
eDebug("PVR source is not valid!");
return -ENOENT;
}
- m_tstools.setSource(source, streaminfo_file);
+ m_source = source;
+ m_tstools.setSource(m_source, streaminfo_file);
/* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
THEN DO A REAL FIX HERE! */
if (m_pvr_fd_dst < 0)
{
/* (this codepath needs to be improved anyway.) */
-#if HAVE_DVB_API_VERSION < 3
- m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
- if (m_pvr_fd_dst < 0)
- {
- eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
- return -ENODEV;
- }
-#else
ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
if (demux)
{
eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
return -ENODEV;
}
-#endif
}
m_pvr_thread = new eDVBChannelFilePush();
m_pvr_thread->enablePVRCommit(1);
/* If the source specifies a length, it's a file. If not, it's a stream */
- m_pvr_thread->setStreamMode(source->length() <= 0);
+ m_pvr_thread->setStreamMode(m_source->isStream());
m_pvr_thread->setScatterGather(this);
m_event(this, evtPreStart);
- m_pvr_thread->start(source, m_pvr_fd_dst);
+ m_pvr_thread->start(m_source, m_pvr_fd_dst);
CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
m_state = state_ok;
m_pvr_thread = 0;
}
if (m_pvr_fd_dst >= 0)
+ {
::close(m_pvr_fd_dst);
- ePtr<iTsSource> d;
- m_tstools.setSource(d);
+ m_pvr_fd_dst = -1;
+ }
+
+ m_source = NULL;
+ m_tstools.setSource(m_source);
}
void eDVBChannel::stopFile()
} else
now = pos; /* fixup supplied */
- off_t off = 0; /* TODO: fixme */
- r = m_tstools.fixupPTS(off, now);
+ r = m_tstools.fixupPTS(m_source ? m_source->offset() : 0, now);
if (r)
{
eDebug("fixup PTS failed");