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/sec.h>
12 #include <sys/ioctl.h>
14 DEFINE_REF(eDVBRegisteredFrontend);
15 DEFINE_REF(eDVBRegisteredDemux);
17 DEFINE_REF(eDVBAllocatedFrontend);
19 eDVBAllocatedFrontend::eDVBAllocatedFrontend(eDVBRegisteredFrontend *fe): m_fe(fe)
24 eDVBAllocatedFrontend::~eDVBAllocatedFrontend()
29 DEFINE_REF(eDVBAllocatedDemux);
31 eDVBAllocatedDemux::eDVBAllocatedDemux(eDVBRegisteredDemux *demux): m_demux(demux)
36 eDVBAllocatedDemux::~eDVBAllocatedDemux()
41 DEFINE_REF(eDVBResourceManager);
43 eDVBResourceManager *eDVBResourceManager::instance;
45 RESULT eDVBResourceManager::getInstance(ePtr<eDVBResourceManager> &ptr)
55 ePtr<eDVBResourceManager> NewResourceManagerPtr(void)
57 ePtr<eDVBResourceManager> ptr;
58 eDVBResourceManager::getInstance(ptr);
62 eDVBResourceManager::eDVBResourceManager()
63 :m_releaseCachedChannelTimer(eApp)
67 m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
71 /* search available adapters... */
76 while (eDVBAdapterLinux::exist(num_adapter))
78 addAdapter(new eDVBAdapterLinux(num_adapter));
82 eDebug("found %d adapter, %d frontends and %d demux",
83 m_adapter.size(), m_frontend.size(), m_demux.size());
85 CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
88 void eDVBResourceManager::feStateChanged()
91 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
93 mask |= ( 1 << i->m_frontend->getSlotID() );
94 /* emit */ frontendUseMaskChanged(mask);
97 DEFINE_REF(eDVBAdapterLinux);
98 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
103 eDebug("scanning for frontends..");
108 #if HAVE_DVB_API_VERSION < 3
109 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
111 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
113 if (stat(filename, &s))
115 ePtr<eDVBFrontend> fe;
118 fe = new eDVBFrontend(m_nr, num_fe, ok);
120 m_frontend.push_back(fe);
130 #if HAVE_DVB_API_VERSION < 3
131 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
133 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
135 if (stat(filename, &s))
137 ePtr<eDVBDemux> demux;
139 demux = new eDVBDemux(m_nr, num_demux);
140 m_demux.push_back(demux);
146 int eDVBAdapterLinux::getNumDemux()
148 return m_demux.size();
151 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
153 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
154 while (nr && (i != m_demux.end()))
160 if (i != m_demux.end())
168 int eDVBAdapterLinux::getNumFrontends()
170 return m_frontend.size();
173 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
175 eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
176 while (nr && (i != m_frontend.end()))
182 if (i != m_frontend.end())
190 int eDVBAdapterLinux::exist(int nr)
194 #if HAVE_DVB_API_VERSION < 3
195 sprintf(filename, "/dev/dvb/card%d", nr);
197 sprintf(filename, "/dev/dvb/adapter%d", nr);
199 if (!stat(filename, &s))
204 eDVBResourceManager::~eDVBResourceManager()
206 if (instance == this)
210 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
212 int num_fe = adapter->getNumFrontends();
213 int num_demux = adapter->getNumDemux();
215 m_adapter.push_back(adapter);
218 for (i=0; i<num_demux; ++i)
220 ePtr<eDVBDemux> demux;
221 if (!adapter->getDemux(demux, i))
222 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
225 ePtr<eDVBRegisteredFrontend> prev_dvbt_frontend;
226 for (i=0; i<num_fe; ++i)
228 ePtr<eDVBFrontend> frontend;
229 if (!adapter->getFrontend(frontend, i))
232 frontend->getFrontendType(frontendType);
233 eDVBRegisteredFrontend *new_fe = new eDVBRegisteredFrontend(frontend, adapter);
234 CONNECT(new_fe->stateChanged, eDVBResourceManager::feStateChanged);
235 m_frontend.push_back(new_fe);
236 frontend->setSEC(m_sec);
237 // we must link all dvb-t frontends ( for active antenna voltage )
238 if (frontendType == iDVBFrontend::feTerrestrial)
240 if (prev_dvbt_frontend)
242 prev_dvbt_frontend->m_frontend->setData(eDVBFrontend::LINKED_NEXT_PTR, (int)new_fe);
243 frontend->setData(eDVBFrontend::LINKED_PREV_PTR, (int)&(*prev_dvbt_frontend));
245 prev_dvbt_frontend = new_fe;
251 void eDVBResourceManager::setFrontendSlotInformations(ePyObject list)
253 if (!PyList_Check(list))
255 PyErr_SetString(PyExc_StandardError, "eDVBResourceManager::setFrontendSlotInformations argument should be a python list");
258 if ((unsigned int)PyList_Size(list) != m_frontend.size())
261 sprintf(blasel, "eDVBResourceManager::setFrontendSlotInformations list size incorrect %d frontends avail, but %d entries in slotlist",
262 m_frontend.size(), PyList_Size(list));
263 PyErr_SetString(PyExc_StandardError, blasel);
267 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
269 ePyObject obj = PyList_GET_ITEM(list, pos++);
270 i->m_frontend->setSlotInfo(obj);
274 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
276 ePtr<eDVBRegisteredFrontend> best;
279 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
282 int c = i->m_frontend->isCompatibleWith(feparm);
292 fe = new eDVBAllocatedFrontend(best);
301 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
303 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
304 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
306 // check if another slot linked to this is in use
307 eDVBRegisteredFrontend *satpos_depends_to_fe =
308 (eDVBRegisteredFrontend*) i->m_frontend->m_data[eDVBFrontend::SATPOS_DEPENDS_PTR];
309 if ( (int)satpos_depends_to_fe != -1 )
311 if (satpos_depends_to_fe->m_inuse)
313 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
314 goto alloc_fe_by_id_not_possible;
317 else // check linked tuners
319 eDVBRegisteredFrontend *next =
320 (eDVBRegisteredFrontend *) i->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
321 while ( (int)next != -1 )
325 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
326 goto alloc_fe_by_id_not_possible;
328 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
330 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)
331 i->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
332 while ( (int)prev != -1 )
336 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
337 goto alloc_fe_by_id_not_possible;
339 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
342 fe = new eDVBAllocatedFrontend(i);
345 alloc_fe_by_id_not_possible:
350 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
352 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
353 never use the first one unless we need a decoding demux. */
355 eDebug("allocate demux");
356 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
358 if (i == m_demux.end())
362 /* FIXME: hardware demux policy */
363 if (!(cap & iDVBChannel::capDecode))
365 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
372 for (; i != m_demux.end(); ++i, ++n)
374 int is_decode = n < 2;
376 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
378 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
380 if ((cap & iDVBChannel::capDecode) && !is_decode)
383 demux = new eDVBAllocatedDemux(i);
385 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
387 demux->get().setSourcePVR(0);
391 eDebug("demux not found");
395 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
401 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
410 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
412 /* first, check if a channel is already existing. */
414 if (m_cached_channel)
416 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
417 if(channelid==cache_chan->getChannelID())
419 eDebug("use cached_channel");
420 channel = m_cached_channel;
423 m_cached_channel_state_changed_conn.disconnect();
425 m_releaseCachedChannelTimer.stop();
428 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
429 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
431 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
432 if (i->m_channel_id == channelid)
434 // eDebug("found shared channel..");
435 channel = i->m_channel;
440 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
444 eDebug("no channel list set!");
448 ePtr<iDVBFrontendParameters> feparm;
449 if (m_list->getChannelFrontendData(channelid, feparm))
451 eDebug("channel not found!");
455 /* allocate a frontend. */
457 ePtr<eDVBAllocatedFrontend> fe;
459 if (allocateFrontend(fe, feparm))
460 return errNoFrontend;
463 ePtr<eDVBChannel> ch;
464 ch = new eDVBChannel(this, fe);
466 res = ch->setChannel(channelid, feparm);
470 return errChidNotFound;
472 m_cached_channel = channel = ch;
473 m_cached_channel_state_changed_conn =
474 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
479 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
482 chan->getState(state);
485 case iDVBChannel::state_release:
486 case iDVBChannel::state_ok:
488 eDebug("stop release channel timer");
489 m_releaseCachedChannelTimer.stop();
492 case iDVBChannel::state_last_instance:
494 eDebug("start release channel timer");
495 m_releaseCachedChannelTimer.start(3000, true);
498 default: // ignore all other events
503 void eDVBResourceManager::releaseCachedChannel()
505 eDebug("release cached channel (timer timeout)");
509 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
511 ePtr<eDVBAllocatedFrontend> fe;
513 if (m_cached_channel)
515 m_cached_channel_state_changed_conn.disconnect();
517 m_releaseCachedChannelTimer.stop();
520 if (allocateFrontendByIndex(fe, slot_index))
521 return errNoFrontend;
524 ch = new eDVBChannel(this, fe);
531 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
533 ePtr<eDVBAllocatedDemux> demux;
535 if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
537 m_cached_channel_state_changed_conn.disconnect();
539 m_releaseCachedChannelTimer.stop();
543 ch = new eDVBChannel(this, 0);
549 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
551 m_active_channels.push_back(active_channel(chid, ch));
552 /* emit */ m_channelAdded(ch);
556 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
559 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
561 if (i->m_channel == ch)
563 i = m_active_channels.erase(i);
574 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
576 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
580 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
582 ePtr<eDVBRegisteredFrontend> best;
585 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
588 int c = i->m_frontend->isCompatibleWith(feparm);
595 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
598 if (m_cached_channel)
600 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
601 if(channelid==cache_chan->getChannelID())
605 /* first, check if a channel is already existing. */
606 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
607 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
609 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
610 if (i->m_channel_id == channelid)
612 // eDebug("found shared channel..");
617 int *decremented_cached_channel_fe_usecount=NULL,
618 *decremented_fe_usecount=NULL;
620 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
622 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
623 if (i->m_channel_id == ignore)
625 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
626 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
627 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
628 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
629 // or 2 when the cached channel is not equal to the compared channel
630 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
632 ePtr<iDVBFrontend> fe;
633 if (!i->m_channel->getFrontend(fe))
635 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
637 if ( &(*fe) == &(*ii->m_frontend) )
640 decremented_fe_usecount = &ii->m_inuse;
641 if (channel == &(*m_cached_channel))
642 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
652 if (!decremented_cached_channel_fe_usecount)
654 if (m_cached_channel)
656 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
657 if (channel->getUseCount() == 1)
659 ePtr<iDVBFrontend> fe;
660 if (!channel->getFrontend(fe))
662 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
664 if ( &(*fe) == &(*ii->m_frontend) )
667 decremented_cached_channel_fe_usecount = &ii->m_inuse;
676 decremented_cached_channel_fe_usecount=NULL;
678 ePtr<iDVBFrontendParameters> feparm;
682 eDebug("no channel list set!");
687 if (m_list->getChannelFrontendData(channelid, feparm))
689 eDebug("channel not found!");
694 ret = canAllocateFrontend(feparm);
697 if (decremented_fe_usecount)
698 ++(*decremented_fe_usecount);
699 if (decremented_cached_channel_fe_usecount)
700 ++(*decremented_cached_channel_fe_usecount);
705 class eDVBChannelFilePush: public eFilePushThread
708 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
710 int m_iframe_search, m_iframe_state, m_pid;
711 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
714 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
717 if (!m_iframe_search)
720 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
722 eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
724 unsigned char *d = data;
725 while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
727 int offset = d - data;
728 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
729 unsigned char *ts = data + ts_offset;
730 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
732 if ((d[3] == 0) && (m_pid == pid)) /* picture start */
734 int picture_type = (d[5] >> 3) & 7;
737 eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
739 if (m_iframe_state == 1)
741 /* we are allowing data, and stop allowing data on the next frame.
742 we now found a frame. so stop here. */
743 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
744 current_span_remaining = 0;
746 unsigned char *fts = ts + 188;
747 while (fts < (data + len))
750 fts[2] |= 0xff; /* drop packet */
754 return len; // ts_offset + 188; /* deliver this packet, but not more. */
757 if (picture_type != 1) /* we are only interested in I frames */
760 unsigned char *fts = data;
764 fts[2] |= 0xff; /* drop packet */
768 /* force payload only */
772 // memset(ts + 4, 0xFF, (offset % 188) - 4);
776 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
780 eDebug("now locked to pid %04x", pid);
790 if (m_iframe_state == 1)
793 return 0; /* we need find an iframe first */
799 DEFINE_REF(eDVBChannel);
801 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
803 m_frontend = frontend;
807 m_skipmode_n = m_skipmode_m = 0;
810 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
813 eDVBChannel::~eDVBChannel()
816 m_mgr->removeChannel(this);
821 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
823 int state, ourstate = 0;
825 /* if we are already in shutdown, don't change state. */
826 if (m_state == state_release)
829 if (fe->getState(state))
832 if (state == iDVBFrontend::stateLock)
834 eDebug("OURSTATE: ok");
836 } else if (state == iDVBFrontend::stateTuning)
838 eDebug("OURSTATE: tuning");
839 ourstate = state_tuning;
840 } else if (state == iDVBFrontend::stateLostLock)
842 /* on managed channels, we try to retune in order to re-acquire lock. */
843 if (m_current_frontend_parameters)
845 eDebug("OURSTATE: lost lock, trying to retune");
846 ourstate = state_tuning;
847 m_frontend->get().tune(*m_current_frontend_parameters);
849 /* on unmanaged channels, we don't do this. the client will do this. */
851 eDebug("OURSTATE: lost lock, unavailable now.");
852 ourstate = state_unavailable;
854 } else if (state == iDVBFrontend::stateFailed)
856 eDebug("OURSTATE: failed");
857 ourstate = state_failed;
859 eFatal("state unknown");
861 if (ourstate != m_state)
864 m_stateChanged(this);
868 void eDVBChannel::pvrEvent(int event)
872 case eFilePushThread::evtEOF:
873 eDebug("eDVBChannel: End of file!");
874 m_event(this, evtEOF);
876 case eFilePushThread::evtUser: /* start */
878 m_event(this, evtSOF);
883 void eDVBChannel::cueSheetEvent(int event)
887 case eCueSheet::evtSeek:
889 flushPVR(m_cue->m_decoding_demux);
891 case eCueSheet::evtSkipmode:
894 eSingleLocker l(m_cue->m_lock);
895 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
896 if (m_cue->m_skipmode_ratio)
898 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
899 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
900 /* i agree that this might look a bit like black magic. */
901 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
902 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
904 if (m_cue->m_skipmode_ratio < 0)
905 m_skipmode_m -= m_skipmode_n;
907 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
909 if (abs(m_skipmode_m) < abs(m_skipmode_n))
911 eWarning("something is wrong with this calculation");
912 m_skipmode_n = m_skipmode_m = 0;
917 eDebug("skipmode ratio is 0, normal play");
918 m_skipmode_n = m_skipmode_m = 0;
921 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
923 flushPVR(m_cue->m_decoding_demux);
927 case eCueSheet::evtSpanChanged:
929 m_source_span.clear();
930 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
932 off_t offset_in, offset_out;
933 pts_t pts_in = i->first, pts_out = i->second;
934 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
936 eDebug("span translation failed.\n");
939 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
940 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
947 /* align toward zero */
948 static inline long long align(long long x, int align)
963 /* remember, this gets called from another thread. */
964 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
966 const int blocksize = 188;
967 unsigned int max = align(10*1024*1024, blocksize);
968 current_offset = align(current_offset, blocksize);
972 eDebug("no cue sheet. forcing normal play");
973 start = current_offset;
978 eSingleLocker l(m_cue->m_lock);
980 if (!m_cue->m_decoding_demux)
982 start = current_offset;
984 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
990 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
991 max = align(m_skipmode_n, blocksize);
994 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
996 current_offset += align(m_skipmode_m, blocksize);
998 while (!m_cue->m_seek_requests.empty())
1000 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1001 m_cue->m_seek_requests.pop_front();
1002 int relative = seek.first;
1003 pts_t pts = seek.second;
1008 if (!m_cue->m_decoder)
1010 eDebug("no decoder - can't seek relative");
1013 if (m_cue->m_decoder->getPTS(0, now))
1015 eDebug("decoder getPTS failed, can't seek relative");
1018 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1020 eDebug("seekTo: getCurrentPosition failed!");
1023 } else if (pts < 0) /* seek relative to end */
1026 if (!getLength(len))
1028 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1032 eWarning("getLength failed - can't seek relative to end!");
1037 if (relative == 1) /* pts relative */
1048 if (relative == 2) /* AP relative */
1050 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1052 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1055 eDebug("AP relative seeking failed!");
1058 eDebug("next ap is %llx\n", pts);
1064 if (m_tstools.getOffset(offset, pts))
1066 eDebug("get offset for pts=%lld failed!", pts);
1070 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1071 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1074 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1076 long long aligned_start = align(i->first, blocksize);
1077 long long aligned_end = align(i->second, blocksize);
1079 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1081 start = current_offset;
1082 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1083 if ((aligned_end - current_offset) > max)
1086 size = aligned_end - current_offset;
1087 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1090 if (current_offset < aligned_start)
1092 /* ok, our current offset is in an 'out' zone. */
1093 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1095 /* in normal playback, just start at the next zone. */
1098 /* size is not 64bit! */
1099 if ((i->second - i->first) > max)
1102 size = aligned_end - aligned_start;
1105 if (m_skipmode_m < 0)
1107 eDebug("reached SOF");
1110 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1114 /* when skipping reverse, however, choose the zone before. */
1116 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1119 if ((i->second - i->first) > max)
1122 len = aligned_end - aligned_start;
1124 start = aligned_end - len;
1125 eDebug("skipping to %llx, %d", start, len);
1128 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1133 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1135 eDebug("reached SOF");
1137 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1140 start = current_offset;
1143 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1147 void eDVBChannel::AddUse()
1149 if (++m_use_count > 1 && m_state == state_last_instance)
1152 m_stateChanged(this);
1156 void eDVBChannel::ReleaseUse()
1160 m_state = state_release;
1161 m_stateChanged(this);
1163 else if (m_use_count == 1)
1165 m_state = state_last_instance;
1166 m_stateChanged(this);
1170 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1173 m_mgr->removeChannel(this);
1180 eDebug("no frontend to tune!");
1184 m_channel_id = channelid;
1185 m_mgr->addChannel(channelid, this);
1186 m_state = state_tuning;
1187 /* if tuning fails, shutdown the channel immediately. */
1189 res = m_frontend->get().tune(*feparm);
1190 m_current_frontend_parameters = feparm;
1194 m_state = state_release;
1195 m_stateChanged(this);
1202 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1204 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1208 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1210 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1214 RESULT eDVBChannel::getState(int &state)
1220 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1225 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1227 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1233 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1238 /* don't hold a reference to the decoding demux, we don't need it. */
1240 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1241 the refcount is lost. thus, decoding demuxes are never allocated.
1243 this poses a big problem for PiP. */
1244 if (cap & capDecode)
1249 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1254 frontend = &m_frontend->get();
1260 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1262 param = m_current_frontend_parameters;
1266 RESULT eDVBChannel::playFile(const char *file)
1268 ASSERT(!m_frontend);
1271 m_pvr_thread->stop();
1272 delete m_pvr_thread;
1276 m_tstools.openFile(file);
1278 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1279 THEN DO A REAL FIX HERE! */
1281 /* (this codepath needs to be improved anyway.) */
1282 #if HAVE_DVB_API_VERSION < 3
1283 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1285 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1287 if (m_pvr_fd_dst < 0)
1289 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1293 m_pvr_thread = new eDVBChannelFilePush();
1294 m_pvr_thread->enablePVRCommit(1);
1295 m_pvr_thread->setStreamMode(1);
1296 m_pvr_thread->setScatterGather(this);
1298 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1300 delete m_pvr_thread;
1302 eDebug("can't open PVR file %s (%m)", file);
1305 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1308 m_stateChanged(this);
1313 void eDVBChannel::stopFile()
1317 m_pvr_thread->stop();
1318 ::close(m_pvr_fd_dst);
1319 delete m_pvr_thread;
1324 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1326 m_conn_cueSheetEvent = 0;
1329 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1332 RESULT eDVBChannel::getLength(pts_t &len)
1334 return m_tstools.calcLen(len);
1337 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1339 if (!decoding_demux)
1346 if (mode == 0) /* demux */
1348 r = decoding_demux->getSTC(now, 0);
1351 eDebug("demux getSTC failed");
1355 now = pos; /* fixup supplied */
1357 off_t off = 0; /* TODO: fixme */
1358 r = m_tstools.fixupPTS(off, now);
1361 eDebug("fixup PTS failed");
1370 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1372 /* when seeking, we have to ensure that all buffers are flushed.
1373 there are basically 3 buffers:
1374 a.) the filepush's internal buffer
1375 b.) the PVR buffer (before demux)
1376 c.) the ratebuffer (after demux)
1378 it's important to clear them in the correct order, otherwise
1379 the ratebuffer (for example) would immediately refill from
1380 the not-yet-flushed PVR buffer.
1383 m_pvr_thread->pause();
1384 /* flush internal filepush buffer */
1385 m_pvr_thread->flush();
1386 /* HACK: flush PVR buffer */
1387 ::ioctl(m_pvr_fd_dst, 0);
1389 /* flush ratebuffers (video, audio) */
1391 decoding_demux->flush();
1393 /* demux will also flush all decoder.. */
1394 /* resume will re-query the SG */
1395 m_pvr_thread->resume();
1398 DEFINE_REF(eCueSheet);
1400 eCueSheet::eCueSheet()
1402 m_skipmode_ratio = 0;
1405 void eCueSheet::seekTo(int relative, const pts_t &pts)
1408 eSingleLocker l(m_lock);
1409 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1414 void eCueSheet::clear()
1416 eSingleLocker l(m_lock);
1420 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1423 eSingleLocker l(m_lock);
1424 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1428 void eCueSheet::commitSpans()
1430 m_event(evtSpanChanged);
1433 void eCueSheet::setSkipmode(const pts_t &ratio)
1436 eSingleLocker l(m_lock);
1437 m_skipmode_ratio = ratio;
1439 m_event(evtSkipmode);
1442 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1444 m_decoding_demux = demux;
1445 m_decoder = decoder;
1448 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1450 connection = new eConnection(this, m_event.connect(event));