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))
148 ePtr<eDVBFrontend> fe;
152 fe = new eDVBFrontend(m_nr, num_fe, ok);
154 m_frontend.push_back(fe);
158 fe = new eDVBFrontend(m_nr, num_fe, ok, true);
160 m_simulate_frontend.push_back(fe);
171 #if HAVE_DVB_API_VERSION < 3
172 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
174 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
176 if (stat(filename, &s))
178 ePtr<eDVBDemux> demux;
180 demux = new eDVBDemux(m_nr, num_demux);
181 m_demux.push_back(demux);
187 int eDVBAdapterLinux::getNumDemux()
189 return m_demux.size();
192 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
194 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
195 while (nr && (i != m_demux.end()))
201 if (i != m_demux.end())
209 int eDVBAdapterLinux::getNumFrontends()
211 return m_frontend.size();
214 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr, bool simulate)
216 eSmartPtrList<eDVBFrontend>::iterator i(simulate ? m_simulate_frontend.begin() : m_frontend.begin());
217 while (nr && (i != m_frontend.end()))
223 if (i != m_frontend.end())
231 int eDVBAdapterLinux::exist(int nr)
235 #if HAVE_DVB_API_VERSION < 3
236 sprintf(filename, "/dev/dvb/card%d", nr);
238 sprintf(filename, "/dev/dvb/adapter%d", nr);
240 if (!stat(filename, &s))
245 eDVBResourceManager::~eDVBResourceManager()
247 if (instance == this)
251 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
253 int num_fe = adapter->getNumFrontends();
254 int num_demux = adapter->getNumDemux();
256 m_adapter.push_back(adapter);
259 for (i=0; i<num_demux; ++i)
261 ePtr<eDVBDemux> demux;
262 if (!adapter->getDemux(demux, i))
263 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
266 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
267 for (i=0; i<num_fe; ++i)
269 ePtr<eDVBFrontend> frontend;
270 if (!adapter->getFrontend(frontend, i))
273 frontend->getFrontendType(frontendType);
274 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
275 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
276 m_frontend.push_back(new_fe);
277 frontend->setSEC(m_sec);
278 // we must link all dvb-t frontends ( for active antenna voltage )
279 if (frontendType == iDVBFrontend::feTerrestrial)
281 if (prev_dvbt_frontend)
283 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
284 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
286 prev_dvbt_frontend = new_fe;
291 prev_dvbt_frontend = 0;
292 for (i=0; i<num_fe; ++i)
294 ePtr<eDVBFrontend> frontend;
295 if (!adapter->getFrontend(frontend, i, true))
298 frontend->getFrontendType(frontendType);
299 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
300 // CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
301 m_simulate_frontend.push_back(new_fe);
302 frontend->setSEC(m_sec);
303 // we must link all dvb-t frontends ( for active antenna voltage )
304 if (frontendType == iDVBFrontend::feTerrestrial)
306 if (prev_dvbt_frontend)
308 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
309 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
311 prev_dvbt_frontend = new_fe;
318 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
320 if (!PyList_Check(list))
322 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
325 unsigned int assigned=0;
326 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
329 while (pos < PyList_Size(list)) {
330 ePyObject obj = PyList_GET_ITEM(list, pos++);
331 if (!i->m_frontend->setSlotInfo(obj))
337 if (assigned != m_frontend.size()) {
339 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations .. assigned %zd socket informations, but %d registered frontends!",
340 m_frontend.size(), assigned);
341 PyErr_SetString(PyExc_StandardError, blasel);
344 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
347 while (pos < PyList_Size(list)) {
348 ePyObject obj = PyList_GET_ITEM(list, pos++);
349 if (!i->m_frontend->setSlotInfo(obj))
357 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
359 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
360 ePtr<eDVBRegisteredFrontend> best;
364 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
366 int c = i->m_frontend->isCompatibleWith(feparm);
368 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
373 // eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
381 // eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
386 fe = new eDVBAllocatedFrontend(best);
393 return errAllSourcesBusy;
395 return errNoSourceFound;
398 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
400 int err = errNoSourceFound;
401 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
402 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
404 // check if another slot linked to this is in use
406 i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
409 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
410 if (satpos_depends_to_fe->m_inuse)
412 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
413 err = errAllSourcesBusy;
414 goto alloc_fe_by_id_not_possible;
417 else // check linked tuners
419 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
422 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
425 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
426 err = errAllSourcesBusy;
427 goto alloc_fe_by_id_not_possible;
429 next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
431 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
434 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
437 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
438 err = errAllSourcesBusy;
439 goto alloc_fe_by_id_not_possible;
441 prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
444 fe = new eDVBAllocatedFrontend(i);
447 alloc_fe_by_id_not_possible:
452 #define capHoldDecodeReference 64
454 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int &cap)
456 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
457 never use the first one unless we need a decoding demux. */
459 eDebug("allocate demux");
460 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
464 if (i == m_demux.end())
467 ePtr<eDVBRegisteredDemux> unused;
469 if (m_boxtype == DM800) // dm800
471 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
472 for (; i != m_demux.end(); ++i, ++n)
483 if (i->m_adapter == fe->m_adapter &&
484 i->m_demux->getSource() == fe->m_frontend->getDVBID())
486 demux = new eDVBAllocatedDemux(i);
490 else if (i->m_demux->getSource() == -1) // PVR
492 demux = new eDVBAllocatedDemux(i);
498 else if (m_boxtype == DM7025) // ATI
500 /* FIXME: hardware demux policy */
501 if (!(cap & iDVBChannel::capDecode))
503 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
510 for (; i != m_demux.end(); ++i, ++n)
512 int is_decode = n < 2;
514 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
516 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
518 if ((cap & iDVBChannel::capDecode) && !is_decode)
525 else if (m_boxtype == DM8000 || m_boxtype == DM500HD || m_boxtype == DM800SE || m_boxtype == DM7020HD)
527 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
528 for (; i != m_demux.end(); ++i, ++n)
537 else if (i->m_adapter == fe->m_adapter &&
538 i->m_demux->getSource() == fe->m_frontend->getDVBID())
540 demux = new eDVBAllocatedDemux(i);
544 else if (n == 4) // always use demux4 for PVR (demux 4 can not descramble...)
547 demux = new eDVBAllocatedDemux(i);
557 demux = new eDVBAllocatedDemux(unused);
559 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
561 demux->get().setSourcePVR(0);
565 eDebug("demux not found");
569 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
575 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
584 #define eDebugNoSimulate(x...) \
591 // eDebugNoNewLine("SIMULATE:"); \
596 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
598 /* first, check if a channel is already existing. */
599 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
601 if (!simulate && m_cached_channel)
603 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
604 if(channelid==cache_chan->getChannelID())
606 eDebug("use cached_channel");
607 channel = m_cached_channel;
610 m_cached_channel_state_changed_conn.disconnect();
612 m_releaseCachedChannelTimer->stop();
615 eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
616 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
618 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
619 if (i->m_channel_id == channelid)
621 eDebugNoSimulate("found shared channel..");
622 channel = i->m_channel;
627 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
631 eDebugNoSimulate("no channel list set!");
632 return errNoChannelList;
635 ePtr<iDVBFrontendParameters> feparm;
636 if (m_list->getChannelFrontendData(channelid, feparm))
638 eDebugNoSimulate("channel not found!");
639 return errChannelNotInList;
642 /* allocate a frontend. */
644 ePtr<eDVBAllocatedFrontend> fe;
646 int err = allocateFrontend(fe, feparm, simulate);
651 ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
653 res = ch->setChannel(channelid, feparm);
657 return errChidNotFound;
664 m_cached_channel = channel = ch;
665 m_cached_channel_state_changed_conn =
666 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
672 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
675 chan->getState(state);
678 case iDVBChannel::state_release:
679 case iDVBChannel::state_ok:
681 eDebug("stop release channel timer");
682 m_releaseCachedChannelTimer->stop();
685 case iDVBChannel::state_last_instance:
687 eDebug("start release channel timer");
688 m_releaseCachedChannelTimer->start(3000, true);
691 default: // ignore all other events
696 void eDVBResourceManager::releaseCachedChannel()
698 eDebug("release cached channel (timer timeout)");
702 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
704 ePtr<eDVBAllocatedFrontend> fe;
706 if (m_cached_channel)
708 m_cached_channel_state_changed_conn.disconnect();
710 m_releaseCachedChannelTimer->stop();
713 int err = allocateFrontendByIndex(fe, slot_index);
717 channel = new eDVBChannel(this, fe);
722 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
724 ePtr<eDVBAllocatedDemux> demux;
726 if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
728 m_cached_channel_state_changed_conn.disconnect();
730 m_releaseCachedChannelTimer->stop();
733 channel = new eDVBChannel(this, 0);
737 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
739 ePtr<iDVBFrontend> fe;
740 if (!ch->getFrontend(fe))
742 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
743 if (frontend->is_simulate())
744 m_active_simulate_channels.push_back(active_channel(chid, ch));
747 m_active_channels.push_back(active_channel(chid, ch));
748 /* emit */ m_channelAdded(ch);
754 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
756 ePtr<iDVBFrontend> fe;
757 if (!ch->getFrontend(fe))
759 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
760 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
762 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
764 if (i->m_channel == ch)
766 i = active_channels.erase(i);
778 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
780 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
784 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
786 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
787 ePtr<eDVBRegisteredFrontend> best;
790 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
793 int c = i->m_frontend->isCompatibleWith(feparm);
800 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
804 ePtr<iDVBFrontendParameters> feparm;
805 if (!channellist->getChannelFrontendData(chid, feparm))
808 if (!feparm->getSystem(system))
812 case iDVBFrontend::feSatellite:
814 case iDVBFrontend::feCable:
816 case iDVBFrontend::feTerrestrial:
827 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, bool simulate)
829 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
831 if (!simulate && m_cached_channel)
833 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
834 if(channelid==cache_chan->getChannelID())
835 return tuner_type_channel_default(m_list, channelid);
838 /* first, check if a channel is already existing. */
839 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
840 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
842 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
843 if (i->m_channel_id == channelid)
845 // eDebug("found shared channel..");
846 return tuner_type_channel_default(m_list, channelid);
850 int *decremented_cached_channel_fe_usecount=NULL,
851 *decremented_fe_usecount=NULL;
853 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
855 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
856 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
857 if (i->m_channel_id == ignore)
859 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
860 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
861 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
862 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
863 // or 2 when the cached channel is not equal to the compared channel
864 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
866 ePtr<iDVBFrontend> fe;
867 if (!i->m_channel->getFrontend(fe))
869 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
871 if ( &(*fe) == &(*ii->m_frontend) )
874 decremented_fe_usecount = &ii->m_inuse;
875 if (channel == &(*m_cached_channel))
876 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
886 if (!decremented_cached_channel_fe_usecount)
888 if (m_cached_channel)
890 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
891 if (channel->getUseCount() == 1)
893 ePtr<iDVBFrontend> fe;
894 if (!channel->getFrontend(fe))
896 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
897 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
899 if ( &(*fe) == &(*ii->m_frontend) )
902 decremented_cached_channel_fe_usecount = &ii->m_inuse;
911 decremented_cached_channel_fe_usecount=NULL;
913 ePtr<iDVBFrontendParameters> feparm;
917 eDebug("no channel list set!");
921 if (m_list->getChannelFrontendData(channelid, feparm))
923 eDebug("channel not found!");
927 ret = canAllocateFrontend(feparm, simulate);
930 if (decremented_fe_usecount)
931 ++(*decremented_fe_usecount);
932 if (decremented_cached_channel_fe_usecount)
933 ++(*decremented_cached_channel_fe_usecount);
938 bool eDVBResourceManager::canMeasureFrontendInputPower()
940 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
942 return i->m_frontend->readInputpower() >= 0;
947 class eDVBChannelFilePush: public eFilePushThread
950 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
951 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
953 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
954 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
955 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
957 int m_iframe_search, m_iframe_state, m_pid;
958 int m_timebase_change;
959 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
962 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
965 if (m_timebase_change)
967 eDebug("timebase change: %d", m_timebase_change);
969 for (offset = 0; offset < len; offset += 188)
971 unsigned char *pkt = (unsigned char*)_data + offset;
972 if (pkt[1] & 0x40) /* pusi */
974 if (pkt[3] & 0x20) // adaption field present?
975 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
977 pkt += 4; /* skip header */
978 if (pkt[0] || pkt[1] || (pkt[2] != 1))
980 eWarning("broken startcode");
986 if (pkt[7] & 0x80) // PTS present?
988 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
989 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
990 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
991 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
992 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
996 RESULT r = m_tstools.fixupPTS(off, pts);
998 eWarning("fixup PTS while trickmode playback failed.\n");
1001 int sec = pts / 90000;
1002 int frm = pts % 90000;
1010 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1012 pts += 0x80000000LL;
1013 pts *= m_timebase_change;
1025 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1033 pkt[9] |= (pts >> 29) & 0xE;
1034 pkt[10] |= (pts >> 22) & 0xFF;
1035 pkt[11] |= (pts >> 14) & 0xFE;
1036 pkt[12] |= (pts >> 7) & 0xFF;
1037 pkt[13] |= (pts << 1) & 0xFE;
1045 if (!m_iframe_search)
1048 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1050 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1052 unsigned char *d = data;
1053 while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1055 int offset = d - data;
1056 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1057 unsigned char *ts = data + ts_offset;
1058 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1060 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */
1062 int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1065 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1067 if (m_iframe_state == 1)
1069 /* we are allowing data, and stop allowing data on the next frame.
1070 we now found a frame. so stop here. */
1071 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1072 current_span_remaining = 0;
1074 unsigned char *fts = ts + 188;
1075 while (fts < (data + len))
1078 fts[2] |= 0xff; /* drop packet */
1082 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1085 if (picture_type != 1) /* we are only interested in I frames */
1088 unsigned char *fts = data;
1092 fts[2] |= 0xff; /* drop packet */
1099 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1101 /* verify that this is actually a PES header, not just some ES data */
1102 if (ts[1] & 0x40) /* PUSI set */
1104 int payload_start = 4;
1105 if (ts[3] & 0x20) /* adaptation field present */
1106 payload_start += ts[4] + 1; /* skip AF */
1107 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1111 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1119 d += 4; /* ignore */
1122 if (m_iframe_state == 1)
1125 return 0; /* we need find an iframe first */
1131 DEFINE_REF(eDVBChannel);
1133 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1135 m_frontend = frontend;
1140 m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1143 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1146 eDVBChannel::~eDVBChannel()
1149 m_mgr->removeChannel(this);
1154 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1156 int state, ourstate = 0;
1158 /* if we are already in shutdown, don't change state. */
1159 if (m_state == state_release)
1162 if (fe->getState(state))
1165 if (state == iDVBFrontend::stateLock)
1167 eDebug("OURSTATE: ok");
1168 ourstate = state_ok;
1169 } else if (state == iDVBFrontend::stateTuning)
1171 eDebug("OURSTATE: tuning");
1172 ourstate = state_tuning;
1173 } else if (state == iDVBFrontend::stateLostLock)
1175 /* on managed channels, we try to retune in order to re-acquire lock. */
1176 if (m_current_frontend_parameters)
1178 eDebug("OURSTATE: lost lock, trying to retune");
1179 ourstate = state_tuning;
1180 m_frontend->get().tune(*m_current_frontend_parameters);
1182 /* on unmanaged channels, we don't do this. the client will do this. */
1184 eDebug("OURSTATE: lost lock, unavailable now.");
1185 ourstate = state_unavailable;
1187 } else if (state == iDVBFrontend::stateFailed)
1189 #ifdef BUILD_VUPLUS /* ikseong */
1190 if (m_current_frontend_parameters)
1192 eDebug("OURSTATE: lost lock, trying to retune");
1193 ourstate = state_tuning;
1194 m_frontend->get().tune(*m_current_frontend_parameters);
1198 eDebug("OURSTATE: failed");
1199 ourstate = state_failed;
1202 eDebug("OURSTATE: failed");
1203 ourstate = state_failed;
1206 eFatal("state unknown");
1208 if (ourstate != m_state)
1211 m_stateChanged(this);
1215 void eDVBChannel::pvrEvent(int event)
1219 case eFilePushThread::evtEOF:
1220 eDebug("eDVBChannel: End of file!");
1221 m_event(this, evtEOF);
1223 case eFilePushThread::evtUser: /* start */
1225 m_event(this, evtSOF);
1230 void eDVBChannel::cueSheetEvent(int event)
1232 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1237 case eCueSheet::evtSeek:
1239 flushPVR(m_cue->m_decoding_demux);
1241 case eCueSheet::evtSkipmode:
1244 m_cue->m_lock.WrLock();
1245 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1246 m_cue->m_lock.Unlock();
1247 eRdLocker l(m_cue->m_lock);
1248 if (m_cue->m_skipmode_ratio)
1250 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1251 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1252 /* i agree that this might look a bit like black magic. */
1253 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1254 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1255 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1256 m_skipmode_frames_remainder = 0;
1258 if (m_cue->m_skipmode_ratio < 0)
1259 m_skipmode_m -= m_skipmode_n;
1261 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1263 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1265 eWarning("something is wrong with this calculation");
1266 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1270 eDebug("skipmode ratio is 0, normal play");
1271 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1274 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1275 if (m_cue->m_skipmode_ratio != 0)
1276 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1278 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1279 eDebug("flush pvr");
1280 flushPVR(m_cue->m_decoding_demux);
1284 case eCueSheet::evtSpanChanged:
1286 m_source_span.clear();
1287 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1289 off_t offset_in, offset_out;
1290 pts_t pts_in = i->first, pts_out = i->second;
1291 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1293 eDebug("span translation failed.\n");
1296 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1297 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1304 /* align toward zero */
1305 static inline long long align(long long x, int align)
1320 /* align toward zero */
1321 static inline long long align_with_len(long long x, int align, size_t &len)
1337 /* remember, this gets called from another thread. */
1338 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1340 const int blocksize = 188;
1341 unsigned int max = align(10*1024*1024, blocksize);
1342 current_offset = align(current_offset, blocksize);
1346 eDebug("no cue sheet. forcing normal play");
1347 start = current_offset;
1354 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1355 max = align(m_skipmode_n, blocksize);
1358 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1359 int frame_skip_success = 0;
1363 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1364 eDebug("we are at %llx, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1366 off_t iframe_start = current_offset;
1367 int frames_skipped = frames_to_skip;
1368 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1370 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1371 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1372 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1373 max = align(iframe_len + 187, blocksize);
1374 frame_skip_success = 1;
1377 m_skipmode_frames_remainder = 0;
1378 eDebug("frame skipping failed, reverting to byte-skipping");
1382 if (!frame_skip_success)
1384 current_offset += align(m_skipmode_m, blocksize);
1388 eDebug("we are at %llx, and we try to find the iframe here:", current_offset);
1390 off_t iframe_start = current_offset;
1392 int direction = (m_skipmode_m < 0) ? -1 : +1;
1393 if (m_tstools.findFrame(iframe_start, iframe_len, direction))
1397 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1398 max = align(iframe_len, blocksize);
1403 m_cue->m_lock.RdLock();
1405 while (!m_cue->m_seek_requests.empty())
1407 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1408 m_cue->m_lock.Unlock();
1409 m_cue->m_lock.WrLock();
1410 m_cue->m_seek_requests.pop_front();
1411 m_cue->m_lock.Unlock();
1412 m_cue->m_lock.RdLock();
1413 int relative = seek.first;
1414 pts_t pts = seek.second;
1419 if (!m_cue->m_decoder)
1421 eDebug("no decoder - can't seek relative");
1424 if (m_cue->m_decoder->getPTS(0, now))
1426 eDebug("decoder getPTS failed, can't seek relative");
1429 if (!m_cue->m_decoding_demux)
1431 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1432 start = current_offset;
1436 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1438 eDebug("seekTo: getCurrentPosition failed!");
1441 } else if (pts < 0) /* seek relative to end */
1444 if (!getLength(len))
1446 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1450 eWarning("getLength failed - can't seek relative to end!");
1455 if (relative == 1) /* pts relative */
1466 if (relative == 2) /* AP relative */
1468 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1470 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1472 pts = now - 90000; /* approx. 1s */
1473 eDebug("AP relative seeking failed!");
1477 eDebug("next ap is %llx\n", pts);
1482 if (m_tstools.getOffset(offset, pts, -1))
1484 eDebug("get offset for pts=%lld failed!", pts);
1488 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1489 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1492 m_cue->m_lock.Unlock();
1494 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1496 long long aligned_start = align(i->first, blocksize);
1497 long long aligned_end = align(i->second, blocksize);
1499 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1501 start = current_offset;
1502 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1503 if ((aligned_end - current_offset) > max)
1506 size = aligned_end - current_offset;
1507 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1510 if (current_offset < aligned_start)
1512 /* ok, our current offset is in an 'out' zone. */
1513 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1515 /* in normal playback, just start at the next zone. */
1518 /* size is not 64bit! */
1519 if ((i->second - i->first) > max)
1522 size = aligned_end - aligned_start;
1525 if (m_skipmode_m < 0)
1527 eDebug("reached SOF");
1530 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1534 /* when skipping reverse, however, choose the zone before. */
1536 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1539 aligned_start = align(i->first, blocksize);
1540 aligned_end = align(i->second, blocksize);
1542 if ((aligned_end - aligned_start) > max)
1545 len = aligned_end - aligned_start;
1547 start = aligned_end - len;
1548 eDebug("skipping to %llx, %zd", start, len);
1551 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1556 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1558 eDebug("reached SOF");
1560 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1563 if (m_source_span.empty())
1565 start = current_offset;
1567 eDebug("NO CUESHEET. (%08llx, %zd)", start, size);
1570 start = current_offset;
1576 void eDVBChannel::AddUse()
1578 if (++m_use_count > 1 && m_state == state_last_instance)
1581 m_stateChanged(this);
1585 void eDVBChannel::ReleaseUse()
1589 m_state = state_release;
1590 m_stateChanged(this);
1592 else if (m_use_count == 1)
1594 m_state = state_last_instance;
1595 m_stateChanged(this);
1599 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1602 m_mgr->removeChannel(this);
1609 eDebug("no frontend to tune!");
1613 m_channel_id = channelid;
1614 m_mgr->addChannel(channelid, this);
1615 m_state = state_tuning;
1616 /* if tuning fails, shutdown the channel immediately. */
1618 res = m_frontend->get().tune(*feparm);
1619 m_current_frontend_parameters = feparm;
1623 m_state = state_release;
1624 m_stateChanged(this);
1631 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1633 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1637 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1639 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1643 RESULT eDVBChannel::getState(int &state)
1649 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1654 void eDVBChannel::SDTready(int result)
1656 ePyObject args = PyTuple_New(2), ret;
1660 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1663 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1664 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1670 PyTuple_SET_ITEM(args, 0, Py_None);
1671 PyTuple_SET_ITEM(args, 1, Py_None);
1675 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1679 Py_DECREF(m_tsid_onid_callback);
1680 m_tsid_onid_callback = ePyObject();
1681 m_tsid_onid_demux = 0;
1685 int eDVBChannel::reserveDemux()
1687 ePtr<iDVBDemux> dmx;
1688 if (!getDemux(dmx, 0))
1691 if (!dmx->getCADemuxID(id))
1697 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1699 if (PyCallable_Check(callback))
1701 if (!getDemux(m_tsid_onid_demux, 0))
1703 m_SDT = new eTable<ServiceDescriptionSection>;
1704 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1705 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1707 m_tsid_onid_demux = 0;
1712 Py_INCREF(callback);
1713 m_tsid_onid_callback = callback;
1721 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1723 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1729 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1734 /* don't hold a reference to the decoding demux, we don't need it. */
1736 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1737 the refcount is lost. thus, decoding demuxes are never allocated.
1739 this poses a big problem for PiP. */
1741 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1743 else if (cap & capDecode)
1752 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1757 frontend = &m_frontend->get();
1763 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1765 param = m_current_frontend_parameters;
1769 RESULT eDVBChannel::playFile(const char *file)
1771 eRawFile *f = new eRawFile();
1772 ePtr<iTsSource> source = f;
1774 if (f->open(file) < 0)
1776 eDebug("can't open PVR file %s (%m)", file);
1780 return playSource(source, file);
1783 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
1785 ASSERT(!m_frontend);
1788 m_pvr_thread->stop();
1789 delete m_pvr_thread;
1793 if (!source->valid())
1795 eDebug("PVR source is not valid!");
1799 m_tstools.setSource(source, streaminfo_file);
1801 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1802 THEN DO A REAL FIX HERE! */
1804 if (m_pvr_fd_dst < 0)
1806 /* (this codepath needs to be improved anyway.) */
1807 #if HAVE_DVB_API_VERSION < 3
1808 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1809 if (m_pvr_fd_dst < 0)
1811 eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1815 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
1818 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
1819 if (m_pvr_fd_dst < 0)
1821 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1827 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
1833 m_pvr_thread = new eDVBChannelFilePush();
1834 m_pvr_thread->enablePVRCommit(1);
1835 m_pvr_thread->setStreamMode(1);
1836 m_pvr_thread->setScatterGather(this);
1838 m_event(this, evtPreStart);
1840 m_pvr_thread->start(source, m_pvr_fd_dst);
1841 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1844 m_stateChanged(this);
1849 void eDVBChannel::stopSource()
1853 m_pvr_thread->stop();
1854 delete m_pvr_thread;
1857 if (m_pvr_fd_dst >= 0)
1858 ::close(m_pvr_fd_dst);
1860 m_tstools.setSource(d);
1863 void eDVBChannel::stopFile()
1868 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1870 m_conn_cueSheetEvent = 0;
1873 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1876 RESULT eDVBChannel::getLength(pts_t &len)
1878 return m_tstools.calcLen(len);
1881 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1883 if (!decoding_demux)
1890 if (mode == 0) /* demux */
1892 r = decoding_demux->getSTC(now, 0);
1895 eDebug("demux getSTC failed");
1899 now = pos; /* fixup supplied */
1901 off_t off = 0; /* TODO: fixme */
1902 r = m_tstools.fixupPTS(off, now);
1905 eDebug("fixup PTS failed");
1914 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1916 /* when seeking, we have to ensure that all buffers are flushed.
1917 there are basically 3 buffers:
1918 a.) the filepush's internal buffer
1919 b.) the PVR buffer (before demux)
1920 c.) the ratebuffer (after demux)
1922 it's important to clear them in the correct order, otherwise
1923 the ratebuffer (for example) would immediately refill from
1924 the not-yet-flushed PVR buffer.
1927 m_pvr_thread->pause();
1928 /* flush internal filepush buffer */
1929 m_pvr_thread->flush();
1930 /* HACK: flush PVR buffer */
1931 ::ioctl(m_pvr_fd_dst, 0);
1933 /* flush ratebuffers (video, audio) */
1935 decoding_demux->flush();
1937 /* demux will also flush all decoder.. */
1938 /* resume will re-query the SG */
1939 m_pvr_thread->resume();
1942 DEFINE_REF(eCueSheet);
1944 eCueSheet::eCueSheet()
1946 m_skipmode_ratio = 0;
1949 void eCueSheet::seekTo(int relative, const pts_t &pts)
1952 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1957 void eCueSheet::clear()
1964 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1966 ASSERT(begin < end);
1968 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1972 void eCueSheet::commitSpans()
1974 m_event(evtSpanChanged);
1977 void eCueSheet::setSkipmode(const pts_t &ratio)
1980 m_skipmode_ratio = ratio;
1982 m_event(evtSkipmode);
1985 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1987 m_decoding_demux = demux;
1988 m_decoder = decoder;
1991 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1993 connection = new eConnection(this, m_event.connect(event));