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());
378 if (i == m_demux.end())
382 /* FIXME: hardware demux policy */
383 if (!(cap & iDVBChannel::capDecode))
385 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
392 for (; i != m_demux.end(); ++i, ++n)
394 int is_decode = n < 2;
396 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
398 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
400 if ((cap & iDVBChannel::capDecode) && !is_decode)
403 demux = new eDVBAllocatedDemux(i);
405 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
407 demux->get().setSourcePVR(0);
411 eDebug("demux not found");
415 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
421 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
430 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
432 /* first, check if a channel is already existing. */
434 if (m_cached_channel)
436 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
437 if(channelid==cache_chan->getChannelID())
439 eDebug("use cached_channel");
440 channel = m_cached_channel;
443 m_cached_channel_state_changed_conn.disconnect();
445 m_releaseCachedChannelTimer.stop();
448 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
449 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
451 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
452 if (i->m_channel_id == channelid)
454 // eDebug("found shared channel..");
455 channel = i->m_channel;
460 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
464 eDebug("no channel list set!");
465 return errNoChannelList;
468 ePtr<iDVBFrontendParameters> feparm;
469 if (m_list->getChannelFrontendData(channelid, feparm))
471 eDebug("channel not found!");
472 return errChannelNotInList;
475 /* allocate a frontend. */
477 ePtr<eDVBAllocatedFrontend> fe;
479 int err = allocateFrontend(fe, feparm);
484 ePtr<eDVBChannel> ch;
485 ch = new eDVBChannel(this, fe);
487 res = ch->setChannel(channelid, feparm);
491 return errChidNotFound;
493 m_cached_channel = channel = ch;
494 m_cached_channel_state_changed_conn =
495 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
500 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
503 chan->getState(state);
506 case iDVBChannel::state_release:
507 case iDVBChannel::state_ok:
509 eDebug("stop release channel timer");
510 m_releaseCachedChannelTimer.stop();
513 case iDVBChannel::state_last_instance:
515 eDebug("start release channel timer");
516 m_releaseCachedChannelTimer.start(3000, true);
519 default: // ignore all other events
524 void eDVBResourceManager::releaseCachedChannel()
526 eDebug("release cached channel (timer timeout)");
530 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
532 ePtr<eDVBAllocatedFrontend> fe;
534 if (m_cached_channel)
536 m_cached_channel_state_changed_conn.disconnect();
538 m_releaseCachedChannelTimer.stop();
541 int err = allocateFrontendByIndex(fe, slot_index);
546 ch = new eDVBChannel(this, fe);
553 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
555 ePtr<eDVBAllocatedDemux> demux;
557 if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
559 m_cached_channel_state_changed_conn.disconnect();
561 m_releaseCachedChannelTimer.stop();
565 ch = new eDVBChannel(this, 0);
571 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
573 m_active_channels.push_back(active_channel(chid, ch));
574 /* emit */ m_channelAdded(ch);
578 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
581 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
583 if (i->m_channel == ch)
585 i = m_active_channels.erase(i);
596 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
598 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
602 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
604 ePtr<eDVBRegisteredFrontend> best;
607 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
610 int c = i->m_frontend->isCompatibleWith(feparm);
617 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
621 ePtr<iDVBFrontendParameters> feparm;
622 if (!channellist->getChannelFrontendData(chid, feparm))
625 if (!feparm->getSystem(system))
629 case iDVBFrontend::feSatellite:
631 case iDVBFrontend::feCable:
633 case iDVBFrontend::feTerrestrial:
644 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
647 if (m_cached_channel)
649 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
650 if(channelid==cache_chan->getChannelID())
651 return tuner_type_channel_default(m_list, channelid);
654 /* first, check if a channel is already existing. */
655 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
656 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
658 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
659 if (i->m_channel_id == channelid)
661 // eDebug("found shared channel..");
662 return tuner_type_channel_default(m_list, channelid);
666 int *decremented_cached_channel_fe_usecount=NULL,
667 *decremented_fe_usecount=NULL;
669 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
671 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
672 if (i->m_channel_id == ignore)
674 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
675 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
676 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
677 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
678 // or 2 when the cached channel is not equal to the compared channel
679 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
681 ePtr<iDVBFrontend> fe;
682 if (!i->m_channel->getFrontend(fe))
684 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
686 if ( &(*fe) == &(*ii->m_frontend) )
689 decremented_fe_usecount = &ii->m_inuse;
690 if (channel == &(*m_cached_channel))
691 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
701 if (!decremented_cached_channel_fe_usecount)
703 if (m_cached_channel)
705 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
706 if (channel->getUseCount() == 1)
708 ePtr<iDVBFrontend> fe;
709 if (!channel->getFrontend(fe))
711 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
713 if ( &(*fe) == &(*ii->m_frontend) )
716 decremented_cached_channel_fe_usecount = &ii->m_inuse;
725 decremented_cached_channel_fe_usecount=NULL;
727 ePtr<iDVBFrontendParameters> feparm;
731 eDebug("no channel list set!");
735 if (m_list->getChannelFrontendData(channelid, feparm))
737 eDebug("channel not found!");
741 ret = canAllocateFrontend(feparm);
744 if (decremented_fe_usecount)
745 ++(*decremented_fe_usecount);
746 if (decremented_cached_channel_fe_usecount)
747 ++(*decremented_cached_channel_fe_usecount);
752 bool eDVBResourceManager::canMeasureFrontendInputPower()
754 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
756 return i->m_frontend->readInputpower() >= 0;
761 class eDVBChannelFilePush: public eFilePushThread
764 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
765 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
767 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
768 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
769 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
771 int m_iframe_search, m_iframe_state, m_pid;
772 int m_timebase_change;
773 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
776 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
779 if (m_timebase_change)
781 eDebug("timebase change: %d", m_timebase_change);
783 for (offset = 0; offset < len; offset += 188)
785 unsigned char *pkt = (unsigned char*)_data + offset;
786 if (pkt[1] & 0x40) /* pusi */
788 if (pkt[3] & 0x20) // adaption field present?
789 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
791 pkt += 4; /* skip header */
792 if (pkt[0] || pkt[1] || (pkt[2] != 1))
794 eWarning("broken startcode");
800 if (pkt[7] & 0x80) // PTS present?
802 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
803 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
804 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
805 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
806 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
810 RESULT r = m_tstools.fixupPTS(off, pts);
812 eWarning("fixup PTS while trickmode playback failed.\n");
815 int sec = pts / 90000;
816 int frm = pts % 90000;
824 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
827 pts *= m_timebase_change;
839 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
847 pkt[9] |= (pts >> 29) & 0xE;
848 pkt[10] |= (pts >> 22) & 0xFF;
849 pkt[11] |= (pts >> 14) & 0xFE;
850 pkt[12] |= (pts >> 7) & 0xFF;
851 pkt[13] |= (pts << 1) & 0xFE;
859 if (!m_iframe_search)
862 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
864 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
866 unsigned char *d = data;
867 while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
869 int offset = d - data;
870 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
871 unsigned char *ts = data + ts_offset;
872 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
874 if ((d[3] == 0) && (m_pid == pid)) /* picture start */
876 int picture_type = (d[5] >> 3) & 7;
879 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
881 if (m_iframe_state == 1)
883 /* we are allowing data, and stop allowing data on the next frame.
884 we now found a frame. so stop here. */
885 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
886 current_span_remaining = 0;
888 unsigned char *fts = ts + 188;
889 while (fts < (data + len))
892 fts[2] |= 0xff; /* drop packet */
896 return len; // ts_offset + 188; /* deliver this packet, but not more. */
899 if (picture_type != 1) /* we are only interested in I frames */
902 unsigned char *fts = data;
906 fts[2] |= 0xff; /* drop packet */
910 /* force payload only */
914 // memset(ts + 4, 0xFF, (offset % 188) - 4);
918 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
922 eDebug("now locked to pid %04x", pid);
932 if (m_iframe_state == 1)
935 return 0; /* we need find an iframe first */
941 DEFINE_REF(eDVBChannel);
943 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
945 m_frontend = frontend;
949 m_skipmode_n = m_skipmode_m = 0;
952 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
955 eDVBChannel::~eDVBChannel()
958 m_mgr->removeChannel(this);
963 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
965 int state, ourstate = 0;
967 /* if we are already in shutdown, don't change state. */
968 if (m_state == state_release)
971 if (fe->getState(state))
974 if (state == iDVBFrontend::stateLock)
976 eDebug("OURSTATE: ok");
978 } else if (state == iDVBFrontend::stateTuning)
980 eDebug("OURSTATE: tuning");
981 ourstate = state_tuning;
982 } else if (state == iDVBFrontend::stateLostLock)
984 /* on managed channels, we try to retune in order to re-acquire lock. */
985 if (m_current_frontend_parameters)
987 eDebug("OURSTATE: lost lock, trying to retune");
988 ourstate = state_tuning;
989 m_frontend->get().tune(*m_current_frontend_parameters);
991 /* on unmanaged channels, we don't do this. the client will do this. */
993 eDebug("OURSTATE: lost lock, unavailable now.");
994 ourstate = state_unavailable;
996 } else if (state == iDVBFrontend::stateFailed)
998 eDebug("OURSTATE: failed");
999 ourstate = state_failed;
1001 eFatal("state unknown");
1003 if (ourstate != m_state)
1006 m_stateChanged(this);
1010 void eDVBChannel::pvrEvent(int event)
1014 case eFilePushThread::evtEOF:
1015 eDebug("eDVBChannel: End of file!");
1016 m_event(this, evtEOF);
1018 case eFilePushThread::evtUser: /* start */
1020 m_event(this, evtSOF);
1025 void eDVBChannel::cueSheetEvent(int event)
1027 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1032 case eCueSheet::evtSeek:
1034 flushPVR(m_cue->m_decoding_demux);
1036 case eCueSheet::evtSkipmode:
1039 m_cue->m_lock.WrLock();
1040 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1041 m_cue->m_lock.Unlock();
1042 eRdLocker l(m_cue->m_lock);
1043 if (m_cue->m_skipmode_ratio)
1045 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1046 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1047 /* i agree that this might look a bit like black magic. */
1048 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1049 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1051 if (m_cue->m_skipmode_ratio < 0)
1052 m_skipmode_m -= m_skipmode_n;
1054 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1056 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1058 eWarning("something is wrong with this calculation");
1059 m_skipmode_n = m_skipmode_m = 0;
1063 eDebug("skipmode ratio is 0, normal play");
1064 m_skipmode_n = m_skipmode_m = 0;
1067 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1068 if (m_cue->m_skipmode_ratio != 0)
1069 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1071 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1072 eDebug("flush pvr");
1073 flushPVR(m_cue->m_decoding_demux);
1077 case eCueSheet::evtSpanChanged:
1079 m_source_span.clear();
1080 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1082 off_t offset_in, offset_out;
1083 pts_t pts_in = i->first, pts_out = i->second;
1084 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
1086 eDebug("span translation failed.\n");
1089 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1090 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1097 /* align toward zero */
1098 static inline long long align(long long x, int align)
1113 /* remember, this gets called from another thread. */
1114 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1116 const int blocksize = 188;
1117 unsigned int max = align(10*1024*1024, blocksize);
1118 current_offset = align(current_offset, blocksize);
1122 eDebug("no cue sheet. forcing normal play");
1123 start = current_offset;
1128 m_cue->m_lock.RdLock();
1129 if (!m_cue->m_decoding_demux)
1131 start = current_offset;
1133 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1134 m_cue->m_lock.Unlock();
1140 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1141 max = align(m_skipmode_n, blocksize);
1144 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1146 current_offset += align(m_skipmode_m, blocksize);
1148 while (!m_cue->m_seek_requests.empty())
1150 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1151 m_cue->m_lock.Unlock();
1152 m_cue->m_lock.WrLock();
1153 m_cue->m_seek_requests.pop_front();
1154 m_cue->m_lock.Unlock();
1155 m_cue->m_lock.RdLock();
1156 int relative = seek.first;
1157 pts_t pts = seek.second;
1162 if (!m_cue->m_decoder)
1164 eDebug("no decoder - can't seek relative");
1167 if (m_cue->m_decoder->getPTS(0, now))
1169 eDebug("decoder getPTS failed, can't seek relative");
1172 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1174 eDebug("seekTo: getCurrentPosition failed!");
1177 } else if (pts < 0) /* seek relative to end */
1180 if (!getLength(len))
1182 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1186 eWarning("getLength failed - can't seek relative to end!");
1191 if (relative == 1) /* pts relative */
1202 if (relative == 2) /* AP relative */
1204 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1206 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1208 pts = now - 90000; /* approx. 1s */
1209 eDebug("AP relative seeking failed!");
1212 eDebug("next ap is %llx\n", pts);
1218 if (m_tstools.getOffset(offset, pts))
1220 eDebug("get offset for pts=%lld failed!", pts);
1224 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1225 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1228 m_cue->m_lock.Unlock();
1230 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1232 long long aligned_start = align(i->first, blocksize);
1233 long long aligned_end = align(i->second, blocksize);
1235 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1237 start = current_offset;
1238 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1239 if ((aligned_end - current_offset) > max)
1242 size = aligned_end - current_offset;
1243 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1246 if (current_offset < aligned_start)
1248 /* ok, our current offset is in an 'out' zone. */
1249 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1251 /* in normal playback, just start at the next zone. */
1254 /* size is not 64bit! */
1255 if ((i->second - i->first) > max)
1258 size = aligned_end - aligned_start;
1261 if (m_skipmode_m < 0)
1263 eDebug("reached SOF");
1266 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1270 /* when skipping reverse, however, choose the zone before. */
1272 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1275 aligned_start = align(i->first, blocksize);
1276 aligned_end = align(i->second, blocksize);
1278 if ((aligned_end - aligned_start) > max)
1281 len = aligned_end - aligned_start;
1283 start = aligned_end - len;
1284 eDebug("skipping to %llx, %d", start, len);
1287 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1292 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1294 eDebug("reached SOF");
1296 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1299 start = current_offset;
1302 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1306 void eDVBChannel::AddUse()
1308 if (++m_use_count > 1 && m_state == state_last_instance)
1311 m_stateChanged(this);
1315 void eDVBChannel::ReleaseUse()
1319 m_state = state_release;
1320 m_stateChanged(this);
1322 else if (m_use_count == 1)
1324 m_state = state_last_instance;
1325 m_stateChanged(this);
1329 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1332 m_mgr->removeChannel(this);
1339 eDebug("no frontend to tune!");
1343 m_channel_id = channelid;
1344 m_mgr->addChannel(channelid, this);
1345 m_state = state_tuning;
1346 /* if tuning fails, shutdown the channel immediately. */
1348 res = m_frontend->get().tune(*feparm);
1349 m_current_frontend_parameters = feparm;
1353 m_state = state_release;
1354 m_stateChanged(this);
1361 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1363 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1367 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1369 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1373 RESULT eDVBChannel::getState(int &state)
1379 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1384 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1386 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1392 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1397 /* don't hold a reference to the decoding demux, we don't need it. */
1399 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1400 the refcount is lost. thus, decoding demuxes are never allocated.
1402 this poses a big problem for PiP. */
1403 if (cap & capDecode)
1408 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1413 frontend = &m_frontend->get();
1419 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1421 param = m_current_frontend_parameters;
1425 RESULT eDVBChannel::playFile(const char *file)
1427 ASSERT(!m_frontend);
1430 m_pvr_thread->stop();
1431 delete m_pvr_thread;
1435 m_tstools.openFile(file);
1437 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1438 THEN DO A REAL FIX HERE! */
1440 /* (this codepath needs to be improved anyway.) */
1441 #if HAVE_DVB_API_VERSION < 3
1442 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1444 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1446 if (m_pvr_fd_dst < 0)
1448 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1452 m_pvr_thread = new eDVBChannelFilePush();
1453 m_pvr_thread->enablePVRCommit(1);
1454 m_pvr_thread->setStreamMode(1);
1455 m_pvr_thread->setScatterGather(this);
1457 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1459 delete m_pvr_thread;
1461 eDebug("can't open PVR file %s (%m)", file);
1464 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1467 m_stateChanged(this);
1472 void eDVBChannel::stopFile()
1476 m_pvr_thread->stop();
1477 ::close(m_pvr_fd_dst);
1478 delete m_pvr_thread;
1483 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1485 m_conn_cueSheetEvent = 0;
1488 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1491 RESULT eDVBChannel::getLength(pts_t &len)
1493 return m_tstools.calcLen(len);
1496 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1498 if (!decoding_demux)
1505 if (mode == 0) /* demux */
1507 r = decoding_demux->getSTC(now, 0);
1510 eDebug("demux getSTC failed");
1514 now = pos; /* fixup supplied */
1516 off_t off = 0; /* TODO: fixme */
1517 r = m_tstools.fixupPTS(off, now);
1520 eDebug("fixup PTS failed");
1529 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1531 /* when seeking, we have to ensure that all buffers are flushed.
1532 there are basically 3 buffers:
1533 a.) the filepush's internal buffer
1534 b.) the PVR buffer (before demux)
1535 c.) the ratebuffer (after demux)
1537 it's important to clear them in the correct order, otherwise
1538 the ratebuffer (for example) would immediately refill from
1539 the not-yet-flushed PVR buffer.
1542 m_pvr_thread->pause();
1543 /* flush internal filepush buffer */
1544 m_pvr_thread->flush();
1545 /* HACK: flush PVR buffer */
1546 ::ioctl(m_pvr_fd_dst, 0);
1548 /* flush ratebuffers (video, audio) */
1550 decoding_demux->flush();
1552 /* demux will also flush all decoder.. */
1553 /* resume will re-query the SG */
1554 m_pvr_thread->resume();
1557 DEFINE_REF(eCueSheet);
1559 eCueSheet::eCueSheet()
1561 m_skipmode_ratio = 0;
1564 void eCueSheet::seekTo(int relative, const pts_t &pts)
1567 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1572 void eCueSheet::clear()
1579 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1581 assert(begin < end);
1583 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1587 void eCueSheet::commitSpans()
1589 m_event(evtSpanChanged);
1592 void eCueSheet::setSkipmode(const pts_t &ratio)
1595 m_skipmode_ratio = ratio;
1597 m_event(evtSkipmode);
1600 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1602 m_decoding_demux = demux;
1603 m_decoder = decoder;
1606 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1608 connection = new eConnection(this, m_event.connect(event));