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
323 eDVBRegisteredFrontend *satpos_depends_to_fe =
324 (eDVBRegisteredFrontend*) i->m_frontend->m_data[eDVBFrontend::SATPOS_DEPENDS_PTR];
325 if ( (long)satpos_depends_to_fe != -1 )
327 if (satpos_depends_to_fe->m_inuse)
329 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
330 err = errAllSourcesBusy;
331 goto alloc_fe_by_id_not_possible;
334 else // check linked tuners
336 eDVBRegisteredFrontend *next =
337 (eDVBRegisteredFrontend *) i->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
338 while ( (long)next != -1 )
342 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
343 err = errAllSourcesBusy;
344 goto alloc_fe_by_id_not_possible;
346 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
348 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)
349 i->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
350 while ( (long)prev != -1 )
354 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
355 err = errAllSourcesBusy;
356 goto alloc_fe_by_id_not_possible;
358 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
361 fe = new eDVBAllocatedFrontend(i);
364 alloc_fe_by_id_not_possible:
369 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
371 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
372 never use the first one unless we need a decoding demux. */
374 eDebug("allocate demux");
375 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
377 if (i == m_demux.end())
381 /* FIXME: hardware demux policy */
382 if (!(cap & iDVBChannel::capDecode))
384 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
391 for (; i != m_demux.end(); ++i, ++n)
393 int is_decode = n < 2;
395 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
397 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
399 if ((cap & iDVBChannel::capDecode) && !is_decode)
402 demux = new eDVBAllocatedDemux(i);
404 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
406 demux->get().setSourcePVR(0);
410 eDebug("demux not found");
414 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
420 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
429 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
431 /* first, check if a channel is already existing. */
433 if (m_cached_channel)
435 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
436 if(channelid==cache_chan->getChannelID())
438 eDebug("use cached_channel");
439 channel = m_cached_channel;
442 m_cached_channel_state_changed_conn.disconnect();
444 m_releaseCachedChannelTimer.stop();
447 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
448 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
450 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
451 if (i->m_channel_id == channelid)
453 // eDebug("found shared channel..");
454 channel = i->m_channel;
459 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
463 eDebug("no channel list set!");
464 return errNoChannelList;
467 ePtr<iDVBFrontendParameters> feparm;
468 if (m_list->getChannelFrontendData(channelid, feparm))
470 eDebug("channel not found!");
471 return errChannelNotInList;
474 /* allocate a frontend. */
476 ePtr<eDVBAllocatedFrontend> fe;
478 int err = allocateFrontend(fe, feparm);
483 ePtr<eDVBChannel> ch;
484 ch = new eDVBChannel(this, fe);
486 res = ch->setChannel(channelid, feparm);
490 return errChidNotFound;
492 m_cached_channel = channel = ch;
493 m_cached_channel_state_changed_conn =
494 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
499 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
502 chan->getState(state);
505 case iDVBChannel::state_release:
506 case iDVBChannel::state_ok:
508 eDebug("stop release channel timer");
509 m_releaseCachedChannelTimer.stop();
512 case iDVBChannel::state_last_instance:
514 eDebug("start release channel timer");
515 m_releaseCachedChannelTimer.start(3000, true);
518 default: // ignore all other events
523 void eDVBResourceManager::releaseCachedChannel()
525 eDebug("release cached channel (timer timeout)");
529 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
531 ePtr<eDVBAllocatedFrontend> fe;
533 if (m_cached_channel)
535 m_cached_channel_state_changed_conn.disconnect();
537 m_releaseCachedChannelTimer.stop();
540 int err = allocateFrontendByIndex(fe, slot_index);
545 ch = new eDVBChannel(this, fe);
552 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
554 ePtr<eDVBAllocatedDemux> demux;
556 if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
558 m_cached_channel_state_changed_conn.disconnect();
560 m_releaseCachedChannelTimer.stop();
564 ch = new eDVBChannel(this, 0);
570 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
572 m_active_channels.push_back(active_channel(chid, ch));
573 /* emit */ m_channelAdded(ch);
577 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
580 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
582 if (i->m_channel == ch)
584 i = m_active_channels.erase(i);
595 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
597 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
601 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
603 ePtr<eDVBRegisteredFrontend> best;
606 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
609 int c = i->m_frontend->isCompatibleWith(feparm);
616 int tuner_type_channel_default(ePtr<iDVBChannelList> &channellist, const eDVBChannelID &chid)
620 ePtr<iDVBFrontendParameters> feparm;
621 if (!channellist->getChannelFrontendData(chid, feparm))
624 if (!feparm->getSystem(system))
628 case iDVBFrontend::feSatellite:
630 case iDVBFrontend::feCable:
632 case iDVBFrontend::feTerrestrial:
643 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
646 if (m_cached_channel)
648 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
649 if(channelid==cache_chan->getChannelID())
650 return tuner_type_channel_default(m_list, channelid);
653 /* first, check if a channel is already existing. */
654 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
655 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
657 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
658 if (i->m_channel_id == channelid)
660 // eDebug("found shared channel..");
661 return tuner_type_channel_default(m_list, channelid);
665 int *decremented_cached_channel_fe_usecount=NULL,
666 *decremented_fe_usecount=NULL;
668 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
670 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
671 if (i->m_channel_id == ignore)
673 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
674 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
675 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
676 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
677 // or 2 when the cached channel is not equal to the compared channel
678 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
680 ePtr<iDVBFrontend> fe;
681 if (!i->m_channel->getFrontend(fe))
683 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
685 if ( &(*fe) == &(*ii->m_frontend) )
688 decremented_fe_usecount = &ii->m_inuse;
689 if (channel == &(*m_cached_channel))
690 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
700 if (!decremented_cached_channel_fe_usecount)
702 if (m_cached_channel)
704 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
705 if (channel->getUseCount() == 1)
707 ePtr<iDVBFrontend> fe;
708 if (!channel->getFrontend(fe))
710 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
712 if ( &(*fe) == &(*ii->m_frontend) )
715 decremented_cached_channel_fe_usecount = &ii->m_inuse;
724 decremented_cached_channel_fe_usecount=NULL;
726 ePtr<iDVBFrontendParameters> feparm;
730 eDebug("no channel list set!");
734 if (m_list->getChannelFrontendData(channelid, feparm))
736 eDebug("channel not found!");
740 ret = canAllocateFrontend(feparm);
743 if (decremented_fe_usecount)
744 ++(*decremented_fe_usecount);
745 if (decremented_cached_channel_fe_usecount)
746 ++(*decremented_cached_channel_fe_usecount);
751 bool eDVBResourceManager::canMeasureFrontendInputPower()
753 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
755 return i->m_frontend->readInputpower() >= 0;
760 class eDVBChannelFilePush: public eFilePushThread
763 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
764 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
766 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
767 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
768 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
770 int m_iframe_search, m_iframe_state, m_pid;
771 int m_timebase_change;
772 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
775 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
778 if (m_timebase_change)
780 eDebug("timebase change: %d", m_timebase_change);
782 for (offset = 0; offset < len; offset += 188)
784 unsigned char *pkt = (unsigned char*)_data + offset;
785 if (pkt[1] & 0x40) /* pusi */
787 if (pkt[3] & 0x20) // adaption field present?
788 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
790 pkt += 4; /* skip header */
791 if (pkt[0] || pkt[1] || (pkt[2] != 1))
793 eWarning("broken startcode");
799 if (pkt[7] & 0x80) // PTS present?
801 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
802 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
803 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
804 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
805 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
809 RESULT r = m_tstools.fixupPTS(off, pts);
811 eWarning("fixup PTS while trickmode playback failed.\n");
814 int sec = pts / 90000;
815 int frm = pts % 90000;
823 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
826 pts *= m_timebase_change;
838 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
846 pkt[9] |= (pts >> 29) & 0xE;
847 pkt[10] |= (pts >> 22) & 0xFF;
848 pkt[11] |= (pts >> 14) & 0xFE;
849 pkt[12] |= (pts >> 7) & 0xFF;
850 pkt[13] |= (pts << 1) & 0xFE;
858 if (!m_iframe_search)
861 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
863 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
865 unsigned char *d = data;
866 while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
868 int offset = d - data;
869 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
870 unsigned char *ts = data + ts_offset;
871 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
873 if ((d[3] == 0) && (m_pid == pid)) /* picture start */
875 int picture_type = (d[5] >> 3) & 7;
878 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
880 if (m_iframe_state == 1)
882 /* we are allowing data, and stop allowing data on the next frame.
883 we now found a frame. so stop here. */
884 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
885 current_span_remaining = 0;
887 unsigned char *fts = ts + 188;
888 while (fts < (data + len))
891 fts[2] |= 0xff; /* drop packet */
895 return len; // ts_offset + 188; /* deliver this packet, but not more. */
898 if (picture_type != 1) /* we are only interested in I frames */
901 unsigned char *fts = data;
905 fts[2] |= 0xff; /* drop packet */
909 /* force payload only */
913 // memset(ts + 4, 0xFF, (offset % 188) - 4);
917 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
921 eDebug("now locked to pid %04x", pid);
931 if (m_iframe_state == 1)
934 return 0; /* we need find an iframe first */
940 DEFINE_REF(eDVBChannel);
942 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
944 m_frontend = frontend;
948 m_skipmode_n = m_skipmode_m = 0;
951 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
954 eDVBChannel::~eDVBChannel()
957 m_mgr->removeChannel(this);
962 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
964 int state, ourstate = 0;
966 /* if we are already in shutdown, don't change state. */
967 if (m_state == state_release)
970 if (fe->getState(state))
973 if (state == iDVBFrontend::stateLock)
975 eDebug("OURSTATE: ok");
977 } else if (state == iDVBFrontend::stateTuning)
979 eDebug("OURSTATE: tuning");
980 ourstate = state_tuning;
981 } else if (state == iDVBFrontend::stateLostLock)
983 /* on managed channels, we try to retune in order to re-acquire lock. */
984 if (m_current_frontend_parameters)
986 eDebug("OURSTATE: lost lock, trying to retune");
987 ourstate = state_tuning;
988 m_frontend->get().tune(*m_current_frontend_parameters);
990 /* on unmanaged channels, we don't do this. the client will do this. */
992 eDebug("OURSTATE: lost lock, unavailable now.");
993 ourstate = state_unavailable;
995 } else if (state == iDVBFrontend::stateFailed)
997 eDebug("OURSTATE: failed");
998 ourstate = state_failed;
1000 eFatal("state unknown");
1002 if (ourstate != m_state)
1005 m_stateChanged(this);
1009 void eDVBChannel::pvrEvent(int event)
1013 case eFilePushThread::evtEOF:
1014 eDebug("eDVBChannel: End of file!");
1015 m_event(this, evtEOF);
1017 case eFilePushThread::evtUser: /* start */
1019 m_event(this, evtSOF);
1024 void eDVBChannel::cueSheetEvent(int event)
1028 case eCueSheet::evtSeek:
1030 flushPVR(m_cue->m_decoding_demux);
1032 case eCueSheet::evtSkipmode:
1035 m_cue->m_lock.WrLock();
1036 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1037 m_cue->m_lock.Unlock();
1038 eRdLocker l(m_cue->m_lock);
1039 if (m_cue->m_skipmode_ratio)
1041 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1042 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1043 /* i agree that this might look a bit like black magic. */
1044 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1045 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1047 if (m_cue->m_skipmode_ratio < 0)
1048 m_skipmode_m -= m_skipmode_n;
1050 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1052 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1054 eWarning("something is wrong with this calculation");
1055 m_skipmode_n = m_skipmode_m = 0;
1059 eDebug("skipmode ratio is 0, normal play");
1060 m_skipmode_n = m_skipmode_m = 0;
1063 ASSERT(m_pvr_thread);
1064 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1065 if (m_cue->m_skipmode_ratio != 0)
1066 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1068 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1069 eDebug("flush pvr");
1070 flushPVR(m_cue->m_decoding_demux);
1074 case eCueSheet::evtSpanChanged:
1076 m_source_span.clear();
1077 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1079 off_t offset_in, offset_out;
1080 pts_t pts_in = i->first, pts_out = i->second;
1081 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
1083 eDebug("span translation failed.\n");
1086 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1087 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1094 /* align toward zero */
1095 static inline long long align(long long x, int align)
1110 /* remember, this gets called from another thread. */
1111 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1113 const int blocksize = 188;
1114 unsigned int max = align(10*1024*1024, blocksize);
1115 current_offset = align(current_offset, blocksize);
1119 eDebug("no cue sheet. forcing normal play");
1120 start = current_offset;
1125 m_cue->m_lock.RdLock();
1126 if (!m_cue->m_decoding_demux)
1128 start = current_offset;
1130 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1131 m_cue->m_lock.Unlock();
1137 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1138 max = align(m_skipmode_n, blocksize);
1141 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1143 current_offset += align(m_skipmode_m, blocksize);
1145 while (!m_cue->m_seek_requests.empty())
1147 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1148 m_cue->m_lock.Unlock();
1149 m_cue->m_lock.WrLock();
1150 m_cue->m_seek_requests.pop_front();
1151 m_cue->m_lock.Unlock();
1152 m_cue->m_lock.RdLock();
1153 int relative = seek.first;
1154 pts_t pts = seek.second;
1159 if (!m_cue->m_decoder)
1161 eDebug("no decoder - can't seek relative");
1164 if (m_cue->m_decoder->getPTS(0, now))
1166 eDebug("decoder getPTS failed, can't seek relative");
1169 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1171 eDebug("seekTo: getCurrentPosition failed!");
1174 } else if (pts < 0) /* seek relative to end */
1177 if (!getLength(len))
1179 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1183 eWarning("getLength failed - can't seek relative to end!");
1188 if (relative == 1) /* pts relative */
1199 if (relative == 2) /* AP relative */
1201 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1203 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1205 pts = now - 90000; /* approx. 1s */
1206 eDebug("AP relative seeking failed!");
1209 eDebug("next ap is %llx\n", pts);
1215 if (m_tstools.getOffset(offset, pts))
1217 eDebug("get offset for pts=%lld failed!", pts);
1221 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1222 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1225 m_cue->m_lock.Unlock();
1227 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1229 long long aligned_start = align(i->first, blocksize);
1230 long long aligned_end = align(i->second, blocksize);
1232 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1234 start = current_offset;
1235 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1236 if ((aligned_end - current_offset) > max)
1239 size = aligned_end - current_offset;
1240 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1243 if (current_offset < aligned_start)
1245 /* ok, our current offset is in an 'out' zone. */
1246 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1248 /* in normal playback, just start at the next zone. */
1251 /* size is not 64bit! */
1252 if ((i->second - i->first) > max)
1255 size = aligned_end - aligned_start;
1258 if (m_skipmode_m < 0)
1260 eDebug("reached SOF");
1263 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1267 /* when skipping reverse, however, choose the zone before. */
1269 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1272 aligned_start = align(i->first, blocksize);
1273 aligned_end = align(i->second, blocksize);
1275 if ((aligned_end - aligned_start) > max)
1278 len = aligned_end - aligned_start;
1280 start = aligned_end - len;
1281 eDebug("skipping to %llx, %d", start, len);
1284 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1289 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1291 eDebug("reached SOF");
1293 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1296 start = current_offset;
1299 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1303 void eDVBChannel::AddUse()
1305 if (++m_use_count > 1 && m_state == state_last_instance)
1308 m_stateChanged(this);
1312 void eDVBChannel::ReleaseUse()
1316 m_state = state_release;
1317 m_stateChanged(this);
1319 else if (m_use_count == 1)
1321 m_state = state_last_instance;
1322 m_stateChanged(this);
1326 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1329 m_mgr->removeChannel(this);
1336 eDebug("no frontend to tune!");
1340 m_channel_id = channelid;
1341 m_mgr->addChannel(channelid, this);
1342 m_state = state_tuning;
1343 /* if tuning fails, shutdown the channel immediately. */
1345 res = m_frontend->get().tune(*feparm);
1346 m_current_frontend_parameters = feparm;
1350 m_state = state_release;
1351 m_stateChanged(this);
1358 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1360 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1364 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1366 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1370 RESULT eDVBChannel::getState(int &state)
1376 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1381 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1383 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1389 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1394 /* don't hold a reference to the decoding demux, we don't need it. */
1396 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1397 the refcount is lost. thus, decoding demuxes are never allocated.
1399 this poses a big problem for PiP. */
1400 if (cap & capDecode)
1405 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1410 frontend = &m_frontend->get();
1416 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1418 param = m_current_frontend_parameters;
1422 RESULT eDVBChannel::playFile(const char *file)
1424 ASSERT(!m_frontend);
1427 m_pvr_thread->stop();
1428 delete m_pvr_thread;
1432 m_tstools.openFile(file);
1434 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1435 THEN DO A REAL FIX HERE! */
1437 /* (this codepath needs to be improved anyway.) */
1438 #if HAVE_DVB_API_VERSION < 3
1439 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1441 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1443 if (m_pvr_fd_dst < 0)
1445 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1449 m_pvr_thread = new eDVBChannelFilePush();
1450 m_pvr_thread->enablePVRCommit(1);
1451 m_pvr_thread->setStreamMode(1);
1452 m_pvr_thread->setScatterGather(this);
1454 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1456 delete m_pvr_thread;
1458 eDebug("can't open PVR file %s (%m)", file);
1461 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1464 m_stateChanged(this);
1469 void eDVBChannel::stopFile()
1473 m_pvr_thread->stop();
1474 ::close(m_pvr_fd_dst);
1475 delete m_pvr_thread;
1480 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1482 m_conn_cueSheetEvent = 0;
1485 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1488 RESULT eDVBChannel::getLength(pts_t &len)
1490 return m_tstools.calcLen(len);
1493 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1495 if (!decoding_demux)
1502 if (mode == 0) /* demux */
1504 r = decoding_demux->getSTC(now, 0);
1507 eDebug("demux getSTC failed");
1511 now = pos; /* fixup supplied */
1513 off_t off = 0; /* TODO: fixme */
1514 r = m_tstools.fixupPTS(off, now);
1517 eDebug("fixup PTS failed");
1526 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1528 /* when seeking, we have to ensure that all buffers are flushed.
1529 there are basically 3 buffers:
1530 a.) the filepush's internal buffer
1531 b.) the PVR buffer (before demux)
1532 c.) the ratebuffer (after demux)
1534 it's important to clear them in the correct order, otherwise
1535 the ratebuffer (for example) would immediately refill from
1536 the not-yet-flushed PVR buffer.
1539 m_pvr_thread->pause();
1540 /* flush internal filepush buffer */
1541 m_pvr_thread->flush();
1542 /* HACK: flush PVR buffer */
1543 ::ioctl(m_pvr_fd_dst, 0);
1545 /* flush ratebuffers (video, audio) */
1547 decoding_demux->flush();
1549 /* demux will also flush all decoder.. */
1550 /* resume will re-query the SG */
1551 m_pvr_thread->resume();
1554 DEFINE_REF(eCueSheet);
1556 eCueSheet::eCueSheet()
1558 m_skipmode_ratio = 0;
1561 void eCueSheet::seekTo(int relative, const pts_t &pts)
1564 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1569 void eCueSheet::clear()
1576 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1578 assert(begin < end);
1580 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1584 void eCueSheet::commitSpans()
1586 m_event(evtSpanChanged);
1589 void eCueSheet::setSkipmode(const pts_t &ratio)
1592 m_skipmode_ratio = ratio;
1594 m_event(evtSkipmode);
1597 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1599 m_decoding_demux = demux;
1600 m_decoder = decoder;
1603 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1605 connection = new eConnection(this, m_event.connect(event));