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 #if HAVE_DVB_API_VERSION < 3
158 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
160 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
162 if (stat(filename, &s))
168 fe = new eDVBFrontend(m_nr, num_fe, ok, true);
170 m_simulate_frontend.push_back(ePtr<eDVBFrontend>(fe));
175 fe = new eDVBFrontend(m_nr, num_fe, ok, false, fe);
177 m_frontend.push_back(ePtr<eDVBFrontend>(fe));
188 #if HAVE_DVB_API_VERSION < 3
189 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
191 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
193 if (stat(filename, &s))
195 ePtr<eDVBDemux> demux;
197 demux = new eDVBDemux(m_nr, num_demux);
198 m_demux.push_back(demux);
204 int eDVBAdapterLinux::getNumDemux()
206 return m_demux.size();
209 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
211 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
212 while (nr && (i != m_demux.end()))
218 if (i != m_demux.end())
226 int eDVBAdapterLinux::getNumFrontends()
228 return m_frontend.size();
231 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr, bool simulate)
233 eSmartPtrList<eDVBFrontend>::iterator i(simulate ? m_simulate_frontend.begin() : m_frontend.begin());
234 while (nr && (i != m_frontend.end()))
240 if (i != m_frontend.end())
248 int eDVBAdapterLinux::exist(int nr)
252 #if HAVE_DVB_API_VERSION < 3
253 sprintf(filename, "/dev/dvb/card%d", nr);
255 sprintf(filename, "/dev/dvb/adapter%d", nr);
257 if (!stat(filename, &s))
262 eDVBResourceManager::~eDVBResourceManager()
264 if (instance == this)
268 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
270 int num_fe = adapter->getNumFrontends();
271 int num_demux = adapter->getNumDemux();
273 m_adapter.push_back(adapter);
276 for (i=0; i<num_demux; ++i)
278 ePtr<eDVBDemux> demux;
279 if (!adapter->getDemux(demux, i))
280 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
283 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
284 for (i=0; i<num_fe; ++i)
286 ePtr<eDVBFrontend> frontend;
287 if (!adapter->getFrontend(frontend, i))
289 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
290 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
291 m_frontend.push_back(new_fe);
292 frontend->setSEC(m_sec);
293 // we must link all dvb-t frontends ( for active antenna voltage )
294 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
296 if (prev_dvbt_frontend)
298 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
299 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
301 prev_dvbt_frontend = new_fe;
306 prev_dvbt_frontend = 0;
307 for (i=0; i<num_fe; ++i)
309 ePtr<eDVBFrontend> frontend;
310 if (!adapter->getFrontend(frontend, i, true))
312 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
313 // CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
314 m_simulate_frontend.push_back(new_fe);
315 frontend->setSEC(m_sec);
316 // we must link all dvb-t frontends ( for active antenna voltage )
317 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
319 if (prev_dvbt_frontend)
321 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
322 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
324 prev_dvbt_frontend = new_fe;
331 void eDVBResourceManager::setUsbTuner()
333 std::ifstream in("/proc/bus/nim_sockets");
338 int usbtuner_idx[8] = {0};
339 int usbtuner_count = 0;
346 if ((res = sscanf(line.c_str(), "NIM Socket %d:", &fe_idx)) == 1)
349 if ((fe_idx != -1) && (line.find("\tName: ") == 0) && (line.find("VTUNER") != -1))
350 usbtuner_idx[usbtuner_count++] = fe_idx;
357 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_frontend.begin()); it != m_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);
369 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator it(m_simulate_frontend.begin()); it != m_simulate_frontend.end(); ++it)
371 int slotid = it->m_frontend->getSlotID();
372 for (int i=0; i < usbtuner_count ; i++)
374 if (slotid == usbtuner_idx[i])
376 it->m_frontend->setUSBTuner(true);
384 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
386 if (!PyList_Check(list))
388 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
391 unsigned int assigned=0;
392 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
395 while (pos < PyList_Size(list)) {
396 ePyObject obj = PyList_GET_ITEM(list, pos++);
397 if (!i->m_frontend->setSlotInfo(obj))
403 if (assigned != m_frontend.size()) {
405 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %zd socket informations, but %d registered frontends!",
406 m_frontend.size(), assigned);
407 PyErr_SetString(PyExc_StandardError, blasel);
410 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
413 while (pos < PyList_Size(list)) {
414 ePyObject obj = PyList_GET_ITEM(list, pos++);
415 if (!i->m_frontend->setSlotInfo(obj))
423 bool eDVBResourceManager::frontendIsCompatible(int index, const char *type)
425 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
427 if (i->m_frontend->getSlotID() == index)
429 if (!strcmp(type, "DVB-S2"))
431 return i->m_frontend->supportsDeliverySystem(SYS_DVBS2, false);
433 else if (!strcmp(type, "DVB-S"))
435 return i->m_frontend->supportsDeliverySystem(SYS_DVBS, false);
437 else if (!strcmp(type, "DVB-T2"))
439 return i->m_frontend->supportsDeliverySystem(SYS_DVBT2, false);
441 else if (!strcmp(type, "DVB-T"))
443 return i->m_frontend->supportsDeliverySystem(SYS_DVBT, false);
445 else if (!strcmp(type, "DVB-C"))
447 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
448 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_A, false);
450 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_AC, false);
458 void eDVBResourceManager::setFrontendType(int index, const char *type)
460 eDebug("[eDVBResourceManager::setFrontendType] index : %d, type : %s", index, type);
462 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
464 if (i->m_frontend->getSlotID() == index)
466 std::vector<fe_delivery_system_t> whitelist;
467 if (!strcmp(type, "DVB-S2") || !strcmp(type, "DVB-S"))
469 whitelist.push_back(SYS_DVBS);
470 whitelist.push_back(SYS_DVBS2);
472 else if (!strcmp(type, "DVB-T2") || !strcmp(type, "DVB-T"))
474 whitelist.push_back(SYS_DVBT);
475 whitelist.push_back(SYS_DVBT2);
477 else if (!strcmp(type, "DVB-C"))
479 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
480 whitelist.push_back(SYS_DVBC_ANNEX_A);
482 whitelist.push_back(SYS_DVBC_ANNEX_AC);
485 i->m_frontend->setDeliverySystemWhitelist(whitelist);
491 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
493 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
494 eDVBRegisteredFrontend *best = NULL;
498 int check_fbc_leaf_linkable = 0;
499 int current_fbc_setid = -1;
500 eDVBRegisteredFrontend *fbc_fe = NULL;
501 eDVBRegisteredFrontend *best_fbc_fe = NULL;
503 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
507 if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
509 int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
510 if (fbc_setid != current_fbc_setid)
512 current_fbc_setid = fbc_setid;
513 check_fbc_leaf_linkable = 0;
516 if (!check_fbc_leaf_linkable)
518 c = m_fbc_mng->isCompatibleWith(feparm, *i, fbc_fe, simulate);
519 check_fbc_leaf_linkable = 1;
520 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);
525 c = i->m_frontend->isCompatibleWith(feparm);
528 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
533 eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
538 best_fbc_fe = fbc_fe;
543 eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
546 eDVBRegisteredFrontend *tmp = *i;
553 m_fbc_mng->addLink(best, best_fbc_fe, simulate);
556 fe = new eDVBAllocatedFrontend(best);
563 return errAllSourcesBusy;
565 return errNoSourceFound;
568 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
570 int err = errNoSourceFound;
571 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
572 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
574 // check if another slot linked to this is in use
576 i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
579 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
580 if (satpos_depends_to_fe->m_inuse)
582 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
583 err = errAllSourcesBusy;
584 goto alloc_fe_by_id_not_possible;
587 else // check linked tuners
589 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
592 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
595 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
596 err = errAllSourcesBusy;
597 goto alloc_fe_by_id_not_possible;
599 next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
601 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
604 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
607 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
608 err = errAllSourcesBusy;
609 goto alloc_fe_by_id_not_possible;
611 prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
614 fe = new eDVBAllocatedFrontend(i);
617 alloc_fe_by_id_not_possible:
622 #define capHoldDecodeReference 64
624 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int &cap)
626 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
627 never use the first one unless we need a decoding demux. */
629 eDebug("allocate demux");
630 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
634 if (i == m_demux.end())
637 ePtr<eDVBRegisteredDemux> unused;
639 if (m_boxtype == DM800) // dm800
641 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
642 for (; i != m_demux.end(); ++i, ++n)
653 if (i->m_adapter == fe->m_adapter &&
654 i->m_demux->getSource() == fe->m_frontend->getDVBID())
656 demux = new eDVBAllocatedDemux(i);
660 else if (i->m_demux->getSource() == -1) // PVR
662 demux = new eDVBAllocatedDemux(i);
668 else if (m_boxtype == DM7025) // ATI
670 /* FIXME: hardware demux policy */
671 if (!(cap & iDVBChannel::capDecode))
673 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
680 for (; i != m_demux.end(); ++i, ++n)
682 int is_decode = n < 2;
684 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
686 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
688 if ((cap & iDVBChannel::capDecode) && !is_decode)
695 else if (m_boxtype == DM8000 || m_boxtype == DM500HD || m_boxtype == DM800SE || m_boxtype == DM7020HD)
697 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 */
698 int source = fe ? fe->m_frontend->getDVBID() : -1;
699 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
703 * For pvr playback, start with the last demux.
704 * On some hardware, we have less ca devices than demuxes,
705 * so we should try to leave the first demuxes for live tv,
706 * and start with the last for pvr playback
711 while (i != m_demux.end())
713 if (i->m_adapter == adapter)
717 /* mark the first unused demux, we'll use that when we do not find a better match */
718 if (!unused) unused = i;
722 /* demux is in use, see if we can share it */
723 if (source >= 0 && i->m_demux->getSource() == source)
725 demux = new eDVBAllocatedDemux(i);
743 demux = new eDVBAllocatedDemux(unused);
745 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
747 demux->get().setSourcePVR(0);
751 eDebug("demux not found");
755 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
761 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
770 #define eDebugNoSimulate(x...) \
776 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
778 /* first, check if a channel is already existing. */
779 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
781 if (!simulate && m_cached_channel)
783 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
784 if(channelid==cache_chan->getChannelID())
786 eDebug("use cached_channel");
787 channel = m_cached_channel;
790 m_cached_channel_state_changed_conn.disconnect();
792 m_releaseCachedChannelTimer->stop();
795 eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
796 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
798 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
799 if (i->m_channel_id == channelid)
801 eDebugNoSimulate("found shared channel..");
802 channel = i->m_channel;
807 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
811 eDebugNoSimulate("no channel list set!");
812 return errNoChannelList;
815 ePtr<iDVBFrontendParameters> feparm;
816 if (m_list->getChannelFrontendData(channelid, feparm))
818 eDebugNoSimulate("channel not found!");
819 return errChannelNotInList;
822 /* allocate a frontend. */
824 ePtr<eDVBAllocatedFrontend> fe;
826 int err = allocateFrontend(fe, feparm, simulate);
831 ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
833 res = ch->setChannel(channelid, feparm);
837 return errChidNotFound;
844 m_cached_channel = channel = ch;
845 m_cached_channel_state_changed_conn =
846 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
852 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
855 chan->getState(state);
858 case iDVBChannel::state_release:
859 case iDVBChannel::state_ok:
861 eDebug("stop release channel timer");
862 m_releaseCachedChannelTimer->stop();
865 case iDVBChannel::state_last_instance:
867 eDebug("start release channel timer");
868 m_releaseCachedChannelTimer->start(3000, true);
871 default: // ignore all other events
876 void eDVBResourceManager::releaseCachedChannel()
878 eDebug("release cached channel (timer timeout)");
882 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
884 ePtr<eDVBAllocatedFrontend> fe;
886 if (m_cached_channel)
888 m_cached_channel_state_changed_conn.disconnect();
890 m_releaseCachedChannelTimer->stop();
893 int err = allocateFrontendByIndex(fe, slot_index);
897 channel = new eDVBChannel(this, fe);
901 RESULT eDVBResourceManager::allocatePVRChannel(const eDVBChannelID &channelid, eUsePtr<iDVBPVRChannel> &channel)
903 ePtr<eDVBAllocatedDemux> demux;
905 if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
907 m_cached_channel_state_changed_conn.disconnect();
909 m_releaseCachedChannelTimer->stop();
912 ePtr<eDVBChannel> ch = new eDVBChannel(this, 0);
916 * user provided a channelid, with the clear intention for
917 * this channel to be registered at the resource manager.
918 * (allowing e.g. epgcache to be started)
920 ePtr<iDVBFrontendParameters> feparm;
921 ch->setChannel(channelid, feparm);
927 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
929 ePtr<iDVBFrontend> fe;
930 if (!ch->getFrontend(fe))
932 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
933 if (frontend->is_simulate())
934 m_active_simulate_channels.push_back(active_channel(chid, ch));
937 m_active_channels.push_back(active_channel(chid, ch));
938 /* emit */ m_channelAdded(ch);
944 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
946 ePtr<iDVBFrontend> fe;
947 if (!ch->getFrontend(fe))
949 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
950 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
952 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
954 if (i->m_channel == ch)
956 i = active_channels.erase(i);
968 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
970 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
974 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
976 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
977 ePtr<eDVBRegisteredFrontend> best;
979 int check_fbc_leaf_linkable = 0;
980 int current_fbc_setid = -1;
982 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
987 if (i->m_frontend->is_FBCTuner() && m_fbc_mng->canLink(*i))
989 int fbc_setid = m_fbc_mng->getFBCSetID(i->m_frontend->getSlotID());
990 if (fbc_setid != current_fbc_setid)
992 current_fbc_setid = fbc_setid;
993 check_fbc_leaf_linkable = 0;
996 if (!check_fbc_leaf_linkable)
998 eDVBRegisteredFrontend *dummy;
999 c = m_fbc_mng->isCompatibleWith(feparm, *i, dummy, simulate);
1000 check_fbc_leaf_linkable = 1;
1005 c = i->m_frontend->isCompatibleWith(feparm);
1014 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid, int &system)
1016 system = iDVBFrontend::feSatellite;
1019 ePtr<iDVBFrontendParameters> feparm;
1020 if (!channellist->getChannelFrontendData(chid, feparm))
1022 if (!feparm->getSystem(system))
1026 case iDVBFrontend::feSatellite:
1028 case iDVBFrontend::feCable:
1030 case iDVBFrontend::feTerrestrial:
1041 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, int &system, bool simulate)
1043 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
1045 system = iDVBFrontend::feSatellite;
1046 if (!simulate && m_cached_channel)
1048 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
1049 if(channelid==cache_chan->getChannelID())
1050 return tuner_type_channel_default(m_list, channelid, system);
1053 /* first, check if a channel is already existing. */
1054 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
1055 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
1057 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
1058 if (i->m_channel_id == channelid)
1060 // eDebug("found shared channel..");
1061 return tuner_type_channel_default(m_list, channelid, system);
1065 int *decremented_cached_channel_fe_usecount=NULL,
1066 *decremented_fe_usecount=NULL;
1068 /* check FCC channels */
1069 std::vector<int*> fcc_decremented_fe_usecounts;
1070 std::map<eDVBChannelID, int> fcc_chids;
1071 int apply_to_ignore = 0;
1072 if (!eFCCServiceManager::getFCCChannelID(fcc_chids))
1074 for (std::map<eDVBChannelID, int>::iterator i(fcc_chids.begin()); i != fcc_chids.end(); ++i)
1076 //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());
1077 if (ignore == i->first)
1079 apply_to_ignore = i->second;
1082 for (std::list<active_channel>::iterator ii(active_channels.begin()); ii != active_channels.end(); ++ii)
1084 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1085 if (ii->m_channel_id == i->first)
1087 eDVBChannel *channel = (eDVBChannel*) &(*ii->m_channel);
1089 int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1090 check_usecount += i->second * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1091 //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1092 if (channel->getUseCount() == check_usecount)
1094 ePtr<iDVBFrontend> fe;
1095 if (!ii->m_channel->getFrontend(fe))
1097 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator iii(frontends.begin()); iii != frontends.end(); ++iii)
1099 if ( &(*fe) == &(*iii->m_frontend) )
1101 //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : decrease fcc fe use_count! feid : %d (%d -> %d)", iii->m_frontend->getSlotID(), iii->m_inuse, iii->m_inuse-1);
1103 int *tmp_decremented_fe_usecount = &iii->m_inuse;
1104 fcc_decremented_fe_usecounts.push_back(tmp_decremented_fe_usecount);
1105 if (channel == &(*m_cached_channel))
1106 decremented_cached_channel_fe_usecount = tmp_decremented_fe_usecount;
1118 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
1120 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1121 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
1122 if (i->m_channel_id == ignore)
1124 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
1125 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
1126 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
1127 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
1128 // or 2 when the cached channel is not equal to the compared channel
1129 int check_usecount = channel == &(*m_cached_channel) ? 1 : 0;
1130 check_usecount += (apply_to_ignore+1) * 2; // one is used in eDVBServicePMTHandler and another is used in eDVBScan.
1131 //eDebug("[eDVBResourceManager::canAllocateChannel] channel->getUseCount() : %d , check_usecount : %d (cached : %d)", channel->getUseCount(), check_usecount, channel == &(*m_cached_channel));
1132 if (channel->getUseCount() == check_usecount) // channel only used once..(except fcc)
1134 ePtr<iDVBFrontend> fe;
1135 if (!i->m_channel->getFrontend(fe))
1137 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1139 if ( &(*fe) == &(*ii->m_frontend) )
1141 //eDebug("[eDVBResourceManager::canAllocateChannel] ignore : decrease fcc fe use_count! feid : %d (%d -> %d)", ii->m_frontend->getSlotID(), ii->m_inuse, ii->m_inuse-1);
1143 decremented_fe_usecount = &ii->m_inuse;
1144 if (channel == &(*m_cached_channel))
1145 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
1155 if (!decremented_cached_channel_fe_usecount)
1157 if (m_cached_channel)
1159 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
1160 if (channel->getUseCount() == 1)
1162 ePtr<iDVBFrontend> fe;
1163 if (!channel->getFrontend(fe))
1165 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
1166 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
1168 if ( &(*fe) == &(*ii->m_frontend) )
1171 decremented_cached_channel_fe_usecount = &ii->m_inuse;
1180 decremented_cached_channel_fe_usecount=NULL;
1182 ePtr<iDVBFrontendParameters> feparm;
1186 eDebug("no channel list set!");
1190 if (m_list->getChannelFrontendData(channelid, feparm))
1192 eDebug("channel not found!");
1195 feparm->getSystem(system);
1197 ret = canAllocateFrontend(feparm, simulate);
1200 if (decremented_fe_usecount)
1201 ++(*decremented_fe_usecount);
1202 if (decremented_cached_channel_fe_usecount)
1203 ++(*decremented_cached_channel_fe_usecount);
1204 if (fcc_decremented_fe_usecounts.size())
1206 for (std::vector<int*>::iterator i(fcc_decremented_fe_usecounts.begin()); i != fcc_decremented_fe_usecounts.end(); ++i)
1208 //eDebug("[eDVBResourceManager::canAllocateChannel] fcc : increase fcc fe use_count!");
1216 bool eDVBResourceManager::canMeasureFrontendInputPower()
1218 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
1220 return i->m_frontend->readInputpower() >= 0;
1225 class eDVBChannelFilePush: public eFilePushThread
1228 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
1229 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
1231 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
1232 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
1233 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
1235 int m_iframe_search, m_iframe_state, m_pid;
1236 int m_timebase_change;
1237 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
1240 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
1243 if (m_timebase_change)
1245 eDebug("timebase change: %d", m_timebase_change);
1247 for (offset = 0; offset < len; offset += 188)
1249 unsigned char *pkt = (unsigned char*)_data + offset;
1250 if (pkt[1] & 0x40) /* pusi */
1252 if (pkt[3] & 0x20) // adaption field present?
1253 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
1255 pkt += 4; /* skip header */
1256 if (pkt[0] || pkt[1] || (pkt[2] != 1))
1258 eWarning("broken startcode");
1264 if (pkt[7] & 0x80) // PTS present?
1266 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
1267 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
1268 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
1269 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
1270 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
1274 RESULT r = m_tstools.fixupPTS(off, pts);
1276 eWarning("fixup PTS while trickmode playback failed.\n");
1279 int sec = pts / 90000;
1280 int frm = pts % 90000;
1288 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1290 pts += 0x80000000LL;
1291 pts *= m_timebase_change;
1303 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1311 pkt[9] |= (pts >> 29) & 0xE;
1312 pkt[10] |= (pts >> 22) & 0xFF;
1313 pkt[11] |= (pts >> 14) & 0xFE;
1314 pkt[12] |= (pts >> 7) & 0xFF;
1315 pkt[13] |= (pts << 1) & 0xFE;
1323 if (!m_iframe_search)
1326 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1328 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1330 unsigned char *d = data;
1331 while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1333 int offset = d - data;
1334 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1335 unsigned char *ts = data + ts_offset;
1336 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1338 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */
1340 int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1343 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1345 if (m_iframe_state == 1)
1347 /* we are allowing data, and stop allowing data on the next frame.
1348 we now found a frame. so stop here. */
1349 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1350 current_span_remaining = 0;
1352 unsigned char *fts = ts + 188;
1353 while (fts < (data + len))
1356 fts[2] |= 0xff; /* drop packet */
1360 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1363 if (picture_type != 1) /* we are only interested in I frames */
1366 unsigned char *fts = data;
1370 fts[2] |= 0xff; /* drop packet */
1377 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1379 /* verify that this is actually a PES header, not just some ES data */
1380 if (ts[1] & 0x40) /* PUSI set */
1382 int payload_start = 4;
1383 if (ts[3] & 0x20) /* adaptation field present */
1384 payload_start += ts[4] + 1; /* skip AF */
1385 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1389 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1397 d += 4; /* ignore */
1400 if (m_iframe_state == 1)
1403 return 0; /* we need find an iframe first */
1409 DEFINE_REF(eDVBChannel);
1411 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1413 m_frontend = frontend;
1418 m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1421 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1424 eDVBChannel::~eDVBChannel()
1427 m_mgr->removeChannel(this);
1432 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1434 int state, ourstate = 0;
1436 /* if we are already in shutdown, don't change state. */
1437 if (m_state == state_release)
1440 if (fe->getState(state))
1443 if (state == iDVBFrontend::stateLock)
1445 eDebug("OURSTATE: ok");
1446 ourstate = state_ok;
1447 } else if (state == iDVBFrontend::stateTuning)
1449 eDebug("OURSTATE: tuning");
1450 ourstate = state_tuning;
1451 } else if (state == iDVBFrontend::stateLostLock)
1453 /* on managed channels, we try to retune in order to re-acquire lock. */
1454 if (m_current_frontend_parameters)
1456 eDebug("OURSTATE: lost lock, trying to retune");
1457 ourstate = state_tuning;
1458 m_frontend->get().tune(*m_current_frontend_parameters);
1460 /* on unmanaged channels, we don't do this. the client will do this. */
1462 eDebug("OURSTATE: lost lock, unavailable now.");
1463 ourstate = state_unavailable;
1465 } else if (state == iDVBFrontend::stateFailed)
1468 if (m_current_frontend_parameters)
1470 eDebug("OURSTATE: lost lock, trying to retune");
1471 ourstate = state_tuning;
1472 m_frontend->get().tune(*m_current_frontend_parameters);
1476 eDebug("OURSTATE: failed");
1477 ourstate = state_failed;
1480 eDebug("OURSTATE: failed");
1481 ourstate = state_failed;
1484 eFatal("state unknown");
1486 if (ourstate != m_state)
1489 m_stateChanged(this);
1493 void eDVBChannel::pvrEvent(int event)
1497 case eFilePushThread::evtEOF:
1498 eDebug("eDVBChannel: End of file!");
1499 m_event(this, evtEOF);
1501 case eFilePushThread::evtUser: /* start */
1503 m_event(this, evtSOF);
1505 case eFilePushThread::evtUser+3: /* limit space */
1506 eDebug("Too large file");
1507 m_event(this, evtFailed+3);
1512 void eDVBChannel::cueSheetEvent(int event)
1514 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1519 case eCueSheet::evtSeek:
1521 flushPVR(m_cue->m_decoding_demux);
1523 case eCueSheet::evtSkipmode:
1526 m_cue->m_lock.WrLock();
1527 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1528 m_cue->m_lock.Unlock();
1529 eRdLocker l(m_cue->m_lock);
1530 if (m_cue->m_skipmode_ratio)
1532 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1533 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1534 /* i agree that this might look a bit like black magic. */
1535 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1536 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1537 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1538 m_skipmode_frames_remainder = 0;
1540 if (m_cue->m_skipmode_ratio < 0)
1541 m_skipmode_m -= m_skipmode_n;
1543 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1545 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1547 eWarning("something is wrong with this calculation");
1548 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1552 eDebug("skipmode ratio is 0, normal play");
1553 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1556 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1557 if (m_cue->m_skipmode_ratio != 0)
1558 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1560 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1561 eDebug("flush pvr");
1562 flushPVR(m_cue->m_decoding_demux);
1566 case eCueSheet::evtSpanChanged:
1568 m_source_span.clear();
1569 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1571 off_t offset_in, offset_out;
1572 pts_t pts_in = i->first, pts_out = i->second;
1573 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1575 eDebug("span translation failed.\n");
1578 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1579 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1586 /* align toward zero */
1587 static inline long long align(long long x, int align)
1602 /* align toward zero */
1603 static inline long long align_with_len(long long x, int align, size_t &len)
1620 /* remember, this gets called from another thread. */
1621 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1623 const int blocksize = 188;
1624 unsigned int max = align(10*1024*1024, blocksize);
1625 current_offset = align(current_offset, blocksize);
1629 eDebug("no cue sheet. forcing normal play");
1630 start = current_offset;
1637 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1638 max = align(m_skipmode_n, blocksize);
1641 eDebug("getNextSourceSpan, current offset is %08lld, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1642 int frame_skip_success = 0;
1646 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1647 eDebug("we are at %lld, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1649 off_t iframe_start = current_offset;
1650 int frames_skipped = frames_to_skip;
1651 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1653 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1654 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1655 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1656 max = align(iframe_len + 187, blocksize);
1657 frame_skip_success = 1;
1660 m_skipmode_frames_remainder = 0;
1661 eDebug("frame skipping failed, reverting to byte-skipping");
1665 if (!frame_skip_success)
1667 current_offset += align(m_skipmode_m, blocksize);
1668 if(current_offset < 0)
1674 eDebug("we are at %lld, and we try to find the iframe here:", current_offset);
1676 off_t start_offset = current_offset;
1677 off_t new_offset = start_offset;
1678 int direction = (m_skipmode_m < 0) ? -1 : +1;
1679 if (m_tstools.findFrame(start_offset, new_offset, iframe_len, direction))
1683 current_offset = align_with_len(new_offset, blocksize, iframe_len);
1684 max = align(iframe_len, blocksize);
1690 m_cue->m_lock.RdLock();
1692 while (!m_cue->m_seek_requests.empty())
1694 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1695 m_cue->m_lock.Unlock();
1696 m_cue->m_lock.WrLock();
1697 m_cue->m_seek_requests.pop_front();
1698 m_cue->m_lock.Unlock();
1699 m_cue->m_lock.RdLock();
1700 int relative = seek.first;
1701 pts_t pts = seek.second;
1706 if (!m_cue->m_decoder)
1708 eDebug("no decoder - can't seek relative");
1711 if (m_cue->m_decoder->getPTS(0, now))
1713 eDebug("decoder getPTS failed, can't seek relative");
1716 if (!m_cue->m_decoding_demux)
1718 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1719 start = current_offset;
1723 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1725 eDebug("seekTo: getCurrentPosition failed!");
1728 } else if (pts < 0) /* seek relative to end */
1731 if (!getLength(len))
1733 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1737 eWarning("getLength failed - can't seek relative to end!");
1742 if (relative == 1) /* pts relative */
1753 if (relative == 2) /* AP relative */
1755 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1757 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1759 pts = now - 90000; /* approx. 1s */
1760 eDebug("AP relative seeking failed!");
1764 eDebug("next ap is %llx\n", pts);
1769 if (m_tstools.getOffset(offset, pts, -1))
1771 eDebug("get offset for pts=%lld failed!", pts);
1775 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1776 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1779 m_cue->m_lock.Unlock();
1781 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1783 long long aligned_start = align(i->first, blocksize);
1784 long long aligned_end = align(i->second, blocksize);
1786 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1788 start = current_offset;
1789 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1790 if ((aligned_end - current_offset) > max)
1793 size = aligned_end - current_offset;
1794 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1797 if (current_offset < aligned_start)
1799 /* ok, our current offset is in an 'out' zone. */
1800 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1802 /* in normal playback, just start at the next zone. */
1805 /* size is not 64bit! */
1806 if ((i->second - i->first) > max)
1809 size = aligned_end - aligned_start;
1812 if (m_skipmode_m < 0)
1814 eDebug("reached SOF");
1817 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1821 /* when skipping reverse, however, choose the zone before. */
1823 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1826 aligned_start = align(i->first, blocksize);
1827 aligned_end = align(i->second, blocksize);
1829 if ((aligned_end - aligned_start) > max)
1832 len = aligned_end - aligned_start;
1834 start = aligned_end - len;
1835 eDebug("skipping to %llx, %zd", start, len);
1838 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1843 if(current_offset <0)
1845 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1847 eDebug("reached SOF");
1849 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1851 if (m_source_span.empty())
1853 start = current_offset;
1855 eDebug("NO CUESHEET. (%08lld, %zd)", start, size);
1858 start = current_offset;
1864 void eDVBChannel::AddUse()
1866 if (++m_use_count > 1 && m_state == state_last_instance)
1869 m_stateChanged(this);
1873 void eDVBChannel::ReleaseUse()
1877 m_state = state_release;
1878 m_stateChanged(this);
1880 else if (m_use_count == 1)
1882 m_state = state_last_instance;
1883 m_stateChanged(this);
1887 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1890 m_mgr->removeChannel(this);
1895 m_channel_id = channelid;
1896 m_mgr->addChannel(channelid, this);
1900 /* no frontend, no need to tune (must be a streamed service) */
1904 m_state = state_tuning;
1905 /* if tuning fails, shutdown the channel immediately. */
1907 res = m_frontend->get().tune(*feparm);
1908 m_current_frontend_parameters = feparm;
1912 m_state = state_release;
1913 m_stateChanged(this);
1920 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1922 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1926 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1928 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1932 RESULT eDVBChannel::getState(int &state)
1938 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1943 void eDVBChannel::SDTready(int result)
1945 ePyObject args = PyTuple_New(2), ret;
1949 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1952 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1953 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1959 PyTuple_SET_ITEM(args, 0, Py_None);
1960 PyTuple_SET_ITEM(args, 1, Py_None);
1964 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1968 Py_DECREF(m_tsid_onid_callback);
1969 m_tsid_onid_callback = ePyObject();
1970 m_tsid_onid_demux = 0;
1974 int eDVBChannel::reserveDemux()
1976 ePtr<iDVBDemux> dmx;
1977 if (!getDemux(dmx, 0))
1980 if (!dmx->getCADemuxID(id))
1986 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1988 if (PyCallable_Check(callback))
1990 if (!getDemux(m_tsid_onid_demux, 0))
1992 m_SDT = new eTable<ServiceDescriptionSection>;
1993 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1994 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1996 m_tsid_onid_demux = 0;
2001 Py_INCREF(callback);
2002 m_tsid_onid_callback = callback;
2010 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
2012 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
2014 if (m_frontend == NULL)
2016 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
2017 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
2024 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
2029 /* don't hold a reference to the decoding demux, we don't need it. */
2031 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
2032 the refcount is lost. thus, decoding demuxes are never allocated.
2034 this poses a big problem for PiP. */
2036 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
2038 else if (cap & capDecode)
2047 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
2052 frontend = &m_frontend->get();
2058 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
2060 param = m_current_frontend_parameters;
2064 RESULT eDVBChannel::playFile(const char *file)
2066 eRawFile *f = new eRawFile();
2067 ePtr<iTsSource> source = f;
2069 if (f->open(file) < 0)
2071 eDebug("can't open PVR file %s (%m)", file);
2075 return playSource(source, file);
2078 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
2080 ASSERT(!m_frontend);
2083 m_pvr_thread->stop();
2084 delete m_pvr_thread;
2088 if (!source->valid() && !source->isStream())
2090 eDebug("PVR source is not valid!");
2095 m_tstools.setSource(m_source, streaminfo_file);
2097 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
2098 THEN DO A REAL FIX HERE! */
2100 if (m_pvr_fd_dst < 0)
2102 /* (this codepath needs to be improved anyway.) */
2103 #if HAVE_DVB_API_VERSION < 3
2104 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
2105 if (m_pvr_fd_dst < 0)
2107 eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2111 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
2114 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
2115 if (m_pvr_fd_dst < 0)
2117 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
2123 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
2129 m_pvr_thread = new eDVBChannelFilePush();
2130 m_pvr_thread->enablePVRCommit(1);
2131 /* If the source specifies a length, it's a file. If not, it's a stream */
2132 m_pvr_thread->setStreamMode(m_source->isStream());
2133 m_pvr_thread->setScatterGather(this);
2135 m_event(this, evtPreStart);
2137 m_pvr_thread->start(m_source, m_pvr_fd_dst);
2138 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
2141 m_stateChanged(this);
2146 void eDVBChannel::stopSource()
2150 m_pvr_thread->stop();
2151 delete m_pvr_thread;
2154 if (m_pvr_fd_dst >= 0)
2156 ::close(m_pvr_fd_dst);
2161 m_tstools.setSource(m_source);
2164 void eDVBChannel::stopFile()
2169 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
2171 m_conn_cueSheetEvent = 0;
2174 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
2177 RESULT eDVBChannel::getLength(pts_t &len)
2179 return m_tstools.calcLen(len);
2182 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
2184 if (!decoding_demux)
2191 if (mode == 0) /* demux */
2193 r = decoding_demux->getSTC(now, 0);
2196 eDebug("demux getSTC failed");
2200 now = pos; /* fixup supplied */
2202 r = m_tstools.fixupPTS(m_source ? m_source->offset() : 0, now);
2205 eDebug("fixup PTS failed");
2214 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
2216 /* when seeking, we have to ensure that all buffers are flushed.
2217 there are basically 3 buffers:
2218 a.) the filepush's internal buffer
2219 b.) the PVR buffer (before demux)
2220 c.) the ratebuffer (after demux)
2222 it's important to clear them in the correct order, otherwise
2223 the ratebuffer (for example) would immediately refill from
2224 the not-yet-flushed PVR buffer.
2227 m_pvr_thread->pause();
2228 /* flush internal filepush buffer */
2229 m_pvr_thread->flush();
2230 /* HACK: flush PVR buffer */
2231 ::ioctl(m_pvr_fd_dst, 0);
2233 /* flush ratebuffers (video, audio) */
2235 decoding_demux->flush();
2237 /* demux will also flush all decoder.. */
2238 /* resume will re-query the SG */
2239 m_pvr_thread->resume();
2242 DEFINE_REF(eCueSheet);
2244 eCueSheet::eCueSheet()
2246 m_skipmode_ratio = 0;
2249 void eCueSheet::seekTo(int relative, const pts_t &pts)
2252 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
2257 void eCueSheet::clear()
2264 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2266 ASSERT(begin < end);
2268 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2272 void eCueSheet::commitSpans()
2274 m_event(evtSpanChanged);
2277 void eCueSheet::setSkipmode(const pts_t &ratio)
2280 m_skipmode_ratio = ratio;
2282 m_event(evtSkipmode);
2285 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2287 m_decoding_demux = demux;
2288 m_decoder = decoder;
2291 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2293 connection = new eConnection(this, m_event.connect(event));