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>
10 #include <sys/types.h>
14 #include <sys/ioctl.h>
16 DEFINE_REF(eDVBRegisteredFrontend);
17 DEFINE_REF(eDVBRegisteredDemux);
19 DEFINE_REF(eDVBAllocatedFrontend);
21 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
26 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
31 DEFINE_REF(eDVBAllocatedDemux);
33 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
38 eDVBAllocatedDemux::~eDVBAllocatedDemux()
43 DEFINE_REF(eDVBResourceManager);
45 eDVBResourceManager *eDVBResourceManager::instance;
47 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
57 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
59 ePtr<eDVBResourceManager> ptr;
60 eDVBResourceManager::getInstance(ptr);
64 eDVBResourceManager::eDVBResourceManager()
65 :m_releaseCachedChannelTimer(eTimer::create(eApp))
69 m_sec = new eDVBSatelliteEquipmentControl(m_frontend, m_simulate_frontend);
74 /* search available adapters... */
79 while (eDVBAdapterLinux::exist(num_adapter))
81 addAdapter(new eDVBAdapterLinux(num_adapter));
85 int fd = open("/proc/stb/info/model", O_RDONLY);
87 int rd = fd >= 0 ? read(fd, tmp, 255) : 0;
91 if (!strncmp(tmp, "dm7025\n", rd))
93 else if (!strncmp(tmp, "dm8000\n", rd))
95 else if (!strncmp(tmp, "dm800\n", rd))
97 else if (!strncmp(tmp, "dm500hd\n", rd))
99 else if (!strncmp(tmp, "dm800se\n", rd))
101 else if (!strncmp(tmp, "dm7020hd\n", rd))
102 m_boxtype = DM7020HD;
104 eDebug("boxtype detection via /proc/stb/info not possible... use fallback via demux count!\n");
105 if (m_demux.size() == 3)
107 else if (m_demux.size() < 5)
113 eDebug("found %zd adapter, %zd frontends(%zd sim) and %zd demux, boxtype %d",
114 m_adapter.size(), m_frontend.size(), m_simulate_frontend.size(), m_demux.size(), m_boxtype);
116 eDVBCAService::registerChannelCallback(this);
118 CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
121 void eDVBResourceManager::feStateChanged()
124 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
126 mask |= ( 1 << i->m_frontend->getSlotID() );
127 /* emit */ frontendUseMaskChanged(mask);
130 DEFINE_REF(eDVBAdapterLinux);
131 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
136 eDebug("scanning for frontends..");
141 #if HAVE_DVB_API_VERSION < 3
142 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
144 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
146 if (stat(filename, &s))
152 fe = new eDVBFrontend(m_nr, num_fe, ok, true);
154 m_simulate_frontend.push_back(ePtr<eDVBFrontend>(fe));
159 fe = new eDVBFrontend(m_nr, num_fe, ok, false, fe);
161 m_frontend.push_back(ePtr<eDVBFrontend>(fe));
172 #if HAVE_DVB_API_VERSION < 3
173 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
175 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
177 if (stat(filename, &s))
179 ePtr<eDVBDemux> demux;
181 demux = new eDVBDemux(m_nr, num_demux);
182 m_demux.push_back(demux);
188 int eDVBAdapterLinux::getNumDemux()
190 return m_demux.size();
193 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
195 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
196 while (nr && (i != m_demux.end()))
202 if (i != m_demux.end())
210 int eDVBAdapterLinux::getNumFrontends()
212 return m_frontend.size();
215 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr, bool simulate)
217 eSmartPtrList<eDVBFrontend>::iterator i(simulate ? m_simulate_frontend.begin() : m_frontend.begin());
218 while (nr && (i != m_frontend.end()))
224 if (i != m_frontend.end())
232 int eDVBAdapterLinux::exist(int nr)
236 #if HAVE_DVB_API_VERSION < 3
237 sprintf(filename, "/dev/dvb/card%d", nr);
239 sprintf(filename, "/dev/dvb/adapter%d", nr);
241 if (!stat(filename, &s))
246 eDVBResourceManager::~eDVBResourceManager()
248 if (instance == this)
252 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
254 int num_fe = adapter->getNumFrontends();
255 int num_demux = adapter->getNumDemux();
257 m_adapter.push_back(adapter);
260 for (i=0; i<num_demux; ++i)
262 ePtr<eDVBDemux> demux;
263 if (!adapter->getDemux(demux, i))
264 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
267 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
268 for (i=0; i<num_fe; ++i)
270 ePtr<eDVBFrontend> frontend;
271 if (!adapter->getFrontend(frontend, i))
273 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
274 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
275 m_frontend.push_back(new_fe);
276 frontend->setSEC(m_sec);
277 // we must link all dvb-t frontends ( for active antenna voltage )
278 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
280 if (prev_dvbt_frontend)
282 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
283 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
285 prev_dvbt_frontend = new_fe;
290 prev_dvbt_frontend = 0;
291 for (i=0; i<num_fe; ++i)
293 ePtr<eDVBFrontend> frontend;
294 if (!adapter->getFrontend(frontend, i, true))
296 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
297 // CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
298 m_simulate_frontend.push_back(new_fe);
299 frontend->setSEC(m_sec);
300 // we must link all dvb-t frontends ( for active antenna voltage )
301 if (frontend->supportsDeliverySystem(SYS_DVBT, false) || frontend->supportsDeliverySystem(SYS_DVBT2, false))
303 if (prev_dvbt_frontend)
305 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
306 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
308 prev_dvbt_frontend = new_fe;
315 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
317 if (!PyList_Check(list))
319 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
322 unsigned int assigned=0;
323 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
326 while (pos < PyList_Size(list)) {
327 ePyObject obj = PyList_GET_ITEM(list, pos++);
328 if (!i->m_frontend->setSlotInfo(obj))
334 if (assigned != m_frontend.size()) {
336 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %zd socket informations, but %d registered frontends!",
337 m_frontend.size(), assigned);
338 PyErr_SetString(PyExc_StandardError, blasel);
341 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
344 while (pos < PyList_Size(list)) {
345 ePyObject obj = PyList_GET_ITEM(list, pos++);
346 if (!i->m_frontend->setSlotInfo(obj))
354 bool eDVBResourceManager::frontendIsCompatible(int index, const char *type)
356 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
358 if (i->m_frontend->getSlotID() == index)
360 if (!strcmp(type, "DVB-S2"))
362 return i->m_frontend->supportsDeliverySystem(SYS_DVBS2, false);
364 else if (!strcmp(type, "DVB-S"))
366 return i->m_frontend->supportsDeliverySystem(SYS_DVBS, false);
368 else if (!strcmp(type, "DVB-T2"))
370 return i->m_frontend->supportsDeliverySystem(SYS_DVBT2, false);
372 else if (!strcmp(type, "DVB-T"))
374 return i->m_frontend->supportsDeliverySystem(SYS_DVBT, false);
376 else if (!strcmp(type, "DVB-C"))
378 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
379 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_A, false);
381 return i->m_frontend->supportsDeliverySystem(SYS_DVBC_ANNEX_AC, false);
389 void eDVBResourceManager::setFrontendType(int index, const char *type)
391 eDebug("[eDVBResourceManager::setFrontendType] index : %d, type : %s", index, type);
393 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
395 if (i->m_frontend->getSlotID() == index)
397 std::vector<fe_delivery_system_t> whitelist;
398 if (!strcmp(type, "DVB-S2") || !strcmp(type, "DVB-S"))
400 whitelist.push_back(SYS_DVBS);
401 whitelist.push_back(SYS_DVBS2);
403 else if (!strcmp(type, "DVB-T2") || !strcmp(type, "DVB-T"))
405 whitelist.push_back(SYS_DVBT);
406 whitelist.push_back(SYS_DVBT2);
408 else if (!strcmp(type, "DVB-C"))
410 #if DVB_API_VERSION > 5 || DVB_API_VERSION == 5 && DVB_API_VERSION_MINOR >= 6
411 whitelist.push_back(SYS_DVBC_ANNEX_A);
413 whitelist.push_back(SYS_DVBC_ANNEX_AC);
416 i->m_frontend->setDeliverySystemWhitelist(whitelist);
422 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
424 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
425 ePtr<eDVBRegisteredFrontend> best;
429 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
431 int c = i->m_frontend->isCompatibleWith(feparm);
433 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
438 // eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
446 // eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
451 fe = new eDVBAllocatedFrontend(best);
458 return errAllSourcesBusy;
460 return errNoSourceFound;
463 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
465 int err = errNoSourceFound;
466 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
467 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
469 // check if another slot linked to this is in use
471 i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
474 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
475 if (satpos_depends_to_fe->m_inuse)
477 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
478 err = errAllSourcesBusy;
479 goto alloc_fe_by_id_not_possible;
482 else // check linked tuners
484 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
487 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
490 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
491 err = errAllSourcesBusy;
492 goto alloc_fe_by_id_not_possible;
494 next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
496 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
499 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
502 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
503 err = errAllSourcesBusy;
504 goto alloc_fe_by_id_not_possible;
506 prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
509 fe = new eDVBAllocatedFrontend(i);
512 alloc_fe_by_id_not_possible:
517 #define capHoldDecodeReference 64
519 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int &cap)
521 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
522 never use the first one unless we need a decoding demux. */
524 eDebug("allocate demux");
525 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
529 if (i == m_demux.end())
532 ePtr<eDVBRegisteredDemux> unused;
534 if (m_boxtype == DM800) // dm800
536 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
537 for (; i != m_demux.end(); ++i, ++n)
548 if (i->m_adapter == fe->m_adapter &&
549 i->m_demux->getSource() == fe->m_frontend->getDVBID())
551 demux = new eDVBAllocatedDemux(i);
555 else if (i->m_demux->getSource() == -1) // PVR
557 demux = new eDVBAllocatedDemux(i);
563 else if (m_boxtype == DM7025) // ATI
565 /* FIXME: hardware demux policy */
566 if (!(cap & iDVBChannel::capDecode))
568 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
575 for (; i != m_demux.end(); ++i, ++n)
577 int is_decode = n < 2;
579 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
581 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
583 if ((cap & iDVBChannel::capDecode) && !is_decode)
590 else if (m_boxtype == DM8000 || m_boxtype == DM500HD || m_boxtype == DM800SE || m_boxtype == DM7020HD)
592 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 */
593 int source = fe ? fe->m_frontend->getDVBID() : -1;
594 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
598 * For pvr playback, start with the last demux.
599 * On some hardware, we have less ca devices than demuxes,
600 * so we should try to leave the first demuxes for live tv,
601 * and start with the last for pvr playback
606 while (i != m_demux.end())
608 if (i->m_adapter == adapter)
612 /* mark the first unused demux, we'll use that when we do not find a better match */
613 if (!unused) unused = i;
617 /* demux is in use, see if we can share it */
618 if (source >= 0 && i->m_demux->getSource() == source)
620 demux = new eDVBAllocatedDemux(i);
638 demux = new eDVBAllocatedDemux(unused);
640 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
642 demux->get().setSourcePVR(0);
646 eDebug("demux not found");
650 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
656 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
665 #define eDebugNoSimulate(x...) \
672 // eDebugNoNewLine("SIMULATE:"); \
677 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
679 /* first, check if a channel is already existing. */
680 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
682 if (!simulate && m_cached_channel)
684 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
685 if(channelid==cache_chan->getChannelID())
687 eDebug("use cached_channel");
688 channel = m_cached_channel;
691 m_cached_channel_state_changed_conn.disconnect();
693 m_releaseCachedChannelTimer->stop();
696 eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
697 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
699 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
700 if (i->m_channel_id == channelid)
702 eDebugNoSimulate("found shared channel..");
703 channel = i->m_channel;
708 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
712 eDebugNoSimulate("no channel list set!");
713 return errNoChannelList;
716 ePtr<iDVBFrontendParameters> feparm;
717 if (m_list->getChannelFrontendData(channelid, feparm))
719 eDebugNoSimulate("channel not found!");
720 return errChannelNotInList;
723 /* allocate a frontend. */
725 ePtr<eDVBAllocatedFrontend> fe;
727 int err = allocateFrontend(fe, feparm, simulate);
732 ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
734 res = ch->setChannel(channelid, feparm);
738 return errChidNotFound;
745 m_cached_channel = channel = ch;
746 m_cached_channel_state_changed_conn =
747 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
753 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
756 chan->getState(state);
759 case iDVBChannel::state_release:
760 case iDVBChannel::state_ok:
762 eDebug("stop release channel timer");
763 m_releaseCachedChannelTimer->stop();
766 case iDVBChannel::state_last_instance:
768 eDebug("start release channel timer");
769 m_releaseCachedChannelTimer->start(3000, true);
772 default: // ignore all other events
777 void eDVBResourceManager::releaseCachedChannel()
779 eDebug("release cached channel (timer timeout)");
783 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
785 ePtr<eDVBAllocatedFrontend> fe;
787 if (m_cached_channel)
789 m_cached_channel_state_changed_conn.disconnect();
791 m_releaseCachedChannelTimer->stop();
794 int err = allocateFrontendByIndex(fe, slot_index);
798 channel = new eDVBChannel(this, fe);
802 RESULT eDVBResourceManager::allocatePVRChannel(const eDVBChannelID &channelid, eUsePtr<iDVBPVRChannel> &channel)
804 ePtr<eDVBAllocatedDemux> demux;
806 if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
808 m_cached_channel_state_changed_conn.disconnect();
810 m_releaseCachedChannelTimer->stop();
813 ePtr<eDVBChannel> ch = new eDVBChannel(this, 0);
817 * user provided a channelid, with the clear intention for
818 * this channel to be registered at the resource manager.
819 * (allowing e.g. epgcache to be started)
821 ePtr<iDVBFrontendParameters> feparm;
822 ch->setChannel(channelid, feparm);
828 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
830 ePtr<iDVBFrontend> fe;
831 if (!ch->getFrontend(fe))
833 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
834 if (frontend->is_simulate())
835 m_active_simulate_channels.push_back(active_channel(chid, ch));
838 m_active_channels.push_back(active_channel(chid, ch));
839 /* emit */ m_channelAdded(ch);
845 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
847 ePtr<iDVBFrontend> fe;
848 if (!ch->getFrontend(fe))
850 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
851 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
853 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
855 if (i->m_channel == ch)
857 i = active_channels.erase(i);
869 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
871 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
875 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
877 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
878 ePtr<eDVBRegisteredFrontend> best;
881 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
884 int c = i->m_frontend->isCompatibleWith(feparm);
891 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid, int &system)
893 system = iDVBFrontend::feSatellite;
896 ePtr<iDVBFrontendParameters> feparm;
897 if (!channellist->getChannelFrontendData(chid, feparm))
899 if (!feparm->getSystem(system))
903 case iDVBFrontend::feSatellite:
905 case iDVBFrontend::feCable:
907 case iDVBFrontend::feTerrestrial:
918 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, int &system, bool simulate)
920 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
922 system = iDVBFrontend::feSatellite;
923 if (!simulate && m_cached_channel)
925 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
926 if(channelid==cache_chan->getChannelID())
927 return tuner_type_channel_default(m_list, channelid, system);
930 /* first, check if a channel is already existing. */
931 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
932 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
934 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
935 if (i->m_channel_id == channelid)
937 // eDebug("found shared channel..");
938 return tuner_type_channel_default(m_list, channelid, system);
942 int *decremented_cached_channel_fe_usecount=NULL,
943 *decremented_fe_usecount=NULL;
945 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
947 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
948 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
949 if (i->m_channel_id == ignore)
951 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
952 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
953 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
954 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
955 // or 2 when the cached channel is not equal to the compared channel
956 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
958 ePtr<iDVBFrontend> fe;
959 if (!i->m_channel->getFrontend(fe))
961 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
963 if ( &(*fe) == &(*ii->m_frontend) )
966 decremented_fe_usecount = &ii->m_inuse;
967 if (channel == &(*m_cached_channel))
968 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
978 if (!decremented_cached_channel_fe_usecount)
980 if (m_cached_channel)
982 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
983 if (channel->getUseCount() == 1)
985 ePtr<iDVBFrontend> fe;
986 if (!channel->getFrontend(fe))
988 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
989 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
991 if ( &(*fe) == &(*ii->m_frontend) )
994 decremented_cached_channel_fe_usecount = &ii->m_inuse;
1003 decremented_cached_channel_fe_usecount=NULL;
1005 ePtr<iDVBFrontendParameters> feparm;
1009 eDebug("no channel list set!");
1013 if (m_list->getChannelFrontendData(channelid, feparm))
1015 eDebug("channel not found!");
1018 feparm->getSystem(system);
1020 ret = canAllocateFrontend(feparm, simulate);
1023 if (decremented_fe_usecount)
1024 ++(*decremented_fe_usecount);
1025 if (decremented_cached_channel_fe_usecount)
1026 ++(*decremented_cached_channel_fe_usecount);
1031 bool eDVBResourceManager::canMeasureFrontendInputPower()
1033 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
1035 return i->m_frontend->readInputpower() >= 0;
1040 class eDVBChannelFilePush: public eFilePushThread
1043 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
1044 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
1046 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
1047 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
1048 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
1050 int m_iframe_search, m_iframe_state, m_pid;
1051 int m_timebase_change;
1052 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
1055 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
1058 if (m_timebase_change)
1060 eDebug("timebase change: %d", m_timebase_change);
1062 for (offset = 0; offset < len; offset += 188)
1064 unsigned char *pkt = (unsigned char*)_data + offset;
1065 if (pkt[1] & 0x40) /* pusi */
1067 if (pkt[3] & 0x20) // adaption field present?
1068 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
1070 pkt += 4; /* skip header */
1071 if (pkt[0] || pkt[1] || (pkt[2] != 1))
1073 eWarning("broken startcode");
1079 if (pkt[7] & 0x80) // PTS present?
1081 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
1082 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
1083 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
1084 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
1085 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
1089 RESULT r = m_tstools.fixupPTS(off, pts);
1091 eWarning("fixup PTS while trickmode playback failed.\n");
1094 int sec = pts / 90000;
1095 int frm = pts % 90000;
1103 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1105 pts += 0x80000000LL;
1106 pts *= m_timebase_change;
1118 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1126 pkt[9] |= (pts >> 29) & 0xE;
1127 pkt[10] |= (pts >> 22) & 0xFF;
1128 pkt[11] |= (pts >> 14) & 0xFE;
1129 pkt[12] |= (pts >> 7) & 0xFF;
1130 pkt[13] |= (pts << 1) & 0xFE;
1138 if (!m_iframe_search)
1141 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1143 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1145 unsigned char *d = data;
1146 while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1148 int offset = d - data;
1149 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1150 unsigned char *ts = data + ts_offset;
1151 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1153 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */
1155 int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1158 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1160 if (m_iframe_state == 1)
1162 /* we are allowing data, and stop allowing data on the next frame.
1163 we now found a frame. so stop here. */
1164 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1165 current_span_remaining = 0;
1167 unsigned char *fts = ts + 188;
1168 while (fts < (data + len))
1171 fts[2] |= 0xff; /* drop packet */
1175 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1178 if (picture_type != 1) /* we are only interested in I frames */
1181 unsigned char *fts = data;
1185 fts[2] |= 0xff; /* drop packet */
1192 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1194 /* verify that this is actually a PES header, not just some ES data */
1195 if (ts[1] & 0x40) /* PUSI set */
1197 int payload_start = 4;
1198 if (ts[3] & 0x20) /* adaptation field present */
1199 payload_start += ts[4] + 1; /* skip AF */
1200 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1204 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1212 d += 4; /* ignore */
1215 if (m_iframe_state == 1)
1218 return 0; /* we need find an iframe first */
1224 DEFINE_REF(eDVBChannel);
1226 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1228 m_frontend = frontend;
1233 m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1236 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1239 eDVBChannel::~eDVBChannel()
1242 m_mgr->removeChannel(this);
1247 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1249 int state, ourstate = 0;
1251 /* if we are already in shutdown, don't change state. */
1252 if (m_state == state_release)
1255 if (fe->getState(state))
1258 if (state == iDVBFrontend::stateLock)
1260 eDebug("OURSTATE: ok");
1261 ourstate = state_ok;
1262 } else if (state == iDVBFrontend::stateTuning)
1264 eDebug("OURSTATE: tuning");
1265 ourstate = state_tuning;
1266 } else if (state == iDVBFrontend::stateLostLock)
1268 /* on managed channels, we try to retune in order to re-acquire lock. */
1269 if (m_current_frontend_parameters)
1271 eDebug("OURSTATE: lost lock, trying to retune");
1272 ourstate = state_tuning;
1273 m_frontend->get().tune(*m_current_frontend_parameters);
1275 /* on unmanaged channels, we don't do this. the client will do this. */
1277 eDebug("OURSTATE: lost lock, unavailable now.");
1278 ourstate = state_unavailable;
1280 } else if (state == iDVBFrontend::stateFailed)
1283 if (m_current_frontend_parameters)
1285 eDebug("OURSTATE: lost lock, trying to retune");
1286 ourstate = state_tuning;
1287 m_frontend->get().tune(*m_current_frontend_parameters);
1291 eDebug("OURSTATE: failed");
1292 ourstate = state_failed;
1295 eDebug("OURSTATE: failed");
1296 ourstate = state_failed;
1299 eFatal("state unknown");
1301 if (ourstate != m_state)
1304 m_stateChanged(this);
1308 void eDVBChannel::pvrEvent(int event)
1312 case eFilePushThread::evtEOF:
1313 eDebug("eDVBChannel: End of file!");
1314 m_event(this, evtEOF);
1316 case eFilePushThread::evtUser: /* start */
1318 m_event(this, evtSOF);
1323 void eDVBChannel::cueSheetEvent(int event)
1325 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1330 case eCueSheet::evtSeek:
1332 flushPVR(m_cue->m_decoding_demux);
1334 case eCueSheet::evtSkipmode:
1337 m_cue->m_lock.WrLock();
1338 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1339 m_cue->m_lock.Unlock();
1340 eRdLocker l(m_cue->m_lock);
1341 if (m_cue->m_skipmode_ratio)
1343 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1344 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1345 /* i agree that this might look a bit like black magic. */
1346 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1347 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1348 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1349 m_skipmode_frames_remainder = 0;
1351 if (m_cue->m_skipmode_ratio < 0)
1352 m_skipmode_m -= m_skipmode_n;
1354 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1356 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1358 eWarning("something is wrong with this calculation");
1359 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1363 eDebug("skipmode ratio is 0, normal play");
1364 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1367 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1368 if (m_cue->m_skipmode_ratio != 0)
1369 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1371 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1372 eDebug("flush pvr");
1373 flushPVR(m_cue->m_decoding_demux);
1377 case eCueSheet::evtSpanChanged:
1379 m_source_span.clear();
1380 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1382 off_t offset_in, offset_out;
1383 pts_t pts_in = i->first, pts_out = i->second;
1384 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1386 eDebug("span translation failed.\n");
1389 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1390 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1397 /* align toward zero */
1398 static inline long long align(long long x, int align)
1413 /* align toward zero */
1414 static inline long long align_with_len(long long x, int align, size_t &len)
1431 /* remember, this gets called from another thread. */
1432 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1434 const int blocksize = 188;
1435 unsigned int max = align(10*1024*1024, blocksize);
1436 current_offset = align(current_offset, blocksize);
1440 eDebug("no cue sheet. forcing normal play");
1441 start = current_offset;
1448 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1449 max = align(m_skipmode_n, blocksize);
1452 eDebug("getNextSourceSpan, current offset is %08lld, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1453 int frame_skip_success = 0;
1457 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1458 eDebug("we are at %lld, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1460 off_t iframe_start = current_offset;
1461 int frames_skipped = frames_to_skip;
1462 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1464 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1465 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1466 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1467 max = align(iframe_len + 187, blocksize);
1468 frame_skip_success = 1;
1471 m_skipmode_frames_remainder = 0;
1472 eDebug("frame skipping failed, reverting to byte-skipping");
1476 if (!frame_skip_success)
1478 current_offset += align(m_skipmode_m, blocksize);
1479 if(current_offset < 0)
1485 eDebug("we are at %lld, and we try to find the iframe here:", current_offset);
1487 off_t start_offset = current_offset;
1488 off_t new_offset = start_offset;
1489 int direction = (m_skipmode_m < 0) ? -1 : +1;
1490 if (m_tstools.findFrame(start_offset, new_offset, iframe_len, direction))
1494 current_offset = align_with_len(new_offset, blocksize, iframe_len);
1495 max = align(iframe_len, blocksize);
1501 m_cue->m_lock.RdLock();
1503 while (!m_cue->m_seek_requests.empty())
1505 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1506 m_cue->m_lock.Unlock();
1507 m_cue->m_lock.WrLock();
1508 m_cue->m_seek_requests.pop_front();
1509 m_cue->m_lock.Unlock();
1510 m_cue->m_lock.RdLock();
1511 int relative = seek.first;
1512 pts_t pts = seek.second;
1517 if (!m_cue->m_decoder)
1519 eDebug("no decoder - can't seek relative");
1522 if (m_cue->m_decoder->getPTS(0, now))
1524 eDebug("decoder getPTS failed, can't seek relative");
1527 if (!m_cue->m_decoding_demux)
1529 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1530 start = current_offset;
1534 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1536 eDebug("seekTo: getCurrentPosition failed!");
1539 } else if (pts < 0) /* seek relative to end */
1542 if (!getLength(len))
1544 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1548 eWarning("getLength failed - can't seek relative to end!");
1553 if (relative == 1) /* pts relative */
1564 if (relative == 2) /* AP relative */
1566 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1568 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1570 pts = now - 90000; /* approx. 1s */
1571 eDebug("AP relative seeking failed!");
1575 eDebug("next ap is %llx\n", pts);
1580 if (m_tstools.getOffset(offset, pts, -1))
1582 eDebug("get offset for pts=%lld failed!", pts);
1586 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1587 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1590 m_cue->m_lock.Unlock();
1592 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1594 long long aligned_start = align(i->first, blocksize);
1595 long long aligned_end = align(i->second, blocksize);
1597 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1599 start = current_offset;
1600 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1601 if ((aligned_end - current_offset) > max)
1604 size = aligned_end - current_offset;
1605 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1608 if (current_offset < aligned_start)
1610 /* ok, our current offset is in an 'out' zone. */
1611 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1613 /* in normal playback, just start at the next zone. */
1616 /* size is not 64bit! */
1617 if ((i->second - i->first) > max)
1620 size = aligned_end - aligned_start;
1623 if (m_skipmode_m < 0)
1625 eDebug("reached SOF");
1628 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1632 /* when skipping reverse, however, choose the zone before. */
1634 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1637 aligned_start = align(i->first, blocksize);
1638 aligned_end = align(i->second, blocksize);
1640 if ((aligned_end - aligned_start) > max)
1643 len = aligned_end - aligned_start;
1645 start = aligned_end - len;
1646 eDebug("skipping to %llx, %zd", start, len);
1649 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1654 if(current_offset <0)
1656 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1658 eDebug("reached SOF");
1660 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1662 if (m_source_span.empty())
1664 start = current_offset;
1666 eDebug("NO CUESHEET. (%08lld, %zd)", start, size);
1669 start = current_offset;
1675 void eDVBChannel::AddUse()
1677 if (++m_use_count > 1 && m_state == state_last_instance)
1680 m_stateChanged(this);
1684 void eDVBChannel::ReleaseUse()
1688 m_state = state_release;
1689 m_stateChanged(this);
1691 else if (m_use_count == 1)
1693 m_state = state_last_instance;
1694 m_stateChanged(this);
1698 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1701 m_mgr->removeChannel(this);
1706 m_channel_id = channelid;
1707 m_mgr->addChannel(channelid, this);
1711 /* no frontend, no need to tune (must be a streamed service) */
1715 m_state = state_tuning;
1716 /* if tuning fails, shutdown the channel immediately. */
1718 res = m_frontend->get().tune(*feparm);
1719 m_current_frontend_parameters = feparm;
1723 m_state = state_release;
1724 m_stateChanged(this);
1731 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1733 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1737 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1739 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1743 RESULT eDVBChannel::getState(int &state)
1749 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1754 void eDVBChannel::SDTready(int result)
1756 ePyObject args = PyTuple_New(2), ret;
1760 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1763 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1764 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1770 PyTuple_SET_ITEM(args, 0, Py_None);
1771 PyTuple_SET_ITEM(args, 1, Py_None);
1775 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1779 Py_DECREF(m_tsid_onid_callback);
1780 m_tsid_onid_callback = ePyObject();
1781 m_tsid_onid_demux = 0;
1785 int eDVBChannel::reserveDemux()
1787 ePtr<iDVBDemux> dmx;
1788 if (!getDemux(dmx, 0))
1791 if (!dmx->getCADemuxID(id))
1797 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1799 if (PyCallable_Check(callback))
1801 if (!getDemux(m_tsid_onid_demux, 0))
1803 m_SDT = new eTable<ServiceDescriptionSection>;
1804 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1805 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1807 m_tsid_onid_demux = 0;
1812 Py_INCREF(callback);
1813 m_tsid_onid_callback = callback;
1821 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1823 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1825 if (m_frontend == NULL)
1827 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
1828 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
1835 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1840 /* don't hold a reference to the decoding demux, we don't need it. */
1842 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1843 the refcount is lost. thus, decoding demuxes are never allocated.
1845 this poses a big problem for PiP. */
1847 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1849 else if (cap & capDecode)
1858 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1863 frontend = &m_frontend->get();
1869 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1871 param = m_current_frontend_parameters;
1875 RESULT eDVBChannel::playFile(const char *file)
1877 eRawFile *f = new eRawFile();
1878 ePtr<iTsSource> source = f;
1880 if (f->open(file) < 0)
1882 eDebug("can't open PVR file %s (%m)", file);
1886 return playSource(source, file);
1889 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
1891 ASSERT(!m_frontend);
1894 m_pvr_thread->stop();
1895 delete m_pvr_thread;
1899 if (!source->valid() && !source->isStream())
1901 eDebug("PVR source is not valid!");
1905 m_tstools.setSource(source, streaminfo_file);
1907 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1908 THEN DO A REAL FIX HERE! */
1910 if (m_pvr_fd_dst < 0)
1912 /* (this codepath needs to be improved anyway.) */
1913 #if HAVE_DVB_API_VERSION < 3
1914 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1915 if (m_pvr_fd_dst < 0)
1917 eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1921 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
1924 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
1925 if (m_pvr_fd_dst < 0)
1927 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1933 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
1939 m_pvr_thread = new eDVBChannelFilePush();
1940 m_pvr_thread->enablePVRCommit(1);
1941 /* If the source specifies a length, it's a file. If not, it's a stream */
1942 m_pvr_thread->setStreamMode(source->isStream());
1943 m_pvr_thread->setScatterGather(this);
1945 m_event(this, evtPreStart);
1947 m_pvr_thread->start(source, m_pvr_fd_dst);
1948 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1951 m_stateChanged(this);
1956 void eDVBChannel::stopSource()
1960 m_pvr_thread->stop();
1961 delete m_pvr_thread;
1964 if (m_pvr_fd_dst >= 0)
1965 ::close(m_pvr_fd_dst);
1967 m_tstools.setSource(d);
1970 void eDVBChannel::stopFile()
1975 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1977 m_conn_cueSheetEvent = 0;
1980 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1983 RESULT eDVBChannel::getLength(pts_t &len)
1985 return m_tstools.calcLen(len);
1988 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1990 if (!decoding_demux)
1997 if (mode == 0) /* demux */
1999 r = decoding_demux->getSTC(now, 0);
2002 eDebug("demux getSTC failed");
2006 now = pos; /* fixup supplied */
2008 off_t off = 0; /* TODO: fixme */
2009 r = m_tstools.fixupPTS(off, now);
2012 eDebug("fixup PTS failed");
2021 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
2023 /* when seeking, we have to ensure that all buffers are flushed.
2024 there are basically 3 buffers:
2025 a.) the filepush's internal buffer
2026 b.) the PVR buffer (before demux)
2027 c.) the ratebuffer (after demux)
2029 it's important to clear them in the correct order, otherwise
2030 the ratebuffer (for example) would immediately refill from
2031 the not-yet-flushed PVR buffer.
2034 m_pvr_thread->pause();
2035 /* flush internal filepush buffer */
2036 m_pvr_thread->flush();
2037 /* HACK: flush PVR buffer */
2038 ::ioctl(m_pvr_fd_dst, 0);
2040 /* flush ratebuffers (video, audio) */
2042 decoding_demux->flush();
2044 /* demux will also flush all decoder.. */
2045 /* resume will re-query the SG */
2046 m_pvr_thread->resume();
2049 DEFINE_REF(eCueSheet);
2051 eCueSheet::eCueSheet()
2053 m_skipmode_ratio = 0;
2056 void eCueSheet::seekTo(int relative, const pts_t &pts)
2059 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
2064 void eCueSheet::clear()
2071 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2073 ASSERT(begin < end);
2075 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2079 void eCueSheet::commitSpans()
2081 m_event(evtSpanChanged);
2084 void eCueSheet::setSkipmode(const pts_t &ratio)
2087 m_skipmode_ratio = ratio;
2089 m_event(evtSkipmode);
2092 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2094 m_decoding_demux = demux;
2095 m_decoder = decoder;
2098 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2100 connection = new eConnection(this, m_event.connect(event));