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->getID() );
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 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
253 ePtr<eDVBRegisteredFrontend> best;
256 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
259 int c = i->m_frontend->isCompatibleWith(feparm);
269 fe = new eDVBAllocatedFrontend(best);
278 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int nr)
280 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i, --nr)
281 if ((!nr) && !i->m_inuse)
283 fe = new eDVBAllocatedFrontend(i);
291 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
293 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
294 never use the first one unless we need a decoding demux. */
296 eDebug("allocate demux");
297 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
299 if (i == m_demux.end())
303 /* FIXME: hardware demux policy */
304 if (!(cap & iDVBChannel::capDecode))
306 if (m_demux.size() > 2) /* assumed to be true, otherwise we have lost anyway */
313 for (; i != m_demux.end(); ++i, ++n)
315 int is_decode = n < 2;
317 int in_use = is_decode ? (i->m_demux->getRefCount() != 2) : i->m_inuse;
319 if ((!in_use) && ((!fe) || (i->m_adapter == fe->m_adapter)))
321 if ((cap & iDVBChannel::capDecode) && !is_decode)
324 demux = new eDVBAllocatedDemux(i);
326 demux->get().setSourceFrontend(fe->m_frontend->getID());
328 demux->get().setSourcePVR(0);
332 eDebug("demux not found");
336 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
342 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
351 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
353 /* first, check if a channel is already existing. */
355 if (m_cached_channel)
357 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
358 if(channelid==cache_chan->getChannelID())
360 eDebug("use cached_channel");
361 channel = m_cached_channel;
364 m_cached_channel_state_changed_conn.disconnect();
366 m_releaseCachedChannelTimer.stop();
369 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
370 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
372 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
373 if (i->m_channel_id == channelid)
375 // eDebug("found shared channel..");
376 channel = i->m_channel;
381 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
385 eDebug("no channel list set!");
389 ePtr<iDVBFrontendParameters> feparm;
390 if (m_list->getChannelFrontendData(channelid, feparm))
392 eDebug("channel not found!");
396 /* allocate a frontend. */
398 ePtr<eDVBAllocatedFrontend> fe;
400 if (allocateFrontend(fe, feparm))
401 return errNoFrontend;
404 ePtr<eDVBChannel> ch;
405 ch = new eDVBChannel(this, fe);
407 res = ch->setChannel(channelid, feparm);
411 return errChidNotFound;
413 m_cached_channel = channel = ch;
414 m_cached_channel_state_changed_conn =
415 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
420 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
423 chan->getState(state);
426 case iDVBChannel::state_release:
427 case iDVBChannel::state_ok:
429 eDebug("stop release channel timer");
430 m_releaseCachedChannelTimer.stop();
433 case iDVBChannel::state_last_instance:
435 eDebug("start release channel timer");
436 m_releaseCachedChannelTimer.start(3000, true);
439 default: // ignore all other events
444 void eDVBResourceManager::releaseCachedChannel()
446 eDebug("release cached channel (timer timeout)");
450 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
452 ePtr<eDVBAllocatedFrontend> fe;
454 if (m_cached_channel)
456 m_cached_channel_state_changed_conn.disconnect();
458 m_releaseCachedChannelTimer.stop();
461 if (allocateFrontendByIndex(fe, frontend_index))
462 return errNoFrontend;
465 ch = new eDVBChannel(this, fe);
472 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
474 ePtr<eDVBAllocatedDemux> demux;
476 if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
478 m_cached_channel_state_changed_conn.disconnect();
480 m_releaseCachedChannelTimer.stop();
484 ch = new eDVBChannel(this, 0);
490 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
492 m_active_channels.push_back(active_channel(chid, ch));
493 /* emit */ m_channelAdded(ch);
497 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
500 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
502 if (i->m_channel == ch)
504 i = m_active_channels.erase(i);
515 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
517 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
521 int eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
523 ePtr<eDVBRegisteredFrontend> best;
526 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
529 int c = i->m_frontend->isCompatibleWith(feparm);
537 int eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
540 if (m_cached_channel)
542 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
543 if(channelid==cache_chan->getChannelID())
547 /* first, check if a channel is already existing. */
548 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
549 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
551 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
552 if (i->m_channel_id == channelid)
554 // eDebug("found shared channel..");
559 int *decremented_cached_channel_fe_usecount=NULL,
560 *decremented_fe_usecount=NULL;
562 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
564 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
565 if (i->m_channel_id == ignore)
567 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
568 // one eUsePtr<iDVBChannel> is used in eDVBServicePMTHandler
569 // another on eUsePtr<iDVBChannel> is used in the eDVBScan instance used in eDVBServicePMTHandler (for SDT scan)
570 // so we must check here if usecount is 3 (when the channel is equal to the cached channel)
571 // or 2 when the cached channel is not equal to the compared channel
572 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 3 : channel->getUseCount() == 2) // channel only used once..
574 ePtr<iDVBFrontend> fe;
575 if (!i->m_channel->getFrontend(fe))
577 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
579 if ( &(*fe) == &(*ii->m_frontend) )
582 decremented_fe_usecount = &ii->m_inuse;
583 if (channel == &(*m_cached_channel))
584 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
594 if (!decremented_cached_channel_fe_usecount)
596 if (m_cached_channel)
598 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
599 if (channel->getUseCount() == 1)
601 ePtr<iDVBFrontend> fe;
602 if (!channel->getFrontend(fe))
604 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
606 if ( &(*fe) == &(*ii->m_frontend) )
609 decremented_cached_channel_fe_usecount = &ii->m_inuse;
618 decremented_cached_channel_fe_usecount=NULL;
620 ePtr<iDVBFrontendParameters> feparm;
624 eDebug("no channel list set!");
629 if (m_list->getChannelFrontendData(channelid, feparm))
631 eDebug("channel not found!");
636 ret = canAllocateFrontend(feparm);
639 if (decremented_fe_usecount)
640 ++(*decremented_fe_usecount);
641 if (decremented_cached_channel_fe_usecount)
642 ++(*decremented_cached_channel_fe_usecount);
647 class eDVBChannelFilePush: public eFilePushThread
650 void setIFrameSearch(int enabled) { m_iframe_search = enabled; m_iframe_state = 0; }
652 int m_iframe_search, m_iframe_state, m_pid;
653 int filterRecordData(const unsigned char *data, int len, size_t ¤t_span_remaining);
656 int eDVBChannelFilePush::filterRecordData(const unsigned char *_data, int len, size_t ¤t_span_remaining)
659 if (!m_iframe_search)
662 unsigned char *data = (unsigned char*)_data; /* remove that const. we know what we are doing. */
664 eDebug("filterRecordData, size=%d (mod 188=%d), first byte is %02x", len, len %188, data[0]);
666 unsigned char *d = data;
667 while ((d = (unsigned char*)memmem(d, data + len - d, "\x00\x00\x01", 3)))
669 int offset = d - data;
670 int ts_offset = offset - offset % 188; /* offset to the start of TS packet */
671 unsigned char *ts = data + ts_offset;
672 int pid = ((ts[1] << 8) | ts[2]) & 0x1FFF;
674 if ((d[3] == 0) && (m_pid == pid)) /* picture start */
676 int picture_type = (d[5] >> 3) & 7;
679 eDebug("%d-frame at %d, offset in TS packet: %d, pid=%04x", picture_type, offset, offset % 188, pid);
681 if (m_iframe_state == 1)
683 /* we are allowing data, and stop allowing data on the next frame.
684 we now found a frame. so stop here. */
685 memset(data + offset, 0, 188 - (offset%188)); /* zero out rest of TS packet */
686 current_span_remaining = 0;
688 unsigned char *fts = ts + 188;
689 while (fts < (data + len))
692 fts[2] |= 0xff; /* drop packet */
696 return len; // ts_offset + 188; /* deliver this packet, but not more. */
699 if (picture_type != 1) /* we are only interested in I frames */
702 unsigned char *fts = data;
706 fts[2] |= 0xff; /* drop packet */
710 /* force payload only */
714 // memset(ts + 4, 0xFF, (offset % 188) - 4);
718 } else if ((d[3] & 0xF0) == 0xE0) /* video stream */
722 eDebug("now locked to pid %04x", pid);
732 if (m_iframe_state == 1)
735 return 0; /* we need find an iframe first */
741 DEFINE_REF(eDVBChannel);
743 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
745 m_frontend = frontend;
749 m_skipmode_n = m_skipmode_m = 0;
752 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
755 eDVBChannel::~eDVBChannel()
758 m_mgr->removeChannel(this);
763 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
765 int state, ourstate = 0;
767 /* if we are already in shutdown, don't change state. */
768 if (m_state == state_release)
771 if (fe->getState(state))
774 if (state == iDVBFrontend::stateLock)
776 eDebug("OURSTATE: ok");
778 } else if (state == iDVBFrontend::stateTuning)
780 eDebug("OURSTATE: tuning");
781 ourstate = state_tuning;
782 } else if (state == iDVBFrontend::stateLostLock)
784 /* on managed channels, we try to retune in order to re-acquire lock. */
785 if (m_current_frontend_parameters)
787 eDebug("OURSTATE: lost lock, trying to retune");
788 ourstate = state_tuning;
789 m_frontend->get().tune(*m_current_frontend_parameters);
791 /* on unmanaged channels, we don't do this. the client will do this. */
793 eDebug("OURSTATE: lost lock, unavailable now.");
794 ourstate = state_unavailable;
796 } else if (state == iDVBFrontend::stateFailed)
798 eDebug("OURSTATE: failed");
799 ourstate = state_failed;
801 eFatal("state unknown");
803 if (ourstate != m_state)
806 m_stateChanged(this);
810 void eDVBChannel::pvrEvent(int event)
814 case eFilePushThread::evtEOF:
815 eDebug("eDVBChannel: End of file!");
816 m_event(this, evtEOF);
818 case eFilePushThread::evtUser: /* start */
820 m_event(this, evtSOF);
825 void eDVBChannel::cueSheetEvent(int event)
829 case eCueSheet::evtSeek:
831 flushPVR(m_cue->m_decoding_demux);
833 case eCueSheet::evtSkipmode:
836 eSingleLocker l(m_cue->m_lock);
837 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
838 if (m_cue->m_skipmode_ratio)
840 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
841 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
842 /* i agree that this might look a bit like black magic. */
843 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
844 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
846 if (m_cue->m_skipmode_ratio < 0)
847 m_skipmode_m -= m_skipmode_n;
849 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
851 if (abs(m_skipmode_m) < abs(m_skipmode_n))
853 eWarning("something is wrong with this calculation");
854 m_skipmode_n = m_skipmode_m = 0;
859 eDebug("skipmode ratio is 0, normal play");
860 m_skipmode_n = m_skipmode_m = 0;
863 m_pvr_thread->setIFrameSearch(m_skipmode_n != 0);
865 flushPVR(m_cue->m_decoding_demux);
869 case eCueSheet::evtSpanChanged:
871 m_source_span.clear();
872 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
874 off_t offset_in, offset_out;
875 pts_t pts_in = i->first, pts_out = i->second;
876 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
878 eDebug("span translation failed.\n");
881 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
882 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
889 /* align toward zero */
890 static inline long long align(long long x, int align)
905 /* remember, this gets called from another thread. */
906 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
908 const int blocksize = 188;
909 unsigned int max = align(10*1024*1024, blocksize);
910 current_offset = align(current_offset, blocksize);
914 eDebug("no cue sheet. forcing normal play");
915 start = current_offset;
920 eSingleLocker l(m_cue->m_lock);
922 if (!m_cue->m_decoding_demux)
924 start = current_offset;
926 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
932 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
933 max = align(m_skipmode_n, blocksize);
936 eDebug("getNextSourceSpan, current offset is %08llx, m_skipmode_m = %d!", current_offset, m_skipmode_m);
938 current_offset += align(m_skipmode_m, blocksize);
940 while (!m_cue->m_seek_requests.empty())
942 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
943 m_cue->m_seek_requests.pop_front();
944 int relative = seek.first;
945 pts_t pts = seek.second;
950 if (!m_cue->m_decoder)
952 eDebug("no decoder - can't seek relative");
955 if (m_cue->m_decoder->getPTS(0, now))
957 eDebug("decoder getPTS failed, can't seek relative");
960 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
962 eDebug("seekTo: getCurrentPosition failed!");
965 } else if (pts < 0) /* seek relative to end */
970 eDebug("seeking relative to end. len=%lld, seek = %lld", len, pts);
974 eWarning("getLength failed - can't seek relative to end!");
979 if (relative == 1) /* pts relative */
990 if (relative == 2) /* AP relative */
992 eDebug("AP relative seeking: %lld, at %lld", pts, now);
994 if (m_tstools.getNextAccessPoint(nextap, now, pts))
997 eDebug("AP relative seeking failed!");
1000 eDebug("next ap is %llx\n", pts);
1006 if (m_tstools.getOffset(offset, pts))
1008 eDebug("get offset for pts=%lld failed!", pts);
1012 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
1013 current_offset = align(offset, blocksize); /* in case tstools return non-aligned offset */
1016 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
1018 long long aligned_start = align(i->first, blocksize);
1019 long long aligned_end = align(i->second, blocksize);
1021 if ((current_offset >= aligned_start) && (current_offset < aligned_end))
1023 start = current_offset;
1024 /* max can not exceed max(size_t). aligned_end - current_offset, however, can. */
1025 if ((aligned_end - current_offset) > max)
1028 size = aligned_end - current_offset;
1029 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
1032 if (current_offset < aligned_start)
1034 /* ok, our current offset is in an 'out' zone. */
1035 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
1037 /* in normal playback, just start at the next zone. */
1040 /* size is not 64bit! */
1041 if ((i->second - i->first) > max)
1044 size = aligned_end - aligned_start;
1047 if (m_skipmode_m < 0)
1049 eDebug("reached SOF");
1052 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1056 /* when skipping reverse, however, choose the zone before. */
1058 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
1061 if ((i->second - i->first) > max)
1064 len = aligned_end - aligned_start;
1066 start = aligned_end - len;
1067 eDebug("skipping to %llx, %d", start, len);
1073 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1075 eDebug("reached SOF");
1077 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1080 start = current_offset;
1083 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1087 void eDVBChannel::AddUse()
1089 if (++m_use_count > 1 && m_state == state_last_instance)
1092 m_stateChanged(this);
1096 void eDVBChannel::ReleaseUse()
1100 m_state = state_release;
1101 m_stateChanged(this);
1103 else if (m_use_count == 1)
1105 m_state = state_last_instance;
1106 m_stateChanged(this);
1110 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1113 m_mgr->removeChannel(this);
1120 eDebug("no frontend to tune!");
1124 m_channel_id = channelid;
1125 m_mgr->addChannel(channelid, this);
1126 m_state = state_tuning;
1127 /* if tuning fails, shutdown the channel immediately. */
1129 res = m_frontend->get().tune(*feparm);
1130 m_current_frontend_parameters = feparm;
1134 m_state = state_release;
1135 m_stateChanged(this);
1142 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1144 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1148 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1150 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1154 RESULT eDVBChannel::getState(int &state)
1160 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1165 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1167 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1173 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1178 /* don't hold a reference to the decoding demux, we don't need it. */
1180 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1181 the refcount is lost. thus, decoding demuxes are never allocated.
1183 this poses a big problem for PiP. */
1184 if (cap & capDecode)
1189 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1194 frontend = &m_frontend->get();
1200 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1202 param = m_current_frontend_parameters;
1206 RESULT eDVBChannel::playFile(const char *file)
1208 ASSERT(!m_frontend);
1211 m_pvr_thread->stop();
1212 delete m_pvr_thread;
1216 m_tstools.openFile(file);
1218 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1219 THEN DO A REAL FIX HERE! */
1221 /* (this codepath needs to be improved anyway.) */
1222 #if HAVE_DVB_API_VERSION < 3
1223 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1225 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1227 if (m_pvr_fd_dst < 0)
1229 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1233 m_pvr_thread = new eDVBChannelFilePush();
1234 m_pvr_thread->enablePVRCommit(1);
1235 m_pvr_thread->setStreamMode(1);
1236 m_pvr_thread->setScatterGather(this);
1238 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1240 delete m_pvr_thread;
1242 eDebug("can't open PVR file %s (%m)", file);
1245 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1248 m_stateChanged(this);
1253 void eDVBChannel::stopFile()
1257 m_pvr_thread->stop();
1258 ::close(m_pvr_fd_dst);
1259 delete m_pvr_thread;
1264 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1266 m_conn_cueSheetEvent = 0;
1269 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1272 RESULT eDVBChannel::getLength(pts_t &len)
1274 return m_tstools.calcLen(len);
1277 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1279 if (!decoding_demux)
1286 if (mode == 0) /* demux */
1288 r = decoding_demux->getSTC(now, 0);
1291 eDebug("demux getSTC failed");
1295 now = pos; /* fixup supplied */
1297 off_t off = 0; /* TODO: fixme */
1298 r = m_tstools.fixupPTS(off, now);
1301 eDebug("fixup PTS failed");
1310 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1312 /* when seeking, we have to ensure that all buffers are flushed.
1313 there are basically 3 buffers:
1314 a.) the filepush's internal buffer
1315 b.) the PVR buffer (before demux)
1316 c.) the ratebuffer (after demux)
1318 it's important to clear them in the correct order, otherwise
1319 the ratebuffer (for example) would immediately refill from
1320 the not-yet-flushed PVR buffer.
1323 m_pvr_thread->pause();
1324 /* flush internal filepush buffer */
1325 m_pvr_thread->flush();
1326 /* HACK: flush PVR buffer */
1327 ::ioctl(m_pvr_fd_dst, 0);
1329 /* flush ratebuffers (video, audio) */
1331 decoding_demux->flush();
1333 /* demux will also flush all decoder.. */
1334 /* resume will re-query the SG */
1335 m_pvr_thread->resume();
1338 DEFINE_REF(eCueSheet);
1340 eCueSheet::eCueSheet()
1342 m_skipmode_ratio = 0;
1345 void eCueSheet::seekTo(int relative, const pts_t &pts)
1348 eSingleLocker l(m_lock);
1349 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1354 void eCueSheet::clear()
1356 eSingleLocker l(m_lock);
1360 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1363 eSingleLocker l(m_lock);
1364 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1368 void eCueSheet::commitSpans()
1370 m_event(evtSpanChanged);
1373 void eCueSheet::setSkipmode(const pts_t &ratio)
1376 eSingleLocker l(m_lock);
1377 m_skipmode_ratio = ratio;
1379 m_event(evtSkipmode);
1382 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1384 m_decoding_demux = demux;
1385 m_decoder = decoder;
1388 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1390 connection = new eConnection(this, m_event.connect(event));