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 ASSERT(m_pvr_thread);
926 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
928 flushPVR(m_cue->m_decoding_demux);
932 case eCueSheet::evtSpanChanged:
934 m_source_span.clear();
935 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
937 off_t offset_in, offset_out;
938 pts_t pts_in = i->first, pts_out = i->second;
939 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
941 eDebug("span translation failed.\n");
944 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
945 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
952 /* align toward zero */
953 static inline long long align(long long x, int align)
968 /* remember, this gets called from another thread. */
969 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
971 const int blocksize = 188;
972 unsigned int max = align(10*1024*1024, blocksize);
973 current_offset = align(current_offset, blocksize);
977 eDebug("no cue sheet. forcing normal play");
978 start = current_offset;
983 m_cue->m_lock.RdLock();
984 if (!m_cue->m_decoding_demux)
986 start = current_offset;
988 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
989 m_cue->m_lock.Unlock();
995 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
996 max = align(m_skipmode_n, blocksize);
999 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
1001 current_offset += align(m_skipmode_m, blocksize);
1003 while (!m_cue->m_seek_requests.empty())
1005 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
1006 m_cue->m_lock.Unlock();
1007 m_cue->m_lock.WrLock();
1008 m_cue->m_seek_requests.pop_front();
1009 m_cue->m_lock.Unlock();
1010 m_cue->m_lock.RdLock();
1011 int relative = seek.first;
1012 pts_t pts = seek.second;
1017 if (!m_cue->m_decoder)
1019 eDebug("no decoder - can't seek relative");
1022 if (m_cue->m_decoder->getPTS(0, now))
1024 eDebug("decoder getPTS failed, can't seek relative");
1027 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
1029 eDebug("seekTo: getCurrentPosition failed!");
1032 } else if (pts < 0) /* seek relative to end */
1035 if (!getLength(len))
1037 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
1041 eWarning("getLength failed - can't seek relative to end!");
1046 if (relative == 1) /* pts relative */
1057 if (relative == 2) /* AP relative */
1059 eDebug("AP relative seeking: %lld, at %lld", pts, now);
1061 if (m_tstools.getNextAccessPoint(nextap, now, pts))
1063 pts = now - 90000; /* approx. 1s */
1064 eDebug("AP relative seeking failed!");
1067 eDebug("next ap is %llx\n", pts);
1073 if (m_tstools.getOffset(offset, pts))
1075 eDebug("get offset for pts=%lld failed!", pts);
1079 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1080 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1083 m_cue->m_lock.Unlock();
1085 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1087 long long aligned_start = align(i->first, blocksize);
1088 long long aligned_end = align(i->second, blocksize);
1090 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1092 start = current_offset;
1093 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1094 if ((aligned_end - current_offset) > max)
1097 size = aligned_end - current_offset;
1098 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1101 if (current_offset < aligned_start)
1103 /* ok, our current offset is in an 'out' zone. */
1104 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1106 /* in normal playback, just start at the next zone. */
1109 /* size is not 64bit! */
1110 if ((i->second - i->first) > max)
1113 size = aligned_end - aligned_start;
1116 if (m_skipmode_m < 0)
1118 eDebug("reached SOF");
1121 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1125 /* when skipping reverse, however, choose the zone before. */
1127 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1130 aligned_start = align(i->first, blocksize);
1131 aligned_end = align(i->second, blocksize);
1133 if ((aligned_end - aligned_start) > max)
1136 len = aligned_end - aligned_start;
1138 start = aligned_end - len;
1139 eDebug("skipping to %llx, %d", start, len);
1142 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1147 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1149 eDebug("reached SOF");
1151 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1154 start = current_offset;
1157 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1161 void eDVBChannel::AddUse()
1163 if (++m_use_count > 1 && m_state == state_last_instance)
1166 m_stateChanged(this);
1170 void eDVBChannel::ReleaseUse()
1174 m_state = state_release;
1175 m_stateChanged(this);
1177 else if (m_use_count == 1)
1179 m_state = state_last_instance;
1180 m_stateChanged(this);
1184 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1187 m_mgr->removeChannel(this);
1194 eDebug("no frontend to tune!");
1198 m_channel_id = channelid;
1199 m_mgr->addChannel(channelid, this);
1200 m_state = state_tuning;
1201 /* if tuning fails, shutdown the channel immediately. */
1203 res = m_frontend->get().tune(*feparm);
1204 m_current_frontend_parameters = feparm;
1208 m_state = state_release;
1209 m_stateChanged(this);
1216 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1218 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1222 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1224 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1228 RESULT eDVBChannel::getState(int &state)
1234 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1239 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1241 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1247 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1252 /* don't hold a reference to the decoding demux, we don't need it. */
1254 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1255 the refcount is lost. thus, decoding demuxes are never allocated.
1257 this poses a big problem for PiP. */
1258 if (cap & capDecode)
1263 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1268 frontend = &m_frontend->get();
1274 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1276 param = m_current_frontend_parameters;
1280 RESULT eDVBChannel::playFile(const char *file)
1282 ASSERT(!m_frontend);
1285 m_pvr_thread->stop();
1286 delete m_pvr_thread;
1290 m_tstools.openFile(file);
1292 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1293 THEN DO A REAL FIX HERE! */
1295 /* (this codepath needs to be improved anyway.) */
1296 #if HAVE_DVB_API_VERSION < 3
1297 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1299 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1301 if (m_pvr_fd_dst < 0)
1303 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1307 m_pvr_thread = new eDVBChannelFilePush();
1308 m_pvr_thread->enablePVRCommit(1);
1309 m_pvr_thread->setStreamMode(1);
1310 m_pvr_thread->setScatterGather(this);
1312 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1314 delete m_pvr_thread;
1316 eDebug("can't open PVR file %s (%m)", file);
1319 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1322 m_stateChanged(this);
1327 void eDVBChannel::stopFile()
1331 m_pvr_thread->stop();
1332 ::close(m_pvr_fd_dst);
1333 delete m_pvr_thread;
1338 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1340 m_conn_cueSheetEvent = 0;
1343 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1346 RESULT eDVBChannel::getLength(pts_t &len)
1348 return m_tstools.calcLen(len);
1351 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1353 if (!decoding_demux)
1360 if (mode == 0) /* demux */
1362 r = decoding_demux->getSTC(now, 0);
1365 eDebug("demux getSTC failed");
1369 now = pos; /* fixup supplied */
1371 off_t off = 0; /* TODO: fixme */
1372 r = m_tstools.fixupPTS(off, now);
1375 eDebug("fixup PTS failed");
1384 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1386 /* when seeking, we have to ensure that all buffers are flushed.
1387 there are basically 3 buffers:
1388 a.) the filepush's internal buffer
1389 b.) the PVR buffer (before demux)
1390 c.) the ratebuffer (after demux)
1392 it's important to clear them in the correct order, otherwise
1393 the ratebuffer (for example) would immediately refill from
1394 the not-yet-flushed PVR buffer.
1397 m_pvr_thread->pause();
1398 /* flush internal filepush buffer */
1399 m_pvr_thread->flush();
1400 /* HACK: flush PVR buffer */
1401 ::ioctl(m_pvr_fd_dst, 0);
1403 /* flush ratebuffers (video, audio) */
1405 decoding_demux->flush();
1407 /* demux will also flush all decoder.. */
1408 /* resume will re-query the SG */
1409 m_pvr_thread->resume();
1412 DEFINE_REF(eCueSheet);
1414 eCueSheet::eCueSheet()
1416 m_skipmode_ratio = 0;
1419 void eCueSheet::seekTo(int relative, const pts_t &pts)
1422 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1427 void eCueSheet::clear()
1434 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1437 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1441 void eCueSheet::commitSpans()
1443 m_event(evtSpanChanged);
1446 void eCueSheet::setSkipmode(const pts_t &ratio)
1449 m_skipmode_ratio = ratio;
1451 m_event(evtSkipmode);
1454 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1456 m_decoding_demux = demux;
1457 m_decoder = decoder;
1460 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1462 connection = new eConnection(this, m_event.connect(event));