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 PyObject *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 if (!i->m_frontend->setSlotInfo(obj))
276 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
278 ePtr<eDVBRegisteredFrontend> best;
281 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
284 int c = i->m_frontend->isCompatibleWith(feparm);
294 fe = new eDVBAllocatedFrontend(best);
303 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int slot_index)
305 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
306 if (!i->m_inuse && i->m_frontend->getSlotID() == slot_index)
308 // check if another slot linked to this is in use
309 eDVBRegisteredFrontend *satpos_depends_to_fe =
310 (eDVBRegisteredFrontend*) i->m_frontend->m_data[eDVBFrontend::SATPOS_DEPENDS_PTR];
311 if ( (int)satpos_depends_to_fe != -1 )
313 if (satpos_depends_to_fe->m_inuse)
315 eDebug("another satpos depending frontend is in use.. so allocateFrontendByIndex not possible!");
316 goto alloc_fe_by_id_not_possible;
319 else // check linked tuners
321 eDVBRegisteredFrontend *next =
322 (eDVBRegisteredFrontend *) i->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
323 while ( (int)next != -1 )
327 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
328 goto alloc_fe_by_id_not_possible;
330 next = (eDVBRegisteredFrontend *)next->m_frontend->m_data[eDVBFrontend::LINKED_NEXT_PTR];
332 eDVBRegisteredFrontend *prev = (eDVBRegisteredFrontend *)
333 i->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
334 while ( (int)prev != -1 )
338 eDebug("another linked frontend is in use.. so allocateFrontendByIndex not possible!");
339 goto alloc_fe_by_id_not_possible;
341 prev = (eDVBRegisteredFrontend *)prev->m_frontend->m_data[eDVBFrontend::LINKED_PREV_PTR];
344 fe = new eDVBAllocatedFrontend(i);
347 alloc_fe_by_id_not_possible:
352 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
354 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
355 never use the first one unless we need a decoding demux. */
357 eDebug("allocate demux");
358 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
360 if (i == m_demux.end())
364 /* FIXME: hardware demux policy */
365 if (!(cap & iDVBChannel::capDecode))
367 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
374 for (; i != m_demux.end(); ++i, ++n)
376 int is_decode = n < 2;
378 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
380 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
382 if ((cap & iDVBChannel::capDecode) && !is_decode)
385 demux = new eDVBAllocatedDemux(i);
387 demux->get().setSourceFrontend(fe->m_frontend->getDVBID());
389 demux->get().setSourcePVR(0);
393 eDebug("demux not found");
397 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
403 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
412 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
414 /* first, check if a channel is already existing. */
416 if (m_cached_channel)
418 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
419 if(channelid==cache_chan->getChannelID())
421 eDebug("use cached_channel");
422 channel = m_cached_channel;
425 m_cached_channel_state_changed_conn.disconnect();
427 m_releaseCachedChannelTimer.stop();
430 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
431 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
433 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
434 if (i->m_channel_id == channelid)
436 // eDebug("found shared channel..");
437 channel = i->m_channel;
442 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
446 eDebug("no channel list set!");
450 ePtr<iDVBFrontendParameters> feparm;
451 if (m_list->getChannelFrontendData(channelid, feparm))
453 eDebug("channel not found!");
457 /* allocate a frontend. */
459 ePtr<eDVBAllocatedFrontend> fe;
461 if (allocateFrontend(fe, feparm))
462 return errNoFrontend;
465 ePtr<eDVBChannel> ch;
466 ch = new eDVBChannel(this, fe);
468 res = ch->setChannel(channelid, feparm);
472 return errChidNotFound;
474 m_cached_channel = channel = ch;
475 m_cached_channel_state_changed_conn =
476 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
481 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
484 chan->getState(state);
487 case iDVBChannel::state_release:
488 case iDVBChannel::state_ok:
490 eDebug("stop release channel timer");
491 m_releaseCachedChannelTimer.stop();
494 case iDVBChannel::state_last_instance:
496 eDebug("start release channel timer");
497 m_releaseCachedChannelTimer.start(3000, true);
500 default: // ignore all other events
505 void eDVBResourceManager::releaseCachedChannel()
507 eDebug("release cached channel (timer timeout)");
511 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int slot_index)
513 ePtr<eDVBAllocatedFrontend> fe;
515 if (m_cached_channel)
517 m_cached_channel_state_changed_conn.disconnect();
519 m_releaseCachedChannelTimer.stop();
522 if (allocateFrontendByIndex(fe, slot_index))
523 return errNoFrontend;
526 ch = new eDVBChannel(this, fe);
533 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
535 ePtr<eDVBAllocatedDemux> demux;
537 if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
539 m_cached_channel_state_changed_conn.disconnect();
541 m_releaseCachedChannelTimer.stop();
545 ch = new eDVBChannel(this, 0);
551 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
553 m_active_channels.push_back(active_channel(chid, ch));
554 /* emit */ m_channelAdded(ch);
558 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
561 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
563 if (i->m_channel == ch)
565 i = m_active_channels.erase(i);
576 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
578 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
582 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
584 ePtr<eDVBRegisteredFrontend> best;
587 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
590 int c = i->m_frontend->isCompatibleWith(feparm);
597 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
600 if (m_cached_channel)
602 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
603 if(channelid==cache_chan->getChannelID())
607 /* first, check if a channel is already existing. */
608 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
609 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
611 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
612 if (i->m_channel_id == channelid)
614 // eDebug("found shared channel..");
619 int *decremented_cached_channel_fe_usecount=NULL,
620 *decremented_fe_usecount=NULL;
622 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
624 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
625 if (i->m_channel_id == ignore)
627 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
628 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
629 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
630 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
631 // or 2 when the cached channel is not equal to the compared channel
632 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
634 ePtr<iDVBFrontend> fe;
635 if (!i->m_channel->getFrontend(fe))
637 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
639 if ( &(*fe) == &(*ii->m_frontend) )
642 decremented_fe_usecount = &ii->m_inuse;
643 if (channel == &(*m_cached_channel))
644 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
654 if (!decremented_cached_channel_fe_usecount)
656 if (m_cached_channel)
658 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
659 if (channel->getUseCount() == 1)
661 ePtr<iDVBFrontend> fe;
662 if (!channel->getFrontend(fe))
664 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
666 if ( &(*fe) == &(*ii->m_frontend) )
669 decremented_cached_channel_fe_usecount = &ii->m_inuse;
678 decremented_cached_channel_fe_usecount=NULL;
680 ePtr<iDVBFrontendParameters> feparm;
684 eDebug("no channel list set!");
689 if (m_list->getChannelFrontendData(channelid, feparm))
691 eDebug("channel not found!");
696 ret = canAllocateFrontend(feparm);
699 if (decremented_fe_usecount)
700 ++(*decremented_fe_usecount);
701 if (decremented_cached_channel_fe_usecount)
702 ++(*decremented_cached_channel_fe_usecount);
707 class eDVBChannelFilePush: public eFilePushThread
710 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
712 int m_iframe_search, m_iframe_state, m_pid;
713 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
716 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
719 if (!m_iframe_search)
722 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
724 eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
726 unsigned char *d = data;
727 while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
729 int offset = d - data;
730 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
731 unsigned char *ts = data + ts_offset;
732 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
734 if ((d[3] == 0) && (m_pid == pid)) /* picture start */
736 int picture_type = (d[5] >> 3) & 7;
739 eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
741 if (m_iframe_state == 1)
743 /* we are allowing data, and stop allowing data on the next frame.
744 we now found a frame. so stop here. */
745 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
746 current_span_remaining = 0;
748 unsigned char *fts = ts + 188;
749 while (fts < (data + len))
752 fts[2] |= 0xff; /* drop packet */
756 return len; // ts_offset + 188; /* deliver this packet, but not more. */
759 if (picture_type != 1) /* we are only interested in I frames */
762 unsigned char *fts = data;
766 fts[2] |= 0xff; /* drop packet */
770 /* force payload only */
774 // memset(ts + 4, 0xFF, (offset % 188) - 4);
778 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
782 eDebug("now locked to pid %04x", pid);
792 if (m_iframe_state == 1)
795 return 0; /* we need find an iframe first */
801 DEFINE_REF(eDVBChannel);
803 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
805 m_frontend = frontend;
809 m_skipmode_n = m_skipmode_m = 0;
812 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
815 eDVBChannel::~eDVBChannel()
818 m_mgr->removeChannel(this);
823 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
825 int state, ourstate = 0;
827 /* if we are already in shutdown, don't change state. */
828 if (m_state == state_release)
831 if (fe->getState(state))
834 if (state == iDVBFrontend::stateLock)
836 eDebug("OURSTATE: ok");
838 } else if (state == iDVBFrontend::stateTuning)
840 eDebug("OURSTATE: tuning");
841 ourstate = state_tuning;
842 } else if (state == iDVBFrontend::stateLostLock)
844 /* on managed channels, we try to retune in order to re-acquire lock. */
845 if (m_current_frontend_parameters)
847 eDebug("OURSTATE: lost lock, trying to retune");
848 ourstate = state_tuning;
849 m_frontend->get().tune(*m_current_frontend_parameters);
851 /* on unmanaged channels, we don't do this. the client will do this. */
853 eDebug("OURSTATE: lost lock, unavailable now.");
854 ourstate = state_unavailable;
856 } else if (state == iDVBFrontend::stateFailed)
858 eDebug("OURSTATE: failed");
859 ourstate = state_failed;
861 eFatal("state unknown");
863 if (ourstate != m_state)
866 m_stateChanged(this);
870 void eDVBChannel::pvrEvent(int event)
874 case eFilePushThread::evtEOF:
875 eDebug("eDVBChannel: End of file!");
876 m_event(this, evtEOF);
878 case eFilePushThread::evtUser: /* start */
880 m_event(this, evtSOF);
885 void eDVBChannel::cueSheetEvent(int event)
889 case eCueSheet::evtSeek:
891 flushPVR(m_cue->m_decoding_demux);
893 case eCueSheet::evtSkipmode:
896 m_cue->m_lock.WrLock();
897 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
898 m_cue->m_lock.Unlock();
899 eRdLocker l(m_cue->m_lock);
900 if (m_cue->m_skipmode_ratio)
902 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
903 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
904 /* i agree that this might look a bit like black magic. */
905 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
906 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
908 if (m_cue->m_skipmode_ratio < 0)
909 m_skipmode_m -= m_skipmode_n;
911 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
913 if (abs(m_skipmode_m) < abs(m_skipmode_n))
915 eWarning("something is wrong with this calculation");
916 m_skipmode_n = m_skipmode_m = 0;
921 eDebug("skipmode ratio is 0, normal play");
922 m_skipmode_n = m_skipmode_m = 0;
925 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
927 flushPVR(m_cue->m_decoding_demux);
931 case eCueSheet::evtSpanChanged:
933 m_source_span.clear();
934 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
936 off_t offset_in, offset_out;
937 pts_t pts_in = i->first, pts_out = i->second;
938 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
940 eDebug("span translation failed.\n");
943 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
944 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
951 /* align toward zero */
952 static inline long long align(long long x, int align)
967 /* remember, this gets called from another thread. */
968 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
970 const int blocksize = 188;
971 unsigned int max = align(10*1024*1024, blocksize);
972 current_offset = align(current_offset, blocksize);
976 eDebug("no cue sheet. forcing normal play");
977 start = current_offset;
982 m_cue->m_lock.RdLock();
983 if (!m_cue->m_decoding_demux)
985 start = current_offset;
987 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
988 m_cue->m_lock.Unlock();
994 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
995 max = align(m_skipmode_n, blocksize);
998 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1000 current_offset += align(m_skipmode_m, blocksize);
1002 while (!m_cue->m_seek_requests.empty())
1004 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1005 m_cue->m_lock.Unlock();
1006 m_cue->m_lock.WrLock();
1007 m_cue->m_seek_requests.pop_front();
1008 m_cue->m_lock.Unlock();
1009 m_cue->m_lock.RdLock();
1010 int relative = seek.first;
1011 pts_t pts = seek.second;
1016 if (!m_cue->m_decoder)
1018 eDebug("no decoder - can't seek relative");
1021 if (m_cue->m_decoder->getPTS(0, now))
1023 eDebug("decoder getPTS failed, can't seek relative");
1026 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1028 eDebug("seekTo: getCurrentPosition failed!");
1031 } else if (pts < 0) /* seek relative to end */
1034 if (!getLength(len))
1036 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1040 eWarning("getLength failed - can't seek relative to end!");
1045 if (relative == 1) /* pts relative */
1056 if (relative == 2) /* AP relative */
1058 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1060 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1062 pts = now - 90000; /* approx. 1s */
1063 eDebug("AP relative seeking failed!");
1066 eDebug("next ap is %llx\n", pts);
1072 if (m_tstools.getOffset(offset, pts))
1074 eDebug("get offset for pts=%lld failed!", pts);
1078 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1079 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1082 m_cue->m_lock.Unlock();
1084 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1086 long long aligned_start = align(i->first, blocksize);
1087 long long aligned_end = align(i->second, blocksize);
1089 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1091 start = current_offset;
1092 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1093 if ((aligned_end - current_offset) > max)
1096 size = aligned_end - current_offset;
1097 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1100 if (current_offset < aligned_start)
1102 /* ok, our current offset is in an 'out' zone. */
1103 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1105 /* in normal playback, just start at the next zone. */
1108 /* size is not 64bit! */
1109 if ((i->second - i->first) > max)
1112 size = aligned_end - aligned_start;
1115 if (m_skipmode_m < 0)
1117 eDebug("reached SOF");
1120 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1124 /* when skipping reverse, however, choose the zone before. */
1126 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1129 aligned_start = align(i->first, blocksize);
1130 aligned_end = align(i->second, blocksize);
1132 if ((aligned_end - aligned_start) > max)
1135 len = aligned_end - aligned_start;
1137 start = aligned_end - len;
1138 eDebug("skipping to %llx, %d", start, len);
1141 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1146 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1148 eDebug("reached SOF");
1150 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1153 start = current_offset;
1156 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1160 void eDVBChannel::AddUse()
1162 if (++m_use_count > 1 && m_state == state_last_instance)
1165 m_stateChanged(this);
1169 void eDVBChannel::ReleaseUse()
1173 m_state = state_release;
1174 m_stateChanged(this);
1176 else if (m_use_count == 1)
1178 m_state = state_last_instance;
1179 m_stateChanged(this);
1183 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1186 m_mgr->removeChannel(this);
1193 eDebug("no frontend to tune!");
1197 m_channel_id = channelid;
1198 m_mgr->addChannel(channelid, this);
1199 m_state = state_tuning;
1200 /* if tuning fails, shutdown the channel immediately. */
1202 res = m_frontend->get().tune(*feparm);
1203 m_current_frontend_parameters = feparm;
1207 m_state = state_release;
1208 m_stateChanged(this);
1215 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1217 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1221 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1223 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1227 RESULT eDVBChannel::getState(int &state)
1233 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1238 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1240 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1246 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1251 /* don't hold a reference to the decoding demux, we don't need it. */
1253 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1254 the refcount is lost. thus, decoding demuxes are never allocated.
1256 this poses a big problem for PiP. */
1257 if (cap & capDecode)
1262 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1267 frontend = &m_frontend->get();
1273 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1275 param = m_current_frontend_parameters;
1279 RESULT eDVBChannel::playFile(const char *file)
1281 ASSERT(!m_frontend);
1284 m_pvr_thread->stop();
1285 delete m_pvr_thread;
1289 m_tstools.openFile(file);
1291 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1292 THEN DO A REAL FIX HERE! */
1294 /* (this codepath needs to be improved anyway.) */
1295 #if HAVE_DVB_API_VERSION < 3
1296 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1298 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1300 if (m_pvr_fd_dst < 0)
1302 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1306 m_pvr_thread = new eDVBChannelFilePush();
1307 m_pvr_thread->enablePVRCommit(1);
1308 m_pvr_thread->setStreamMode(1);
1309 m_pvr_thread->setScatterGather(this);
1311 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1313 delete m_pvr_thread;
1315 eDebug("can't open PVR file %s (%m)", file);
1318 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1321 m_stateChanged(this);
1326 void eDVBChannel::stopFile()
1330 m_pvr_thread->stop();
1331 ::close(m_pvr_fd_dst);
1332 delete m_pvr_thread;
1337 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1339 m_conn_cueSheetEvent = 0;
1342 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1345 RESULT eDVBChannel::getLength(pts_t &len)
1347 return m_tstools.calcLen(len);
1350 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1352 if (!decoding_demux)
1359 if (mode == 0) /* demux */
1361 r = decoding_demux->getSTC(now, 0);
1364 eDebug("demux getSTC failed");
1368 now = pos; /* fixup supplied */
1370 off_t off = 0; /* TODO: fixme */
1371 r = m_tstools.fixupPTS(off, now);
1374 eDebug("fixup PTS failed");
1383 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1385 /* when seeking, we have to ensure that all buffers are flushed.
1386 there are basically 3 buffers:
1387 a.) the filepush's internal buffer
1388 b.) the PVR buffer (before demux)
1389 c.) the ratebuffer (after demux)
1391 it's important to clear them in the correct order, otherwise
1392 the ratebuffer (for example) would immediately refill from
1393 the not-yet-flushed PVR buffer.
1396 m_pvr_thread->pause();
1397 /* flush internal filepush buffer */
1398 m_pvr_thread->flush();
1399 /* HACK: flush PVR buffer */
1400 ::ioctl(m_pvr_fd_dst, 0);
1402 /* flush ratebuffers (video, audio) */
1404 decoding_demux->flush();
1406 /* demux will also flush all decoder.. */
1407 /* resume will re-query the SG */
1408 m_pvr_thread->resume();
1411 DEFINE_REF(eCueSheet);
1413 eCueSheet::eCueSheet()
1415 m_skipmode_ratio = 0;
1418 void eCueSheet::seekTo(int relative, const pts_t &pts)
1421 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1426 void eCueSheet::clear()
1433 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1436 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1440 void eCueSheet::commitSpans()
1442 m_event(evtSpanChanged);
1445 void eCueSheet::setSkipmode(const pts_t &ratio)
1448 m_skipmode_ratio = ratio;
1450 m_event(evtSkipmode);
1453 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1455 m_decoding_demux = demux;
1456 m_decoder = decoder;
1459 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1461 connection = new eConnection(this, m_event.connect(event));