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>
20 DEFINE_REF(eDVBRegisteredFrontend);
21 DEFINE_REF(eDVBRegisteredDemux);
23 DEFINE_REF(eDVBAllocatedFrontend);
25 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
30 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
33 if (m_fe->m_frontend->is_FBCTuner())
35 eFBCTunerManager* fbcmng = eFBCTunerManager::getInstance();
43 DEFINE_REF(eDVBAllocatedDemux);
45 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
50 eDVBAllocatedDemux::~eDVBAllocatedDemux()
55 DEFINE_REF(eDVBResourceManager);
57 eDVBResourceManager *eDVBResourceManager::instance;
59 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
69 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
71 ePtr<eDVBResourceManager> ptr;
72 eDVBResourceManager::getInstance(ptr);
76 eDVBResourceManager::eDVBResourceManager()
77 :m_releaseCachedChannelTimer(eTimer::create(eApp))
81 m_sec = new eDVBSatelliteEquipmentControl(m_frontend, m_simulate_frontend);
86 /* search available adapters... */
91 while (eDVBAdapterLinux::exist(num_adapter))
93 addAdapter(new eDVBAdapterLinux(num_adapter));
99 int fd = open("/proc/stb/info/model", O_RDONLY);
101 int rd = fd >= 0 ? read(fd, tmp, 255) : 0;
105 if (!strncmp(tmp, "dm7025\n", rd))
107 else if (!strncmp(tmp, "dm8000\n", rd))
109 else if (!strncmp(tmp, "dm800\n", rd))
111 else if (!strncmp(tmp, "dm500hd\n", rd))
113 else if (!strncmp(tmp, "dm800se\n", rd))
115 else if (!strncmp(tmp, "dm7020hd\n", rd))
116 m_boxtype = DM7020HD;
118 eDebug("boxtype detection via /proc/stb/info not possible... use fallback via demux count!\n");
119 if (m_demux.size() == 3)
121 else if (m_demux.size() < 5)
127 eDebug("found %zd adapter, %zd frontends(%zd sim) and %zd demux, boxtype %d",
128 m_adapter.size(), m_frontend.size(), m_simulate_frontend.size(), m_demux.size(), m_boxtype);
130 eDVBCAService::registerChannelCallback(this);
132 m_fbc_mng = new eFBCTunerManager(this);
134 CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
137 void eDVBResourceManager::feStateChanged()
140 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
142 mask |= ( 1 << i->m_frontend->getSlotID() );
143 /* emit */ frontendUseMaskChanged(mask);
146 DEFINE_REF(eDVBAdapterLinux);
147 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
152 eDebug("scanning for frontends..");
157 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
158 if (stat(filename, &s))
164 fe = new eDVBFrontend(m_nr, num_fe, ok, true);
166 m_simulate_frontend.push_back(ePtr<eDVBFrontend>(fe));
171 fe = new eDVBFrontend(m_nr, num_fe, ok, false, fe);
173 m_frontend.push_back(ePtr<eDVBFrontend>(fe));
184 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
185 if (stat(filename, &s))
187 ePtr<eDVBDemux> demux;
189 demux = new eDVBDemux(m_nr, num_demux);
190 m_demux.push_back(demux);
196 int eDVBAdapterLinux::getNumDemux()
198 return m_demux.size();
201 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
203 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
204 while (nr && (i != m_demux.end()))
210 if (i != m_demux.end())
218 int eDVBAdapterLinux::getNumFrontends()
220 return m_frontend.size();
223 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr, bool simulate)
225 eSmartPtrList<eDVBFrontend>::iterator i(simulate ? m_simulate_frontend.begin() : m_frontend.begin());
226 while (nr && (i != m_frontend.end()))
232 if (i != m_frontend.end())
240 int eDVBAdapterLinux::exist(int nr)
244 sprintf(filename, "/dev/dvb/adapter%d", nr);
245 if (!stat(filename, &s))
250 eDVBResourceManager::~eDVBResourceManager()
252 if (instance == this)
256 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
258 int num_fe = adapter->getNumFrontends();
259 int num_demux = adapter->getNumDemux();
261 m_adapter.push_back(adapter);
264 for (i=0; i<num_demux; ++i)
266 ePtr<eDVBDemux> demux;
267 if (!adapter->getDemux(demux, i))
268 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
271 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
272 for (i=0; i<num_fe; ++i)
274 ePtr<eDVBFrontend> frontend;
275 if (!adapter->getFrontend(frontend, i))
277 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
278 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
279 m_frontend.push_back(new_fe);
280 frontend->setSEC(m_sec);
281 // we must link all dvb-t frontends ( for active antenna voltage )
282 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
284 if (prev_dvbt_frontend)
286 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
287 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
289 prev_dvbt_frontend = new_fe;
294 prev_dvbt_frontend = 0;
295 for (i=0; i<num_fe; ++i)
297 ePtr<eDVBFrontend> frontend;
298 if (!adapter->getFrontend(frontend, i, true))
300 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
301 // CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
302 m_simulate_frontend.push_back(new_fe);
303 frontend->setSEC(m_sec);
304 // we must link all dvb-t frontends ( for active antenna voltage )
305 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
307 if (prev_dvbt_frontend)
309 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
310 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
312 prev_dvbt_frontend = new_fe;
319 void eDVBResourceManager::setUsbTuner()
321 std::ifstream in("/proc/bus/nim_sockets");
326 int usbtuner_idx[8] = {0};
327 int usbtuner_count = 0;
334 if ((res = sscanf(line.c_str(), "NIM Socket %d:", &fe_idx)) == 1)
337 if ((fe_idx != -1) && (line.find("\tName: ") == 0) && (line.find("VTUNER") != -1))
338 usbtuner_idx[usbtuner_count++] = fe_idx;
345 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_frontend.begin()); it != m_frontend.end(); ++it)
347 int slotid = it->m_frontend->getSlotID();
348 for (int i=0; i < usbtuner_count ; i++)
350 if (slotid == usbtuner_idx[i])
352 it->m_frontend->setUSBTuner(true);
357 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_simulate_frontend.begin()); it != m_simulate_frontend.end(); ++it)
359 int slotid = it->m_frontend->getSlotID();
360 for (int i=0; i < usbtuner_count ; i++)
362 if (slotid == usbtuner_idx[i])
364 it->m_frontend->setUSBTuner(true);
372 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
374 if (!PyList_Check(list))
376 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
379 unsigned int assigned=0;
380 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
383 while (pos < PyList_Size(list)) {
384 ePyObject obj = PyList_GET_ITEM(list, pos++);
385 if (!i->m_frontend->setSlotInfo(obj))
391 if (assigned != m_frontend.size()) {
393 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %zd socket informations, but %d registered frontends!",
394 m_frontend.size(), assigned);
395 PyErr_SetString(PyExc_StandardError, blasel);
398 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
401 while (pos < PyList_Size(list)) {
402 ePyObject obj = PyList_GET_ITEM(list, pos++);
403 if (!i->m_frontend->setSlotInfo(obj))
411 bool eDVBResourceManager::frontendIsCompatible(int index, const char *type)
413 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
415 if (i->m_frontend->getSlotID() == index)
417 if (!strcmp(type, "DVB-S2X"))
419 return i->m_frontend->supportsDeliverySystem(SYS_DVBS2X, false);
421 if (!strcmp(type, "DVB-S2"))
423 return i->m_frontend->supportsDeliverySystem(SYS_DVBS2, false);
425 else if (!strcmp(type, "DVB-S"))
427 return i->m_frontend->supportsDeliverySystem(SYS_DVBS, false);
429 else if (!strcmp(type, "DVB-T2"))
431 return i->m_frontend->supportsDeliverySystem(SYS_DVBT2, false);
433 else if (!strcmp(type, "DVB-T"))
435 return i->m_frontend->supportsDeliverySystem(SYS_DVBT, false);
437 else if (!strcmp(type, "DVB-C"))
439 #if defined SYS_DVBC_ANNEX_A
440 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_A, false);
442 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_AC, false);
450 bool eDVBResourceManager::frontendIsMultistream(int index)
452 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
454 if (i->m_frontend->getSlotID() == index)
456 return i->m_frontend->is_multistream();
462 void eDVBResourceManager::setFrontendType(int index, const char *type)
464 eDebug("[eDVBResourceManager::setFrontendType] index : %d, type : %s", index, type);
466 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
468 if (i->m_frontend->getSlotID() == index)
470 std::vector<fe_delivery_system_t> whitelist;
471 if (!strcmp(type, "DVB-S2") || !strcmp(type, "DVB-S"))
473 whitelist.push_back(SYS_DVBS);
474 whitelist.push_back(SYS_DVBS2);
475 if (!strcmp(type, "DVB-S2X"))
476 whitelist.push_back(SYS_DVBS2X);
478 else if (!strcmp(type, "DVB-T2") || !strcmp(type, "DVB-T"))
480 whitelist.push_back(SYS_DVBT);
481 whitelist.push_back(SYS_DVBT2);
483 else if (!strcmp(type, "DVB-C"))
485 #if defined SYS_DVBC_ANNEX_A
486 whitelist.push_back(SYS_DVBC_ANNEX_A);
488 whitelist.push_back(SYS_DVBC_ANNEX_AC);
491 i->m_frontend->setDeliverySystemWhitelist(whitelist);
497 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
499 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
500 eDVBRegisteredFrontend *best = NULL;
504 int check_fbc_leaf_linkable = 0;
505 int current_fbc_setid = -1;
506 eDVBRegisteredFrontend *fbc_fe = NULL;
507 eDVBRegisteredFrontend *best_fbc_fe = NULL;
509 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
513 if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
515 int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
516 if (fbc_setid != current_fbc_setid)
518 current_fbc_setid = fbc_setid;
519 check_fbc_leaf_linkable = 0;
522 if (!check_fbc_leaf_linkable)
524 c = m_fbc_mng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
525 check_fbc_leaf_linkable = 1;
526 eDebug("[eDVBResourceManager::allocateFrontend] m_fbc_mng->isCompatibleWith slotid : %p (%d), fbc_fe : %p (%d), score : %d", (eDVBRegisteredFrontend *)*i, i->m_frontend->getSlotID(), fbc_fe, fbc_fe?fbc_fe->m_frontend->getSlotID():-1, c);
531 c = i->m_frontend->isCompatibleWith(feparm);
534 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
539 eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
544 best_fbc_fe = fbc_fe;
549 eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
552 eDVBRegisteredFrontend *tmp = *i;
559 m_fbc_mng->addLink(best, best_fbc_fe, simulate);
562 fe = new eDVBAllocatedFrontend(best);
569 return errAllSourcesBusy;
571 return errNoSourceFound;
574 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
576 int err = errNoSourceFound;
577 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
578 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
580 // check if another slot linked to this is in use
582 i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
585 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
586 if (satpos_depends_to_fe->m_inuse)
588 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
589 err = errAllSourcesBusy;
590 goto alloc_fe_by_id_not_possible;
593 else // check linked tuners
595 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
598 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
601 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
602 err = errAllSourcesBusy;
603 goto alloc_fe_by_id_not_possible;
605 next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
607 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
610 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
613 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
614 err = errAllSourcesBusy;
615 goto alloc_fe_by_id_not_possible;
617 prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
620 fe = new eDVBAllocatedFrontend(i);
623 alloc_fe_by_id_not_possible:
628 #define capHoldDecodeReference 64
630 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int &cap)
632 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
633 never use the first one unless we need a decoding demux. */
635 eDebug("allocate demux");
636 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
640 if (i == m_demux.end())
643 ePtr<eDVBRegisteredDemux> unused;
645 if (m_boxtype == DM800) // dm800
647 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
648 for (; i != m_demux.end(); ++i, ++n)
659 if (i->m_adapter == fe->m_adapter &&
660 i->m_demux->getSource() == fe->m_frontend->getDVBID())
662 demux = new eDVBAllocatedDemux(i);
666 else if (i->m_demux->getSource() == -1) // PVR
668 demux = new eDVBAllocatedDemux(i);
674 else if (m_boxtype == DM7025) // ATI
676 /* FIXME: hardware demux policy */
677 if (!(cap & iDVBChannel::capDecode))
679 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
686 for (; i != m_demux.end(); ++i, ++n)
688 int is_decode = n < 2;
690 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
692 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
694 if ((cap & iDVBChannel::capDecode) && !is_decode)
701 else if (m_boxtype == DM8000 || m_boxtype == DM500HD || m_boxtype == DM800SE || m_boxtype == DM7020HD)
703 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 */
704 int source = fe ? fe->m_frontend->getDVBID() : -1;
705 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
709 * For pvr playback, start with the last demux.
710 * On some hardware, we have less ca devices than demuxes,
711 * so we should try to leave the first demuxes for live tv,
712 * and start with the last for pvr playback
717 while (i != m_demux.end())
719 if (i->m_adapter == adapter)
723 /* mark the first unused demux, we'll use that when we do not find a better match */
724 if (!unused) unused = i;
728 /* demux is in use, see if we can share it */
729 if (source >= 0 && i->m_demux->getSource() == source)
731 demux = new eDVBAllocatedDemux(i);
749 demux = new eDVBAllocatedDemux(unused);
751 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
753 demux->get().setSourcePVR(0);
757 eDebug("demux not found");
761 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
767 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
776 #define eDebugNoSimulate(x...) \
782 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
784 /* first, check if a channel is already existing. */
785 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
787 if (!simulate && m_cached_channel)
789 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
790 if(channelid==cache_chan->getChannelID())
792 eDebug("use cached_channel");
793 channel = m_cached_channel;
796 m_cached_channel_state_changed_conn.disconnect();
798 m_releaseCachedChannelTimer->stop();
801 eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
802 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
804 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
805 if (i->m_channel_id == channelid)
807 eDebugNoSimulate("found shared channel..");
808 channel = i->m_channel;
813 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
817 eDebugNoSimulate("no channel list set!");
818 return errNoChannelList;
821 ePtr<iDVBFrontendParameters> feparm;
822 if (m_list->getChannelFrontendData(channelid, feparm))
824 eDebugNoSimulate("channel not found!");
825 return errChannelNotInList;
828 /* allocate a frontend. */
830 ePtr<eDVBAllocatedFrontend> fe;
832 int err = allocateFrontend(fe, feparm, simulate);
837 ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
839 res = ch->setChannel(channelid, feparm);
843 return errChidNotFound;
850 m_cached_channel = channel = ch;
851 m_cached_channel_state_changed_conn =
852 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
858 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
861 chan->getState(state);
864 case iDVBChannel::state_release:
865 case iDVBChannel::state_ok:
867 eDebug("stop release channel timer");
868 m_releaseCachedChannelTimer->stop();
871 case iDVBChannel::state_last_instance:
873 eDebug("start release channel timer");
874 m_releaseCachedChannelTimer->start(3000, true);
877 default: // ignore all other events
882 void eDVBResourceManager::releaseCachedChannel()
884 eDebug("release cached channel (timer timeout)");
888 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
890 ePtr<eDVBAllocatedFrontend> fe;
892 if (m_cached_channel)
894 m_cached_channel_state_changed_conn.disconnect();
896 m_releaseCachedChannelTimer->stop();
899 int err = allocateFrontendByIndex(fe, slot_index);
903 channel = new eDVBChannel(this, fe);
907 RESULT eDVBResourceManager::allocatePVRChannel(const eDVBChannelID &channelid, eUsePtr<iDVBPVRChannel> &channel)
909 ePtr<eDVBAllocatedDemux> demux;
911 if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
913 m_cached_channel_state_changed_conn.disconnect();
915 m_releaseCachedChannelTimer->stop();
918 ePtr<eDVBChannel> ch = new eDVBChannel(this, 0);
922 * user provided a channelid, with the clear intention for
923 * this channel to be registered at the resource manager.
924 * (allowing e.g. epgcache to be started)
926 ePtr<iDVBFrontendParameters> feparm;
927 ch->setChannel(channelid, feparm);
933 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
935 ePtr<iDVBFrontend> fe;
936 if (!ch->getFrontend(fe))
938 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
939 if (frontend->is_simulate())
940 m_active_simulate_channels.push_back(active_channel(chid, ch));
943 m_active_channels.push_back(active_channel(chid, ch));
944 /* emit */ m_channelAdded(ch);
950 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
952 ePtr<iDVBFrontend> fe;
953 if (!ch->getFrontend(fe))
955 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
956 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
958 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
960 if (i->m_channel == ch)
962 i = active_channels.erase(i);
974 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
976 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
980 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
982 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
983 ePtr<eDVBRegisteredFrontend> best;
985 int check_fbc_leaf_linkable = 0;
986 int current_fbc_setid = -1;
988 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
993 if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
995 int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
996 if (fbc_setid != current_fbc_setid)
998 current_fbc_setid = fbc_setid;
999 check_fbc_leaf_linkable = 0;
1002 if (!check_fbc_leaf_linkable)
1004 eDVBRegisteredFrontend *dummy;
1005 c = m_fbc_mng->isCompatibleWith(feparm, *i, dummy, simulate);
1006 check_fbc_leaf_linkable = 1;
1011 c = i->m_frontend->isCompatibleWith(feparm);
1020 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid, int &system)
1022 system = iDVBFrontend::feSatellite;
1025 ePtr<iDVBFrontendParameters> feparm;
1026 if (!channellist->getChannelFrontendData(chid, feparm))
1028 if (!feparm->getSystem(system))
1032 case iDVBFrontend::feSatellite:
1034 case iDVBFrontend::feCable:
1036 case iDVBFrontend::feTerrestrial:
1047 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, int &system, bool simulate)
1049 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
1051 system = iDVBFrontend::feSatellite;
1052 if (!simulate && m_cached_channel)
1054 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
1055 if(channelid==cache_chan->getChannelID())
1056 return tuner_type_channel_default(m_list, channelid, system);
1059 /* first, check if a channel is already existing. */
1060 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
1061 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
1063 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
1064 if (i->m_channel_id == channelid)
1066 // eDebug("found shared channel..");
1067 return tuner_type_channel_default(m_list, channelid, system);
1071 int *decremented_cached_channel_fe_usecount=NULL,
1072 *decremented_fe_usecount=NULL;
1074 /* check FCC channels */
1075 std::vector<int*> fcc_decremented_fe_usecounts;
1076 std::map<eDVBChannelID, int> fcc_chids;
1077 int apply_to_ignore = 0;
1078 if (!eFCCServiceManager::getFCCChannelID(fcc_chids))
1080 for (std::map<eDVBChannelID, int>::iterator i(fcc_chids.begin()); i != fcc_chids.end(); ++i)
1082 //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());
1083 if (ignore == i->first)
1085 apply_to_ignore = i->second;
1088 for (std::list<active_channel>::iterator ii(active_channels.begin()); ii != active_channels.end(); ++ii)
1090 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1091 if (ii->m_channel_id == i->first)
1093 eDVBChannel *channel = (eDVBChannel*) &(*ii->m_channel);
1095 int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1096 check_usecount += i->second * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1097 //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1098 if (channel->getUseCount() == check_usecount)
1100 ePtr<iDVBFrontend> fe;
1101 if (!ii->m_channel->getFrontend(fe))
1103 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator iii(frontends.begin()); iii != frontends.end(); ++iii)
1105 if ( &(*fe) == &(*iii->m_frontend) )
1107 //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : decrease fcc fe use_count! feid : %d (%d -> %d)", iii->m_frontend->getSlotID(), iii->m_inuse, iii->m_inuse-1);
1109 int *tmp_decremented_fe_usecount = &iii->m_inuse;
1110 fcc_decremented_fe_usecounts.push_back(tmp_decremented_fe_usecount);
1111 if (channel == &(*m_cached_channel))
1112 decremented_cached_channel_fe_usecount = tmp_decremented_fe_usecount;
1124 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
1126 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1127 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
1128 if (i->m_channel_id == ignore)
1130 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
1131 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
1132 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
1133 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
1134 // or 2 when the cached channel is not equal to the compared channel
1135 int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1136 check_usecount += (apply_to_ignore+1) * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1137 //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1138 if (channel->getUseCount() == check_usecount) // channel only used once..(except fcc)
1140 ePtr<iDVBFrontend> fe;
1141 if (!i->m_channel->getFrontend(fe))
1143 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1145 if ( &(*fe) == &(*ii->m_frontend) )
1147 //eDebug("[eDVBResourceManager::canAllocateChannel] ignore : decrease fcc fe use_count! feid : %d (%d -> %d)", ii->m_frontend->getSlotID(), ii->m_inuse, ii->m_inuse-1);
1149 decremented_fe_usecount = &ii->m_inuse;
1150 if (channel == &(*m_cached_channel))
1151 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
1161 if (!decremented_cached_channel_fe_usecount)
1163 if (m_cached_channel)
1165 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
1166 if (channel->getUseCount() == 1)
1168 ePtr<iDVBFrontend> fe;
1169 if (!channel->getFrontend(fe))
1171 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1172 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1174 if ( &(*fe) == &(*ii->m_frontend) )
1177 decremented_cached_channel_fe_usecount = &ii->m_inuse;
1186 decremented_cached_channel_fe_usecount=NULL;
1188 ePtr<iDVBFrontendParameters> feparm;
1192 eDebug("no channel list set!");
1196 if (m_list->getChannelFrontendData(channelid, feparm))
1198 eDebug("channel not found!");
1201 feparm->getSystem(system);
1203 ret = canAllocateFrontend(feparm, simulate);
1206 if (decremented_fe_usecount)
1207 ++(*decremented_fe_usecount);
1208 if (decremented_cached_channel_fe_usecount)
1209 ++(*decremented_cached_channel_fe_usecount);
1210 if (fcc_decremented_fe_usecounts.size())
1212 for (std::vector<int*>::iterator i(fcc_decremented_fe_usecounts.begin()); i != fcc_decremented_fe_usecounts.end(); ++i)
1214 //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : increase fcc fe use_count!");
1222 bool eDVBResourceManager::canMeasureFrontendInputPower()
1224 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
1226 return i->m_frontend->readInputpower() >= 0;
1231 class eDVBChannelFilePush: public eFilePushThread
1234 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
1235 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
1237 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
1238 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
1239 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
1241 int m_iframe_search, m_iframe_state, m_pid;
1242 int m_timebase_change;
1243 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
1246 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
1249 if (m_timebase_change)
1251 eDebug("timebase change: %d", m_timebase_change);
1253 for (offset = 0; offset < len; offset += 188)
1255 unsigned char *pkt = (unsigned char*)_data + offset;
1256 if (pkt[1] & 0x40) /* pusi */
1258 if (pkt[3] & 0x20) // adaption field present?
1259 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
1261 pkt += 4; /* skip header */
1262 if (pkt[0] || pkt[1] || (pkt[2] != 1))
1264 eWarning("broken startcode");
1270 if (pkt[7] & 0x80) // PTS present?
1272 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
1273 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
1274 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
1275 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
1276 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
1280 RESULT r = m_tstools.fixupPTS(off, pts);
1282 eWarning("fixup PTS while trickmode playback failed.\n");
1285 int sec = pts / 90000;
1286 int frm = pts % 90000;
1294 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1296 pts += 0x80000000LL;
1297 pts *= m_timebase_change;
1309 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1317 pkt[9] |= (pts >> 29) & 0xE;
1318 pkt[10] |= (pts >> 22) & 0xFF;
1319 pkt[11] |= (pts >> 14) & 0xFE;
1320 pkt[12] |= (pts >> 7) & 0xFF;
1321 pkt[13] |= (pts << 1) & 0xFE;
1329 if (!m_iframe_search)
1332 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1334 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1336 unsigned char *d = data;
1337 while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1339 int offset = d - data;
1340 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1341 unsigned char *ts = data + ts_offset;
1342 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1344 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */
1346 int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1349 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1351 if (m_iframe_state == 1)
1353 /* we are allowing data, and stop allowing data on the next frame.
1354 we now found a frame. so stop here. */
1355 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1356 current_span_remaining = 0;
1358 unsigned char *fts = ts + 188;
1359 while (fts < (data + len))
1362 fts[2] |= 0xff; /* drop packet */
1366 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1369 if (picture_type != 1) /* we are only interested in I frames */
1372 unsigned char *fts = data;
1376 fts[2] |= 0xff; /* drop packet */
1383 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1385 /* verify that this is actually a PES header, not just some ES data */
1386 if (ts[1] & 0x40) /* PUSI set */
1388 int payload_start = 4;
1389 if (ts[3] & 0x20) /* adaptation field present */
1390 payload_start += ts[4] + 1; /* skip AF */
1391 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1395 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1403 d += 4; /* ignore */
1406 if (m_iframe_state == 1)
1409 return 0; /* we need find an iframe first */
1415 DEFINE_REF(eDVBChannel);
1417 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1419 m_frontend = frontend;
1424 m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1427 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1430 eDVBChannel::~eDVBChannel()
1433 m_mgr->removeChannel(this);
1438 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1440 int state, ourstate = 0;
1442 /* if we are already in shutdown, don't change state. */
1443 if (m_state == state_release)
1446 if (fe->getState(state))
1449 if (state == iDVBFrontend::stateLock)
1451 eDebug("OURSTATE: ok");
1452 ourstate = state_ok;
1453 } else if (state == iDVBFrontend::stateTuning)
1455 eDebug("OURSTATE: tuning");
1456 ourstate = state_tuning;
1457 } else if (state == iDVBFrontend::stateLostLock)
1459 /* on managed channels, we try to retune in order to re-acquire lock. */
1460 if (m_current_frontend_parameters)
1462 eDebug("OURSTATE: lost lock, trying to retune");
1463 ourstate = state_tuning;
1464 m_frontend->get().tune(*m_current_frontend_parameters);
1466 /* on unmanaged channels, we don't do this. the client will do this. */
1468 eDebug("OURSTATE: lost lock, unavailable now.");
1469 ourstate = state_unavailable;
1471 } else if (state == iDVBFrontend::stateFailed)
1474 if (m_current_frontend_parameters)
1476 eDebug("OURSTATE: lost lock, trying to retune");
1477 ourstate = state_tuning;
1478 m_frontend->get().tune(*m_current_frontend_parameters);
1482 eDebug("OURSTATE: failed");
1483 ourstate = state_failed;
1486 eDebug("OURSTATE: failed");
1487 ourstate = state_failed;
1490 eFatal("state unknown");
1492 if (ourstate != m_state)
1495 m_stateChanged(this);
1499 void eDVBChannel::pvrEvent(int event)
1503 case eFilePushThread::evtEOF:
1504 eDebug("eDVBChannel: End of file!");
1505 m_event(this, evtEOF);
1507 case eFilePushThread::evtUser: /* start */
1509 m_event(this, evtSOF);
1511 case eFilePushThread::evtUser+3: /* limit space */
1512 eDebug("Too large file");
1513 m_event(this, evtFailed+3);
1518 void eDVBChannel::cueSheetEvent(int event)
1520 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1525 case eCueSheet::evtSeek:
1527 flushPVR(m_cue->m_decoding_demux);
1529 case eCueSheet::evtSkipmode:
1532 m_cue->m_lock.WrLock();
1533 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1534 m_cue->m_lock.Unlock();
1535 eRdLocker l(m_cue->m_lock);
1536 if (m_cue->m_skipmode_ratio)
1538 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1539 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1540 /* i agree that this might look a bit like black magic. */
1541 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1542 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1543 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1544 m_skipmode_frames_remainder = 0;
1546 if (m_cue->m_skipmode_ratio < 0)
1547 m_skipmode_m -= m_skipmode_n;
1549 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1551 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1553 eWarning("something is wrong with this calculation");
1554 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1558 eDebug("skipmode ratio is 0, normal play");
1559 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1562 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1563 if (m_cue->m_skipmode_ratio != 0)
1564 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1566 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1567 eDebug("flush pvr");
1568 flushPVR(m_cue->m_decoding_demux);
1572 case eCueSheet::evtSpanChanged:
1574 m_source_span.clear();
1575 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1577 off_t offset_in, offset_out;
1578 pts_t pts_in = i->first, pts_out = i->second;
1579 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1581 eDebug("span translation failed.\n");
1584 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1585 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1592 /* align toward zero */
1593 static inline long long align(long long x, int align)
1608 /* align toward zero */
1609 static inline long long align_with_len(long long x, int align, size_t &len)
1626 /* remember, this gets called from another thread. */
1627 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1629 const int blocksize = 188;
1630 unsigned int max = align(10*1024*1024, blocksize);
1631 current_offset = align(current_offset, blocksize);
1635 eDebug("no cue sheet. forcing normal play");
1636 start = current_offset;
1643 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1644 max = align(m_skipmode_n, blocksize);
1647 eDebug("getNextSourceSpan, current offset is %08lld, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1648 int frame_skip_success = 0;
1652 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1653 eDebug("we are at %lld, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1655 off_t iframe_start = current_offset;
1656 int frames_skipped = frames_to_skip;
1657 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1659 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1660 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1661 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1662 max = align(iframe_len + 187, blocksize);
1663 frame_skip_success = 1;
1666 m_skipmode_frames_remainder = 0;
1667 eDebug("frame skipping failed, reverting to byte-skipping");
1671 if (!frame_skip_success)
1673 current_offset += align(m_skipmode_m, blocksize);
1674 if(current_offset < 0)
1680 eDebug("we are at %lld, and we try to find the iframe here:", current_offset);
1682 off_t start_offset = current_offset;
1683 off_t new_offset = start_offset;
1684 int direction = (m_skipmode_m < 0) ? -1 : +1;
1685 if (m_tstools.findFrame(start_offset, new_offset, iframe_len, direction))
1689 current_offset = align_with_len(new_offset, blocksize, iframe_len);
1690 max = align(iframe_len, blocksize);
1696 m_cue->m_lock.RdLock();
1698 while (!m_cue->m_seek_requests.empty())
1700 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1701 m_cue->m_lock.Unlock();
1702 m_cue->m_lock.WrLock();
1703 m_cue->m_seek_requests.pop_front();
1704 m_cue->m_lock.Unlock();
1705 m_cue->m_lock.RdLock();
1706 int relative = seek.first;
1707 pts_t pts = seek.second;
1712 if (!m_cue->m_decoder)
1714 eDebug("no decoder - can't seek relative");
1717 if (m_cue->m_decoder->getPTS(0, now))
1719 eDebug("decoder getPTS failed, can't seek relative");
1722 if (!m_cue->m_decoding_demux)
1724 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1725 start = current_offset;
1729 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1731 eDebug("seekTo: getCurrentPosition failed!");
1734 } else if (pts < 0) /* seek relative to end */
1737 if (!getLength(len))
1739 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1743 eWarning("getLength failed - can't seek relative to end!");
1748 if (relative == 1) /* pts relative */
1759 if (relative == 2) /* AP relative */
1761 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1763 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1765 pts = now - 90000; /* approx. 1s */
1766 eDebug("AP relative seeking failed!");
1770 eDebug("next ap is %llx\n", pts);
1775 if (m_tstools.getOffset(offset, pts, -1))
1777 eDebug("get offset for pts=%lld failed!", pts);
1781 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1782 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1785 m_cue->m_lock.Unlock();
1787 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1789 long long aligned_start = align(i->first, blocksize);
1790 long long aligned_end = align(i->second, blocksize);
1792 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1794 start = current_offset;
1795 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1796 if ((aligned_end - current_offset) > max)
1799 size = aligned_end - current_offset;
1800 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1803 if (current_offset < aligned_start)
1805 /* ok, our current offset is in an 'out' zone. */
1806 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1808 /* in normal playback, just start at the next zone. */
1811 /* size is not 64bit! */
1812 if ((i->second - i->first) > max)
1815 size = aligned_end - aligned_start;
1818 if (m_skipmode_m < 0)
1820 eDebug("reached SOF");
1823 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1827 /* when skipping reverse, however, choose the zone before. */
1829 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1832 aligned_start = align(i->first, blocksize);
1833 aligned_end = align(i->second, blocksize);
1835 if ((aligned_end - aligned_start) > max)
1838 len = aligned_end - aligned_start;
1840 start = aligned_end - len;
1841 eDebug("skipping to %llx, %zd", start, len);
1844 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1849 if(current_offset <0)
1851 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1853 eDebug("reached SOF");
1855 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1857 if (m_source_span.empty())
1859 start = current_offset;
1861 eDebug("NO CUESHEET. (%08lld, %zd)", start, size);
1864 start = current_offset;
1870 void eDVBChannel::AddUse()
1872 if (++m_use_count > 1 && m_state == state_last_instance)
1875 m_stateChanged(this);
1879 void eDVBChannel::ReleaseUse()
1883 m_state = state_release;
1884 m_stateChanged(this);
1886 else if (m_use_count == 1)
1888 m_state = state_last_instance;
1889 m_stateChanged(this);
1893 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1896 m_mgr->removeChannel(this);
1901 m_channel_id = channelid;
1902 m_mgr->addChannel(channelid, this);
1906 /* no frontend, no need to tune (must be a streamed service) */
1910 m_state = state_tuning;
1911 /* if tuning fails, shutdown the channel immediately. */
1913 res = m_frontend->get().tune(*feparm);
1914 m_current_frontend_parameters = feparm;
1918 m_state = state_release;
1919 m_stateChanged(this);
1926 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1928 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1932 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1934 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1938 RESULT eDVBChannel::getState(int &state)
1944 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1949 void eDVBChannel::SDTready(int result)
1951 ePyObject args = PyTuple_New(2), ret;
1955 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1958 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1959 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1965 PyTuple_SET_ITEM(args, 0, Py_None);
1966 PyTuple_SET_ITEM(args, 1, Py_None);
1970 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1974 Py_DECREF(m_tsid_onid_callback);
1975 m_tsid_onid_callback = ePyObject();
1976 m_tsid_onid_demux = 0;
1980 int eDVBChannel::reserveDemux()
1982 ePtr<iDVBDemux> dmx;
1983 if (!getDemux(dmx, 0))
1986 if (!dmx->getCADemuxID(id))
1992 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1994 if (PyCallable_Check(callback))
1996 if (!getDemux(m_tsid_onid_demux, 0))
1998 m_SDT = new eTable<ServiceDescriptionSection>;
1999 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
2000 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
2002 m_tsid_onid_demux = 0;
2007 Py_INCREF(callback);
2008 m_tsid_onid_callback = callback;
2016 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
2018 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
2020 if (m_frontend == NULL)
2022 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
2023 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
2030 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
2035 /* don't hold a reference to the decoding demux, we don't need it. */
2037 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
2038 the refcount is lost. thus, decoding demuxes are never allocated.
2040 this poses a big problem for PiP. */
2042 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
2044 else if (cap & capDecode)
2053 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
2058 frontend = &m_frontend->get();
2064 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
2066 param = m_current_frontend_parameters;
2070 RESULT eDVBChannel::playFile(const char *file)
2072 eRawFile *f = new eRawFile();
2073 ePtr<iTsSource> source = f;
2075 if (f->open(file) < 0)
2077 eDebug("can't open PVR file %s (%m)", file);
2081 return playSource(source, file);
2084 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
2086 ASSERT(!m_frontend);
2089 m_pvr_thread->stop();
2090 delete m_pvr_thread;
2094 if (!source->valid() && !source->isStream())
2096 eDebug("PVR source is not valid!");
2101 m_tstools.setSource(m_source, streaminfo_file);
2103 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
2104 THEN DO A REAL FIX HERE! */
2106 if (m_pvr_fd_dst < 0)
2108 /* (this codepath needs to be improved anyway.) */
2109 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
2112 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
2113 if (m_pvr_fd_dst < 0)
2115 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2121 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
2126 m_pvr_thread = new eDVBChannelFilePush();
2127 m_pvr_thread->enablePVRCommit(1);
2128 /* If the source specifies a length, it's a file. If not, it's a stream */
2129 m_pvr_thread->setStreamMode(m_source->isStream());
2130 m_pvr_thread->setScatterGather(this);
2132 m_event(this, evtPreStart);
2134 m_pvr_thread->start(m_source, m_pvr_fd_dst);
2135 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
2138 m_stateChanged(this);
2143 void eDVBChannel::stopSource()
2147 m_pvr_thread->stop();
2148 delete m_pvr_thread;
2151 if (m_pvr_fd_dst >= 0)
2153 ::close(m_pvr_fd_dst);
2158 m_tstools.setSource(m_source);
2161 void eDVBChannel::stopFile()
2166 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
2168 m_conn_cueSheetEvent = 0;
2171 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
2174 RESULT eDVBChannel::getLength(pts_t &len)
2176 return m_tstools.calcLen(len);
2179 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
2181 if (!decoding_demux)
2188 if (mode == 0) /* demux */
2190 r = decoding_demux->getSTC(now, 0);
2193 eDebug("demux getSTC failed");
2197 now = pos; /* fixup supplied */
2199 r = m_tstools.fixupPTS(m_source ? m_source->offset() : 0, now);
2202 eDebug("fixup PTS failed");
2211 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
2213 /* when seeking, we have to ensure that all buffers are flushed.
2214 there are basically 3 buffers:
2215 a.) the filepush's internal buffer
2216 b.) the PVR buffer (before demux)
2217 c.) the ratebuffer (after demux)
2219 it's important to clear them in the correct order, otherwise
2220 the ratebuffer (for example) would immediately refill from
2221 the not-yet-flushed PVR buffer.
2224 m_pvr_thread->pause();
2225 /* flush internal filepush buffer */
2226 m_pvr_thread->flush();
2227 /* HACK: flush PVR buffer */
2228 ::ioctl(m_pvr_fd_dst, 0);
2230 /* flush ratebuffers (video, audio) */
2232 decoding_demux->flush();
2234 /* demux will also flush all decoder.. */
2235 /* resume will re-query the SG */
2236 m_pvr_thread->resume();
2239 DEFINE_REF(eCueSheet);
2241 eCueSheet::eCueSheet()
2243 m_skipmode_ratio = 0;
2246 void eCueSheet::seekTo(int relative, const pts_t &pts)
2249 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
2254 void eCueSheet::clear()
2261 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2263 ASSERT(begin < end);
2265 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2269 void eCueSheet::commitSpans()
2271 m_event(evtSpanChanged);
2274 void eCueSheet::setSkipmode(const pts_t &ratio)
2277 m_skipmode_ratio = ratio;
2279 m_event(evtSkipmode);
2282 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2284 m_decoding_demux = demux;
2285 m_decoder = decoder;
2288 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2290 connection = new eConnection(this, m_event.connect(event));