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 class eDVBChannelFilePush: public eFilePushThread
754 eDVBChannelFilePush() { setIFrameSearch(0); setTimebaseChange(0); }
755 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
757 /* "timebase change" is for doing trickmode playback at an exact speed, even when pictures are skipped. */
758 /* you need to set it to 1/16 if you want 16x playback, for example. you need video master sync. */
759 void setTimebaseChange(int ratio) { m_timebase_change = ratio; } /* 16bit fixpoint, 0 for disable */
761 int m_iframe_search, m_iframe_state, m_pid;
762 int m_timebase_change;
763 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
766 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
769 if (m_timebase_change)
771 eDebug("timebase change: %d", m_timebase_change);
773 for (offset = 0; offset < len; offset += 188)
775 unsigned char *pkt = (unsigned char*)_data + offset;
776 if (pkt[1] & 0x40) /* pusi */
778 if (pkt[3] & 0x20) // adaption field present?
779 pkt += pkt[4] + 4 + 1; /* skip adaption field and header */
781 pkt += 4; /* skip header */
782 if (pkt[0] || pkt[1] || (pkt[2] != 1))
784 eWarning("broken startcode");
790 if (pkt[7] & 0x80) // PTS present?
792 pts = ((unsigned long long)(pkt[ 9]&0xE)) << 29;
793 pts |= ((unsigned long long)(pkt[10]&0xFF)) << 22;
794 pts |= ((unsigned long long)(pkt[11]&0xFE)) << 14;
795 pts |= ((unsigned long long)(pkt[12]&0xFF)) << 7;
796 pts |= ((unsigned long long)(pkt[13]&0xFE)) >> 1;
800 RESULT r = m_tstools.fixupPTS(off, pts);
802 eWarning("fixup PTS while trickmode playback failed.\n");
805 int sec = pts / 90000;
806 int frm = pts % 90000;
814 // eDebug("original, fixed pts: %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
817 pts *= m_timebase_change;
829 // eDebug("new pts (after timebase change): %016llx %d:%02d:%02d:%02d:%05d", pts, d, hr, min, sec, frm);
837 pkt[9] |= (pts >> 29) & 0xE;
838 pkt[10] |= (pts >> 22) & 0xFF;
839 pkt[11] |= (pts >> 14) & 0xFE;
840 pkt[12] |= (pts >> 7) & 0xFF;
841 pkt[13] |= (pts << 1) & 0xFE;
849 if (!m_iframe_search)
852 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
854 // eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
856 unsigned char *d = data;
857 while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
859 int offset = d - data;
860 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
861 unsigned char *ts = data + ts_offset;
862 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
864 if ((d[3] == 0) && (m_pid == pid)) /* picture start */
866 int picture_type = (d[5] >> 3) & 7;
869 // eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
871 if (m_iframe_state == 1)
873 /* we are allowing data, and stop allowing data on the next frame.
874 we now found a frame. so stop here. */
875 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
876 current_span_remaining = 0;
878 unsigned char *fts = ts + 188;
879 while (fts < (data + len))
882 fts[2] |= 0xff; /* drop packet */
886 return len; // ts_offset + 188; /* deliver this packet, but not more. */
889 if (picture_type != 1) /* we are only interested in I frames */
892 unsigned char *fts = data;
896 fts[2] |= 0xff; /* drop packet */
900 /* force payload only */
904 // memset(ts + 4, 0xFF, (offset % 188) - 4);
908 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
912 eDebug("now locked to pid %04x", pid);
922 if (m_iframe_state == 1)
925 return 0; /* we need find an iframe first */
931 DEFINE_REF(eDVBChannel);
933 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
935 m_frontend = frontend;
939 m_skipmode_n = m_skipmode_m = 0;
942 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
945 eDVBChannel::~eDVBChannel()
948 m_mgr->removeChannel(this);
953 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
955 int state, ourstate = 0;
957 /* if we are already in shutdown, don't change state. */
958 if (m_state == state_release)
961 if (fe->getState(state))
964 if (state == iDVBFrontend::stateLock)
966 eDebug("OURSTATE: ok");
968 } else if (state == iDVBFrontend::stateTuning)
970 eDebug("OURSTATE: tuning");
971 ourstate = state_tuning;
972 } else if (state == iDVBFrontend::stateLostLock)
974 /* on managed channels, we try to retune in order to re-acquire lock. */
975 if (m_current_frontend_parameters)
977 eDebug("OURSTATE: lost lock, trying to retune");
978 ourstate = state_tuning;
979 m_frontend->get().tune(*m_current_frontend_parameters);
981 /* on unmanaged channels, we don't do this. the client will do this. */
983 eDebug("OURSTATE: lost lock, unavailable now.");
984 ourstate = state_unavailable;
986 } else if (state == iDVBFrontend::stateFailed)
988 eDebug("OURSTATE: failed");
989 ourstate = state_failed;
991 eFatal("state unknown");
993 if (ourstate != m_state)
996 m_stateChanged(this);
1000 void eDVBChannel::pvrEvent(int event)
1004 case eFilePushThread::evtEOF:
1005 eDebug("eDVBChannel: End of file!");
1006 m_event(this, evtEOF);
1008 case eFilePushThread::evtUser: /* start */
1010 m_event(this, evtSOF);
1015 void eDVBChannel::cueSheetEvent(int event)
1019 case eCueSheet::evtSeek:
1021 flushPVR(m_cue->m_decoding_demux);
1023 case eCueSheet::evtSkipmode:
1026 m_cue->m_lock.WrLock();
1027 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
1028 m_cue->m_lock.Unlock();
1029 eRdLocker l(m_cue->m_lock);
1030 if (m_cue->m_skipmode_ratio)
1032 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
1033 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
1034 /* i agree that this might look a bit like black magic. */
1035 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
1036 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
1038 if (m_cue->m_skipmode_ratio < 0)
1039 m_skipmode_m -= m_skipmode_n;
1041 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
1043 if (abs(m_skipmode_m) < abs(m_skipmode_n))
1045 eWarning("something is wrong with this calculation");
1046 m_skipmode_n = m_skipmode_m = 0;
1050 eDebug("skipmode ratio is 0, normal play");
1051 m_skipmode_n = m_skipmode_m = 0;
1054 ASSERT(m_pvr_thread);
1055 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
1056 if (m_cue->m_skipmode_ratio != 0)
1057 m_pvr_thread->setTimebaseChange(0x10000 * 9000 / (m_cue->m_skipmode_ratio / 10)); /* negative values are also ok */
1059 m_pvr_thread->setTimebaseChange(0); /* normal playback */
1060 eDebug("flush pvr");
1061 flushPVR(m_cue->m_decoding_demux);
1065 case eCueSheet::evtSpanChanged:
1067 m_source_span.clear();
1068 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
1070 off_t offset_in, offset_out;
1071 pts_t pts_in = i->first, pts_out = i->second;
1072 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
1074 eDebug("span translation failed.\n");
1077 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
1078 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
1085 /* align toward zero */
1086 static inline long long align(long long x, int align)
1101 /* remember, this gets called from another thread. */
1102 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
1104 const int blocksize = 188;
1105 unsigned int max = align(10*1024*1024, blocksize);
1106 current_offset = align(current_offset, blocksize);
1110 eDebug("no cue sheet. forcing normal play");
1111 start = current_offset;
1116 m_cue->m_lock.RdLock();
1117 if (!m_cue->m_decoding_demux)
1119 start = current_offset;
1121 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
1122 m_cue->m_lock.Unlock();
1128 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
1129 max = align(m_skipmode_n, blocksize);
1132 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1134 current_offset += align(m_skipmode_m, blocksize);
1136 while (!m_cue->m_seek_requests.empty())
1138 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1139 m_cue->m_lock.Unlock();
1140 m_cue->m_lock.WrLock();
1141 m_cue->m_seek_requests.pop_front();
1142 m_cue->m_lock.Unlock();
1143 m_cue->m_lock.RdLock();
1144 int relative = seek.first;
1145 pts_t pts = seek.second;
1150 if (!m_cue->m_decoder)
1152 eDebug("no decoder - can't seek relative");
1155 if (m_cue->m_decoder->getPTS(0, now))
1157 eDebug("decoder getPTS failed, can't seek relative");
1160 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1162 eDebug("seekTo: getCurrentPosition failed!");
1165 } else if (pts < 0) /* seek relative to end */
1168 if (!getLength(len))
1170 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1174 eWarning("getLength failed - can't seek relative to end!");
1179 if (relative == 1) /* pts relative */
1190 if (relative == 2) /* AP relative */
1192 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1194 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1196 pts = now - 90000; /* approx. 1s */
1197 eDebug("AP relative seeking failed!");
1200 eDebug("next ap is %llx\n", pts);
1206 if (m_tstools.getOffset(offset, pts))
1208 eDebug("get offset for pts=%lld failed!", pts);
1212 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1213 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1216 m_cue->m_lock.Unlock();
1218 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1220 long long aligned_start = align(i->first, blocksize);
1221 long long aligned_end = align(i->second, blocksize);
1223 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1225 start = current_offset;
1226 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1227 if ((aligned_end - current_offset) > max)
1230 size = aligned_end - current_offset;
1231 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1234 if (current_offset < aligned_start)
1236 /* ok, our current offset is in an 'out' zone. */
1237 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1239 /* in normal playback, just start at the next zone. */
1242 /* size is not 64bit! */
1243 if ((i->second - i->first) > max)
1246 size = aligned_end - aligned_start;
1249 if (m_skipmode_m < 0)
1251 eDebug("reached SOF");
1254 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1258 /* when skipping reverse, however, choose the zone before. */
1260 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1263 aligned_start = align(i->first, blocksize);
1264 aligned_end = align(i->second, blocksize);
1266 if ((aligned_end - aligned_start) > max)
1269 len = aligned_end - aligned_start;
1271 start = aligned_end - len;
1272 eDebug("skipping to %llx, %d", start, len);
1275 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1280 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1282 eDebug("reached SOF");
1284 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1287 start = current_offset;
1290 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1294 void eDVBChannel::AddUse()
1296 if (++m_use_count > 1 && m_state == state_last_instance)
1299 m_stateChanged(this);
1303 void eDVBChannel::ReleaseUse()
1307 m_state = state_release;
1308 m_stateChanged(this);
1310 else if (m_use_count == 1)
1312 m_state = state_last_instance;
1313 m_stateChanged(this);
1317 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1320 m_mgr->removeChannel(this);
1327 eDebug("no frontend to tune!");
1331 m_channel_id = channelid;
1332 m_mgr->addChannel(channelid, this);
1333 m_state = state_tuning;
1334 /* if tuning fails, shutdown the channel immediately. */
1336 res = m_frontend->get().tune(*feparm);
1337 m_current_frontend_parameters = feparm;
1341 m_state = state_release;
1342 m_stateChanged(this);
1349 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1351 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1355 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1357 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1361 RESULT eDVBChannel::getState(int &state)
1367 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1372 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1374 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1380 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1385 /* don't hold a reference to the decoding demux, we don't need it. */
1387 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1388 the refcount is lost. thus, decoding demuxes are never allocated.
1390 this poses a big problem for PiP. */
1391 if (cap & capDecode)
1396 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1401 frontend = &m_frontend->get();
1407 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1409 param = m_current_frontend_parameters;
1413 RESULT eDVBChannel::playFile(const char *file)
1415 ASSERT(!m_frontend);
1418 m_pvr_thread->stop();
1419 delete m_pvr_thread;
1423 m_tstools.openFile(file);
1425 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1426 THEN DO A REAL FIX HERE! */
1428 /* (this codepath needs to be improved anyway.) */
1429 #if HAVE_DVB_API_VERSION < 3
1430 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1432 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1434 if (m_pvr_fd_dst < 0)
1436 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1440 m_pvr_thread = new eDVBChannelFilePush();
1441 m_pvr_thread->enablePVRCommit(1);
1442 m_pvr_thread->setStreamMode(1);
1443 m_pvr_thread->setScatterGather(this);
1445 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1447 delete m_pvr_thread;
1449 eDebug("can't open PVR file %s (%m)", file);
1452 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1455 m_stateChanged(this);
1460 void eDVBChannel::stopFile()
1464 m_pvr_thread->stop();
1465 ::close(m_pvr_fd_dst);
1466 delete m_pvr_thread;
1471 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1473 m_conn_cueSheetEvent = 0;
1476 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1479 RESULT eDVBChannel::getLength(pts_t &len)
1481 return m_tstools.calcLen(len);
1484 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1486 if (!decoding_demux)
1493 if (mode == 0) /* demux */
1495 r = decoding_demux->getSTC(now, 0);
1498 eDebug("demux getSTC failed");
1502 now = pos; /* fixup supplied */
1504 off_t off = 0; /* TODO: fixme */
1505 r = m_tstools.fixupPTS(off, now);
1508 eDebug("fixup PTS failed");
1517 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1519 /* when seeking, we have to ensure that all buffers are flushed.
1520 there are basically 3 buffers:
1521 a.) the filepush's internal buffer
1522 b.) the PVR buffer (before demux)
1523 c.) the ratebuffer (after demux)
1525 it's important to clear them in the correct order, otherwise
1526 the ratebuffer (for example) would immediately refill from
1527 the not-yet-flushed PVR buffer.
1530 m_pvr_thread->pause();
1531 /* flush internal filepush buffer */
1532 m_pvr_thread->flush();
1533 /* HACK: flush PVR buffer */
1534 ::ioctl(m_pvr_fd_dst, 0);
1536 /* flush ratebuffers (video, audio) */
1538 decoding_demux->flush();
1540 /* demux will also flush all decoder.. */
1541 /* resume will re-query the SG */
1542 m_pvr_thread->resume();
1545 DEFINE_REF(eCueSheet);
1547 eCueSheet::eCueSheet()
1549 m_skipmode_ratio = 0;
1552 void eCueSheet::seekTo(int relative, const pts_t &pts)
1555 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1560 void eCueSheet::clear()
1567 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1569 assert(begin < end);
1571 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1575 void eCueSheet::commitSpans()
1577 m_event(evtSpanChanged);
1580 void eCueSheet::setSkipmode(const pts_t &ratio)
1583 m_skipmode_ratio = ratio;
1585 m_event(evtSkipmode);
1588 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1590 m_decoding_demux = demux;
1591 m_decoder = decoder;
1594 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1596 connection = new eConnection(this, m_event.connect(event));