1 #include <lib/base/eerror.h>
2 #include <lib/base/filepush.h>
3 #include <lib/dvb/idvb.h>
4 #include <lib/dvb/dvb.h>
5 #include <lib/dvb/pmt.h>
6 #include <lib/dvb/sec.h>
7 #include <lib/dvb/specs.h>
9 #include <lib/dvb/fbc.h>
10 #include <lib/dvb/fcc.h>
13 #include <sys/types.h>
17 #include <sys/ioctl.h>
19 DEFINE_REF(eDVBRegisteredFrontend);
20 DEFINE_REF(eDVBRegisteredDemux);
22 DEFINE_REF(eDVBAllocatedFrontend);
24 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
29 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
32 if (m_fe->m_frontend->is_FBCTuner())
34 eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
42 DEFINE_REF(eDVBAllocatedDemux);
44 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
49 eDVBAllocatedDemux::~eDVBAllocatedDemux()
54 DEFINE_REF(eDVBResourceManager);
56 eDVBResourceManager *eDVBResourceManager::instance;
58 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
68 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
70 ePtr<eDVBResourceManager> ptr;
71 eDVBResourceManager::getInstance(ptr);
75 eDVBResourceManager::eDVBResourceManager()
76 :m_releaseCachedChannelTimer(eTimer::create(eApp))
80 m_sec = new eDVBSatelliteEquipmentControl(m_frontend, m_simulate_frontend);
85 /* search available adapters... */
90 while (eDVBAdapterLinux::exist(num_adapter))
92 addAdapter(new eDVBAdapterLinux(num_adapter));
96 int fd = open("/proc/stb/info/model", O_RDONLY);
98 int rd = fd >= 0 ? read(fd, tmp, 255) : 0;
102 if (!strncmp(tmp, "dm7025\n", rd))
104 else if (!strncmp(tmp, "dm8000\n", rd))
106 else if (!strncmp(tmp, "dm800\n", rd))
108 else if (!strncmp(tmp, "dm500hd\n", rd))
110 else if (!strncmp(tmp, "dm800se\n", rd))
112 else if (!strncmp(tmp, "dm7020hd\n", rd))
113 m_boxtype = DM7020HD;
115 eDebug("boxtype detection via /proc/stb/info not possible... use fallback via demux count!\n");
116 if (m_demux.size() == 3)
118 else if (m_demux.size() < 5)
124 eDebug("found %zd adapter, %zd frontends(%zd sim) and %zd demux, boxtype %d",
125 m_adapter.size(), m_frontend.size(), m_simulate_frontend.size(), m_demux.size(), m_boxtype);
127 eDVBCAService::registerChannelCallback(this);
129 CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
132 void eDVBResourceManager::feStateChanged()
135 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
137 mask |= ( 1 << i->m_frontend->getSlotID() );
138 /* emit */ frontendUseMaskChanged(mask);
141 DEFINE_REF(eDVBAdapterLinux);
142 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
147 eDebug("scanning for frontends..");
152 #if HAVE_DVB_API_VERSION < 3
153 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
155 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
157 if (stat(filename, &s))
163 fe = new eDVBFrontend(m_nr, num_fe, ok, true);
165 m_simulate_frontend.push_back(ePtr<eDVBFrontend>(fe));
170 fe = new eDVBFrontend(m_nr, num_fe, ok, false, fe);
172 m_frontend.push_back(ePtr<eDVBFrontend>(fe));
183 #if HAVE_DVB_API_VERSION < 3
184 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
186 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
188 if (stat(filename, &s))
190 ePtr<eDVBDemux> demux;
192 demux = new eDVBDemux(m_nr, num_demux);
193 m_demux.push_back(demux);
199 int eDVBAdapterLinux::getNumDemux()
201 return m_demux.size();
204 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
206 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
207 while (nr && (i != m_demux.end()))
213 if (i != m_demux.end())
221 int eDVBAdapterLinux::getNumFrontends()
223 return m_frontend.size();
226 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr, bool simulate)
228 eSmartPtrList<eDVBFrontend>::iterator i(simulate ? m_simulate_frontend.begin() : m_frontend.begin());
229 while (nr && (i != m_frontend.end()))
235 if (i != m_frontend.end())
243 int eDVBAdapterLinux::exist(int nr)
247 #if HAVE_DVB_API_VERSION < 3
248 sprintf(filename, "/dev/dvb/card%d", nr);
250 sprintf(filename, "/dev/dvb/adapter%d", nr);
252 if (!stat(filename, &s))
257 eDVBResourceManager::~eDVBResourceManager()
259 if (instance == this)
263 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
265 int num_fe = adapter->getNumFrontends();
266 int num_demux = adapter->getNumDemux();
268 m_adapter.push_back(adapter);
271 for (i=0; i<num_demux; ++i)
273 ePtr<eDVBDemux> demux;
274 if (!adapter->getDemux(demux, i))
275 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
278 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
279 for (i=0; i<num_fe; ++i)
281 ePtr<eDVBFrontend> frontend;
282 if (!adapter->getFrontend(frontend, i))
284 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
285 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
286 m_frontend.push_back(new_fe);
287 frontend->setSEC(m_sec);
288 // we must link all dvb-t frontends ( for active antenna voltage )
289 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
291 if (prev_dvbt_frontend)
293 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
294 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
296 prev_dvbt_frontend = new_fe;
301 prev_dvbt_frontend = 0;
302 for (i=0; i<num_fe; ++i)
304 ePtr<eDVBFrontend> frontend;
305 if (!adapter->getFrontend(frontend, i, true))
307 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
308 // CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
309 m_simulate_frontend.push_back(new_fe);
310 frontend->setSEC(m_sec);
311 // we must link all dvb-t frontends ( for active antenna voltage )
312 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
314 if (prev_dvbt_frontend)
316 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
317 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
319 prev_dvbt_frontend = new_fe;
326 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
328 if (!PyList_Check(list))
330 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
333 unsigned int assigned=0;
334 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
337 while (pos < PyList_Size(list)) {
338 ePyObject obj = PyList_GET_ITEM(list, pos++);
339 if (!i->m_frontend->setSlotInfo(obj))
345 if (assigned != m_frontend.size()) {
347 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %zd socket informations, but %d registered frontends!",
348 m_frontend.size(), assigned);
349 PyErr_SetString(PyExc_StandardError, blasel);
352 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
355 while (pos < PyList_Size(list)) {
356 ePyObject obj = PyList_GET_ITEM(list, pos++);
357 if (!i->m_frontend->setSlotInfo(obj))
365 bool eDVBResourceManager::frontendIsCompatible(int index, const char *type)
367 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
369 if (i->m_frontend->getSlotID() == index)
371 if (!strcmp(type, "DVB-S2"))
373 return i->m_frontend->supportsDeliverySystem(SYS_DVBS2, false);
375 else if (!strcmp(type, "DVB-S"))
377 return i->m_frontend->supportsDeliverySystem(SYS_DVBS, false);
379 else if (!strcmp(type, "DVB-T2"))
381 return i->m_frontend->supportsDeliverySystem(SYS_DVBT2, false);
383 else if (!strcmp(type, "DVB-T"))
385 return i->m_frontend->supportsDeliverySystem(SYS_DVBT, false);
387 else if (!strcmp(type, "DVB-C"))
389 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
390 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_A, false);
392 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_AC, false);
400 void eDVBResourceManager::setFrontendType(int index, const char *type)
402 eDebug("[eDVBResourceManager::setFrontendType] index : %d, type : %s", index, type);
404 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
406 if (i->m_frontend->getSlotID() == index)
408 std::vector<fe_delivery_system_t> whitelist;
409 if (!strcmp(type, "DVB-S2") || !strcmp(type, "DVB-S"))
411 whitelist.push_back(SYS_DVBS);
412 whitelist.push_back(SYS_DVBS2);
414 else if (!strcmp(type, "DVB-T2") || !strcmp(type, "DVB-T"))
416 whitelist.push_back(SYS_DVBT);
417 whitelist.push_back(SYS_DVBT2);
419 else if (!strcmp(type, "DVB-C"))
421 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
422 whitelist.push_back(SYS_DVBC_ANNEX_A);
424 whitelist.push_back(SYS_DVBC_ANNEX_AC);
427 i->m_frontend->setDeliverySystemWhitelist(whitelist);
433 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
435 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
436 // ePtr<eDVBRegisteredFrontend> best;
437 eDVBRegisteredFrontend *best = NULL;
441 int check_fbc_linked = 0;
442 eDVBRegisteredFrontend *fbc_fe = NULL;
443 eDVBRegisteredFrontend *best_fbc_fe = NULL;
444 eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
446 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
450 if (!check_fbc_linked && i->m_frontend->is_FBCTuner() && fbcmng && fbcmng->canLink(*i))
452 check_fbc_linked = 1;
453 c = fbcmng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
455 // eDebug("[eDVBResourceManager::allocateFrontend] fbcmng->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);
459 c = i->m_frontend->isCompatibleWith(feparm);
462 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
467 // eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
473 best_fbc_fe = fbc_fe;
478 // eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
481 eDVBRegisteredFrontend *tmp = *i;
486 if (fbcmng && best_fbc_fe)
488 fbcmng->addLink(best, best_fbc_fe, simulate);
491 fe = new eDVBAllocatedFrontend(best);
498 return errAllSourcesBusy;
500 return errNoSourceFound;
503 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
505 int err = errNoSourceFound;
506 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
507 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
509 // check if another slot linked to this is in use
511 i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
514 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
515 if (satpos_depends_to_fe->m_inuse)
517 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
518 err = errAllSourcesBusy;
519 goto alloc_fe_by_id_not_possible;
522 else // check linked tuners
524 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
527 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
530 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
531 err = errAllSourcesBusy;
532 goto alloc_fe_by_id_not_possible;
534 next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
536 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
539 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
542 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
543 err = errAllSourcesBusy;
544 goto alloc_fe_by_id_not_possible;
546 prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
549 fe = new eDVBAllocatedFrontend(i);
552 alloc_fe_by_id_not_possible:
557 #define capHoldDecodeReference 64
559 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int &cap)
561 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
562 never use the first one unless we need a decoding demux. */
564 eDebug("allocate demux");
565 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
569 if (i == m_demux.end())
572 ePtr<eDVBRegisteredDemux> unused;
574 if (m_boxtype == DM800) // dm800
576 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
577 for (; i != m_demux.end(); ++i, ++n)
588 if (i->m_adapter == fe->m_adapter &&
589 i->m_demux->getSource() == fe->m_frontend->getDVBID())
591 demux = new eDVBAllocatedDemux(i);
595 else if (i->m_demux->getSource() == -1) // PVR
597 demux = new eDVBAllocatedDemux(i);
603 else if (m_boxtype == DM7025) // ATI
605 /* FIXME: hardware demux policy */
606 if (!(cap & iDVBChannel::capDecode))
608 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
615 for (; i != m_demux.end(); ++i, ++n)
617 int is_decode = n < 2;
619 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
621 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
623 if ((cap & iDVBChannel::capDecode) && !is_decode)
630 else if (m_boxtype == DM8000 || m_boxtype == DM500HD || m_boxtype == DM800SE || m_boxtype == DM7020HD)
632 iDVBAdapter *adapter = fe ? fe->m_adapter : m_adapter.begin(); /* look for a demux on the same adapter as the frontend, or the first adapter for dvr playback */
633 int source = fe ? fe->m_frontend->getDVBID() : -1;
634 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
638 * For pvr playback, start with the last demux.
639 * On some hardware, we have less ca devices than demuxes,
640 * so we should try to leave the first demuxes for live tv,
641 * and start with the last for pvr playback
646 while (i != m_demux.end())
648 if (i->m_adapter == adapter)
652 /* mark the first unused demux, we'll use that when we do not find a better match */
653 if (!unused) unused = i;
657 /* demux is in use, see if we can share it */
658 if (source >= 0 && i->m_demux->getSource() == source)
660 demux = new eDVBAllocatedDemux(i);
678 demux = new eDVBAllocatedDemux(unused);
680 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
682 demux->get().setSourcePVR(0);
686 eDebug("demux not found");
690 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
696 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
705 #define eDebugNoSimulate(x...) \
711 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
713 /* first, check if a channel is already existing. */
714 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
716 if (!simulate && m_cached_channel)
718 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
719 if(channelid==cache_chan->getChannelID())
721 eDebug("use cached_channel");
722 channel = m_cached_channel;
725 m_cached_channel_state_changed_conn.disconnect();
727 m_releaseCachedChannelTimer->stop();
730 eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
731 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
733 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
734 if (i->m_channel_id == channelid)
736 eDebugNoSimulate("found shared channel..");
737 channel = i->m_channel;
742 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
746 eDebugNoSimulate("no channel list set!");
747 return errNoChannelList;
750 ePtr<iDVBFrontendParameters> feparm;
751 if (m_list->getChannelFrontendData(channelid, feparm))
753 eDebugNoSimulate("channel not found!");
754 return errChannelNotInList;
757 /* allocate a frontend. */
759 ePtr<eDVBAllocatedFrontend> fe;
761 int err = allocateFrontend(fe, feparm, simulate);
766 ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
768 res = ch->setChannel(channelid, feparm);
772 return errChidNotFound;
779 m_cached_channel = channel = ch;
780 m_cached_channel_state_changed_conn =
781 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
787 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
790 chan->getState(state);
793 case iDVBChannel::state_release:
794 case iDVBChannel::state_ok:
796 eDebug("stop release channel timer");
797 m_releaseCachedChannelTimer->stop();
800 case iDVBChannel::state_last_instance:
802 eDebug("start release channel timer");
803 m_releaseCachedChannelTimer->start(3000, true);
806 default: // ignore all other events
811 void eDVBResourceManager::releaseCachedChannel()
813 eDebug("release cached channel (timer timeout)");
817 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
819 ePtr<eDVBAllocatedFrontend> fe;
821 if (m_cached_channel)
823 m_cached_channel_state_changed_conn.disconnect();
825 m_releaseCachedChannelTimer->stop();
828 int err = allocateFrontendByIndex(fe, slot_index);
832 channel = new eDVBChannel(this, fe);
836 RESULT eDVBResourceManager::allocatePVRChannel(const eDVBChannelID &channelid, eUsePtr<iDVBPVRChannel> &channel)
838 ePtr<eDVBAllocatedDemux> demux;
840 if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
842 m_cached_channel_state_changed_conn.disconnect();
844 m_releaseCachedChannelTimer->stop();
847 ePtr<eDVBChannel> ch = new eDVBChannel(this, 0);
851 * user provided a channelid, with the clear intention for
852 * this channel to be registered at the resource manager.
853 * (allowing e.g. epgcache to be started)
855 ePtr<iDVBFrontendParameters> feparm;
856 ch->setChannel(channelid, feparm);
862 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
864 ePtr<iDVBFrontend> fe;
865 if (!ch->getFrontend(fe))
867 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
868 if (frontend->is_simulate())
869 m_active_simulate_channels.push_back(active_channel(chid, ch));
872 m_active_channels.push_back(active_channel(chid, ch));
873 /* emit */ m_channelAdded(ch);
879 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
881 ePtr<iDVBFrontend> fe;
882 if (!ch->getFrontend(fe))
884 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
885 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
887 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
889 if (i->m_channel == ch)
891 i = active_channels.erase(i);
903 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
905 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
909 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
911 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
912 ePtr<eDVBRegisteredFrontend> best;
914 int check_fbc_link = 0;
915 eFBCTunerManager *fbcmng = eFBCTunerManager::getInstance();
917 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
922 if(fbcmng && i->m_frontend->is_FBCTuner() && fbcmng->canLink(*i) && !check_fbc_link)
925 c = fbcmng->isCompatibleWith(feparm, *i, simulate);
929 c = i->m_frontend->isCompatibleWith(feparm);
938 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid, int &system)
940 system = iDVBFrontend::feSatellite;
943 ePtr<iDVBFrontendParameters> feparm;
944 if (!channellist->getChannelFrontendData(chid, feparm))
946 if (!feparm->getSystem(system))
950 case iDVBFrontend::feSatellite:
952 case iDVBFrontend::feCable:
954 case iDVBFrontend::feTerrestrial:
965 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, int &system, bool simulate)
967 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
969 system = iDVBFrontend::feSatellite;
970 if (!simulate && m_cached_channel)
972 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
973 if(channelid==cache_chan->getChannelID())
974 return tuner_type_channel_default(m_list, channelid, system);
977 /* first, check if a channel is already existing. */
978 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
979 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
981 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
982 if (i->m_channel_id == channelid)
984 // eDebug("found shared channel..");
985 return tuner_type_channel_default(m_list, channelid, system);
989 int *decremented_cached_channel_fe_usecount=NULL,
990 *decremented_fe_usecount=NULL;
992 /* check FCC channels */
993 std::vector<int*> fcc_decremented_fe_usecounts;
994 std::map<eDVBChannelID, int> fcc_chids;
995 int apply_to_ignore = 0;
996 if (!eFCCServiceManager::getFCCChannelID(fcc_chids))
998 for (std::map<eDVBChannelID, int>::iterator i(fcc_chids.begin()); i != fcc_chids.end(); ++i)
1000 //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());
1001 if (ignore == i->first)
1003 apply_to_ignore = i->second;
1006 for (std::list<active_channel>::iterator ii(active_channels.begin()); ii != active_channels.end(); ++ii)
1008 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1009 if (ii->m_channel_id == i->first)
1011 eDVBChannel *channel = (eDVBChannel*) &(*ii->m_channel);
1013 int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1014 check_usecount += i->second * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1015 //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1016 if (channel->getUseCount() == check_usecount)
1018 ePtr<iDVBFrontend> fe;
1019 if (!ii->m_channel->getFrontend(fe))
1021 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator iii(frontends.begin()); iii != frontends.end(); ++iii)
1023 if ( &(*fe) == &(*iii->m_frontend) )
1025 //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : decrease fcc fe use_count! feid : %d (%d -> %d)", iii->m_frontend->getSlotID(), iii->m_inuse, iii->m_inuse-1);
1027 int *tmp_decremented_fe_usecount = &iii->m_inuse;
1028 fcc_decremented_fe_usecounts.push_back(tmp_decremented_fe_usecount);
1029 if (channel == &(*m_cached_channel))
1030 decremented_cached_channel_fe_usecount = tmp_decremented_fe_usecount;
1042 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
1044 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1045 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
1046 if (i->m_channel_id == ignore)
1048 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
1049 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
1050 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
1051 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
1052 // or 2 when the cached channel is not equal to the compared channel
1053 int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1054 check_usecount += (apply_to_ignore+1) * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1055 //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1056 if (channel->getUseCount() == check_usecount) // channel only used once..(except fcc)
1058 ePtr<iDVBFrontend> fe;
1059 if (!i->m_channel->getFrontend(fe))
1061 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1063 if ( &(*fe) == &(*ii->m_frontend) )
1065 //eDebug("[eDVBResourceManager::canAllocateChannel] ignore : decrease fcc fe use_count! feid : %d (%d -> %d)", ii->m_frontend->getSlotID(), ii->m_inuse, ii->m_inuse-1);
1067 decremented_fe_usecount = &ii->m_inuse;
1068 if (channel == &(*m_cached_channel))
1069 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
1079 if (!decremented_cached_channel_fe_usecount)
1081 if (m_cached_channel)
1083 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
1084 if (channel->getUseCount() == 1)
1086 ePtr<iDVBFrontend> fe;
1087 if (!channel->getFrontend(fe))
1089 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1090 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1092 if ( &(*fe) == &(*ii->m_frontend) )
1095 decremented_cached_channel_fe_usecount = &ii->m_inuse;
1104 decremented_cached_channel_fe_usecount=NULL;
1106 ePtr<iDVBFrontendParameters> feparm;
1110 eDebug("no channel list set!");
1114 if (m_list->getChannelFrontendData(channelid, feparm))
1116 eDebug("channel not found!");
1119 feparm->getSystem(system);
1121 ret = canAllocateFrontend(feparm, simulate);
1124 if (decremented_fe_usecount)
1125 ++(*decremented_fe_usecount);
1126 if (decremented_cached_channel_fe_usecount)
1127 ++(*decremented_cached_channel_fe_usecount);
1128 if (fcc_decremented_fe_usecounts.size())
1130 for (std::vector<int*>::iterator i(fcc_decremented_fe_usecounts.begin()); i != fcc_decremented_fe_usecounts.end(); ++i)
1132 //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : increase fcc fe use_count!");
1140 bool eDVBResourceManager::canMeasureFrontendInputPower()
1142 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
1144 return i->m_frontend->readInputpower() >= 0;
1149 class eDVBChannelFilePush: public eFilePushThread
1152 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
1153 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
1155 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
1156 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
1157 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
1159 int m_iframe_search, m_iframe_state, m_pid;
1160 int m_timebase_change;
1161 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
1164 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
1167 if (m_timebase_change)
1169 eDebug("timebase change: %d", m_timebase_change);
1171 for (offset = 0; offset < len; offset += 188)
1173 unsigned char *pkt = (unsigned char*)_data + offset;
1174 if (pkt[1] & 0x40) /* pusi */
1176 if (pkt[3] & 0x20) // adaption field present?
1177 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
1179 pkt += 4; /* skip header */
1180 if (pkt[0] || pkt[1] || (pkt[2] != 1))
1182 eWarning("broken startcode");
1188 if (pkt[7] & 0x80) // PTS present?
1190 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
1191 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
1192 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
1193 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
1194 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
1198 RESULT r = m_tstools.fixupPTS(off, pts);
1200 eWarning("fixup PTS while trickmode playback failed.\n");
1203 int sec = pts / 90000;
1204 int frm = pts % 90000;
1212 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1214 pts += 0x80000000LL;
1215 pts *= m_timebase_change;
1227 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1235 pkt[9] |= (pts >> 29) & 0xE;
1236 pkt[10] |= (pts >> 22) & 0xFF;
1237 pkt[11] |= (pts >> 14) & 0xFE;
1238 pkt[12] |= (pts >> 7) & 0xFF;
1239 pkt[13] |= (pts << 1) & 0xFE;
1247 if (!m_iframe_search)
1250 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1252 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1254 unsigned char *d = data;
1255 while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1257 int offset = d - data;
1258 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1259 unsigned char *ts = data + ts_offset;
1260 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1262 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */
1264 int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1267 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1269 if (m_iframe_state == 1)
1271 /* we are allowing data, and stop allowing data on the next frame.
1272 we now found a frame. so stop here. */
1273 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1274 current_span_remaining = 0;
1276 unsigned char *fts = ts + 188;
1277 while (fts < (data + len))
1280 fts[2] |= 0xff; /* drop packet */
1284 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1287 if (picture_type != 1) /* we are only interested in I frames */
1290 unsigned char *fts = data;
1294 fts[2] |= 0xff; /* drop packet */
1301 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1303 /* verify that this is actually a PES header, not just some ES data */
1304 if (ts[1] & 0x40) /* PUSI set */
1306 int payload_start = 4;
1307 if (ts[3] & 0x20) /* adaptation field present */
1308 payload_start += ts[4] + 1; /* skip AF */
1309 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1313 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1321 d += 4; /* ignore */
1324 if (m_iframe_state == 1)
1327 return 0; /* we need find an iframe first */
1333 DEFINE_REF(eDVBChannel);
1335 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1337 m_frontend = frontend;
1342 m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1345 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1348 eDVBChannel::~eDVBChannel()
1351 m_mgr->removeChannel(this);
1356 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1358 int state, ourstate = 0;
1360 /* if we are already in shutdown, don't change state. */
1361 if (m_state == state_release)
1364 if (fe->getState(state))
1367 if (state == iDVBFrontend::stateLock)
1369 eDebug("OURSTATE: ok");
1370 ourstate = state_ok;
1371 } else if (state == iDVBFrontend::stateTuning)
1373 eDebug("OURSTATE: tuning");
1374 ourstate = state_tuning;
1375 } else if (state == iDVBFrontend::stateLostLock)
1377 /* on managed channels, we try to retune in order to re-acquire lock. */
1378 if (m_current_frontend_parameters)
1380 eDebug("OURSTATE: lost lock, trying to retune");
1381 ourstate = state_tuning;
1382 m_frontend->get().tune(*m_current_frontend_parameters);
1384 /* on unmanaged channels, we don't do this. the client will do this. */
1386 eDebug("OURSTATE: lost lock, unavailable now.");
1387 ourstate = state_unavailable;
1389 } else if (state == iDVBFrontend::stateFailed)
1392 if (m_current_frontend_parameters)
1394 eDebug("OURSTATE: lost lock, trying to retune");
1395 ourstate = state_tuning;
1396 m_frontend->get().tune(*m_current_frontend_parameters);
1400 eDebug("OURSTATE: failed");
1401 ourstate = state_failed;
1404 eDebug("OURSTATE: failed");
1405 ourstate = state_failed;
1408 eFatal("state unknown");
1410 if (ourstate != m_state)
1413 m_stateChanged(this);
1417 void eDVBChannel::pvrEvent(int event)
1421 case eFilePushThread::evtEOF:
1422 eDebug("eDVBChannel: End of file!");
1423 m_event(this, evtEOF);
1425 case eFilePushThread::evtUser: /* start */
1427 m_event(this, evtSOF);
1429 case eFilePushThread::evtUser+3: /* limit space */
1430 eDebug("Too large file");
1431 m_event(this, evtFailed+3);
1436 void eDVBChannel::cueSheetEvent(int event)
1438 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1443 case eCueSheet::evtSeek:
1445 flushPVR(m_cue->m_decoding_demux);
1447 case eCueSheet::evtSkipmode:
1450 m_cue->m_lock.WrLock();
1451 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1452 m_cue->m_lock.Unlock();
1453 eRdLocker l(m_cue->m_lock);
1454 if (m_cue->m_skipmode_ratio)
1456 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1457 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1458 /* i agree that this might look a bit like black magic. */
1459 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1460 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1461 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1462 m_skipmode_frames_remainder = 0;
1464 if (m_cue->m_skipmode_ratio < 0)
1465 m_skipmode_m -= m_skipmode_n;
1467 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1469 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1471 eWarning("something is wrong with this calculation");
1472 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1476 eDebug("skipmode ratio is 0, normal play");
1477 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1480 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1481 if (m_cue->m_skipmode_ratio != 0)
1482 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1484 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1485 eDebug("flush pvr");
1486 flushPVR(m_cue->m_decoding_demux);
1490 case eCueSheet::evtSpanChanged:
1492 m_source_span.clear();
1493 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1495 off_t offset_in, offset_out;
1496 pts_t pts_in = i->first, pts_out = i->second;
1497 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1499 eDebug("span translation failed.\n");
1502 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1503 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1510 /* align toward zero */
1511 static inline long long align(long long x, int align)
1526 /* align toward zero */
1527 static inline long long align_with_len(long long x, int align, size_t &len)
1544 /* remember, this gets called from another thread. */
1545 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1547 const int blocksize = 188;
1548 unsigned int max = align(10*1024*1024, blocksize);
1549 current_offset = align(current_offset, blocksize);
1553 eDebug("no cue sheet. forcing normal play");
1554 start = current_offset;
1561 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1562 max = align(m_skipmode_n, blocksize);
1565 eDebug("getNextSourceSpan, current offset is %08lld, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1566 int frame_skip_success = 0;
1570 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1571 eDebug("we are at %lld, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1573 off_t iframe_start = current_offset;
1574 int frames_skipped = frames_to_skip;
1575 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1577 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1578 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1579 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1580 max = align(iframe_len + 187, blocksize);
1581 frame_skip_success = 1;
1584 m_skipmode_frames_remainder = 0;
1585 eDebug("frame skipping failed, reverting to byte-skipping");
1589 if (!frame_skip_success)
1591 current_offset += align(m_skipmode_m, blocksize);
1592 if(current_offset < 0)
1598 eDebug("we are at %lld, and we try to find the iframe here:", current_offset);
1600 off_t start_offset = current_offset;
1601 off_t new_offset = start_offset;
1602 int direction = (m_skipmode_m < 0) ? -1 : +1;
1603 if (m_tstools.findFrame(start_offset, new_offset, iframe_len, direction))
1607 current_offset = align_with_len(new_offset, blocksize, iframe_len);
1608 max = align(iframe_len, blocksize);
1614 m_cue->m_lock.RdLock();
1616 while (!m_cue->m_seek_requests.empty())
1618 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1619 m_cue->m_lock.Unlock();
1620 m_cue->m_lock.WrLock();
1621 m_cue->m_seek_requests.pop_front();
1622 m_cue->m_lock.Unlock();
1623 m_cue->m_lock.RdLock();
1624 int relative = seek.first;
1625 pts_t pts = seek.second;
1630 if (!m_cue->m_decoder)
1632 eDebug("no decoder - can't seek relative");
1635 if (m_cue->m_decoder->getPTS(0, now))
1637 eDebug("decoder getPTS failed, can't seek relative");
1640 if (!m_cue->m_decoding_demux)
1642 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1643 start = current_offset;
1647 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1649 eDebug("seekTo: getCurrentPosition failed!");
1652 } else if (pts < 0) /* seek relative to end */
1655 if (!getLength(len))
1657 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1661 eWarning("getLength failed - can't seek relative to end!");
1666 if (relative == 1) /* pts relative */
1677 if (relative == 2) /* AP relative */
1679 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1681 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1683 pts = now - 90000; /* approx. 1s */
1684 eDebug("AP relative seeking failed!");
1688 eDebug("next ap is %llx\n", pts);
1693 if (m_tstools.getOffset(offset, pts, -1))
1695 eDebug("get offset for pts=%lld failed!", pts);
1699 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1700 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1703 m_cue->m_lock.Unlock();
1705 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1707 long long aligned_start = align(i->first, blocksize);
1708 long long aligned_end = align(i->second, blocksize);
1710 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1712 start = current_offset;
1713 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1714 if ((aligned_end - current_offset) > max)
1717 size = aligned_end - current_offset;
1718 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1721 if (current_offset < aligned_start)
1723 /* ok, our current offset is in an 'out' zone. */
1724 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1726 /* in normal playback, just start at the next zone. */
1729 /* size is not 64bit! */
1730 if ((i->second - i->first) > max)
1733 size = aligned_end - aligned_start;
1736 if (m_skipmode_m < 0)
1738 eDebug("reached SOF");
1741 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1745 /* when skipping reverse, however, choose the zone before. */
1747 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1750 aligned_start = align(i->first, blocksize);
1751 aligned_end = align(i->second, blocksize);
1753 if ((aligned_end - aligned_start) > max)
1756 len = aligned_end - aligned_start;
1758 start = aligned_end - len;
1759 eDebug("skipping to %llx, %zd", start, len);
1762 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1767 if(current_offset <0)
1769 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1771 eDebug("reached SOF");
1773 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1775 if (m_source_span.empty())
1777 start = current_offset;
1779 eDebug("NO CUESHEET. (%08lld, %zd)", start, size);
1782 start = current_offset;
1788 void eDVBChannel::AddUse()
1790 if (++m_use_count > 1 && m_state == state_last_instance)
1793 m_stateChanged(this);
1797 void eDVBChannel::ReleaseUse()
1801 m_state = state_release;
1802 m_stateChanged(this);
1804 else if (m_use_count == 1)
1806 m_state = state_last_instance;
1807 m_stateChanged(this);
1811 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1814 m_mgr->removeChannel(this);
1819 m_channel_id = channelid;
1820 m_mgr->addChannel(channelid, this);
1824 /* no frontend, no need to tune (must be a streamed service) */
1828 m_state = state_tuning;
1829 /* if tuning fails, shutdown the channel immediately. */
1831 res = m_frontend->get().tune(*feparm);
1832 m_current_frontend_parameters = feparm;
1836 m_state = state_release;
1837 m_stateChanged(this);
1844 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1846 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1850 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1852 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1856 RESULT eDVBChannel::getState(int &state)
1862 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1867 void eDVBChannel::SDTready(int result)
1869 ePyObject args = PyTuple_New(2), ret;
1873 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1876 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1877 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1883 PyTuple_SET_ITEM(args, 0, Py_None);
1884 PyTuple_SET_ITEM(args, 1, Py_None);
1888 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1892 Py_DECREF(m_tsid_onid_callback);
1893 m_tsid_onid_callback = ePyObject();
1894 m_tsid_onid_demux = 0;
1898 int eDVBChannel::reserveDemux()
1900 ePtr<iDVBDemux> dmx;
1901 if (!getDemux(dmx, 0))
1904 if (!dmx->getCADemuxID(id))
1910 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1912 if (PyCallable_Check(callback))
1914 if (!getDemux(m_tsid_onid_demux, 0))
1916 m_SDT = new eTable<ServiceDescriptionSection>;
1917 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1918 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1920 m_tsid_onid_demux = 0;
1925 Py_INCREF(callback);
1926 m_tsid_onid_callback = callback;
1934 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1936 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1938 if (m_frontend == NULL)
1940 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
1941 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
1948 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1953 /* don't hold a reference to the decoding demux, we don't need it. */
1955 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1956 the refcount is lost. thus, decoding demuxes are never allocated.
1958 this poses a big problem for PiP. */
1960 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1962 else if (cap & capDecode)
1971 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1976 frontend = &m_frontend->get();
1982 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1984 param = m_current_frontend_parameters;
1988 RESULT eDVBChannel::playFile(const char *file)
1990 eRawFile *f = new eRawFile();
1991 ePtr<iTsSource> source = f;
1993 if (f->open(file) < 0)
1995 eDebug("can't open PVR file %s (%m)", file);
1999 return playSource(source, file);
2002 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
2004 ASSERT(!m_frontend);
2007 m_pvr_thread->stop();
2008 delete m_pvr_thread;
2012 if (!source->valid() && !source->isStream())
2014 eDebug("PVR source is not valid!");
2018 m_tstools.setSource(source, streaminfo_file);
2020 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
2021 THEN DO A REAL FIX HERE! */
2023 if (m_pvr_fd_dst < 0)
2025 /* (this codepath needs to be improved anyway.) */
2026 #if HAVE_DVB_API_VERSION < 3
2027 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
2028 if (m_pvr_fd_dst < 0)
2030 eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2034 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
2037 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
2038 if (m_pvr_fd_dst < 0)
2040 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2046 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
2052 m_pvr_thread = new eDVBChannelFilePush();
2053 m_pvr_thread->enablePVRCommit(1);
2054 /* If the source specifies a length, it's a file. If not, it's a stream */
2055 m_pvr_thread->setStreamMode(source->isStream());
2056 m_pvr_thread->setScatterGather(this);
2058 m_event(this, evtPreStart);
2060 m_pvr_thread->start(source, m_pvr_fd_dst);
2061 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
2064 m_stateChanged(this);
2069 void eDVBChannel::stopSource()
2073 m_pvr_thread->stop();
2074 delete m_pvr_thread;
2077 if (m_pvr_fd_dst >= 0)
2079 ::close(m_pvr_fd_dst);
2083 m_tstools.setSource(d);
2086 void eDVBChannel::stopFile()
2091 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
2093 m_conn_cueSheetEvent = 0;
2096 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
2099 RESULT eDVBChannel::getLength(pts_t &len)
2101 return m_tstools.calcLen(len);
2104 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
2106 if (!decoding_demux)
2113 if (mode == 0) /* demux */
2115 r = decoding_demux->getSTC(now, 0);
2118 eDebug("demux getSTC failed");
2122 now = pos; /* fixup supplied */
2124 off_t off = 0; /* TODO: fixme */
2125 r = m_tstools.fixupPTS(off, now);
2128 eDebug("fixup PTS failed");
2137 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
2139 /* when seeking, we have to ensure that all buffers are flushed.
2140 there are basically 3 buffers:
2141 a.) the filepush's internal buffer
2142 b.) the PVR buffer (before demux)
2143 c.) the ratebuffer (after demux)
2145 it's important to clear them in the correct order, otherwise
2146 the ratebuffer (for example) would immediately refill from
2147 the not-yet-flushed PVR buffer.
2150 m_pvr_thread->pause();
2151 /* flush internal filepush buffer */
2152 m_pvr_thread->flush();
2153 /* HACK: flush PVR buffer */
2154 ::ioctl(m_pvr_fd_dst, 0);
2156 /* flush ratebuffers (video, audio) */
2158 decoding_demux->flush();
2160 /* demux will also flush all decoder.. */
2161 /* resume will re-query the SG */
2162 m_pvr_thread->resume();
2165 DEFINE_REF(eCueSheet);
2167 eCueSheet::eCueSheet()
2169 m_skipmode_ratio = 0;
2172 void eCueSheet::seekTo(int relative, const pts_t &pts)
2175 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
2180 void eCueSheet::clear()
2187 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2189 ASSERT(begin < end);
2191 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2195 void eCueSheet::commitSpans()
2197 m_event(evtSpanChanged);
2200 void eCueSheet::setSkipmode(const pts_t &ratio)
2203 m_skipmode_ratio = ratio;
2205 m_event(evtSkipmode);
2208 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2210 m_decoding_demux = demux;
2211 m_decoder = decoder;
2214 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2216 connection = new eConnection(this, m_event.connect(event));