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 cap |= capHoldDecodeReference; // this is checked in eDVBChannel::getDemux
529 for (; i != m_demux.end(); ++i, ++n)
538 else if (i->m_adapter == fe->m_adapter &&
539 i->m_demux->getSource() == fe->m_frontend->getDVBID())
541 demux = new eDVBAllocatedDemux(i);
545 else if (n == 4) // always use demux4 for PVR (demux 4 can not descramble...)
548 demux = new eDVBAllocatedDemux(i);
558 demux = new eDVBAllocatedDemux(unused);
560 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
562 demux->get().setSourcePVR(0);
566 eDebug("demux not found");
570 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
576 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
585 #define eDebugNoSimulate(x...) \
592 // eDebugNoNewLine("SIMULATE:"); \
597 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
599 /* first, check if a channel is already existing. */
600 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
602 if (!simulate && m_cached_channel)
604 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
605 if(channelid==cache_chan->getChannelID())
607 eDebug("use cached_channel");
608 channel = m_cached_channel;
611 m_cached_channel_state_changed_conn.disconnect();
613 m_releaseCachedChannelTimer->stop();
616 eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
617 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
619 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
620 if (i->m_channel_id == channelid)
622 eDebugNoSimulate("found shared channel..");
623 channel = i->m_channel;
628 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
632 eDebugNoSimulate("no channel list set!");
633 return errNoChannelList;
636 ePtr<iDVBFrontendParameters> feparm;
637 if (m_list->getChannelFrontendData(channelid, feparm))
639 eDebugNoSimulate("channel not found!");
640 return errChannelNotInList;
643 /* allocate a frontend. */
645 ePtr<eDVBAllocatedFrontend> fe;
647 int err = allocateFrontend(fe, feparm, simulate);
652 ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
654 res = ch->setChannel(channelid, feparm);
658 return errChidNotFound;
665 m_cached_channel = channel = ch;
666 m_cached_channel_state_changed_conn =
667 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
673 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
676 chan->getState(state);
679 case iDVBChannel::state_release:
680 case iDVBChannel::state_ok:
682 eDebug("stop release channel timer");
683 m_releaseCachedChannelTimer->stop();
686 case iDVBChannel::state_last_instance:
688 eDebug("start release channel timer");
689 m_releaseCachedChannelTimer->start(3000, true);
692 default: // ignore all other events
697 void eDVBResourceManager::releaseCachedChannel()
699 eDebug("release cached channel (timer timeout)");
703 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
705 ePtr<eDVBAllocatedFrontend> fe;
707 if (m_cached_channel)
709 m_cached_channel_state_changed_conn.disconnect();
711 m_releaseCachedChannelTimer->stop();
714 int err = allocateFrontendByIndex(fe, slot_index);
718 channel = new eDVBChannel(this, fe);
723 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
725 ePtr<eDVBAllocatedDemux> demux;
727 if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
729 m_cached_channel_state_changed_conn.disconnect();
731 m_releaseCachedChannelTimer->stop();
734 channel = new eDVBChannel(this, 0);
738 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
740 ePtr<iDVBFrontend> fe;
741 if (!ch->getFrontend(fe))
743 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
744 if (frontend->is_simulate())
745 m_active_simulate_channels.push_back(active_channel(chid, ch));
748 m_active_channels.push_back(active_channel(chid, ch));
749 /* emit */ m_channelAdded(ch);
755 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
757 ePtr<iDVBFrontend> fe;
758 if (!ch->getFrontend(fe))
760 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
761 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
763 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
765 if (i->m_channel == ch)
767 i = active_channels.erase(i);
779 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
781 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
785 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
787 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
788 ePtr<eDVBRegisteredFrontend> best;
791 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
794 int c = i->m_frontend->isCompatibleWith(feparm);
801 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
805 ePtr<iDVBFrontendParameters> feparm;
806 if (!channellist->getChannelFrontendData(chid, feparm))
809 if (!feparm->getSystem(system))
813 case iDVBFrontend::feSatellite:
815 case iDVBFrontend::feCable:
817 case iDVBFrontend::feTerrestrial:
828 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, bool simulate)
830 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
832 if (!simulate && m_cached_channel)
834 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
835 if(channelid==cache_chan->getChannelID())
836 return tuner_type_channel_default(m_list, channelid);
839 /* first, check if a channel is already existing. */
840 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
841 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
843 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
844 if (i->m_channel_id == channelid)
846 // eDebug("found shared channel..");
847 return tuner_type_channel_default(m_list, channelid);
851 int *decremented_cached_channel_fe_usecount=NULL,
852 *decremented_fe_usecount=NULL;
854 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
856 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
857 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
858 if (i->m_channel_id == ignore)
860 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
861 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
862 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
863 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
864 // or 2 when the cached channel is not equal to the compared channel
865 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
867 ePtr<iDVBFrontend> fe;
868 if (!i->m_channel->getFrontend(fe))
870 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
872 if ( &(*fe) == &(*ii->m_frontend) )
875 decremented_fe_usecount = &ii->m_inuse;
876 if (channel == &(*m_cached_channel))
877 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
887 if (!decremented_cached_channel_fe_usecount)
889 if (m_cached_channel)
891 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
892 if (channel->getUseCount() == 1)
894 ePtr<iDVBFrontend> fe;
895 if (!channel->getFrontend(fe))
897 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
898 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
900 if ( &(*fe) == &(*ii->m_frontend) )
903 decremented_cached_channel_fe_usecount = &ii->m_inuse;
912 decremented_cached_channel_fe_usecount=NULL;
914 ePtr<iDVBFrontendParameters> feparm;
918 eDebug("no channel list set!");
922 if (m_list->getChannelFrontendData(channelid, feparm))
924 eDebug("channel not found!");
928 ret = canAllocateFrontend(feparm, simulate);
931 if (decremented_fe_usecount)
932 ++(*decremented_fe_usecount);
933 if (decremented_cached_channel_fe_usecount)
934 ++(*decremented_cached_channel_fe_usecount);
939 bool eDVBResourceManager::canMeasureFrontendInputPower()
941 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
943 return i->m_frontend->readInputpower() >= 0;
948 class eDVBChannelFilePush: public eFilePushThread
951 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
952 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
954 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
955 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
956 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
958 int m_iframe_search, m_iframe_state, m_pid;
959 int m_timebase_change;
960 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
963 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
966 if (m_timebase_change)
968 eDebug("timebase change: %d", m_timebase_change);
970 for (offset = 0; offset < len; offset += 188)
972 unsigned char *pkt = (unsigned char*)_data + offset;
973 if (pkt[1] & 0x40) /* pusi */
975 if (pkt[3] & 0x20) // adaption field present?
976 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
978 pkt += 4; /* skip header */
979 if (pkt[0] || pkt[1] || (pkt[2] != 1))
981 eWarning("broken startcode");
987 if (pkt[7] & 0x80) // PTS present?
989 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
990 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
991 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
992 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
993 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
997 RESULT r = m_tstools.fixupPTS(off, pts);
999 eWarning("fixup PTS while trickmode playback failed.\n");
1002 int sec = pts / 90000;
1003 int frm = pts % 90000;
1011 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1013 pts += 0x80000000LL;
1014 pts *= m_timebase_change;
1026 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
1034 pkt[9] |= (pts >> 29) & 0xE;
1035 pkt[10] |= (pts >> 22) & 0xFF;
1036 pkt[11] |= (pts >> 14) & 0xFE;
1037 pkt[12] |= (pts >> 7) & 0xFF;
1038 pkt[13] |= (pts << 1) & 0xFE;
1046 if (!m_iframe_search)
1049 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
1051 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
1053 unsigned char *d = data;
1054 while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
1056 int offset = d - data;
1057 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
1058 unsigned char *ts = data + ts_offset;
1059 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
1061 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */
1063 int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
1066 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
1068 if (m_iframe_state == 1)
1070 /* we are allowing data, and stop allowing data on the next frame.
1071 we now found a frame. so stop here. */
1072 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1073 current_span_remaining = 0;
1075 unsigned char *fts = ts + 188;
1076 while (fts < (data + len))
1079 fts[2] |= 0xff; /* drop packet */
1083 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1086 if (picture_type != 1) /* we are only interested in I frames */
1089 unsigned char *fts = data;
1093 fts[2] |= 0xff; /* drop packet */
1100 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1102 /* verify that this is actually a PES header, not just some ES data */
1103 if (ts[1] & 0x40) /* PUSI set */
1105 int payload_start = 4;
1106 if (ts[3] & 0x20) /* adaptation field present */
1107 payload_start += ts[4] + 1; /* skip AF */
1108 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1112 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1120 d += 4; /* ignore */
1123 if (m_iframe_state == 1)
1126 return 0; /* we need find an iframe first */
1132 DEFINE_REF(eDVBChannel);
1134 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1136 m_frontend = frontend;
1141 m_skipmode_n = m_skipmode_m = m_skipmode_frames = 0;
1144 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1147 eDVBChannel::~eDVBChannel()
1150 m_mgr->removeChannel(this);
1155 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1157 int state, ourstate = 0;
1159 /* if we are already in shutdown, don't change state. */
1160 if (m_state == state_release)
1163 if (fe->getState(state))
1166 if (state == iDVBFrontend::stateLock)
1168 eDebug("OURSTATE: ok");
1169 ourstate = state_ok;
1170 } else if (state == iDVBFrontend::stateTuning)
1172 eDebug("OURSTATE: tuning");
1173 ourstate = state_tuning;
1174 } else if (state == iDVBFrontend::stateLostLock)
1176 /* on managed channels, we try to retune in order to re-acquire lock. */
1177 if (m_current_frontend_parameters)
1179 eDebug("OURSTATE: lost lock, trying to retune");
1180 ourstate = state_tuning;
1181 m_frontend->get().tune(*m_current_frontend_parameters);
1183 /* on unmanaged channels, we don't do this. the client will do this. */
1185 eDebug("OURSTATE: lost lock, unavailable now.");
1186 ourstate = state_unavailable;
1188 } else if (state == iDVBFrontend::stateFailed)
1190 #ifdef BUILD_VUPLUS /* ikseong */
1191 if (m_current_frontend_parameters)
1193 eDebug("OURSTATE: lost lock, trying to retune");
1194 ourstate = state_tuning;
1195 m_frontend->get().tune(*m_current_frontend_parameters);
1199 eDebug("OURSTATE: failed");
1200 ourstate = state_failed;
1203 eDebug("OURSTATE: failed");
1204 ourstate = state_failed;
1207 eFatal("state unknown");
1209 if (ourstate != m_state)
1212 m_stateChanged(this);
1216 void eDVBChannel::pvrEvent(int event)
1220 case eFilePushThread::evtEOF:
1221 eDebug("eDVBChannel: End of file!");
1222 m_event(this, evtEOF);
1224 case eFilePushThread::evtUser: /* start */
1226 m_event(this, evtSOF);
1231 void eDVBChannel::cueSheetEvent(int event)
1233 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1238 case eCueSheet::evtSeek:
1240 flushPVR(m_cue->m_decoding_demux);
1242 case eCueSheet::evtSkipmode:
1245 m_cue->m_lock.WrLock();
1246 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1247 m_cue->m_lock.Unlock();
1248 eRdLocker l(m_cue->m_lock);
1249 if (m_cue->m_skipmode_ratio)
1251 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1252 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1253 /* i agree that this might look a bit like black magic. */
1254 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1255 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1256 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1257 m_skipmode_frames_remainder = 0;
1259 if (m_cue->m_skipmode_ratio < 0)
1260 m_skipmode_m -= m_skipmode_n;
1262 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1264 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1266 eWarning("something is wrong with this calculation");
1267 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1271 eDebug("skipmode ratio is 0, normal play");
1272 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1275 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1276 if (m_cue->m_skipmode_ratio != 0)
1277 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1279 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1280 eDebug("flush pvr");
1281 flushPVR(m_cue->m_decoding_demux);
1285 case eCueSheet::evtSpanChanged:
1287 m_source_span.clear();
1288 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1290 off_t offset_in, offset_out;
1291 pts_t pts_in = i->first, pts_out = i->second;
1292 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1294 eDebug("span translation failed.\n");
1297 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1298 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1305 /* align toward zero */
1306 static inline long long align(long long x, int align)
1321 /* align toward zero */
1322 static inline long long align_with_len(long long x, int align, size_t &len)
1338 /* remember, this gets called from another thread. */
1339 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1341 const int blocksize = 188;
1342 unsigned int max = align(10*1024*1024, blocksize);
1343 current_offset = align(current_offset, blocksize);
1347 eDebug("no cue sheet. forcing normal play");
1348 start = current_offset;
1355 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1356 max = align(m_skipmode_n, blocksize);
1359 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1360 int frame_skip_success = 0;
1364 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1365 eDebug("we are at %llx, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1367 off_t iframe_start = current_offset;
1368 int frames_skipped = frames_to_skip;
1369 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1371 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1372 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1373 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1374 max = align(iframe_len + 187, blocksize);
1375 frame_skip_success = 1;
1378 m_skipmode_frames_remainder = 0;
1379 eDebug("frame skipping failed, reverting to byte-skipping");
1383 if (!frame_skip_success)
1385 current_offset += align(m_skipmode_m, blocksize);
1389 eDebug("we are at %llx, and we try to find the iframe here:", current_offset);
1391 off_t iframe_start = current_offset;
1393 int direction = (m_skipmode_m < 0) ? -1 : +1;
1394 if (m_tstools.findFrame(iframe_start, iframe_len, direction))
1398 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1399 max = align(iframe_len, blocksize);
1404 m_cue->m_lock.RdLock();
1406 while (!m_cue->m_seek_requests.empty())
1408 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1409 m_cue->m_lock.Unlock();
1410 m_cue->m_lock.WrLock();
1411 m_cue->m_seek_requests.pop_front();
1412 m_cue->m_lock.Unlock();
1413 m_cue->m_lock.RdLock();
1414 int relative = seek.first;
1415 pts_t pts = seek.second;
1420 if (!m_cue->m_decoder)
1422 eDebug("no decoder - can't seek relative");
1425 if (m_cue->m_decoder->getPTS(0, now))
1427 eDebug("decoder getPTS failed, can't seek relative");
1430 if (!m_cue->m_decoding_demux)
1432 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1433 start = current_offset;
1437 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1439 eDebug("seekTo: getCurrentPosition failed!");
1442 } else if (pts < 0) /* seek relative to end */
1445 if (!getLength(len))
1447 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1451 eWarning("getLength failed - can't seek relative to end!");
1456 if (relative == 1) /* pts relative */
1467 if (relative == 2) /* AP relative */
1469 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1471 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1473 pts = now - 90000; /* approx. 1s */
1474 eDebug("AP relative seeking failed!");
1478 eDebug("next ap is %llx\n", pts);
1483 if (m_tstools.getOffset(offset, pts, -1))
1485 eDebug("get offset for pts=%lld failed!", pts);
1489 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1490 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1493 m_cue->m_lock.Unlock();
1495 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1497 long long aligned_start = align(i->first, blocksize);
1498 long long aligned_end = align(i->second, blocksize);
1500 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1502 start = current_offset;
1503 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1504 if ((aligned_end - current_offset) > max)
1507 size = aligned_end - current_offset;
1508 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1511 if (current_offset < aligned_start)
1513 /* ok, our current offset is in an 'out' zone. */
1514 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1516 /* in normal playback, just start at the next zone. */
1519 /* size is not 64bit! */
1520 if ((i->second - i->first) > max)
1523 size = aligned_end - aligned_start;
1526 if (m_skipmode_m < 0)
1528 eDebug("reached SOF");
1531 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1535 /* when skipping reverse, however, choose the zone before. */
1537 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1540 aligned_start = align(i->first, blocksize);
1541 aligned_end = align(i->second, blocksize);
1543 if ((aligned_end - aligned_start) > max)
1546 len = aligned_end - aligned_start;
1548 start = aligned_end - len;
1549 eDebug("skipping to %llx, %zd", start, len);
1552 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1557 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1559 eDebug("reached SOF");
1561 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1564 if (m_source_span.empty())
1566 start = current_offset;
1568 eDebug("NO CUESHEET. (%08llx, %zd)", start, size);
1571 start = current_offset;
1577 void eDVBChannel::AddUse()
1579 if (++m_use_count > 1 && m_state == state_last_instance)
1582 m_stateChanged(this);
1586 void eDVBChannel::ReleaseUse()
1590 m_state = state_release;
1591 m_stateChanged(this);
1593 else if (m_use_count == 1)
1595 m_state = state_last_instance;
1596 m_stateChanged(this);
1600 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1603 m_mgr->removeChannel(this);
1610 eDebug("no frontend to tune!");
1614 m_channel_id = channelid;
1615 m_mgr->addChannel(channelid, this);
1616 m_state = state_tuning;
1617 /* if tuning fails, shutdown the channel immediately. */
1619 res = m_frontend->get().tune(*feparm);
1620 m_current_frontend_parameters = feparm;
1624 m_state = state_release;
1625 m_stateChanged(this);
1632 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1634 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1638 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1640 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1644 RESULT eDVBChannel::getState(int &state)
1650 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1655 void eDVBChannel::SDTready(int result)
1657 ePyObject args = PyTuple_New(2), ret;
1661 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1664 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1665 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1671 PyTuple_SET_ITEM(args, 0, Py_None);
1672 PyTuple_SET_ITEM(args, 1, Py_None);
1676 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1680 Py_DECREF(m_tsid_onid_callback);
1681 m_tsid_onid_callback = ePyObject();
1682 m_tsid_onid_demux = 0;
1686 int eDVBChannel::reserveDemux()
1688 ePtr<iDVBDemux> dmx;
1689 if (!getDemux(dmx, 0))
1692 if (!dmx->getCADemuxID(id))
1698 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1700 if (PyCallable_Check(callback))
1702 if (!getDemux(m_tsid_onid_demux, 0))
1704 m_SDT = new eTable<ServiceDescriptionSection>;
1705 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1706 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1708 m_tsid_onid_demux = 0;
1713 Py_INCREF(callback);
1714 m_tsid_onid_callback = callback;
1722 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1724 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1730 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1735 /* don't hold a reference to the decoding demux, we don't need it. */
1737 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1738 the refcount is lost. thus, decoding demuxes are never allocated.
1740 this poses a big problem for PiP. */
1742 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1744 else if (cap & capDecode)
1753 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1758 frontend = &m_frontend->get();
1764 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1766 param = m_current_frontend_parameters;
1770 RESULT eDVBChannel::playFile(const char *file)
1772 eRawFile *f = new eRawFile();
1773 ePtr<iTsSource> source = f;
1775 if (f->open(file) < 0)
1777 eDebug("can't open PVR file %s (%m)", file);
1781 return playSource(source, file);
1784 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
1786 ASSERT(!m_frontend);
1789 m_pvr_thread->stop();
1790 delete m_pvr_thread;
1794 if (!source->valid())
1796 eDebug("PVR source is not valid!");
1800 m_tstools.setSource(source, streaminfo_file);
1802 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1803 THEN DO A REAL FIX HERE! */
1805 if (m_pvr_fd_dst < 0)
1807 /* (this codepath needs to be improved anyway.) */
1808 #if HAVE_DVB_API_VERSION < 3
1809 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1810 if (m_pvr_fd_dst < 0)
1812 eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1816 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
1819 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
1820 if (m_pvr_fd_dst < 0)
1822 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1828 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
1834 m_pvr_thread = new eDVBChannelFilePush();
1835 m_pvr_thread->enablePVRCommit(1);
1836 m_pvr_thread->setStreamMode(1);
1837 m_pvr_thread->setScatterGather(this);
1839 m_event(this, evtPreStart);
1841 m_pvr_thread->start(source, m_pvr_fd_dst);
1842 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1845 m_stateChanged(this);
1850 void eDVBChannel::stopSource()
1854 m_pvr_thread->stop();
1855 delete m_pvr_thread;
1858 if (m_pvr_fd_dst >= 0)
1859 ::close(m_pvr_fd_dst);
1861 m_tstools.setSource(d);
1864 void eDVBChannel::stopFile()
1869 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1871 m_conn_cueSheetEvent = 0;
1874 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1877 RESULT eDVBChannel::getLength(pts_t &len)
1879 return m_tstools.calcLen(len);
1882 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1884 if (!decoding_demux)
1891 if (mode == 0) /* demux */
1893 r = decoding_demux->getSTC(now, 0);
1896 eDebug("demux getSTC failed");
1900 now = pos; /* fixup supplied */
1902 off_t off = 0; /* TODO: fixme */
1903 r = m_tstools.fixupPTS(off, now);
1906 eDebug("fixup PTS failed");
1915 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1917 /* when seeking, we have to ensure that all buffers are flushed.
1918 there are basically 3 buffers:
1919 a.) the filepush's internal buffer
1920 b.) the PVR buffer (before demux)
1921 c.) the ratebuffer (after demux)
1923 it's important to clear them in the correct order, otherwise
1924 the ratebuffer (for example) would immediately refill from
1925 the not-yet-flushed PVR buffer.
1928 m_pvr_thread->pause();
1929 /* flush internal filepush buffer */
1930 m_pvr_thread->flush();
1931 /* HACK: flush PVR buffer */
1932 ::ioctl(m_pvr_fd_dst, 0);
1934 /* flush ratebuffers (video, audio) */
1936 decoding_demux->flush();
1938 /* demux will also flush all decoder.. */
1939 /* resume will re-query the SG */
1940 m_pvr_thread->resume();
1943 DEFINE_REF(eCueSheet);
1945 eCueSheet::eCueSheet()
1947 m_skipmode_ratio = 0;
1950 void eCueSheet::seekTo(int relative, const pts_t &pts)
1953 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1958 void eCueSheet::clear()
1965 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1967 ASSERT(begin < end);
1969 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1973 void eCueSheet::commitSpans()
1975 m_event(evtSpanChanged);
1978 void eCueSheet::setSkipmode(const pts_t &ratio)
1981 m_skipmode_ratio = ratio;
1983 m_event(evtSkipmode);
1986 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1988 m_decoding_demux = demux;
1989 m_decoder = decoder;
1992 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1994 connection = new eConnection(this, m_event.connect(event));