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>
13 #include <sys/ioctl.h>
15 DEFINE_REF(eDVBRegisteredFrontend);
16 DEFINE_REF(eDVBRegisteredDemux);
18 DEFINE_REF(eDVBAllocatedFrontend);
20 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
25 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
30 DEFINE_REF(eDVBAllocatedDemux);
32 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
37 eDVBAllocatedDemux::~eDVBAllocatedDemux()
42 DEFINE_REF(eDVBResourceManager);
44 eDVBResourceManager *eDVBResourceManager::instance;
46 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
56 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
58 ePtr<eDVBResourceManager> ptr;
59 eDVBResourceManager::getInstance(ptr);
63 eDVBResourceManager::eDVBResourceManager()
64 :m_releaseCachedChannelTimer(eTimer::create(eApp))
68 m_sec = new eDVBSatelliteEquipmentControl(m_frontend, m_simulate_frontend);
73 /* search available adapters... */
78 while (eDVBAdapterLinux::exist(num_adapter))
80 addAdapter(new eDVBAdapterLinux(num_adapter));
84 eDebug("found %d adapter, %d frontends(%d sim) and %d demux",
85 m_adapter.size(), m_frontend.size(), m_simulate_frontend.size(), m_demux.size());
87 eDVBCAService::registerChannelCallback(this);
89 CONNECT(m_releaseCachedChannelTimer->timeout, eDVBResourceManager::releaseCachedChannel);
92 void eDVBResourceManager::feStateChanged()
95 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
97 mask |= ( 1 << i->m_frontend->getSlotID() );
98 /* emit */ frontendUseMaskChanged(mask);
101 DEFINE_REF(eDVBAdapterLinux);
102 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
107 eDebug("scanning for frontends..");
112 #if HAVE_DVB_API_VERSION < 3
113 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
115 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
117 if (stat(filename, &s))
119 ePtr<eDVBFrontend> fe;
123 fe = new eDVBFrontend(m_nr, num_fe, ok);
125 m_frontend.push_back(fe);
129 fe = new eDVBFrontend(m_nr, num_fe, ok, true);
131 m_simulate_frontend.push_back(fe);
142 #if HAVE_DVB_API_VERSION < 3
143 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
145 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
147 if (stat(filename, &s))
149 ePtr<eDVBDemux> demux;
151 demux = new eDVBDemux(m_nr, num_demux);
152 m_demux.push_back(demux);
158 int eDVBAdapterLinux::getNumDemux()
160 return m_demux.size();
163 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
165 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
166 while (nr && (i != m_demux.end()))
172 if (i != m_demux.end())
180 int eDVBAdapterLinux::getNumFrontends()
182 return m_frontend.size();
185 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr, bool simulate)
187 eSmartPtrList<eDVBFrontend>::iterator i(simulate ? m_simulate_frontend.begin() : m_frontend.begin());
188 while (nr && (i != m_frontend.end()))
194 if (i != m_frontend.end())
202 int eDVBAdapterLinux::exist(int nr)
206 #if HAVE_DVB_API_VERSION < 3
207 sprintf(filename, "/dev/dvb/card%d", nr);
209 sprintf(filename, "/dev/dvb/adapter%d", nr);
211 if (!stat(filename, &s))
216 eDVBResourceManager::~eDVBResourceManager()
218 if (instance == this)
222 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
224 int num_fe = adapter->getNumFrontends();
225 int num_demux = adapter->getNumDemux();
227 m_adapter.push_back(adapter);
230 for (i=0; i<num_demux; ++i)
232 ePtr<eDVBDemux> demux;
233 if (!adapter->getDemux(demux, i))
234 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
237 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
238 for (i=0; i<num_fe; ++i)
240 ePtr<eDVBFrontend> frontend;
241 if (!adapter->getFrontend(frontend, i))
244 frontend->getFrontendType(frontendType);
245 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
246 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
247 m_frontend.push_back(new_fe);
248 frontend->setSEC(m_sec);
249 // we must link all dvb-t frontends ( for active antenna voltage )
250 if (frontendType == iDVBFrontend::feTerrestrial)
252 if (prev_dvbt_frontend)
254 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
255 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
257 prev_dvbt_frontend = new_fe;
262 prev_dvbt_frontend = 0;
263 for (i=0; i<num_fe; ++i)
265 ePtr<eDVBFrontend> frontend;
266 if (!adapter->getFrontend(frontend, i, true))
269 frontend->getFrontendType(frontendType);
270 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
271 // CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
272 m_simulate_frontend.push_back(new_fe);
273 frontend->setSEC(m_sec);
274 // we must link all dvb-t frontends ( for active antenna voltage )
275 if (frontendType == iDVBFrontend::feTerrestrial)
277 if (prev_dvbt_frontend)
279 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
280 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
282 prev_dvbt_frontend = new_fe;
289 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
291 if (!PyList_Check(list))
293 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
296 if ((unsigned int)PyList_Size(list) != m_frontend.size())
299 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations list size incorrect %d frontends avail, but %d entries in slotlist",
300 m_frontend.size(), PyList_Size(list));
301 PyErr_SetString(PyExc_StandardError, blasel);
305 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
307 ePyObject obj = PyList_GET_ITEM(list, pos++);
308 if (!i->m_frontend->setSlotInfo(obj))
312 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_simulate_frontend.begin()); i != m_simulate_frontend.end(); ++i)
314 ePyObject obj = PyList_GET_ITEM(list, pos++);
315 if (!i->m_frontend->setSlotInfo(obj))
321 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm, bool simulate)
323 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
324 ePtr<eDVBRegisteredFrontend> best;
328 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
330 int c = i->m_frontend->isCompatibleWith(feparm);
332 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
337 // eDebug("Slot %d, score %d", i->m_frontend->getSlotID(), c);
345 // eDebug("Slot %d, score %d... but BUSY!!!!!!!!!!!", i->m_frontend->getSlotID(), c);
350 fe = new eDVBAllocatedFrontend(best);
357 return errAllSourcesBusy;
359 return errNoSourceFound;
362 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
364 int err = errNoSourceFound;
365 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
366 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
368 // check if another slot linked to this is in use
370 i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
373 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
374 if (satpos_depends_to_fe->m_inuse)
376 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
377 err = errAllSourcesBusy;
378 goto alloc_fe_by_id_not_possible;
381 else // check linked tuners
383 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
386 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
389 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
390 err = errAllSourcesBusy;
391 goto alloc_fe_by_id_not_possible;
393 next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
395 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
398 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
401 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
402 err = errAllSourcesBusy;
403 goto alloc_fe_by_id_not_possible;
405 prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
408 fe = new eDVBAllocatedFrontend(i);
411 alloc_fe_by_id_not_possible:
416 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
418 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
419 never use the first one unless we need a decoding demux. */
421 eDebug("allocate demux");
422 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
426 if (i == m_demux.end())
429 ePtr<eDVBRegisteredDemux> unused;
431 if (m_demux.size() < 5)
433 /* FIXME: hardware demux policy */
434 if (!(cap & iDVBChannel::capDecode))
436 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
443 for (; i != m_demux.end(); ++i, ++n)
445 int is_decode = n < 2;
447 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
449 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
451 if ((cap & iDVBChannel::capDecode) && !is_decode)
458 else // we asume dm8000
460 for (; i != m_demux.end(); ++i, ++n)
469 else if (i->m_adapter == fe->m_adapter &&
470 i->m_demux->getSource() == fe->m_frontend->getDVBID())
472 demux = new eDVBAllocatedDemux(i);
476 else if (n == 4) // always use demux4 for PVR (demux 4 can not descramble...)
479 demux = new eDVBAllocatedDemux(i);
489 demux = new eDVBAllocatedDemux(unused);
491 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
493 demux->get().setSourcePVR(0);
497 eDebug("demux not found");
501 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
507 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
516 #define eDebugNoSimulate(x...) \
523 // eDebugNoNewLine("SIMULATE:"); \
528 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel, bool simulate)
530 /* first, check if a channel is already existing. */
531 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
533 if (!simulate && m_cached_channel)
535 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
536 if(channelid==cache_chan->getChannelID())
538 eDebug("use cached_channel");
539 channel = m_cached_channel;
542 m_cached_channel_state_changed_conn.disconnect();
544 m_releaseCachedChannelTimer->stop();
547 eDebugNoSimulate("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
548 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
550 eDebugNoSimulate("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
551 if (i->m_channel_id == channelid)
553 eDebugNoSimulate("found shared channel..");
554 channel = i->m_channel;
559 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
563 eDebugNoSimulate("no channel list set!");
564 return errNoChannelList;
567 ePtr<iDVBFrontendParameters> feparm;
568 if (m_list->getChannelFrontendData(channelid, feparm))
570 eDebugNoSimulate("channel not found!");
571 return errChannelNotInList;
574 /* allocate a frontend. */
576 ePtr<eDVBAllocatedFrontend> fe;
578 int err = allocateFrontend(fe, feparm, simulate);
583 ePtr<eDVBChannel> ch = new eDVBChannel(this, fe);
585 res = ch->setChannel(channelid, feparm);
589 return errChidNotFound;
596 m_cached_channel = channel = ch;
597 m_cached_channel_state_changed_conn =
598 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
604 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
607 chan->getState(state);
610 case iDVBChannel::state_release:
611 case iDVBChannel::state_ok:
613 eDebug("stop release channel timer");
614 m_releaseCachedChannelTimer->stop();
617 case iDVBChannel::state_last_instance:
619 eDebug("start release channel timer");
620 m_releaseCachedChannelTimer->start(3000, true);
623 default: // ignore all other events
628 void eDVBResourceManager::releaseCachedChannel()
630 eDebug("release cached channel (timer timeout)");
634 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
636 ePtr<eDVBAllocatedFrontend> fe;
638 if (m_cached_channel)
640 m_cached_channel_state_changed_conn.disconnect();
642 m_releaseCachedChannelTimer->stop();
645 int err = allocateFrontendByIndex(fe, slot_index);
649 channel = new eDVBChannel(this, fe);
654 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
656 ePtr<eDVBAllocatedDemux> demux;
658 if (m_cached_channel && m_releaseCachedChannelTimer->isActive())
660 m_cached_channel_state_changed_conn.disconnect();
662 m_releaseCachedChannelTimer->stop();
665 channel = new eDVBChannel(this, 0);
669 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
671 ePtr<iDVBFrontend> fe;
672 if (!ch->getFrontend(fe))
674 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
675 if (frontend->is_simulate())
676 m_active_simulate_channels.push_back(active_channel(chid, ch));
679 m_active_channels.push_back(active_channel(chid, ch));
680 /* emit */ m_channelAdded(ch);
686 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
688 ePtr<iDVBFrontend> fe;
689 if (!ch->getFrontend(fe))
691 eDVBFrontend *frontend = (eDVBFrontend*)&(*fe);
692 std::list<active_channel> &active_channels = frontend->is_simulate() ? m_active_simulate_channels : m_active_channels;
694 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end();)
696 if (i->m_channel == ch)
698 i = active_channels.erase(i);
710 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
712 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
716 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm, bool simulate)
718 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
719 ePtr<eDVBRegisteredFrontend> best;
722 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(frontends.begin()); i != frontends.end(); ++i)
725 int c = i->m_frontend->isCompatibleWith(feparm);
732 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
736 ePtr<iDVBFrontendParameters> feparm;
737 if (!channellist->getChannelFrontendData(chid, feparm))
740 if (!feparm->getSystem(system))
744 case iDVBFrontend::feSatellite:
746 case iDVBFrontend::feCable:
748 case iDVBFrontend::feTerrestrial:
759 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore, bool simulate)
761 std::list<active_channel> &active_channels = simulate ? m_active_simulate_channels : m_active_channels;
763 if (!simulate && m_cached_channel)
765 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
766 if(channelid==cache_chan->getChannelID())
767 return tuner_type_channel_default(m_list, channelid);
770 /* first, check if a channel is already existing. */
771 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
772 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
774 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
775 if (i->m_channel_id == channelid)
777 // eDebug("found shared channel..");
778 return tuner_type_channel_default(m_list, channelid);
782 int *decremented_cached_channel_fe_usecount=NULL,
783 *decremented_fe_usecount=NULL;
785 for (std::list<active_channel>::iterator i(active_channels.begin()); i != active_channels.end(); ++i)
787 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
788 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
789 if (i->m_channel_id == ignore)
791 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
792 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
793 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
794 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
795 // or 2 when the cached channel is not equal to the compared channel
796 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
798 ePtr<iDVBFrontend> fe;
799 if (!i->m_channel->getFrontend(fe))
801 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
803 if ( &(*fe) == &(*ii->m_frontend) )
806 decremented_fe_usecount = &ii->m_inuse;
807 if (channel == &(*m_cached_channel))
808 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
818 if (!decremented_cached_channel_fe_usecount)
820 if (m_cached_channel)
822 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
823 if (channel->getUseCount() == 1)
825 ePtr<iDVBFrontend> fe;
826 if (!channel->getFrontend(fe))
828 eSmartPtrList<eDVBRegisteredFrontend> &frontends = simulate ? m_simulate_frontend : m_frontend;
829 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(frontends.begin()); ii != frontends.end(); ++ii)
831 if ( &(*fe) == &(*ii->m_frontend) )
834 decremented_cached_channel_fe_usecount = &ii->m_inuse;
843 decremented_cached_channel_fe_usecount=NULL;
845 ePtr<iDVBFrontendParameters> feparm;
849 eDebug("no channel list set!");
853 if (m_list->getChannelFrontendData(channelid, feparm))
855 eDebug("channel not found!");
859 ret = canAllocateFrontend(feparm, simulate);
862 if (decremented_fe_usecount)
863 ++(*decremented_fe_usecount);
864 if (decremented_cached_channel_fe_usecount)
865 ++(*decremented_cached_channel_fe_usecount);
870 bool eDVBResourceManager::canMeasureFrontendInputPower()
872 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
874 return i->m_frontend->readInputpower() >= 0;
879 class eDVBChannelFilePush: public eFilePushThread
882 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
883 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
885 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
886 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
887 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
889 int m_iframe_search, m_iframe_state, m_pid;
890 int m_timebase_change;
891 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
894 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
897 if (m_timebase_change)
899 eDebug("timebase change: %d", m_timebase_change);
901 for (offset = 0; offset < len; offset += 188)
903 unsigned char *pkt = (unsigned char*)_data + offset;
904 if (pkt[1] & 0x40) /* pusi */
906 if (pkt[3] & 0x20) // adaption field present?
907 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
909 pkt += 4; /* skip header */
910 if (pkt[0] || pkt[1] || (pkt[2] != 1))
912 eWarning("broken startcode");
918 if (pkt[7] & 0x80) // PTS present?
920 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
921 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
922 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
923 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
924 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
928 RESULT r = m_tstools.fixupPTS(off, pts);
930 eWarning("fixup PTS while trickmode playback failed.\n");
933 int sec = pts / 90000;
934 int frm = pts % 90000;
942 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
945 pts *= m_timebase_change;
957 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
965 pkt[9] |= (pts >> 29) & 0xE;
966 pkt[10] |= (pts >> 22) & 0xFF;
967 pkt[11] |= (pts >> 14) & 0xFE;
968 pkt[12] |= (pts >> 7) & 0xFF;
969 pkt[13] |= (pts << 1) & 0xFE;
976 #if 1 /* This codepath is required on Broadcom-based Dreamboxes (DM800, DM8000) and strips away non-I-frames. */
977 if (!m_iframe_search)
980 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
982 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
984 unsigned char *d = data;
985 while ((d + 3 < data + len) && (d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
987 int offset = d - data;
988 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
989 unsigned char *ts = data + ts_offset;
990 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
992 if ((d[3] == 0 || d[3] == 0x09 && d[-1] == 0 && (ts[1] & 0x40)) && (m_pid == pid)) /* picture start */
994 int picture_type = (d[3]==0 ? (d[5] >> 3) & 7 : (d[4] >> 5) + 1);
997 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
999 if (m_iframe_state == 1)
1001 /* we are allowing data, and stop allowing data on the next frame.
1002 we now found a frame. so stop here. */
1003 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
1004 current_span_remaining = 0;
1006 unsigned char *fts = ts + 188;
1007 while (fts < (data + len))
1010 fts[2] |= 0xff; /* drop packet */
1014 return len; // ts_offset + 188; /* deliver this packet, but not more. */
1017 if (picture_type != 1) /* we are only interested in I frames */
1020 unsigned char *fts = data;
1024 fts[2] |= 0xff; /* drop packet */
1028 /* force payload only */
1032 // memset(ts + 4, 0xFF, (offset % 188) - 4);
1036 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
1038 /* verify that this is actually a PES header, not just some ES data */
1039 if (ts[1] & 0x40) /* PUSI set */
1041 int payload_start = 4;
1042 if (ts[3] & 0x20) /* adaptation field present */
1043 payload_start += ts[4] + 1; /* skip AF */
1044 if (payload_start == (offset%188)) /* the 00 00 01 should be directly at the payload start, otherwise it's not a PES header */
1048 eDebug("now locked to pid %04x (%02x %02x %02x %02x)", pid, ts[0], ts[1], ts[2], ts[3]);
1056 d += 4; /* ignore */
1059 if (m_iframe_state == 1)
1062 return 0; /* we need find an iframe first */
1068 DEFINE_REF(eDVBChannel);
1070 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
1072 m_frontend = frontend;
1076 m_skipmode_n = m_skipmode_m = 0;
1079 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
1082 eDVBChannel::~eDVBChannel()
1085 m_mgr->removeChannel(this);
1090 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1092 int state, ourstate = 0;
1094 /* if we are already in shutdown, don't change state. */
1095 if (m_state == state_release)
1098 if (fe->getState(state))
1101 if (state == iDVBFrontend::stateLock)
1103 eDebug("OURSTATE: ok");
1104 ourstate = state_ok;
1105 } else if (state == iDVBFrontend::stateTuning)
1107 eDebug("OURSTATE: tuning");
1108 ourstate = state_tuning;
1109 } else if (state == iDVBFrontend::stateLostLock)
1111 /* on managed channels, we try to retune in order to re-acquire lock. */
1112 if (m_current_frontend_parameters)
1114 eDebug("OURSTATE: lost lock, trying to retune");
1115 ourstate = state_tuning;
1116 m_frontend->get().tune(*m_current_frontend_parameters);
1118 /* on unmanaged channels, we don't do this. the client will do this. */
1120 eDebug("OURSTATE: lost lock, unavailable now.");
1121 ourstate = state_unavailable;
1123 } else if (state == iDVBFrontend::stateFailed)
1125 eDebug("OURSTATE: failed");
1126 ourstate = state_failed;
1128 eFatal("state unknown");
1130 if (ourstate != m_state)
1133 m_stateChanged(this);
1137 void eDVBChannel::pvrEvent(int event)
1141 case eFilePushThread::evtEOF:
1142 eDebug("eDVBChannel: End of file!");
1143 m_event(this, evtEOF);
1145 case eFilePushThread::evtUser: /* start */
1147 m_event(this, evtSOF);
1152 void eDVBChannel::cueSheetEvent(int event)
1154 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1159 case eCueSheet::evtSeek:
1161 flushPVR(m_cue->m_decoding_demux);
1163 case eCueSheet::evtSkipmode:
1166 m_cue->m_lock.WrLock();
1167 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1168 m_cue->m_lock.Unlock();
1169 eRdLocker l(m_cue->m_lock);
1170 if (m_cue->m_skipmode_ratio)
1172 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1173 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1174 /* i agree that this might look a bit like black magic. */
1175 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1176 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1178 if (m_cue->m_skipmode_ratio < 0)
1179 m_skipmode_m -= m_skipmode_n;
1181 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1183 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1185 eWarning("something is wrong with this calculation");
1186 m_skipmode_n = m_skipmode_m = 0;
1190 eDebug("skipmode ratio is 0, normal play");
1191 m_skipmode_n = m_skipmode_m = 0;
1194 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1195 if (m_cue->m_skipmode_ratio != 0)
1196 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1198 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1199 eDebug("flush pvr");
1200 flushPVR(m_cue->m_decoding_demux);
1204 case eCueSheet::evtSpanChanged:
1206 m_source_span.clear();
1207 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1209 off_t offset_in, offset_out;
1210 pts_t pts_in = i->first, pts_out = i->second;
1211 if (m_tstools.getOffset(offset_in, pts_in, -1) || m_tstools.getOffset(offset_out, pts_out, 1))
1213 eDebug("span translation failed.\n");
1216 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1217 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1224 /* align toward zero */
1225 static inline long long align(long long x, int align)
1240 /* remember, this gets called from another thread. */
1241 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1243 const int blocksize = 188;
1244 unsigned int max = align(10*1024*1024, blocksize);
1245 current_offset = align(current_offset, blocksize);
1249 eDebug("no cue sheet. forcing normal play");
1250 start = current_offset;
1255 m_cue->m_lock.RdLock();
1256 if (!m_cue->m_decoding_demux)
1258 start = current_offset;
1260 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1261 m_cue->m_lock.Unlock();
1267 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1268 max = align(m_skipmode_n, blocksize);
1271 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1273 current_offset += align(m_skipmode_m, blocksize);
1275 while (!m_cue->m_seek_requests.empty())
1277 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1278 m_cue->m_lock.Unlock();
1279 m_cue->m_lock.WrLock();
1280 m_cue->m_seek_requests.pop_front();
1281 m_cue->m_lock.Unlock();
1282 m_cue->m_lock.RdLock();
1283 int relative = seek.first;
1284 pts_t pts = seek.second;
1289 if (!m_cue->m_decoder)
1291 eDebug("no decoder - can't seek relative");
1294 if (m_cue->m_decoder->getPTS(0, now))
1296 eDebug("decoder getPTS failed, can't seek relative");
1299 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1301 eDebug("seekTo: getCurrentPosition failed!");
1304 } else if (pts < 0) /* seek relative to end */
1307 if (!getLength(len))
1309 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1313 eWarning("getLength failed - can't seek relative to end!");
1318 if (relative == 1) /* pts relative */
1329 if (relative == 2) /* AP relative */
1331 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1333 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1335 pts = now - 90000; /* approx. 1s */
1336 eDebug("AP relative seeking failed!");
1340 eDebug("next ap is %llx\n", pts);
1345 if (m_tstools.getOffset(offset, pts, -1))
1347 eDebug("get offset for pts=%lld failed!", pts);
1351 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1352 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1355 m_cue->m_lock.Unlock();
1357 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1359 long long aligned_start = align(i->first, blocksize);
1360 long long aligned_end = align(i->second, blocksize);
1362 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1364 start = current_offset;
1365 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1366 if ((aligned_end - current_offset) > max)
1369 size = aligned_end - current_offset;
1370 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1373 if (current_offset < aligned_start)
1375 /* ok, our current offset is in an 'out' zone. */
1376 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1378 /* in normal playback, just start at the next zone. */
1381 /* size is not 64bit! */
1382 if ((i->second - i->first) > max)
1385 size = aligned_end - aligned_start;
1388 if (m_skipmode_m < 0)
1390 eDebug("reached SOF");
1393 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1397 /* when skipping reverse, however, choose the zone before. */
1399 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1402 aligned_start = align(i->first, blocksize);
1403 aligned_end = align(i->second, blocksize);
1405 if ((aligned_end - aligned_start) > max)
1408 len = aligned_end - aligned_start;
1410 start = aligned_end - len;
1411 eDebug("skipping to %llx, %d", start, len);
1414 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1419 if (m_source_span.empty()) {
1420 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1422 eDebug("reached SOF");
1424 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1426 start = current_offset;
1429 off_t tmp2, tmp = align(m_source_span.rbegin()->second, blocksize);
1432 m_tstools.getOffset(tmp2, len, 1);
1433 if (current_offset == tmp || current_offset == tmp2) {
1437 start = tmp - align(512*1024, blocksize);
1438 size = align(512*1024, blocksize);
1442 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1446 void eDVBChannel::AddUse()
1448 if (++m_use_count > 1 && m_state == state_last_instance)
1451 m_stateChanged(this);
1455 void eDVBChannel::ReleaseUse()
1459 m_state = state_release;
1460 m_stateChanged(this);
1462 else if (m_use_count == 1)
1464 m_state = state_last_instance;
1465 m_stateChanged(this);
1469 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1472 m_mgr->removeChannel(this);
1479 eDebug("no frontend to tune!");
1483 m_channel_id = channelid;
1484 m_mgr->addChannel(channelid, this);
1485 m_state = state_tuning;
1486 /* if tuning fails, shutdown the channel immediately. */
1488 res = m_frontend->get().tune(*feparm);
1489 m_current_frontend_parameters = feparm;
1493 m_state = state_release;
1494 m_stateChanged(this);
1501 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1503 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1507 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1509 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1513 RESULT eDVBChannel::getState(int &state)
1519 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1524 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1526 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1532 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1537 /* don't hold a reference to the decoding demux, we don't need it. */
1539 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1540 the refcount is lost. thus, decoding demuxes are never allocated.
1542 this poses a big problem for PiP. */
1543 if (cap & capDecode)
1548 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1553 frontend = &m_frontend->get();
1559 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1561 param = m_current_frontend_parameters;
1565 RESULT eDVBChannel::playFile(const char *file)
1567 ASSERT(!m_frontend);
1570 m_pvr_thread->stop();
1571 delete m_pvr_thread;
1575 m_tstools.openFile(file);
1577 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1578 THEN DO A REAL FIX HERE! */
1580 /* (this codepath needs to be improved anyway.) */
1581 #if HAVE_DVB_API_VERSION < 3
1582 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1584 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1586 if (m_pvr_fd_dst < 0)
1588 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1592 m_pvr_thread = new eDVBChannelFilePush();
1593 m_pvr_thread->enablePVRCommit(1);
1594 m_pvr_thread->setStreamMode(1);
1595 m_pvr_thread->setScatterGather(this);
1597 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1599 delete m_pvr_thread;
1601 eDebug("can't open PVR file %s (%m)", file);
1604 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1607 m_stateChanged(this);
1612 void eDVBChannel::stopFile()
1616 m_pvr_thread->stop();
1617 ::close(m_pvr_fd_dst);
1618 delete m_pvr_thread;
1623 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1625 m_conn_cueSheetEvent = 0;
1628 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1631 RESULT eDVBChannel::getLength(pts_t &len)
1633 return m_tstools.calcLen(len);
1636 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1638 if (!decoding_demux)
1645 if (mode == 0) /* demux */
1647 r = decoding_demux->getSTC(now, 0);
1650 eDebug("demux getSTC failed");
1654 now = pos; /* fixup supplied */
1656 off_t off = 0; /* TODO: fixme */
1657 r = m_tstools.fixupPTS(off, now);
1660 eDebug("fixup PTS failed");
1669 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1671 /* when seeking, we have to ensure that all buffers are flushed.
1672 there are basically 3 buffers:
1673 a.) the filepush's internal buffer
1674 b.) the PVR buffer (before demux)
1675 c.) the ratebuffer (after demux)
1677 it's important to clear them in the correct order, otherwise
1678 the ratebuffer (for example) would immediately refill from
1679 the not-yet-flushed PVR buffer.
1682 m_pvr_thread->pause();
1683 /* flush internal filepush buffer */
1684 m_pvr_thread->flush();
1685 /* HACK: flush PVR buffer */
1686 ::ioctl(m_pvr_fd_dst, 0);
1688 /* flush ratebuffers (video, audio) */
1690 decoding_demux->flush();
1692 /* demux will also flush all decoder.. */
1693 /* resume will re-query the SG */
1694 m_pvr_thread->resume();
1697 DEFINE_REF(eCueSheet);
1699 eCueSheet::eCueSheet()
1701 m_skipmode_ratio = 0;
1704 void eCueSheet::seekTo(int relative, const pts_t &pts)
1707 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1712 void eCueSheet::clear()
1719 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1721 assert(begin < end);
1723 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1727 void eCueSheet::commitSpans()
1729 m_event(evtSpanChanged);
1732 void eCueSheet::setSkipmode(const pts_t &ratio)
1735 m_skipmode_ratio = ratio;
1737 m_event(evtSkipmode);
1740 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1742 m_decoding_demux = demux;
1743 m_decoder = decoder;
1746 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1748 connection = new eConnection(this, m_event.connect(event));