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))
274 frontend->getFrontendType(frontendType);
275 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
276 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
277 m_frontend.push_back(new_fe);
278 frontend->setSEC(m_sec);
279 // we must link all dvb-t frontends ( for active antenna voltage )
280 if (frontendType == iDVBFrontend::feTerrestrial)
282 if (prev_dvbt_frontend)
284 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
285 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
287 prev_dvbt_frontend = new_fe;
292 prev_dvbt_frontend = 0;
293 for (i=0; i<num_fe; ++i)
295 ePtr<eDVBFrontend> frontend;
296 if (!adapter->getFrontend(frontend, i, true))
299 frontend->getFrontendType(frontendType);
300 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
301 // CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
302 m_simulate_frontend.push_back(new_fe);
303 frontend->setSEC(m_sec);
304 // we must link all dvb-t frontends ( for active antenna voltage )
305 if (frontendType == iDVBFrontend::feTerrestrial)
307 if (prev_dvbt_frontend)
309 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
310 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
312 prev_dvbt_frontend = new_fe;
319 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
321 if (!PyList_Check(list))
323 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
326 unsigned int assigned=0;
327 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
330 while (pos < PyList_Size(list)) {
331 ePyObject obj = PyList_GET_ITEM(list, pos++);
332 if (!i->m_frontend->setSlotInfo(obj))
338 if (assigned != m_frontend.size()) {
340 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %zd socket informations, but %d registered frontends!",
341 m_frontend.size(), assigned);
342 PyErr_SetString(PyExc_StandardError, blasel);
345 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
348 while (pos < PyList_Size(list)) {
349 ePyObject obj = PyList_GET_ITEM(list, pos++);
350 if (!i->m_frontend->setSlotInfo(obj))
358 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
360 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
361 ePtr<eDVBRegisteredFrontend> best;
365 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
367 int c = i->m_frontend->isCompatibleWith(feparm);
369 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
374 // eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
382 // eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
387 fe = new eDVBAllocatedFrontend(best);
394 return errAllSourcesBusy;
396 return errNoSourceFound;
399 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
401 int err = errNoSourceFound;
402 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
403 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
405 // check if another slot linked to this is in use
407 i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
410 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
411 if (satpos_depends_to_fe->m_inuse)
413 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
414 err = errAllSourcesBusy;
415 goto alloc_fe_by_id_not_possible;
418 else // check linked tuners
420 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
423 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
426 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
427 err = errAllSourcesBusy;
428 goto alloc_fe_by_id_not_possible;
430 next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
432 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
435 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
438 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
439 err = errAllSourcesBusy;
440 goto alloc_fe_by_id_not_possible;
442 prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
445 fe = new eDVBAllocatedFrontend(i);
448 alloc_fe_by_id_not_possible:
453 #define capHoldDecodeReference 64
455 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int &cap)
457 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
458 never use the first one unless we need a decoding demux. */
460 eDebug("allocate demux");
461 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
465 if (i == m_demux.end())
468 ePtr<eDVBRegisteredDemux> unused;
470 if (m_boxtype == DM800) // dm800
472 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
473 for (; i != m_demux.end(); ++i, ++n)
484 if (i->m_adapter == fe->m_adapter &&
485 i->m_demux->getSource() == fe->m_frontend->getDVBID())
487 demux = new eDVBAllocatedDemux(i);
491 else if (i->m_demux->getSource() == -1) // PVR
493 demux = new eDVBAllocatedDemux(i);
499 else if (m_boxtype == DM7025) // ATI
501 /* FIXME: hardware demux policy */
502 if (!(cap & iDVBChannel::capDecode))
504 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
511 for (; i != m_demux.end(); ++i, ++n)
513 int is_decode = n < 2;
515 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
517 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
519 if ((cap & iDVBChannel::capDecode) && !is_decode)
526 else if (m_boxtype == DM8000 || m_boxtype == DM500HD || m_boxtype == DM800SE || m_boxtype == DM7020HD)
528 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 */
529 int source = fe ? fe->m_frontend->getDVBID() : -1;
530 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
534 * For pvr playback, start with the last demux.
535 * On some hardware, we have less ca devices than demuxes,
536 * so we should try to leave the first demuxes for live tv,
537 * and start with the last for pvr playback
542 while (i != m_demux.end())
544 if (i->m_adapter == adapter)
548 /* mark the first unused demux, we'll use that when we do not find a better match */
549 if (!unused) unused = i;
553 /* demux is in use, see if we can share it */
554 if (source >= 0 && i->m_demux->getSource() == source)
556 demux = new eDVBAllocatedDemux(i);
574 demux = new eDVBAllocatedDemux(unused);
576 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
578 demux->get().setSourcePVR(0);
582 eDebug("demux not found");
586 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
592 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
601 #define eDebugNoSimulate(x...) \
608 // eDebugNoNewLine("SIMULATE:"); \
613 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
615 /* first, check if a channel is already existing. */
616 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
618 if (!simulate && m_cached_channel)
620 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
621 if(channelid==cache_chan->getChannelID())
623 eDebug("use cached_channel");
624 channel = m_cached_channel;
627 m_cached_channel_state_changed_conn.disconnect();
629 m_releaseCachedChannelTimer->stop();
632 eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
633 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
635 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
636 if (i->m_channel_id == channelid)
638 eDebugNoSimulate("found shared channel..");
639 channel = i->m_channel;
644 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
648 eDebugNoSimulate("no channel list set!");
649 return errNoChannelList;
652 ePtr<iDVBFrontendParameters> feparm;
653 if (m_list->getChannelFrontendData(channelid, feparm))
655 eDebugNoSimulate("channel not found!");
656 return errChannelNotInList;
659 /* allocate a frontend. */
661 ePtr<eDVBAllocatedFrontend> fe;
663 int err = allocateFrontend(fe, feparm, simulate);
668 ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
670 res = ch->setChannel(channelid, feparm);
674 return errChidNotFound;
681 m_cached_channel = channel = ch;
682 m_cached_channel_state_changed_conn =
683 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
689 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
692 chan->getState(state);
695 case iDVBChannel::state_release:
696 case iDVBChannel::state_ok:
698 eDebug("stop release channel timer");
699 m_releaseCachedChannelTimer->stop();
702 case iDVBChannel::state_last_instance:
704 eDebug("start release channel timer");
705 m_releaseCachedChannelTimer->start(3000, true);
708 default: // ignore all other events
713 void eDVBResourceManager::releaseCachedChannel()
715 eDebug("release cached channel (timer timeout)");
719 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
721 ePtr<eDVBAllocatedFrontend> fe;
723 if (m_cached_channel)
725 m_cached_channel_state_changed_conn.disconnect();
727 m_releaseCachedChannelTimer->stop();
730 int err = allocateFrontendByIndex(fe, slot_index);
734 channel = new eDVBChannel(this, fe);
738 RESULT eDVBResourceManager::allocatePVRChannel(const eDVBChannelID &channelid, eUsePtr<iDVBPVRChannel> &channel)
740 ePtr<eDVBAllocatedDemux> demux;
742 if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
744 m_cached_channel_state_changed_conn.disconnect();
746 m_releaseCachedChannelTimer->stop();
749 ePtr<eDVBChannel> ch = new eDVBChannel(this, 0);
753 * user provided a channelid, with the clear intention for
754 * this channel to be registered at the resource manager.
755 * (allowing e.g. epgcache to be started)
757 ePtr<iDVBFrontendParameters> feparm;
758 ch->setChannel(channelid, feparm);
764 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
766 ePtr<iDVBFrontend> fe;
767 if (!ch->getFrontend(fe))
769 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
770 if (frontend->is_simulate())
771 m_active_simulate_channels.push_back(active_channel(chid, ch));
774 m_active_channels.push_back(active_channel(chid, ch));
775 /* emit */ m_channelAdded(ch);
781 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
783 ePtr<iDVBFrontend> fe;
784 if (!ch->getFrontend(fe))
786 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
787 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
789 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
791 if (i->m_channel == ch)
793 i = active_channels.erase(i);
805 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
807 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
811 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
813 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
814 ePtr<eDVBRegisteredFrontend> best;
817 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
820 int c = i->m_frontend->isCompatibleWith(feparm);
827 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
831 ePtr<iDVBFrontendParameters> feparm;
832 if (!channellist->getChannelFrontendData(chid, feparm))
835 if (!feparm->getSystem(system))
839 case iDVBFrontend::feSatellite:
841 case iDVBFrontend::feCable:
843 case iDVBFrontend::feTerrestrial:
854 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, bool simulate)
856 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
858 if (!simulate && m_cached_channel)
860 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
861 if(channelid==cache_chan->getChannelID())
862 return tuner_type_channel_default(m_list, channelid);
865 /* first, check if a channel is already existing. */
866 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
867 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
869 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
870 if (i->m_channel_id == channelid)
872 // eDebug("found shared channel..");
873 return tuner_type_channel_default(m_list, channelid);
877 int *decremented_cached_channel_fe_usecount=NULL,
878 *decremented_fe_usecount=NULL;
880 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
882 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
883 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
884 if (i->m_channel_id == ignore)
886 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
887 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
888 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
889 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
890 // or 2 when the cached channel is not equal to the compared channel
891 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
893 ePtr<iDVBFrontend> fe;
894 if (!i->m_channel->getFrontend(fe))
896 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
898 if ( &(*fe) == &(*ii->m_frontend) )
901 decremented_fe_usecount = &ii->m_inuse;
902 if (channel == &(*m_cached_channel))
903 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
913 if (!decremented_cached_channel_fe_usecount)
915 if (m_cached_channel)
917 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
918 if (channel->getUseCount() == 1)
920 ePtr<iDVBFrontend> fe;
921 if (!channel->getFrontend(fe))
923 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
924 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
926 if ( &(*fe) == &(*ii->m_frontend) )
929 decremented_cached_channel_fe_usecount = &ii->m_inuse;
938 decremented_cached_channel_fe_usecount=NULL;
940 ePtr<iDVBFrontendParameters> feparm;
944 eDebug("no channel list set!");
948 if (m_list->getChannelFrontendData(channelid, feparm))
950 eDebug("channel not found!");
954 ret = canAllocateFrontend(feparm, simulate);
957 if (decremented_fe_usecount)
958 ++(*decremented_fe_usecount);
959 if (decremented_cached_channel_fe_usecount)
960 ++(*decremented_cached_channel_fe_usecount);
965 bool eDVBResourceManager::canMeasureFrontendInputPower()
967 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
969 return i->m_frontend->readInputpower() >= 0;
974 class eDVBChannelFilePush: public eFilePushThread
977 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
978 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
980 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
981 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
982 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
984 int m_iframe_search, m_iframe_state, m_pid;
985 int m_timebase_change;
986 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
989 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
992 if (m_timebase_change)
994 eDebug("timebase change: %d", m_timebase_change);
996 for (offset = 0; offset < len; offset += 188)
998 unsigned char *pkt = (unsigned char*)_data + offset;
999 if (pkt[1] & 0x40) /* pusi */
1001 if (pkt[3] & 0x20) // adaption field present?
1002 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
1004 pkt += 4; /* skip header */
1005 if (pkt[0] || pkt[1] || (pkt[2] != 1))
1007 eWarning("broken startcode");
1013 if (pkt[7] & 0x80) // PTS present?
1015 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
1016 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
1017 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
1018 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
1019 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
1023 RESULT r = m_tstools.fixupPTS(off, pts);
1025 eWarning("fixup PTS while trickmode playback failed.\n");
1028 int sec = pts / 90000;
1029 int frm = pts % 90000;
1037 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1039 pts += 0x80000000LL;
1040 pts *= m_timebase_change;
1052 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1060 pkt[9] |= (pts >> 29) & 0xE;
1061 pkt[10] |= (pts >> 22) & 0xFF;
1062 pkt[11] |= (pts >> 14) & 0xFE;
1063 pkt[12] |= (pts >> 7) & 0xFF;
1064 pkt[13] |= (pts << 1) & 0xFE;
1072 if (!m_iframe_search)
1075 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1077 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1079 unsigned char *d = data;
1080 while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1082 int offset = d - data;
1083 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1084 unsigned char *ts = data + ts_offset;
1085 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1087 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */
1089 int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1092 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1094 if (m_iframe_state == 1)
1096 /* we are allowing data, and stop allowing data on the next frame.
1097 we now found a frame. so stop here. */
1098 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1099 current_span_remaining = 0;
1101 unsigned char *fts = ts + 188;
1102 while (fts < (data + len))
1105 fts[2] |= 0xff; /* drop packet */
1109 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1112 if (picture_type != 1) /* we are only interested in I frames */
1115 unsigned char *fts = data;
1119 fts[2] |= 0xff; /* drop packet */
1126 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1128 /* verify that this is actually a PES header, not just some ES data */
1129 if (ts[1] & 0x40) /* PUSI set */
1131 int payload_start = 4;
1132 if (ts[3] & 0x20) /* adaptation field present */
1133 payload_start += ts[4] + 1; /* skip AF */
1134 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1138 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1146 d += 4; /* ignore */
1149 if (m_iframe_state == 1)
1152 return 0; /* we need find an iframe first */
1158 DEFINE_REF(eDVBChannel);
1160 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1162 m_frontend = frontend;
1167 m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1170 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1173 eDVBChannel::~eDVBChannel()
1176 m_mgr->removeChannel(this);
1181 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1183 int state, ourstate = 0;
1185 /* if we are already in shutdown, don't change state. */
1186 if (m_state == state_release)
1189 if (fe->getState(state))
1192 if (state == iDVBFrontend::stateLock)
1194 eDebug("OURSTATE: ok");
1195 ourstate = state_ok;
1196 } else if (state == iDVBFrontend::stateTuning)
1198 eDebug("OURSTATE: tuning");
1199 ourstate = state_tuning;
1200 } else if (state == iDVBFrontend::stateLostLock)
1202 /* on managed channels, we try to retune in order to re-acquire lock. */
1203 if (m_current_frontend_parameters)
1205 eDebug("OURSTATE: lost lock, trying to retune");
1206 ourstate = state_tuning;
1207 m_frontend->get().tune(*m_current_frontend_parameters);
1209 /* on unmanaged channels, we don't do this. the client will do this. */
1211 eDebug("OURSTATE: lost lock, unavailable now.");
1212 ourstate = state_unavailable;
1214 } else if (state == iDVBFrontend::stateFailed)
1216 #ifdef BUILD_VUPLUS /* ikseong */
1217 if (m_current_frontend_parameters)
1219 eDebug("OURSTATE: lost lock, trying to retune");
1220 ourstate = state_tuning;
1221 m_frontend->get().tune(*m_current_frontend_parameters);
1225 eDebug("OURSTATE: failed");
1226 ourstate = state_failed;
1229 eDebug("OURSTATE: failed");
1230 ourstate = state_failed;
1233 eFatal("state unknown");
1235 if (ourstate != m_state)
1238 m_stateChanged(this);
1242 void eDVBChannel::pvrEvent(int event)
1246 case eFilePushThread::evtEOF:
1247 eDebug("eDVBChannel: End of file!");
1248 m_event(this, evtEOF);
1250 case eFilePushThread::evtUser: /* start */
1252 m_event(this, evtSOF);
1257 void eDVBChannel::cueSheetEvent(int event)
1259 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1264 case eCueSheet::evtSeek:
1266 flushPVR(m_cue->m_decoding_demux);
1268 case eCueSheet::evtSkipmode:
1271 m_cue->m_lock.WrLock();
1272 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1273 m_cue->m_lock.Unlock();
1274 eRdLocker l(m_cue->m_lock);
1275 if (m_cue->m_skipmode_ratio)
1277 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1278 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1279 /* i agree that this might look a bit like black magic. */
1280 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1281 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1282 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1283 m_skipmode_frames_remainder = 0;
1285 if (m_cue->m_skipmode_ratio < 0)
1286 m_skipmode_m -= m_skipmode_n;
1288 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1290 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1292 eWarning("something is wrong with this calculation");
1293 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1297 eDebug("skipmode ratio is 0, normal play");
1298 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1301 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1302 if (m_cue->m_skipmode_ratio != 0)
1303 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1305 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1306 eDebug("flush pvr");
1307 flushPVR(m_cue->m_decoding_demux);
1311 case eCueSheet::evtSpanChanged:
1313 m_source_span.clear();
1314 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1316 off_t offset_in, offset_out;
1317 pts_t pts_in = i->first, pts_out = i->second;
1318 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1320 eDebug("span translation failed.\n");
1323 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1324 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1331 /* align toward zero */
1332 static inline long long align(long long x, int align)
1347 /* align toward zero */
1348 static inline long long align_with_len(long long x, int align, size_t &len)
1364 /* remember, this gets called from another thread. */
1365 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1367 const int blocksize = 188;
1368 unsigned int max = align(10*1024*1024, blocksize);
1369 current_offset = align(current_offset, blocksize);
1373 eDebug("no cue sheet. forcing normal play");
1374 start = current_offset;
1381 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1382 max = align(m_skipmode_n, blocksize);
1385 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1386 int frame_skip_success = 0;
1390 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1391 eDebug("we are at %llx, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1393 off_t iframe_start = current_offset;
1394 int frames_skipped = frames_to_skip;
1395 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1397 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1398 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1399 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1400 max = align(iframe_len + 187, blocksize);
1401 frame_skip_success = 1;
1404 m_skipmode_frames_remainder = 0;
1405 eDebug("frame skipping failed, reverting to byte-skipping");
1409 if (!frame_skip_success)
1411 current_offset += align(m_skipmode_m, blocksize);
1415 eDebug("we are at %llx, and we try to find the iframe here:", current_offset);
1417 off_t iframe_start = current_offset;
1419 int direction = (m_skipmode_m < 0) ? -1 : +1;
1420 if (m_tstools.findFrame(iframe_start, iframe_len, direction))
1424 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1425 max = align(iframe_len, blocksize);
1430 m_cue->m_lock.RdLock();
1432 while (!m_cue->m_seek_requests.empty())
1434 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1435 m_cue->m_lock.Unlock();
1436 m_cue->m_lock.WrLock();
1437 m_cue->m_seek_requests.pop_front();
1438 m_cue->m_lock.Unlock();
1439 m_cue->m_lock.RdLock();
1440 int relative = seek.first;
1441 pts_t pts = seek.second;
1446 if (!m_cue->m_decoder)
1448 eDebug("no decoder - can't seek relative");
1451 if (m_cue->m_decoder->getPTS(0, now))
1453 eDebug("decoder getPTS failed, can't seek relative");
1456 if (!m_cue->m_decoding_demux)
1458 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1459 start = current_offset;
1463 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1465 eDebug("seekTo: getCurrentPosition failed!");
1468 } else if (pts < 0) /* seek relative to end */
1471 if (!getLength(len))
1473 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1477 eWarning("getLength failed - can't seek relative to end!");
1482 if (relative == 1) /* pts relative */
1493 if (relative == 2) /* AP relative */
1495 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1497 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1499 pts = now - 90000; /* approx. 1s */
1500 eDebug("AP relative seeking failed!");
1504 eDebug("next ap is %llx\n", pts);
1509 if (m_tstools.getOffset(offset, pts, -1))
1511 eDebug("get offset for pts=%lld failed!", pts);
1515 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1516 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1519 m_cue->m_lock.Unlock();
1521 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1523 long long aligned_start = align(i->first, blocksize);
1524 long long aligned_end = align(i->second, blocksize);
1526 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1528 start = current_offset;
1529 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1530 if ((aligned_end - current_offset) > max)
1533 size = aligned_end - current_offset;
1534 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1537 if (current_offset < aligned_start)
1539 /* ok, our current offset is in an 'out' zone. */
1540 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1542 /* in normal playback, just start at the next zone. */
1545 /* size is not 64bit! */
1546 if ((i->second - i->first) > max)
1549 size = aligned_end - aligned_start;
1552 if (m_skipmode_m < 0)
1554 eDebug("reached SOF");
1557 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1561 /* when skipping reverse, however, choose the zone before. */
1563 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1566 aligned_start = align(i->first, blocksize);
1567 aligned_end = align(i->second, blocksize);
1569 if ((aligned_end - aligned_start) > max)
1572 len = aligned_end - aligned_start;
1574 start = aligned_end - len;
1575 eDebug("skipping to %llx, %zd", start, len);
1578 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1583 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1585 eDebug("reached SOF");
1587 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1590 if (m_source_span.empty())
1592 start = current_offset;
1594 eDebug("NO CUESHEET. (%08llx, %zd)", start, size);
1597 start = current_offset;
1603 void eDVBChannel::AddUse()
1605 if (++m_use_count > 1 && m_state == state_last_instance)
1608 m_stateChanged(this);
1612 void eDVBChannel::ReleaseUse()
1616 m_state = state_release;
1617 m_stateChanged(this);
1619 else if (m_use_count == 1)
1621 m_state = state_last_instance;
1622 m_stateChanged(this);
1626 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1629 m_mgr->removeChannel(this);
1634 m_channel_id = channelid;
1635 m_mgr->addChannel(channelid, this);
1639 /* no frontend, no need to tune (must be a streamed service) */
1643 m_state = state_tuning;
1644 /* if tuning fails, shutdown the channel immediately. */
1646 res = m_frontend->get().tune(*feparm);
1647 m_current_frontend_parameters = feparm;
1651 m_state = state_release;
1652 m_stateChanged(this);
1659 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1661 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1665 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1667 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1671 RESULT eDVBChannel::getState(int &state)
1677 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1682 void eDVBChannel::SDTready(int result)
1684 ePyObject args = PyTuple_New(2), ret;
1688 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1691 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1692 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1698 PyTuple_SET_ITEM(args, 0, Py_None);
1699 PyTuple_SET_ITEM(args, 1, Py_None);
1703 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1707 Py_DECREF(m_tsid_onid_callback);
1708 m_tsid_onid_callback = ePyObject();
1709 m_tsid_onid_demux = 0;
1713 int eDVBChannel::reserveDemux()
1715 ePtr<iDVBDemux> dmx;
1716 if (!getDemux(dmx, 0))
1719 if (!dmx->getCADemuxID(id))
1725 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1727 if (PyCallable_Check(callback))
1729 if (!getDemux(m_tsid_onid_demux, 0))
1731 m_SDT = new eTable<ServiceDescriptionSection>;
1732 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1733 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1735 m_tsid_onid_demux = 0;
1740 Py_INCREF(callback);
1741 m_tsid_onid_callback = callback;
1749 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1751 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1753 if (m_frontend == NULL)
1755 /* in dvr mode, we have to stick to a single demux (the one connected to our dvr device) */
1756 our_demux = m_decoder_demux ? m_decoder_demux : m_demux;
1763 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1768 /* don't hold a reference to the decoding demux, we don't need it. */
1770 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1771 the refcount is lost. thus, decoding demuxes are never allocated.
1773 this poses a big problem for PiP. */
1775 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1777 else if (cap & capDecode)
1786 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1791 frontend = &m_frontend->get();
1797 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1799 param = m_current_frontend_parameters;
1803 RESULT eDVBChannel::playFile(const char *file)
1805 eRawFile *f = new eRawFile();
1806 ePtr<iTsSource> source = f;
1808 if (f->open(file) < 0)
1810 eDebug("can't open PVR file %s (%m)", file);
1814 return playSource(source, file);
1817 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
1819 ASSERT(!m_frontend);
1822 m_pvr_thread->stop();
1823 delete m_pvr_thread;
1827 if (!source->valid())
1829 eDebug("PVR source is not valid!");
1833 m_tstools.setSource(source, streaminfo_file);
1835 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1836 THEN DO A REAL FIX HERE! */
1838 if (m_pvr_fd_dst < 0)
1840 /* (this codepath needs to be improved anyway.) */
1841 #if HAVE_DVB_API_VERSION < 3
1842 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1843 if (m_pvr_fd_dst < 0)
1845 eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1849 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
1852 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
1853 if (m_pvr_fd_dst < 0)
1855 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1861 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
1867 m_pvr_thread = new eDVBChannelFilePush();
1868 m_pvr_thread->enablePVRCommit(1);
1869 /* If the source specifies a length, it's a file. If not, it's a stream */
1870 m_pvr_thread->setStreamMode(source->length() <= 0);
1871 m_pvr_thread->setScatterGather(this);
1873 m_event(this, evtPreStart);
1875 m_pvr_thread->start(source, m_pvr_fd_dst);
1876 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1879 m_stateChanged(this);
1884 void eDVBChannel::stopSource()
1888 m_pvr_thread->stop();
1889 delete m_pvr_thread;
1892 if (m_pvr_fd_dst >= 0)
1893 ::close(m_pvr_fd_dst);
1895 m_tstools.setSource(d);
1898 void eDVBChannel::stopFile()
1903 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1905 m_conn_cueSheetEvent = 0;
1908 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1911 RESULT eDVBChannel::getLength(pts_t &len)
1913 return m_tstools.calcLen(len);
1916 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1918 if (!decoding_demux)
1925 if (mode == 0) /* demux */
1927 r = decoding_demux->getSTC(now, 0);
1930 eDebug("demux getSTC failed");
1934 now = pos; /* fixup supplied */
1936 off_t off = 0; /* TODO: fixme */
1937 r = m_tstools.fixupPTS(off, now);
1940 eDebug("fixup PTS failed");
1949 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1951 /* when seeking, we have to ensure that all buffers are flushed.
1952 there are basically 3 buffers:
1953 a.) the filepush's internal buffer
1954 b.) the PVR buffer (before demux)
1955 c.) the ratebuffer (after demux)
1957 it's important to clear them in the correct order, otherwise
1958 the ratebuffer (for example) would immediately refill from
1959 the not-yet-flushed PVR buffer.
1962 m_pvr_thread->pause();
1963 /* flush internal filepush buffer */
1964 m_pvr_thread->flush();
1965 /* HACK: flush PVR buffer */
1966 ::ioctl(m_pvr_fd_dst, 0);
1968 /* flush ratebuffers (video, audio) */
1970 decoding_demux->flush();
1972 /* demux will also flush all decoder.. */
1973 /* resume will re-query the SG */
1974 m_pvr_thread->resume();
1977 DEFINE_REF(eCueSheet);
1979 eCueSheet::eCueSheet()
1981 m_skipmode_ratio = 0;
1984 void eCueSheet::seekTo(int relative, const pts_t &pts)
1987 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1992 void eCueSheet::clear()
1999 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
2001 ASSERT(begin < end);
2003 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
2007 void eCueSheet::commitSpans()
2009 m_event(evtSpanChanged);
2012 void eCueSheet::setSkipmode(const pts_t &ratio)
2015 m_skipmode_ratio = ratio;
2017 m_event(evtSkipmode);
2020 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
2022 m_decoding_demux = demux;
2023 m_decoder = decoder;
2026 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
2028 connection = new eConnection(this, m_event.connect(event));