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);
1070 eDebug("result: %llx, %x (%llx %llx)", start, size, aligned_start, aligned_end);
1075 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
1077 eDebug("reached SOF");
1079 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
1082 start = current_offset;
1085 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
1089 void eDVBChannel::AddUse()
1091 if (++m_use_count > 1 && m_state == state_last_instance)
1094 m_stateChanged(this);
1098 void eDVBChannel::ReleaseUse()
1102 m_state = state_release;
1103 m_stateChanged(this);
1105 else if (m_use_count == 1)
1107 m_state = state_last_instance;
1108 m_stateChanged(this);
1112 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
1115 m_mgr->removeChannel(this);
1122 eDebug("no frontend to tune!");
1126 m_channel_id = channelid;
1127 m_mgr->addChannel(channelid, this);
1128 m_state = state_tuning;
1129 /* if tuning fails, shutdown the channel immediately. */
1131 res = m_frontend->get().tune(*feparm);
1132 m_current_frontend_parameters = feparm;
1136 m_state = state_release;
1137 m_stateChanged(this);
1144 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
1146 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
1150 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
1152 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
1156 RESULT eDVBChannel::getState(int &state)
1162 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
1167 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
1169 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
1175 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
1180 /* don't hold a reference to the decoding demux, we don't need it. */
1182 /* FIXME: by dropping the 'allocated demux' in favour of the 'iDVBDemux',
1183 the refcount is lost. thus, decoding demuxes are never allocated.
1185 this poses a big problem for PiP. */
1186 if (cap & capDecode)
1191 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1196 frontend = &m_frontend->get();
1202 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1204 param = m_current_frontend_parameters;
1208 RESULT eDVBChannel::playFile(const char *file)
1210 ASSERT(!m_frontend);
1213 m_pvr_thread->stop();
1214 delete m_pvr_thread;
1218 m_tstools.openFile(file);
1220 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1221 THEN DO A REAL FIX HERE! */
1223 /* (this codepath needs to be improved anyway.) */
1224 #if HAVE_DVB_API_VERSION < 3
1225 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1227 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1229 if (m_pvr_fd_dst < 0)
1231 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1235 m_pvr_thread = new eDVBChannelFilePush();
1236 m_pvr_thread->enablePVRCommit(1);
1237 m_pvr_thread->setStreamMode(1);
1238 m_pvr_thread->setScatterGather(this);
1240 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1242 delete m_pvr_thread;
1244 eDebug("can't open PVR file %s (%m)", file);
1247 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1250 m_stateChanged(this);
1255 void eDVBChannel::stopFile()
1259 m_pvr_thread->stop();
1260 ::close(m_pvr_fd_dst);
1261 delete m_pvr_thread;
1266 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1268 m_conn_cueSheetEvent = 0;
1271 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1274 RESULT eDVBChannel::getLength(pts_t &len)
1276 return m_tstools.calcLen(len);
1279 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1281 if (!decoding_demux)
1288 if (mode == 0) /* demux */
1290 r = decoding_demux->getSTC(now, 0);
1293 eDebug("demux getSTC failed");
1297 now = pos; /* fixup supplied */
1299 off_t off = 0; /* TODO: fixme */
1300 r = m_tstools.fixupPTS(off, now);
1303 eDebug("fixup PTS failed");
1312 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1314 /* when seeking, we have to ensure that all buffers are flushed.
1315 there are basically 3 buffers:
1316 a.) the filepush's internal buffer
1317 b.) the PVR buffer (before demux)
1318 c.) the ratebuffer (after demux)
1320 it's important to clear them in the correct order, otherwise
1321 the ratebuffer (for example) would immediately refill from
1322 the not-yet-flushed PVR buffer.
1325 m_pvr_thread->pause();
1326 /* flush internal filepush buffer */
1327 m_pvr_thread->flush();
1328 /* HACK: flush PVR buffer */
1329 ::ioctl(m_pvr_fd_dst, 0);
1331 /* flush ratebuffers (video, audio) */
1333 decoding_demux->flush();
1335 /* demux will also flush all decoder.. */
1336 /* resume will re-query the SG */
1337 m_pvr_thread->resume();
1340 DEFINE_REF(eCueSheet);
1342 eCueSheet::eCueSheet()
1344 m_skipmode_ratio = 0;
1347 void eCueSheet::seekTo(int relative, const pts_t &pts)
1350 eSingleLocker l(m_lock);
1351 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1356 void eCueSheet::clear()
1358 eSingleLocker l(m_lock);
1362 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1365 eSingleLocker l(m_lock);
1366 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1370 void eCueSheet::commitSpans()
1372 m_event(evtSpanChanged);
1375 void eCueSheet::setSkipmode(const pts_t &ratio)
1378 eSingleLocker l(m_lock);
1379 m_skipmode_ratio = ratio;
1381 m_event(evtSkipmode);
1384 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1386 m_decoding_demux = demux;
1387 m_decoder = decoder;
1390 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1392 connection = new eConnection(this, m_event.connect(event));