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);
1432 void eDVBChannel::cueSheetEvent(int event)
1434 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1439 case eCueSheet::evtSeek:
1441 flushPVR(m_cue->m_decoding_demux);
1443 case eCueSheet::evtSkipmode:
1446 m_cue->m_lock.WrLock();
1447 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1448 m_cue->m_lock.Unlock();
1449 eRdLocker l(m_cue->m_lock);
1450 if (m_cue->m_skipmode_ratio)
1452 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1453 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1454 /* i agree that this might look a bit like black magic. */
1455 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1456 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1457 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1458 m_skipmode_frames_remainder = 0;
1460 if (m_cue->m_skipmode_ratio < 0)
1461 m_skipmode_m -= m_skipmode_n;
1463 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1465 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1467 eWarning("something is wrong with this calculation");
1468 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1472 eDebug("skipmode ratio is 0, normal play");
1473 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1476 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1477 if (m_cue->m_skipmode_ratio != 0)
1478 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1480 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1481 eDebug("flush pvr");
1482 flushPVR(m_cue->m_decoding_demux);
1486 case eCueSheet::evtSpanChanged:
1488 m_source_span.clear();
1489 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1491 off_t offset_in, offset_out;
1492 pts_t pts_in = i->first, pts_out = i->second;
1493 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1495 eDebug("span translation failed.\n");
1498 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1499 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1506 /* align toward zero */
1507 static inline long long align(long long x, int align)
1522 /* align toward zero */
1523 static inline long long align_with_len(long long x, int align, size_t &len)
1540 /* remember, this gets called from another thread. */
1541 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1543 const int blocksize = 188;
1544 unsigned int max = align(10*1024*1024, blocksize);
1545 current_offset = align(current_offset, blocksize);
1549 eDebug("no cue sheet. forcing normal play");
1550 start = current_offset;
1557 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1558 max = align(m_skipmode_n, blocksize);
1561 eDebug("getNextSourceSpan, current offset is %08lld, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1562 int frame_skip_success = 0;
1566 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1567 eDebug("we are at %lld, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1569 off_t iframe_start = current_offset;
1570 int frames_skipped = frames_to_skip;
1571 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1573 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1574 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1575 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1576 max = align(iframe_len + 187, blocksize);
1577 frame_skip_success = 1;
1580 m_skipmode_frames_remainder = 0;
1581 eDebug("frame skipping failed, reverting to byte-skipping");
1585 if (!frame_skip_success)
1587 current_offset += align(m_skipmode_m, blocksize);
1588 if(current_offset < 0)
1594 eDebug("we are at %lld, and we try to find the iframe here:", current_offset);
1596 off_t start_offset = current_offset;
1597 off_t new_offset = start_offset;
1598 int direction = (m_skipmode_m < 0) ? -1 : +1;
1599 if (m_tstools.findFrame(start_offset, new_offset, iframe_len, direction))
1603 current_offset = align_with_len(new_offset, blocksize, iframe_len);
1604 max = align(iframe_len, blocksize);
1610 m_cue->m_lock.RdLock();
1612 while (!m_cue->m_seek_requests.empty())
1614 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1615 m_cue->m_lock.Unlock();
1616 m_cue->m_lock.WrLock();
1617 m_cue->m_seek_requests.pop_front();
1618 m_cue->m_lock.Unlock();
1619 m_cue->m_lock.RdLock();
1620 int relative = seek.first;
1621 pts_t pts = seek.second;
1626 if (!m_cue->m_decoder)
1628 eDebug("no decoder - can't seek relative");
1631 if (m_cue->m_decoder->getPTS(0, now))
1633 eDebug("decoder getPTS failed, can't seek relative");
1636 if (!m_cue->m_decoding_demux)
1638 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1639 start = current_offset;
1643 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1645 eDebug("seekTo: getCurrentPosition failed!");
1648 } else if (pts < 0) /* seek relative to end */
1651 if (!getLength(len))
1653 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1657 eWarning("getLength failed - can't seek relative to end!");
1662 if (relative == 1) /* pts relative */
1673 if (relative == 2) /* AP relative */
1675 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1677 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1679 pts = now - 90000; /* approx. 1s */
1680 eDebug("AP relative seeking failed!");
1684 eDebug("next ap is %llx\n", pts);
1689 if (m_tstools.getOffset(offset, pts, -1))
1691 eDebug("get offset for pts=%lld failed!", pts);
1695 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1696 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1699 m_cue->m_lock.Unlock();
1701 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1703 long long aligned_start = align(i->first, blocksize);
1704 long long aligned_end = align(i->second, blocksize);
1706 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1708 start = current_offset;
1709 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1710 if ((aligned_end - current_offset) > max)
1713 size = aligned_end - current_offset;
1714 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1717 if (current_offset < aligned_start)
1719 /* ok, our current offset is in an 'out' zone. */
1720 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1722 /* in normal playback, just start at the next zone. */
1725 /* size is not 64bit! */
1726 if ((i->second - i->first) > max)
1729 size = aligned_end - aligned_start;
1732 if (m_skipmode_m < 0)
1734 eDebug("reached SOF");
1737 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1741 /* when skipping reverse, however, choose the zone before. */
1743 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1746 aligned_start = align(i->first, blocksize);
1747 aligned_end = align(i->second, blocksize);
1749 if ((aligned_end - aligned_start) > max)
1752 len = aligned_end - aligned_start;
1754 start = aligned_end - len;
1755 eDebug("skipping to %llx, %zd", start, len);
1758 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1763 if(current_offset <0)
1765 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1767 eDebug("reached SOF");
1769 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1771 if (m_source_span.empty())
1773 start = current_offset;
1775 eDebug("NO CUESHEET. (%08lld, %zd)", start, size);
1778 start = current_offset;
1784 void eDVBChannel::AddUse()
1786 if (++m_use_count > 1 && m_state == state_last_instance)
1789 m_stateChanged(this);
1793 void eDVBChannel::ReleaseUse()
1797 m_state = state_release;
1798 m_stateChanged(this);
1800 else if (m_use_count == 1)
1802 m_state = state_last_instance;
1803 m_stateChanged(this);
1807 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1810 m_mgr->removeChannel(this);
1815 m_channel_id = channelid;
1816 m_mgr->addChannel(channelid, this);
1820 /* no frontend, no need to tune (must be a streamed service) */
1824 m_state = state_tuning;
1825 /* if tuning fails, shutdown the channel immediately. */
1827 res = m_frontend->get().tune(*feparm);
1828 m_current_frontend_parameters = feparm;
1832 m_state = state_release;
1833 m_stateChanged(this);
1840 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1842 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1846 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1848 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1852 RESULT eDVBChannel::getState(int &state)
1858 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1863 void eDVBChannel::SDTready(int result)
1865 ePyObject args = PyTuple_New(2), ret;
1869 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1872 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1873 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1879 PyTuple_SET_ITEM(args, 0, Py_None);
1880 PyTuple_SET_ITEM(args, 1, Py_None);
1884 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1888 Py_DECREF(m_tsid_onid_callback);
1889 m_tsid_onid_callback = ePyObject();
1890 m_tsid_onid_demux = 0;
1894 int eDVBChannel::reserveDemux()
1896 ePtr<iDVBDemux> dmx;
1897 if (!getDemux(dmx, 0))
1900 if (!dmx->getCADemuxID(id))
1906 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1908 if (PyCallable_Check(callback))
1910 if (!getDemux(m_tsid_onid_demux, 0))
1912 m_SDT = new eTable<ServiceDescriptionSection>;
1913 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1914 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1916 m_tsid_onid_demux = 0;
1921 Py_INCREF(callback);
1922 m_tsid_onid_callback = callback;
1930 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1932 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1934 if (m_frontend == NULL)
1936 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
1937 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
1944 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1949 /* don't hold a reference to the decoding demux, we don't need it. */
1951 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1952 the refcount is lost. thus, decoding demuxes are never allocated.
1954 this poses a big problem for PiP. */
1956 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1958 else if (cap & capDecode)
1967 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1972 frontend = &m_frontend->get();
1978 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1980 param = m_current_frontend_parameters;
1984 RESULT eDVBChannel::playFile(const char *file)
1986 eRawFile *f = new eRawFile();
1987 ePtr<iTsSource> source = f;
1989 if (f->open(file) < 0)
1991 eDebug("can't open PVR file %s (%m)", file);
1995 return playSource(source, file);
1998 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
2000 ASSERT(!m_frontend);
2003 m_pvr_thread->stop();
2004 delete m_pvr_thread;
2008 if (!source->valid() && !source->isStream())
2010 eDebug("PVR source is not valid!");
2014 m_tstools.setSource(source, streaminfo_file);
2016 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
2017 THEN DO A REAL FIX HERE! */
2019 if (m_pvr_fd_dst < 0)
2021 /* (this codepath needs to be improved anyway.) */
2022 #if HAVE_DVB_API_VERSION < 3
2023 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
2024 if (m_pvr_fd_dst < 0)
2026 eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2030 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
2033 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
2034 if (m_pvr_fd_dst < 0)
2036 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2042 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
2048 m_pvr_thread = new eDVBChannelFilePush();
2049 m_pvr_thread->enablePVRCommit(1);
2050 /* If the source specifies a length, it's a file. If not, it's a stream */
2051 m_pvr_thread->setStreamMode(source->isStream());
2052 m_pvr_thread->setScatterGather(this);
2054 m_event(this, evtPreStart);
2056 m_pvr_thread->start(source, m_pvr_fd_dst);
2057 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
2060 m_stateChanged(this);
2065 void eDVBChannel::stopSource()
2069 m_pvr_thread->stop();
2070 delete m_pvr_thread;
2073 if (m_pvr_fd_dst >= 0)
2074 ::close(m_pvr_fd_dst);
2076 m_tstools.setSource(d);
2079 void eDVBChannel::stopFile()
2084 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
2086 m_conn_cueSheetEvent = 0;
2089 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
2092 RESULT eDVBChannel::getLength(pts_t &len)
2094 return m_tstools.calcLen(len);
2097 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
2099 if (!decoding_demux)
2106 if (mode == 0) /* demux */
2108 r = decoding_demux->getSTC(now, 0);
2111 eDebug("demux getSTC failed");
2115 now = pos; /* fixup supplied */
2117 off_t off = 0; /* TODO: fixme */
2118 r = m_tstools.fixupPTS(off, now);
2121 eDebug("fixup PTS failed");
2130 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
2132 /* when seeking, we have to ensure that all buffers are flushed.
2133 there are basically 3 buffers:
2134 a.) the filepush's internal buffer
2135 b.) the PVR buffer (before demux)
2136 c.) the ratebuffer (after demux)
2138 it's important to clear them in the correct order, otherwise
2139 the ratebuffer (for example) would immediately refill from
2140 the not-yet-flushed PVR buffer.
2143 m_pvr_thread->pause();
2144 /* flush internal filepush buffer */
2145 m_pvr_thread->flush();
2146 /* HACK: flush PVR buffer */
2147 ::ioctl(m_pvr_fd_dst, 0);
2149 /* flush ratebuffers (video, audio) */
2151 decoding_demux->flush();
2153 /* demux will also flush all decoder.. */
2154 /* resume will re-query the SG */
2155 m_pvr_thread->resume();
2158 DEFINE_REF(eCueSheet);
2160 eCueSheet::eCueSheet()
2162 m_skipmode_ratio = 0;
2165 void eCueSheet::seekTo(int relative, const pts_t &pts)
2168 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
2173 void eCueSheet::clear()
2180 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2182 ASSERT(begin < end);
2184 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2188 void eCueSheet::commitSpans()
2190 m_event(evtSpanChanged);
2193 void eCueSheet::setSkipmode(const pts_t &ratio)
2196 m_skipmode_ratio = ratio;
2198 m_event(evtSkipmode);
2201 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2203 m_decoding_demux = demux;
2204 m_decoder = decoder;
2207 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2209 connection = new eConnection(this, m_event.connect(event));