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 eDebug("OURSTATE: failed");
1191 ourstate = state_failed;
1193 eFatal("state unknown");
1195 if (ourstate != m_state)
1198 m_stateChanged(this);
1202 void eDVBChannel::pvrEvent(int event)
1206 case eFilePushThread::evtEOF:
1207 eDebug("eDVBChannel: End of file!");
1208 m_event(this, evtEOF);
1210 case eFilePushThread::evtUser: /* start */
1212 m_event(this, evtSOF);
1217 void eDVBChannel::cueSheetEvent(int event)
1219 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1224 case eCueSheet::evtSeek:
1226 flushPVR(m_cue->m_decoding_demux);
1228 case eCueSheet::evtSkipmode:
1231 m_cue->m_lock.WrLock();
1232 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1233 m_cue->m_lock.Unlock();
1234 eRdLocker l(m_cue->m_lock);
1235 if (m_cue->m_skipmode_ratio)
1237 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1238 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1239 /* i agree that this might look a bit like black magic. */
1240 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1241 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1242 m_skipmode_frames = m_cue->m_skipmode_ratio / 90000;
1243 m_skipmode_frames_remainder = 0;
1245 if (m_cue->m_skipmode_ratio < 0)
1246 m_skipmode_m -= m_skipmode_n;
1248 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1250 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1252 eWarning("something is wrong with this calculation");
1253 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1257 eDebug("skipmode ratio is 0, normal play");
1258 m_skipmode_frames = m_skipmode_n = m_skipmode_m = 0;
1261 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1262 if (m_cue->m_skipmode_ratio != 0)
1263 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1265 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1266 eDebug("flush pvr");
1267 flushPVR(m_cue->m_decoding_demux);
1271 case eCueSheet::evtSpanChanged:
1273 m_source_span.clear();
1274 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1276 off_t offset_in, offset_out;
1277 pts_t pts_in = i->first, pts_out = i->second;
1278 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1280 eDebug("span translation failed.\n");
1283 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1284 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1291 /* align toward zero */
1292 static inline long long align(long long x, int align)
1307 /* align toward zero */
1308 static inline long long align_with_len(long long x, int align, size_t &len)
1324 /* remember, this gets called from another thread. */
1325 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1327 const int blocksize = 188;
1328 unsigned int max = align(10*1024*1024, blocksize);
1329 current_offset = align(current_offset, blocksize);
1333 eDebug("no cue sheet. forcing normal play");
1334 start = current_offset;
1341 eDebug("skipmode %d:%d (x%d)", m_skipmode_m, m_skipmode_n, m_skipmode_frames);
1342 max = align(m_skipmode_n, blocksize);
1345 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1346 int frame_skip_success = 0;
1350 int frames_to_skip = m_skipmode_frames + m_skipmode_frames_remainder;
1351 eDebug("we are at %llx, and we try to skip %d+%d frames from here", current_offset, m_skipmode_frames, m_skipmode_frames_remainder);
1353 off_t iframe_start = current_offset;
1354 int frames_skipped = frames_to_skip;
1355 if (!m_tstools.findNextPicture(iframe_start, iframe_len, frames_skipped))
1357 m_skipmode_frames_remainder = frames_to_skip - frames_skipped;
1358 eDebug("successfully skipped %d (out of %d, rem now %d) frames.", frames_skipped, frames_to_skip, m_skipmode_frames_remainder);
1359 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1360 max = align(iframe_len + 187, blocksize);
1361 frame_skip_success = 1;
1364 m_skipmode_frames_remainder = 0;
1365 eDebug("frame skipping failed, reverting to byte-skipping");
1369 if (!frame_skip_success)
1371 current_offset += align(m_skipmode_m, blocksize);
1375 eDebug("we are at %llx, and we try to find the iframe here:", current_offset);
1377 off_t iframe_start = current_offset;
1379 int direction = (m_skipmode_m < 0) ? -1 : +1;
1380 if (m_tstools.findFrame(iframe_start, iframe_len, direction))
1384 current_offset = align_with_len(iframe_start, blocksize, iframe_len);
1385 max = align(iframe_len, blocksize);
1390 m_cue->m_lock.RdLock();
1392 while (!m_cue->m_seek_requests.empty())
1394 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1395 m_cue->m_lock.Unlock();
1396 m_cue->m_lock.WrLock();
1397 m_cue->m_seek_requests.pop_front();
1398 m_cue->m_lock.Unlock();
1399 m_cue->m_lock.RdLock();
1400 int relative = seek.first;
1401 pts_t pts = seek.second;
1406 if (!m_cue->m_decoder)
1408 eDebug("no decoder - can't seek relative");
1411 if (m_cue->m_decoder->getPTS(0, now))
1413 eDebug("decoder getPTS failed, can't seek relative");
1416 if (!m_cue->m_decoding_demux)
1418 eDebug("getNextSourceSpan, no decoding demux. couldn't seek to %llx... ignore request!", pts);
1419 start = current_offset;
1423 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1425 eDebug("seekTo: getCurrentPosition failed!");
1428 } else if (pts < 0) /* seek relative to end */
1431 if (!getLength(len))
1433 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1437 eWarning("getLength failed - can't seek relative to end!");
1442 if (relative == 1) /* pts relative */
1453 if (relative == 2) /* AP relative */
1455 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1457 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1459 pts = now - 90000; /* approx. 1s */
1460 eDebug("AP relative seeking failed!");
1464 eDebug("next ap is %llx\n", pts);
1469 if (m_tstools.getOffset(offset, pts, -1))
1471 eDebug("get offset for pts=%lld failed!", pts);
1475 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1476 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1479 m_cue->m_lock.Unlock();
1481 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1483 long long aligned_start = align(i->first, blocksize);
1484 long long aligned_end = align(i->second, blocksize);
1486 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1488 start = current_offset;
1489 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1490 if ((aligned_end - current_offset) > max)
1493 size = aligned_end - current_offset;
1494 eDebug("HIT, %lld < %lld < %lld, size: %zd", i->first, current_offset, i->second, size);
1497 if (current_offset < aligned_start)
1499 /* ok, our current offset is in an 'out' zone. */
1500 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1502 /* in normal playback, just start at the next zone. */
1505 /* size is not 64bit! */
1506 if ((i->second - i->first) > max)
1509 size = aligned_end - aligned_start;
1512 if (m_skipmode_m < 0)
1514 eDebug("reached SOF");
1517 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1521 /* when skipping reverse, however, choose the zone before. */
1523 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1526 aligned_start = align(i->first, blocksize);
1527 aligned_end = align(i->second, blocksize);
1529 if ((aligned_end - aligned_start) > max)
1532 len = aligned_end - aligned_start;
1534 start = aligned_end - len;
1535 eDebug("skipping to %llx, %zd", start, len);
1538 eDebug("result: %llx, %zx (%llx %llx)", start, size, aligned_start, aligned_end);
1543 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1545 eDebug("reached SOF");
1547 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1550 if (m_source_span.empty())
1552 start = current_offset;
1554 eDebug("NO CUESHEET. (%08llx, %zd)", start, size);
1557 start = current_offset;
1563 void eDVBChannel::AddUse()
1565 if (++m_use_count > 1 && m_state == state_last_instance)
1568 m_stateChanged(this);
1572 void eDVBChannel::ReleaseUse()
1576 m_state = state_release;
1577 m_stateChanged(this);
1579 else if (m_use_count == 1)
1581 m_state = state_last_instance;
1582 m_stateChanged(this);
1586 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1589 m_mgr->removeChannel(this);
1596 eDebug("no frontend to tune!");
1600 m_channel_id = channelid;
1601 m_mgr->addChannel(channelid, this);
1602 m_state = state_tuning;
1603 /* if tuning fails, shutdown the channel immediately. */
1605 res = m_frontend->get().tune(*feparm);
1606 m_current_frontend_parameters = feparm;
1610 m_state = state_release;
1611 m_stateChanged(this);
1618 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1620 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1624 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1626 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1630 RESULT eDVBChannel::getState(int &state)
1636 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1641 void eDVBChannel::SDTready(int result)
1643 ePyObject args = PyTuple_New(2), ret;
1647 for (std::vector<ServiceDescriptionSection*>::const_iterator i = m_SDT->getSections().begin(); i != m_SDT->getSections().end(); ++i)
1650 PyTuple_SET_ITEM(args, 0, PyInt_FromLong((*i)->getTransportStreamId()));
1651 PyTuple_SET_ITEM(args, 1, PyInt_FromLong((*i)->getOriginalNetworkId()));
1657 PyTuple_SET_ITEM(args, 0, Py_None);
1658 PyTuple_SET_ITEM(args, 1, Py_None);
1662 ret = PyObject_CallObject(m_tsid_onid_callback, args);
1666 Py_DECREF(m_tsid_onid_callback);
1667 m_tsid_onid_callback = ePyObject();
1668 m_tsid_onid_demux = 0;
1672 int eDVBChannel::reserveDemux()
1674 ePtr<iDVBDemux> dmx;
1675 if (!getDemux(dmx, 0))
1678 if (!dmx->getCADemuxID(id))
1684 RESULT eDVBChannel::requestTsidOnid(ePyObject callback)
1686 if (PyCallable_Check(callback))
1688 if (!getDemux(m_tsid_onid_demux, 0))
1690 m_SDT = new eTable<ServiceDescriptionSection>;
1691 CONNECT(m_SDT->tableReady, eDVBChannel::SDTready);
1692 if (m_SDT->start(m_tsid_onid_demux, eDVBSDTSpec()))
1694 m_tsid_onid_demux = 0;
1699 Py_INCREF(callback);
1700 m_tsid_onid_callback = callback;
1708 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1710 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1716 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1721 /* don't hold a reference to the decoding demux, we don't need it. */
1723 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1724 the refcount is lost. thus, decoding demuxes are never allocated.
1726 this poses a big problem for PiP. */
1728 if (cap & capHoldDecodeReference) // this is set in eDVBResourceManager::allocateDemux for Dm500HD/DM800 and DM8000
1730 else if (cap & capDecode)
1739 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1744 frontend = &m_frontend->get();
1750 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1752 param = m_current_frontend_parameters;
1756 RESULT eDVBChannel::playFile(const char *file)
1758 eRawFile *f = new eRawFile();
1759 ePtr<iTsSource> source = f;
1761 if (f->open(file) < 0)
1763 eDebug("can't open PVR file %s (%m)", file);
1767 return playSource(source, file);
1770 RESULT eDVBChannel::playSource(ePtr<iTsSource> &source, const char *streaminfo_file)
1772 ASSERT(!m_frontend);
1775 m_pvr_thread->stop();
1776 delete m_pvr_thread;
1780 if (!source->valid())
1782 eDebug("PVR source is not valid!");
1786 m_tstools.setSource(source, streaminfo_file);
1788 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1789 THEN DO A REAL FIX HERE! */
1791 if (m_pvr_fd_dst < 0)
1793 /* (this codepath needs to be improved anyway.) */
1794 #if HAVE_DVB_API_VERSION < 3
1795 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1796 if (m_pvr_fd_dst < 0)
1798 eDebug("can't open /dev/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1802 ePtr<eDVBAllocatedDemux> &demux = m_demux ? m_demux : m_decoder_demux;
1805 m_pvr_fd_dst = demux->get().openDVR(O_WRONLY);
1806 if (m_pvr_fd_dst < 0)
1808 eDebug("can't open /dev/dvb/adapterX/dvrX - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1814 eDebug("no demux allocated yet.. so its not possible to open the dvr device!!");
1820 m_pvr_thread = new eDVBChannelFilePush();
1821 m_pvr_thread->enablePVRCommit(1);
1822 m_pvr_thread->setStreamMode(1);
1823 m_pvr_thread->setScatterGather(this);
1825 m_event(this, evtPreStart);
1827 m_pvr_thread->start(source, m_pvr_fd_dst);
1828 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1831 m_stateChanged(this);
1836 void eDVBChannel::stopSource()
1840 m_pvr_thread->stop();
1841 delete m_pvr_thread;
1844 if (m_pvr_fd_dst >= 0)
1845 ::close(m_pvr_fd_dst);
1847 m_tstools.setSource(d);
1850 void eDVBChannel::stopFile()
1855 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1857 m_conn_cueSheetEvent = 0;
1860 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1863 RESULT eDVBChannel::getLength(pts_t &len)
1865 return m_tstools.calcLen(len);
1868 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1870 if (!decoding_demux)
1877 if (mode == 0) /* demux */
1879 r = decoding_demux->getSTC(now, 0);
1882 eDebug("demux getSTC failed");
1886 now = pos; /* fixup supplied */
1888 off_t off = 0; /* TODO: fixme */
1889 r = m_tstools.fixupPTS(off, now);
1892 eDebug("fixup PTS failed");
1901 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1903 /* when seeking, we have to ensure that all buffers are flushed.
1904 there are basically 3 buffers:
1905 a.) the filepush's internal buffer
1906 b.) the PVR buffer (before demux)
1907 c.) the ratebuffer (after demux)
1909 it's important to clear them in the correct order, otherwise
1910 the ratebuffer (for example) would immediately refill from
1911 the not-yet-flushed PVR buffer.
1914 m_pvr_thread->pause();
1915 /* flush internal filepush buffer */
1916 m_pvr_thread->flush();
1917 /* HACK: flush PVR buffer */
1918 ::ioctl(m_pvr_fd_dst, 0);
1920 /* flush ratebuffers (video, audio) */
1922 decoding_demux->flush();
1924 /* demux will also flush all decoder.. */
1925 /* resume will re-query the SG */
1926 m_pvr_thread->resume();
1929 DEFINE_REF(eCueSheet);
1931 eCueSheet::eCueSheet()
1933 m_skipmode_ratio = 0;
1936 void eCueSheet::seekTo(int relative, const pts_t &pts)
1939 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1944 void eCueSheet::clear()
1951 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1953 ASSERT(begin < end);
1955 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1959 void eCueSheet::commitSpans()
1961 m_event(evtSpanChanged);
1964 void eCueSheet::setSkipmode(const pts_t &ratio)
1967 m_skipmode_ratio = ratio;
1969 m_event(evtSkipmode);
1972 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1974 m_decoding_demux = demux;
1975 m_decoder = decoder;
1978 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1980 connection = new eConnection(this, m_event.connect(event));