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(eApp)
68 m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
72 /* search available adapters... */
77 while (eDVBAdapterLinux::exist(num_adapter))
79 addAdapter(new eDVBAdapterLinux(num_adapter));
83 eDebug("found %d adapter, %d frontends and %d demux",
84 m_adapter.size(), m_frontend.size(), m_demux.size());
86 eDVBCAService::registerChannelCallback(this);
88 CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
91 void eDVBResourceManager::feStateChanged()
94 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
96 mask |= ( 1 << i->m_frontend->getSlotID() );
97 /* emit */ frontendUseMaskChanged(mask);
100 DEFINE_REF(eDVBAdapterLinux);
101 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
106 eDebug("scanning for frontends..");
111 #if HAVE_DVB_API_VERSION < 3
112 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
114 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
116 if (stat(filename, &s))
118 ePtr<eDVBFrontend> fe;
121 fe = new eDVBFrontend(m_nr, num_fe, ok);
123 m_frontend.push_back(fe);
133 #if HAVE_DVB_API_VERSION < 3
134 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
136 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
138 if (stat(filename, &s))
140 ePtr<eDVBDemux> demux;
142 demux = new eDVBDemux(m_nr, num_demux);
143 m_demux.push_back(demux);
149 int eDVBAdapterLinux::getNumDemux()
151 return m_demux.size();
154 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
156 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
157 while (nr && (i != m_demux.end()))
163 if (i != m_demux.end())
171 int eDVBAdapterLinux::getNumFrontends()
173 return m_frontend.size();
176 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
178 eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
179 while (nr && (i != m_frontend.end()))
185 if (i != m_frontend.end())
193 int eDVBAdapterLinux::exist(int nr)
197 #if HAVE_DVB_API_VERSION < 3
198 sprintf(filename, "/dev/dvb/card%d", nr);
200 sprintf(filename, "/dev/dvb/adapter%d", nr);
202 if (!stat(filename, &s))
207 eDVBResourceManager::~eDVBResourceManager()
209 if (instance == this)
213 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
215 int num_fe = adapter->getNumFrontends();
216 int num_demux = adapter->getNumDemux();
218 m_adapter.push_back(adapter);
221 for (i=0; i<num_demux; ++i)
223 ePtr<eDVBDemux> demux;
224 if (!adapter->getDemux(demux, i))
225 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
228 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
229 for (i=0; i<num_fe; ++i)
231 ePtr<eDVBFrontend> frontend;
232 if (!adapter->getFrontend(frontend, i))
235 frontend->getFrontendType(frontendType);
236 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
237 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
238 m_frontend.push_back(new_fe);
239 frontend->setSEC(m_sec);
240 // we must link all dvb-t frontends ( for active antenna voltage )
241 if (frontendType == iDVBFrontend::feTerrestrial)
243 if (prev_dvbt_frontend)
245 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (long)new_fe);
246 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (long)&(*prev_dvbt_frontend));
248 prev_dvbt_frontend = new_fe;
254 PyObject *eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
256 if (!PyList_Check(list))
258 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
261 if ((unsigned int)PyList_Size(list) != m_frontend.size())
264 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations list size incorrect %d frontends avail, but %d entries in slotlist",
265 m_frontend.size(), PyList_Size(list));
266 PyErr_SetString(PyExc_StandardError, blasel);
270 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
272 ePyObject obj = PyList_GET_ITEM(list, pos++);
273 if (!i->m_frontend->setSlotInfo(obj))
279 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
281 ePtr<eDVBRegisteredFrontend> best;
285 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
287 int c = i->m_frontend->isCompatibleWith(feparm);
289 if (c) /* if we have at least one frontend which is compatible with the source, flag this. */
304 fe = new eDVBAllocatedFrontend(best);
311 return errAllSourcesBusy;
313 return errNoSourceFound;
316 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
318 int err = errNoSourceFound;
319 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
320 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
322 // check if another slot linked to this is in use
324 i->m_frontend->getData(eDVBFrontend::SATPOS_DEPENDS_PTR, tmp);
327 eDVBRegisteredFrontend *satpos_depends_to_fe = (eDVBRegisteredFrontend *)tmp;
328 if (satpos_depends_to_fe->m_inuse)
330 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
331 err = errAllSourcesBusy;
332 goto alloc_fe_by_id_not_possible;
335 else // check linked tuners
337 i->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
340 eDVBRegisteredFrontend *next = (eDVBRegisteredFrontend *) tmp;
343 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
344 err = errAllSourcesBusy;
345 goto alloc_fe_by_id_not_possible;
347 next->m_frontend->getData(eDVBFrontend::LINKED_NEXT_PTR, tmp);
349 i->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
352 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *) tmp;
355 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
356 err = errAllSourcesBusy;
357 goto alloc_fe_by_id_not_possible;
359 prev->m_frontend->getData(eDVBFrontend::LINKED_PREV_PTR, tmp);
362 fe = new eDVBAllocatedFrontend(i);
365 alloc_fe_by_id_not_possible:
370 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
372 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
373 never use the first one unless we need a decoding demux. */
375 eDebug("allocate demux");
376 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
380 if (i == m_demux.end())
383 ePtr<eDVBRegisteredDemux> unused;
385 if (m_demux.size() < 5)
387 /* FIXME: hardware demux policy */
388 if (!(cap & iDVBChannel::capDecode))
390 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
397 for (; i != m_demux.end(); ++i, ++n)
399 int is_decode = n < 2;
401 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
403 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
405 if ((cap & iDVBChannel::capDecode) && !is_decode)
412 else // we asume dm8000
414 for (; i != m_demux.end(); ++i, ++n)
423 else if (i->m_adapter == fe->m_adapter &&
424 i->m_demux->getSource() == fe->m_frontend->getDVBID())
426 demux = new eDVBAllocatedDemux(i);
430 else if (n == 4) // always use demux4 for PVR (demux 4 can not descramble...)
433 demux = new eDVBAllocatedDemux(i);
443 demux = new eDVBAllocatedDemux(unused);
445 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
447 demux->get().setSourcePVR(0);
451 eDebug("demux not found");
455 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
461 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
470 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
472 /* first, check if a channel is already existing. */
474 if (m_cached_channel)
476 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
477 if(channelid==cache_chan->getChannelID())
479 eDebug("use cached_channel");
480 channel = m_cached_channel;
483 m_cached_channel_state_changed_conn.disconnect();
485 m_releaseCachedChannelTimer.stop();
488 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
489 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
491 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
492 if (i->m_channel_id == channelid)
494 // eDebug("found shared channel..");
495 channel = i->m_channel;
500 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
504 eDebug("no channel list set!");
505 return errNoChannelList;
508 ePtr<iDVBFrontendParameters> feparm;
509 if (m_list->getChannelFrontendData(channelid, feparm))
511 eDebug("channel not found!");
512 return errChannelNotInList;
515 /* allocate a frontend. */
517 ePtr<eDVBAllocatedFrontend> fe;
519 int err = allocateFrontend(fe, feparm);
524 ePtr<eDVBChannel> ch;
525 ch = new eDVBChannel(this, fe);
527 res = ch->setChannel(channelid, feparm);
531 return errChidNotFound;
533 m_cached_channel = channel = ch;
534 m_cached_channel_state_changed_conn =
535 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
540 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
543 chan->getState(state);
546 case iDVBChannel::state_release:
547 case iDVBChannel::state_ok:
549 eDebug("stop release channel timer");
550 m_releaseCachedChannelTimer.stop();
553 case iDVBChannel::state_last_instance:
555 eDebug("start release channel timer");
556 m_releaseCachedChannelTimer.start(3000, true);
559 default: // ignore all other events
564 void eDVBResourceManager::releaseCachedChannel()
566 eDebug("release cached channel (timer timeout)");
570 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
572 ePtr<eDVBAllocatedFrontend> fe;
574 if (m_cached_channel)
576 m_cached_channel_state_changed_conn.disconnect();
578 m_releaseCachedChannelTimer.stop();
581 int err = allocateFrontendByIndex(fe, slot_index);
586 ch = new eDVBChannel(this, fe);
593 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
595 ePtr<eDVBAllocatedDemux> demux;
597 if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
599 m_cached_channel_state_changed_conn.disconnect();
601 m_releaseCachedChannelTimer.stop();
605 ch = new eDVBChannel(this, 0);
611 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
613 m_active_channels.push_back(active_channel(chid, ch));
614 /* emit */ m_channelAdded(ch);
618 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
621 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
623 if (i->m_channel == ch)
625 i = m_active_channels.erase(i);
636 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
638 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
642 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
644 ePtr<eDVBRegisteredFrontend> best;
647 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
650 int c = i->m_frontend->isCompatibleWith(feparm);
657 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
661 ePtr<iDVBFrontendParameters> feparm;
662 if (!channellist->getChannelFrontendData(chid, feparm))
665 if (!feparm->getSystem(system))
669 case iDVBFrontend::feSatellite:
671 case iDVBFrontend::feCable:
673 case iDVBFrontend::feTerrestrial:
684 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
687 if (m_cached_channel)
689 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
690 if(channelid==cache_chan->getChannelID())
691 return tuner_type_channel_default(m_list, channelid);
694 /* first, check if a channel is already existing. */
695 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
696 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
698 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
699 if (i->m_channel_id == channelid)
701 // eDebug("found shared channel..");
702 return tuner_type_channel_default(m_list, channelid);
706 int *decremented_cached_channel_fe_usecount=NULL,
707 *decremented_fe_usecount=NULL;
709 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
711 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
712 if (i->m_channel_id == ignore)
714 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
715 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
716 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
717 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
718 // or 2 when the cached channel is not equal to the compared channel
719 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
721 ePtr<iDVBFrontend> fe;
722 if (!i->m_channel->getFrontend(fe))
724 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
726 if ( &(*fe) == &(*ii->m_frontend) )
729 decremented_fe_usecount = &ii->m_inuse;
730 if (channel == &(*m_cached_channel))
731 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
741 if (!decremented_cached_channel_fe_usecount)
743 if (m_cached_channel)
745 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
746 if (channel->getUseCount() == 1)
748 ePtr<iDVBFrontend> fe;
749 if (!channel->getFrontend(fe))
751 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
753 if ( &(*fe) == &(*ii->m_frontend) )
756 decremented_cached_channel_fe_usecount = &ii->m_inuse;
765 decremented_cached_channel_fe_usecount=NULL;
767 ePtr<iDVBFrontendParameters> feparm;
771 eDebug("no channel list set!");
775 if (m_list->getChannelFrontendData(channelid, feparm))
777 eDebug("channel not found!");
781 ret = canAllocateFrontend(feparm);
784 if (decremented_fe_usecount)
785 ++(*decremented_fe_usecount);
786 if (decremented_cached_channel_fe_usecount)
787 ++(*decremented_cached_channel_fe_usecount);
792 bool eDVBResourceManager::canMeasureFrontendInputPower()
794 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
796 return i->m_frontend->readInputpower() >= 0;
801 class eDVBChannelFilePush: public eFilePushThread
804 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
805 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
807 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
808 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
809 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
811 int m_iframe_search, m_iframe_state, m_pid;
812 int m_timebase_change;
813 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
816 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
819 if (m_timebase_change)
821 eDebug("timebase change: %d", m_timebase_change);
823 for (offset = 0; offset < len; offset += 188)
825 unsigned char *pkt = (unsigned char*)_data + offset;
826 if (pkt[1] & 0x40) /* pusi */
828 if (pkt[3] & 0x20) // adaption field present?
829 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
831 pkt += 4; /* skip header */
832 if (pkt[0] || pkt[1] || (pkt[2] != 1))
834 eWarning("broken startcode");
840 if (pkt[7] & 0x80) // PTS present?
842 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
843 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
844 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
845 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
846 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
850 RESULT r = m_tstools.fixupPTS(off, pts);
852 eWarning("fixup PTS while trickmode playback failed.\n");
855 int sec = pts / 90000;
856 int frm = pts % 90000;
864 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
867 pts *= m_timebase_change;
879 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
887 pkt[9] |= (pts >> 29) & 0xE;
888 pkt[10] |= (pts >> 22) & 0xFF;
889 pkt[11] |= (pts >> 14) & 0xFE;
890 pkt[12] |= (pts >> 7) & 0xFF;
891 pkt[13] |= (pts << 1) & 0xFE;
899 if (!m_iframe_search)
902 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
904 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
906 unsigned char *d = data;
907 while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
909 int offset = d - data;
910 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
911 unsigned char *ts = data + ts_offset;
912 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
914 if ((d[3] == 0) && (m_pid == pid)) /* picture start */
916 int picture_type = (d[5] >> 3) & 7;
919 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
921 if (m_iframe_state == 1)
923 /* we are allowing data, and stop allowing data on the next frame.
924 we now found a frame. so stop here. */
925 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
926 current_span_remaining = 0;
928 unsigned char *fts = ts + 188;
929 while (fts < (data + len))
932 fts[2] |= 0xff; /* drop packet */
936 return len; // ts_offset + 188; /* deliver this packet, but not more. */
939 if (picture_type != 1) /* we are only interested in I frames */
942 unsigned char *fts = data;
946 fts[2] |= 0xff; /* drop packet */
950 /* force payload only */
954 // memset(ts + 4, 0xFF, (offset % 188) - 4);
958 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
962 eDebug("now locked to pid %04x", pid);
972 if (m_iframe_state == 1)
975 return 0; /* we need find an iframe first */
981 DEFINE_REF(eDVBChannel);
983 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
985 m_frontend = frontend;
989 m_skipmode_n = m_skipmode_m = 0;
992 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
995 eDVBChannel::~eDVBChannel()
998 m_mgr->removeChannel(this);
1003 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
1005 int state, ourstate = 0;
1007 /* if we are already in shutdown, don't change state. */
1008 if (m_state == state_release)
1011 if (fe->getState(state))
1014 if (state == iDVBFrontend::stateLock)
1016 eDebug("OURSTATE: ok");
1017 ourstate = state_ok;
1018 } else if (state == iDVBFrontend::stateTuning)
1020 eDebug("OURSTATE: tuning");
1021 ourstate = state_tuning;
1022 } else if (state == iDVBFrontend::stateLostLock)
1024 /* on managed channels, we try to retune in order to re-acquire lock. */
1025 if (m_current_frontend_parameters)
1027 eDebug("OURSTATE: lost lock, trying to retune");
1028 ourstate = state_tuning;
1029 m_frontend->get().tune(*m_current_frontend_parameters);
1031 /* on unmanaged channels, we don't do this. the client will do this. */
1033 eDebug("OURSTATE: lost lock, unavailable now.");
1034 ourstate = state_unavailable;
1036 } else if (state == iDVBFrontend::stateFailed)
1038 eDebug("OURSTATE: failed");
1039 ourstate = state_failed;
1041 eFatal("state unknown");
1043 if (ourstate != m_state)
1046 m_stateChanged(this);
1050 void eDVBChannel::pvrEvent(int event)
1054 case eFilePushThread::evtEOF:
1055 eDebug("eDVBChannel: End of file!");
1056 m_event(this, evtEOF);
1058 case eFilePushThread::evtUser: /* start */
1060 m_event(this, evtSOF);
1065 void eDVBChannel::cueSheetEvent(int event)
1067 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1072 case eCueSheet::evtSeek:
1074 flushPVR(m_cue->m_decoding_demux);
1076 case eCueSheet::evtSkipmode:
1079 m_cue->m_lock.WrLock();
1080 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1081 m_cue->m_lock.Unlock();
1082 eRdLocker l(m_cue->m_lock);
1083 if (m_cue->m_skipmode_ratio)
1085 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1086 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1087 /* i agree that this might look a bit like black magic. */
1088 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1089 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1091 if (m_cue->m_skipmode_ratio < 0)
1092 m_skipmode_m -= m_skipmode_n;
1094 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1096 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1098 eWarning("something is wrong with this calculation");
1099 m_skipmode_n = m_skipmode_m = 0;
1103 eDebug("skipmode ratio is 0, normal play");
1104 m_skipmode_n = m_skipmode_m = 0;
1107 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1108 if (m_cue->m_skipmode_ratio != 0)
1109 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1111 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1112 eDebug("flush pvr");
1113 flushPVR(m_cue->m_decoding_demux);
1117 case eCueSheet::evtSpanChanged:
1119 m_source_span.clear();
1120 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1122 off_t offset_in, offset_out;
1123 pts_t pts_in = i->first, pts_out = i->second;
1124 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
1126 eDebug("span translation failed.\n");
1129 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1130 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1137 /* align toward zero */
1138 static inline long long align(long long x, int align)
1153 /* remember, this gets called from another thread. */
1154 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1156 const int blocksize = 188;
1157 unsigned int max = align(10*1024*1024, blocksize);
1158 current_offset = align(current_offset, blocksize);
1162 eDebug("no cue sheet. forcing normal play");
1163 start = current_offset;
1168 m_cue->m_lock.RdLock();
1169 if (!m_cue->m_decoding_demux)
1171 start = current_offset;
1173 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1174 m_cue->m_lock.Unlock();
1180 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1181 max = align(m_skipmode_n, blocksize);
1184 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1186 current_offset += align(m_skipmode_m, blocksize);
1188 while (!m_cue->m_seek_requests.empty())
1190 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1191 m_cue->m_lock.Unlock();
1192 m_cue->m_lock.WrLock();
1193 m_cue->m_seek_requests.pop_front();
1194 m_cue->m_lock.Unlock();
1195 m_cue->m_lock.RdLock();
1196 int relative = seek.first;
1197 pts_t pts = seek.second;
1202 if (!m_cue->m_decoder)
1204 eDebug("no decoder - can't seek relative");
1207 if (m_cue->m_decoder->getPTS(0, now))
1209 eDebug("decoder getPTS failed, can't seek relative");
1212 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1214 eDebug("seekTo: getCurrentPosition failed!");
1217 } else if (pts < 0) /* seek relative to end */
1220 if (!getLength(len))
1222 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1226 eWarning("getLength failed - can't seek relative to end!");
1231 if (relative == 1) /* pts relative */
1242 if (relative == 2) /* AP relative */
1244 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1246 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1248 pts = now - 90000; /* approx. 1s */
1249 eDebug("AP relative seeking failed!");
1252 eDebug("next ap is %llx\n", pts);
1258 if (m_tstools.getOffset(offset, pts))
1260 eDebug("get offset for pts=%lld failed!", pts);
1264 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1265 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1268 m_cue->m_lock.Unlock();
1270 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1272 long long aligned_start = align(i->first, blocksize);
1273 long long aligned_end = align(i->second, blocksize);
1275 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1277 start = current_offset;
1278 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1279 if ((aligned_end - current_offset) > max)
1282 size = aligned_end - current_offset;
1283 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1286 if (current_offset < aligned_start)
1288 /* ok, our current offset is in an 'out' zone. */
1289 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1291 /* in normal playback, just start at the next zone. */
1294 /* size is not 64bit! */
1295 if ((i->second - i->first) > max)
1298 size = aligned_end - aligned_start;
1301 if (m_skipmode_m < 0)
1303 eDebug("reached SOF");
1306 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1310 /* when skipping reverse, however, choose the zone before. */
1312 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1315 aligned_start = align(i->first, blocksize);
1316 aligned_end = align(i->second, blocksize);
1318 if ((aligned_end - aligned_start) > max)
1321 len = aligned_end - aligned_start;
1323 start = aligned_end - len;
1324 eDebug("skipping to %llx, %d", start, len);
1327 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1332 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1334 eDebug("reached SOF");
1336 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1339 start = current_offset;
1342 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1346 void eDVBChannel::AddUse()
1348 if (++m_use_count > 1 && m_state == state_last_instance)
1351 m_stateChanged(this);
1355 void eDVBChannel::ReleaseUse()
1359 m_state = state_release;
1360 m_stateChanged(this);
1362 else if (m_use_count == 1)
1364 m_state = state_last_instance;
1365 m_stateChanged(this);
1369 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1372 m_mgr->removeChannel(this);
1379 eDebug("no frontend to tune!");
1383 m_channel_id = channelid;
1384 m_mgr->addChannel(channelid, this);
1385 m_state = state_tuning;
1386 /* if tuning fails, shutdown the channel immediately. */
1388 res = m_frontend->get().tune(*feparm);
1389 m_current_frontend_parameters = feparm;
1393 m_state = state_release;
1394 m_stateChanged(this);
1401 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1403 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1407 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1409 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1413 RESULT eDVBChannel::getState(int &state)
1419 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1424 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1426 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1432 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1437 /* don't hold a reference to the decoding demux, we don't need it. */
1439 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1440 the refcount is lost. thus, decoding demuxes are never allocated.
1442 this poses a big problem for PiP. */
1443 if (cap & capDecode)
1448 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1453 frontend = &m_frontend->get();
1459 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1461 param = m_current_frontend_parameters;
1465 RESULT eDVBChannel::playFile(const char *file)
1467 ASSERT(!m_frontend);
1470 m_pvr_thread->stop();
1471 delete m_pvr_thread;
1475 m_tstools.openFile(file);
1477 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1478 THEN DO A REAL FIX HERE! */
1480 /* (this codepath needs to be improved anyway.) */
1481 #if HAVE_DVB_API_VERSION < 3
1482 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1484 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1486 if (m_pvr_fd_dst < 0)
1488 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1492 m_pvr_thread = new eDVBChannelFilePush();
1493 m_pvr_thread->enablePVRCommit(1);
1494 m_pvr_thread->setStreamMode(1);
1495 m_pvr_thread->setScatterGather(this);
1497 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1499 delete m_pvr_thread;
1501 eDebug("can't open PVR file %s (%m)", file);
1504 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1507 m_stateChanged(this);
1512 void eDVBChannel::stopFile()
1516 m_pvr_thread->stop();
1517 ::close(m_pvr_fd_dst);
1518 delete m_pvr_thread;
1523 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1525 m_conn_cueSheetEvent = 0;
1528 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1531 RESULT eDVBChannel::getLength(pts_t &len)
1533 return m_tstools.calcLen(len);
1536 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1538 if (!decoding_demux)
1545 if (mode == 0) /* demux */
1547 r = decoding_demux->getSTC(now, 0);
1550 eDebug("demux getSTC failed");
1554 now = pos; /* fixup supplied */
1556 off_t off = 0; /* TODO: fixme */
1557 r = m_tstools.fixupPTS(off, now);
1560 eDebug("fixup PTS failed");
1569 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1571 /* when seeking, we have to ensure that all buffers are flushed.
1572 there are basically 3 buffers:
1573 a.) the filepush's internal buffer
1574 b.) the PVR buffer (before demux)
1575 c.) the ratebuffer (after demux)
1577 it's important to clear them in the correct order, otherwise
1578 the ratebuffer (for example) would immediately refill from
1579 the not-yet-flushed PVR buffer.
1582 m_pvr_thread->pause();
1583 /* flush internal filepush buffer */
1584 m_pvr_thread->flush();
1585 /* HACK: flush PVR buffer */
1586 ::ioctl(m_pvr_fd_dst, 0);
1588 /* flush ratebuffers (video, audio) */
1590 decoding_demux->flush();
1592 /* demux will also flush all decoder.. */
1593 /* resume will re-query the SG */
1594 m_pvr_thread->resume();
1597 DEFINE_REF(eCueSheet);
1599 eCueSheet::eCueSheet()
1601 m_skipmode_ratio = 0;
1604 void eCueSheet::seekTo(int relative, const pts_t &pts)
1607 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1612 void eCueSheet::clear()
1619 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1621 assert(begin < end);
1623 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1627 void eCueSheet::commitSpans()
1629 m_event(evtSpanChanged);
1632 void eCueSheet::setSkipmode(const pts_t &ratio)
1635 m_skipmode_ratio = ratio;
1637 m_event(evtSkipmode);
1640 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1642 m_decoding_demux = demux;
1643 m_decoder = decoder;
1646 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1648 connection = new eConnection(this, m_event.connect(event));