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)
1026 /* we might end up here if playing failed or stopped, but the client hasn't (yet) noted. */
1031 case eCueSheet::evtSeek:
1033 flushPVR(m_cue->m_decoding_demux);
1035 case eCueSheet::evtSkipmode:
1038 m_cue->m_lock.WrLock();
1039 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1040 m_cue->m_lock.Unlock();
1041 eRdLocker l(m_cue->m_lock);
1042 if (m_cue->m_skipmode_ratio)
1044 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1045 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1046 /* i agree that this might look a bit like black magic. */
1047 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1048 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1050 if (m_cue->m_skipmode_ratio < 0)
1051 m_skipmode_m -= m_skipmode_n;
1053 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1055 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1057 eWarning("something is wrong with this calculation");
1058 m_skipmode_n = m_skipmode_m = 0;
1062 eDebug("skipmode ratio is 0, normal play");
1063 m_skipmode_n = m_skipmode_m = 0;
1066 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1067 if (m_cue->m_skipmode_ratio != 0)
1068 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1070 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1071 eDebug("flush pvr");
1072 flushPVR(m_cue->m_decoding_demux);
1076 case eCueSheet::evtSpanChanged:
1078 m_source_span.clear();
1079 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1081 off_t offset_in, offset_out;
1082 pts_t pts_in = i->first, pts_out = i->second;
1083 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
1085 eDebug("span translation failed.\n");
1088 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1089 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1096 /* align toward zero */
1097 static inline long long align(long long x, int align)
1112 /* remember, this gets called from another thread. */
1113 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1115 const int blocksize = 188;
1116 unsigned int max = align(10*1024*1024, blocksize);
1117 current_offset = align(current_offset, blocksize);
1121 eDebug("no cue sheet. forcing normal play");
1122 start = current_offset;
1127 m_cue->m_lock.RdLock();
1128 if (!m_cue->m_decoding_demux)
1130 start = current_offset;
1132 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1133 m_cue->m_lock.Unlock();
1139 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1140 max = align(m_skipmode_n, blocksize);
1143 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1145 current_offset += align(m_skipmode_m, blocksize);
1147 while (!m_cue->m_seek_requests.empty())
1149 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1150 m_cue->m_lock.Unlock();
1151 m_cue->m_lock.WrLock();
1152 m_cue->m_seek_requests.pop_front();
1153 m_cue->m_lock.Unlock();
1154 m_cue->m_lock.RdLock();
1155 int relative = seek.first;
1156 pts_t pts = seek.second;
1161 if (!m_cue->m_decoder)
1163 eDebug("no decoder - can't seek relative");
1166 if (m_cue->m_decoder->getPTS(0, now))
1168 eDebug("decoder getPTS failed, can't seek relative");
1171 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1173 eDebug("seekTo: getCurrentPosition failed!");
1176 } else if (pts < 0) /* seek relative to end */
1179 if (!getLength(len))
1181 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1185 eWarning("getLength failed - can't seek relative to end!");
1190 if (relative == 1) /* pts relative */
1201 if (relative == 2) /* AP relative */
1203 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1205 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1207 pts = now - 90000; /* approx. 1s */
1208 eDebug("AP relative seeking failed!");
1211 eDebug("next ap is %llx\n", pts);
1217 if (m_tstools.getOffset(offset, pts))
1219 eDebug("get offset for pts=%lld failed!", pts);
1223 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1224 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1227 m_cue->m_lock.Unlock();
1229 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1231 long long aligned_start = align(i->first, blocksize);
1232 long long aligned_end = align(i->second, blocksize);
1234 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1236 start = current_offset;
1237 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1238 if ((aligned_end - current_offset) > max)
1241 size = aligned_end - current_offset;
1242 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1245 if (current_offset < aligned_start)
1247 /* ok, our current offset is in an 'out' zone. */
1248 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1250 /* in normal playback, just start at the next zone. */
1253 /* size is not 64bit! */
1254 if ((i->second - i->first) > max)
1257 size = aligned_end - aligned_start;
1260 if (m_skipmode_m < 0)
1262 eDebug("reached SOF");
1265 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1269 /* when skipping reverse, however, choose the zone before. */
1271 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1274 aligned_start = align(i->first, blocksize);
1275 aligned_end = align(i->second, blocksize);
1277 if ((aligned_end - aligned_start) > max)
1280 len = aligned_end - aligned_start;
1282 start = aligned_end - len;
1283 eDebug("skipping to %llx, %d", start, len);
1286 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1291 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1293 eDebug("reached SOF");
1295 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1298 start = current_offset;
1301 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1305 void eDVBChannel::AddUse()
1307 if (++m_use_count > 1 && m_state == state_last_instance)
1310 m_stateChanged(this);
1314 void eDVBChannel::ReleaseUse()
1318 m_state = state_release;
1319 m_stateChanged(this);
1321 else if (m_use_count == 1)
1323 m_state = state_last_instance;
1324 m_stateChanged(this);
1328 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1331 m_mgr->removeChannel(this);
1338 eDebug("no frontend to tune!");
1342 m_channel_id = channelid;
1343 m_mgr->addChannel(channelid, this);
1344 m_state = state_tuning;
1345 /* if tuning fails, shutdown the channel immediately. */
1347 res = m_frontend->get().tune(*feparm);
1348 m_current_frontend_parameters = feparm;
1352 m_state = state_release;
1353 m_stateChanged(this);
1360 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1362 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1366 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1368 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1372 RESULT eDVBChannel::getState(int &state)
1378 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1383 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1385 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1391 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1396 /* don't hold a reference to the decoding demux, we don't need it. */
1398 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1399 the refcount is lost. thus, decoding demuxes are never allocated.
1401 this poses a big problem for PiP. */
1402 if (cap & capDecode)
1407 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1412 frontend = &m_frontend->get();
1418 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1420 param = m_current_frontend_parameters;
1424 RESULT eDVBChannel::playFile(const char *file)
1426 ASSERT(!m_frontend);
1429 m_pvr_thread->stop();
1430 delete m_pvr_thread;
1434 m_tstools.openFile(file);
1436 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1437 THEN DO A REAL FIX HERE! */
1439 /* (this codepath needs to be improved anyway.) */
1440 #if HAVE_DVB_API_VERSION < 3
1441 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1443 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1445 if (m_pvr_fd_dst < 0)
1447 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1451 m_pvr_thread = new eDVBChannelFilePush();
1452 m_pvr_thread->enablePVRCommit(1);
1453 m_pvr_thread->setStreamMode(1);
1454 m_pvr_thread->setScatterGather(this);
1456 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1458 delete m_pvr_thread;
1460 eDebug("can't open PVR file %s (%m)", file);
1463 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1466 m_stateChanged(this);
1471 void eDVBChannel::stopFile()
1475 m_pvr_thread->stop();
1476 ::close(m_pvr_fd_dst);
1477 delete m_pvr_thread;
1482 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1484 m_conn_cueSheetEvent = 0;
1487 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1490 RESULT eDVBChannel::getLength(pts_t &len)
1492 return m_tstools.calcLen(len);
1495 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1497 if (!decoding_demux)
1504 if (mode == 0) /* demux */
1506 r = decoding_demux->getSTC(now, 0);
1509 eDebug("demux getSTC failed");
1513 now = pos; /* fixup supplied */
1515 off_t off = 0; /* TODO: fixme */
1516 r = m_tstools.fixupPTS(off, now);
1519 eDebug("fixup PTS failed");
1528 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1530 /* when seeking, we have to ensure that all buffers are flushed.
1531 there are basically 3 buffers:
1532 a.) the filepush's internal buffer
1533 b.) the PVR buffer (before demux)
1534 c.) the ratebuffer (after demux)
1536 it's important to clear them in the correct order, otherwise
1537 the ratebuffer (for example) would immediately refill from
1538 the not-yet-flushed PVR buffer.
1541 m_pvr_thread->pause();
1542 /* flush internal filepush buffer */
1543 m_pvr_thread->flush();
1544 /* HACK: flush PVR buffer */
1545 ::ioctl(m_pvr_fd_dst, 0);
1547 /* flush ratebuffers (video, audio) */
1549 decoding_demux->flush();
1551 /* demux will also flush all decoder.. */
1552 /* resume will re-query the SG */
1553 m_pvr_thread->resume();
1556 DEFINE_REF(eCueSheet);
1558 eCueSheet::eCueSheet()
1560 m_skipmode_ratio = 0;
1563 void eCueSheet::seekTo(int relative, const pts_t &pts)
1566 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1571 void eCueSheet::clear()
1578 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1580 assert(begin < end);
1582 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1586 void eCueSheet::commitSpans()
1588 m_event(evtSpanChanged);
1591 void eCueSheet::setSkipmode(const pts_t &ratio)
1594 m_skipmode_ratio = ratio;
1596 m_event(evtSkipmode);
1599 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1601 m_decoding_demux = demux;
1602 m_decoder = decoder;
1605 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1607 connection = new eConnection(this, m_event.connect(event));