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 eDVBResourceManager::eDVBResourceManager()
56 :m_releaseCachedChannelTimer(eApp)
60 m_sec = new eDVBSatelliteEquipmentControl(m_frontend);
64 /* search available adapters... */
69 while (eDVBAdapterLinux::exist(num_adapter))
71 addAdapter(new eDVBAdapterLinux(num_adapter));
75 eDebug("found %d adapter, %d frontends and %d demux",
76 m_adapter.size(), m_frontend.size(), m_demux.size());
78 CONNECT(m_releaseCachedChannelTimer.timeout, eDVBResourceManager::releaseCachedChannel);
82 DEFINE_REF(eDVBAdapterLinux);
83 eDVBAdapterLinux::eDVBAdapterLinux(int nr): m_nr(nr)
88 eDebug("scanning for frontends..");
93 #if HAVE_DVB_API_VERSION < 3
94 sprintf(filename, "/dev/dvb/card%d/frontend%d", m_nr, num_fe);
96 sprintf(filename, "/dev/dvb/adapter%d/frontend%d", m_nr, num_fe);
98 if (stat(filename, &s))
100 ePtr<eDVBFrontend> fe;
103 fe = new eDVBFrontend(m_nr, num_fe, ok);
105 m_frontend.push_back(fe);
115 #if HAVE_DVB_API_VERSION < 3
116 sprintf(filename, "/dev/dvb/card%d/demux%d", m_nr, num_demux);
118 sprintf(filename, "/dev/dvb/adapter%d/demux%d", m_nr, num_demux);
120 if (stat(filename, &s))
122 ePtr<eDVBDemux> demux;
124 demux = new eDVBDemux(m_nr, num_demux);
125 m_demux.push_back(demux);
131 int eDVBAdapterLinux::getNumDemux()
133 return m_demux.size();
136 RESULT eDVBAdapterLinux::getDemux(ePtr<eDVBDemux> &demux, int nr)
138 eSmartPtrList<eDVBDemux>::iterator i(m_demux.begin());
139 while (nr && (i != m_demux.end()))
145 if (i != m_demux.end())
153 int eDVBAdapterLinux::getNumFrontends()
155 return m_frontend.size();
158 RESULT eDVBAdapterLinux::getFrontend(ePtr<eDVBFrontend> &fe, int nr)
160 eSmartPtrList<eDVBFrontend>::iterator i(m_frontend.begin());
161 while (nr && (i != m_frontend.end()))
167 if (i != m_frontend.end())
175 int eDVBAdapterLinux::exist(int nr)
179 #if HAVE_DVB_API_VERSION < 3
180 sprintf(filename, "/dev/dvb/card%d", nr);
182 sprintf(filename, "/dev/dvb/adapter%d", nr);
184 if (!stat(filename, &s))
189 eDVBResourceManager::~eDVBResourceManager()
191 if (instance == this)
195 void eDVBResourceManager::addAdapter(iDVBAdapter *adapter)
197 int num_fe = adapter->getNumFrontends();
198 int num_demux = adapter->getNumDemux();
200 m_adapter.push_back(adapter);
203 for (i=0; i<num_demux; ++i)
205 ePtr<eDVBDemux> demux;
206 if (!adapter->getDemux(demux, i))
207 m_demux.push_back(new eDVBRegisteredDemux(demux, adapter));
210 for (i=0; i<num_fe; ++i)
212 ePtr<eDVBFrontend> frontend;
214 if (!adapter->getFrontend(frontend, i))
216 frontend->setSEC(m_sec);
217 m_frontend.push_back(new eDVBRegisteredFrontend(frontend, adapter));
222 RESULT eDVBResourceManager::allocateFrontend(ePtr<eDVBAllocatedFrontend> &fe, ePtr<iDVBFrontendParameters> &feparm)
224 ePtr<eDVBRegisteredFrontend> best;
227 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
230 int c = i->m_frontend->isCompatibleWith(feparm);
240 fe = new eDVBAllocatedFrontend(best);
249 RESULT eDVBResourceManager::allocateFrontendByIndex(ePtr<eDVBAllocatedFrontend> &fe, int nr)
251 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i, --nr)
252 if ((!nr) && !i->m_inuse)
254 fe = new eDVBAllocatedFrontend(i);
262 RESULT eDVBResourceManager::allocateDemux(eDVBRegisteredFrontend *fe, ePtr<eDVBAllocatedDemux> &demux, int cap)
264 /* find first unused demux which is on same adapter as frontend (or any, if PVR)
265 never use the first one unless we need a decoding demux. */
267 eDebug("allocate demux");
268 eSmartPtrList<eDVBRegisteredDemux>::iterator i(m_demux.begin());
270 if (i == m_demux.end())
274 /* FIXME: hardware demux policy */
275 if (!(cap & iDVBChannel::capDecode))
278 for (; i != m_demux.end(); ++i, ++n)
279 if ((!i->m_inuse) && ((!fe) || (i->m_adapter == fe->m_adapter)))
281 if ((cap & iDVBChannel::capDecode) && n)
284 demux = new eDVBAllocatedDemux(i);
286 demux->get().setSourceFrontend(fe->m_frontend->getID());
288 demux->get().setSourcePVR(0);
291 eDebug("demux not found");
295 RESULT eDVBResourceManager::setChannelList(iDVBChannelList *list)
301 RESULT eDVBResourceManager::getChannelList(ePtr<iDVBChannelList> &list)
310 RESULT eDVBResourceManager::allocateChannel(const eDVBChannelID &channelid, eUsePtr<iDVBChannel> &channel)
312 /* first, check if a channel is already existing. */
314 if (m_cached_channel)
316 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
317 if(channelid==cache_chan->getChannelID())
319 eDebug("use cached_channel");
320 channel = m_cached_channel;
323 m_cached_channel_state_changed_conn.disconnect();
325 m_releaseCachedChannelTimer.stop();
328 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
329 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
331 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
332 if (i->m_channel_id == channelid)
334 // eDebug("found shared channel..");
335 channel = i->m_channel;
340 /* no currently available channel is tuned to this channelid. create a new one, if possible. */
344 eDebug("no channel list set!");
348 ePtr<iDVBFrontendParameters> feparm;
349 if (m_list->getChannelFrontendData(channelid, feparm))
351 eDebug("channel not found!");
355 /* allocate a frontend. */
357 ePtr<eDVBAllocatedFrontend> fe;
359 if (allocateFrontend(fe, feparm))
360 return errNoFrontend;
363 ePtr<eDVBChannel> ch;
364 ch = new eDVBChannel(this, fe);
366 res = ch->setChannel(channelid, feparm);
370 return errChidNotFound;
372 m_cached_channel = channel = ch;
373 m_cached_channel_state_changed_conn =
374 CONNECT(ch->m_stateChanged,eDVBResourceManager::DVBChannelStateChanged);
379 void eDVBResourceManager::DVBChannelStateChanged(iDVBChannel *chan)
382 chan->getState(state);
385 case iDVBChannel::state_release:
386 case iDVBChannel::state_ok:
388 eDebug("stop release channel timer");
389 m_releaseCachedChannelTimer.stop();
392 case iDVBChannel::state_last_instance:
394 eDebug("start release channel timer");
395 m_releaseCachedChannelTimer.start(3000, true);
398 default: // ignore all other events
403 void eDVBResourceManager::releaseCachedChannel()
405 eDebug("release cached channel (timer timeout)");
409 RESULT eDVBResourceManager::allocateRawChannel(eUsePtr<iDVBChannel> &channel, int frontend_index)
411 ePtr<eDVBAllocatedFrontend> fe;
413 if (m_cached_channel)
415 m_cached_channel_state_changed_conn.disconnect();
417 m_releaseCachedChannelTimer.stop();
420 if (allocateFrontendByIndex(fe, frontend_index))
421 return errNoFrontend;
424 ch = new eDVBChannel(this, fe);
431 RESULT eDVBResourceManager::allocatePVRChannel(eUsePtr<iDVBPVRChannel> &channel)
433 ePtr<eDVBAllocatedDemux> demux;
435 if (m_cached_channel && m_releaseCachedChannelTimer.isActive())
437 m_cached_channel_state_changed_conn.disconnect();
439 m_releaseCachedChannelTimer.stop();
443 ch = new eDVBChannel(this, 0);
449 RESULT eDVBResourceManager::addChannel(const eDVBChannelID &chid, eDVBChannel *ch)
451 m_active_channels.push_back(active_channel(chid, ch));
452 /* emit */ m_channelAdded(ch);
456 RESULT eDVBResourceManager::removeChannel(eDVBChannel *ch)
459 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end();)
461 if (i->m_channel == ch)
463 i = m_active_channels.erase(i);
474 RESULT eDVBResourceManager::connectChannelAdded(const Slot1<void,eDVBChannel*> &channelAdded, ePtr<eConnection> &connection)
476 connection = new eConnection((eDVBResourceManager*)this, m_channelAdded.connect(channelAdded));
480 bool eDVBResourceManager::canAllocateFrontend(ePtr<iDVBFrontendParameters> &feparm)
482 ePtr<eDVBRegisteredFrontend> best;
485 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator i(m_frontend.begin()); i != m_frontend.end(); ++i)
488 int c = i->m_frontend->isCompatibleWith(feparm);
496 bool eDVBResourceManager::canAllocateChannel(const eDVBChannelID &channelid, const eDVBChannelID& ignore)
499 if (m_cached_channel)
501 eDVBChannel *cache_chan = (eDVBChannel*)&(*m_cached_channel);
502 if(channelid==cache_chan->getChannelID())
506 /* first, check if a channel is already existing. */
507 // eDebug("allocate channel.. %04x:%04x", channelid.transport_stream_id.get(), channelid.original_network_id.get());
508 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
510 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
511 if (i->m_channel_id == channelid)
513 // eDebug("found shared channel..");
518 int *decremented_cached_channel_fe_usecount=NULL,
519 *decremented_fe_usecount=NULL;
521 for (std::list<active_channel>::iterator i(m_active_channels.begin()); i != m_active_channels.end(); ++i)
523 // eDebug("available channel.. %04x:%04x", i->m_channel_id.transport_stream_id.get(), i->m_channel_id.original_network_id.get());
524 if (i->m_channel_id == ignore)
526 eDVBChannel *channel = (eDVBChannel*) &(*i->m_channel);
527 if (channel == &(*m_cached_channel) ? channel->getUseCount() == 2 : channel->getUseCount() == 1) // channel only used once..
529 ePtr<iDVBFrontend> fe;
530 if (!i->m_channel->getFrontend(fe))
532 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
534 if ( &(*fe) == &(*ii->m_frontend) )
537 decremented_fe_usecount = &ii->m_inuse;
538 if (channel == &(*m_cached_channel))
539 decremented_cached_channel_fe_usecount = decremented_fe_usecount;
549 if (!decremented_cached_channel_fe_usecount)
551 if (m_cached_channel)
553 eDVBChannel *channel = (eDVBChannel*) &(*m_cached_channel);
554 if (channel->getUseCount() == 1)
556 ePtr<iDVBFrontend> fe;
557 if (!channel->getFrontend(fe))
559 for (eSmartPtrList<eDVBRegisteredFrontend>::iterator ii(m_frontend.begin()); ii != m_frontend.end(); ++ii)
561 if ( &(*fe) == &(*ii->m_frontend) )
564 decremented_cached_channel_fe_usecount = &ii->m_inuse;
573 decremented_cached_channel_fe_usecount=NULL;
575 ePtr<iDVBFrontendParameters> feparm;
579 eDebug("no channel list set!");
584 if (m_list->getChannelFrontendData(channelid, feparm))
586 eDebug("channel not found!");
591 ret = canAllocateFrontend(feparm);
594 if (decremented_fe_usecount)
595 ++(*decremented_fe_usecount);
596 if (decremented_cached_channel_fe_usecount)
597 ++(*decremented_cached_channel_fe_usecount);
602 DEFINE_REF(eDVBChannel);
604 eDVBChannel::eDVBChannel(eDVBResourceManager *mgr, eDVBAllocatedFrontend *frontend): m_state(state_idle), m_mgr(mgr)
606 m_frontend = frontend;
610 m_skipmode_n = m_skipmode_m = 0;
613 m_frontend->get().connectStateChange(slot(*this, &eDVBChannel::frontendStateChanged), m_conn_frontendStateChanged);
616 eDVBChannel::~eDVBChannel()
619 m_mgr->removeChannel(this);
624 void eDVBChannel::frontendStateChanged(iDVBFrontend*fe)
626 int state, ourstate = 0;
628 /* if we are already in shutdown, don't change state. */
629 if (m_state == state_release)
632 if (fe->getState(state))
635 if (state == iDVBFrontend::stateLock)
637 eDebug("OURSTATE: ok");
639 } else if (state == iDVBFrontend::stateTuning)
641 eDebug("OURSTATE: tuning");
642 ourstate = state_tuning;
643 } else if (state == iDVBFrontend::stateLostLock)
645 /* on managed channels, we try to retune in order to re-acquire lock. */
646 if (m_current_frontend_parameters)
648 eDebug("OURSTATE: lost lock, trying to retune");
649 ourstate = state_tuning;
650 m_frontend->get().tune(*m_current_frontend_parameters);
652 /* on unmanaged channels, we don't do this. the client will do this. */
654 eDebug("OURSTATE: lost lock, unavailable now.");
655 ourstate = state_unavailable;
657 } else if (state == iDVBFrontend::stateFailed)
659 eDebug("OURSTATE: failed");
660 ourstate = state_failed;
662 eFatal("state unknown");
664 if (ourstate != m_state)
667 m_stateChanged(this);
671 void eDVBChannel::pvrEvent(int event)
675 case eFilePushThread::evtEOF:
676 eDebug("eDVBChannel: End of file!");
677 m_event(this, evtEOF);
679 case eFilePushThread::evtUser: /* start */
681 m_event(this, evtSOF);
686 void eDVBChannel::cueSheetEvent(int event)
690 case eCueSheet::evtSeek:
692 flushPVR(m_cue->m_decoding_demux);
694 case eCueSheet::evtSkipmode:
697 eSingleLocker l(m_cue->m_lock);
698 m_cue->m_seek_requests.push_back(std::pair<int, pts_t>(1, 0)); /* resync */
699 if (m_cue->m_skipmode_ratio)
701 int bitrate = m_tstools.calcBitrate(); /* in bits/s */
702 eDebug("skipmode ratio is %lld:90000, bitrate is %d bit/s", m_cue->m_skipmode_ratio, bitrate);
703 /* i agree that this might look a bit like black magic. */
704 m_skipmode_n = 512*1024; /* must be 1 iframe at least. */
705 m_skipmode_m = bitrate / 8 / 90000 * m_cue->m_skipmode_ratio / 8;
707 if (m_cue->m_skipmode_ratio < 0)
708 m_skipmode_m -= m_skipmode_n;
710 eDebug("resolved to: %d %d", m_skipmode_m, m_skipmode_n);
712 if (abs(m_skipmode_m) < abs(m_skipmode_n))
714 eWarning("something is wrong with this calculation");
715 m_skipmode_n = m_skipmode_m = 0;
720 eDebug("skipmode ratio is 0, normal play");
721 m_skipmode_n = m_skipmode_m = 0;
724 flushPVR(m_cue->m_decoding_demux);
727 case eCueSheet::evtSpanChanged:
729 m_source_span.clear();
730 for (std::list<std::pair<pts_t, pts_t> >::const_iterator i(m_cue->m_spans.begin()); i != m_cue->m_spans.end(); ++i)
732 off_t offset_in, offset_out;
733 pts_t pts_in = i->first, pts_out = i->second;
734 if (m_tstools.getOffset(offset_in, pts_in) || m_tstools.getOffset(offset_out, pts_out))
736 eDebug("span translation failed.\n");
739 eDebug("source span: %llx .. %llx, translated to %llx..%llx", pts_in, pts_out, offset_in, offset_out);
740 m_source_span.push_back(std::pair<off_t, off_t>(offset_in, offset_out));
747 /* remember, this gets called from another thread. */
748 void eDVBChannel::getNextSourceSpan(off_t current_offset, size_t bytes_read, off_t &start, size_t &size)
750 unsigned int max = 10*1024*1024;
754 eDebug("no cue sheet. forcing normal play");
755 start = current_offset;
760 eSingleLocker l(m_cue->m_lock);
762 if (!m_cue->m_decoding_demux)
764 start = current_offset;
766 eDebug("getNextSourceSpan, no decoding demux. forcing normal play");
772 eDebug("skipmode %d:%d", m_skipmode_m, m_skipmode_n);
776 eDebug("getNextSourceSpan, current offset is %08llx!", current_offset);
778 current_offset += m_skipmode_m;
780 while (!m_cue->m_seek_requests.empty())
782 std::pair<int, pts_t> seek = m_cue->m_seek_requests.front();
783 m_cue->m_seek_requests.pop_front();
784 int relative = seek.first;
785 pts_t pts = seek.second;
790 if (!m_cue->m_decoder)
792 eDebug("no decoder - can't seek relative");
795 if (m_cue->m_decoder->getPTS(0, now))
797 eDebug("decoder getPTS failed, can't seek relative");
800 if (getCurrentPosition(m_cue->m_decoding_demux, now, 1))
802 eDebug("seekTo: getCurrentPosition failed!");
807 if (relative == 1) /* pts relative */
818 if (relative == 2) /* AP relative */
820 eDebug("AP relative seeking: %lld, at %lld", pts, now);
822 if (m_tstools.getNextAccessPoint(nextap, now, pts))
825 eDebug("AP relative seeking failed!");
828 eDebug("next ap is %llx\n", pts);
834 if (m_tstools.getOffset(offset, pts))
837 eDebug("ok, resolved skip (rel: %d, diff %lld), now at %08llx", relative, pts, offset);
838 current_offset = offset;
841 for (std::list<std::pair<off_t, off_t> >::const_iterator i(m_source_span.begin()); i != m_source_span.end(); ++i)
843 if ((current_offset >= i->first) && (current_offset < i->second))
845 start = current_offset;
846 /* max can not exceed max(size_t). i->second - current_offset, however, can. */
847 if ((i->second - current_offset) > max)
850 size = i->second - current_offset;
851 eDebug("HIT, %lld < %lld < %lld, size: %d", i->first, current_offset, i->second, size);
854 if (current_offset < i->first)
856 /* ok, our current offset is in an 'out' zone. */
857 if ((m_skipmode_m >= 0) || (i == m_source_span.begin()))
859 /* in normal playback, just start at the next zone. */
862 /* size is not 64bit! */
863 if ((i->second - i->first) > max)
866 size = i->second - i->first;
869 if (m_skipmode_m < 0)
871 eDebug("reached SOF");
874 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
878 /* when skipping reverse, however, choose the zone before. */
880 eDebug("skip to previous block, which is %llx..%llx", i->first, i->second);
883 if ((i->second - i->first) > max)
886 len = i->second - i->first;
888 start = i->second - len;
889 eDebug("skipping to %llx, %d", start, len);
895 if ((current_offset < -m_skipmode_m) && (m_skipmode_m < 0))
897 eDebug("reached SOF");
899 m_pvr_thread->sendEvent(eFilePushThread::evtUser);
902 start = current_offset;
904 eDebug("END OF CUESHEET. (%08llx, %d)", start, size);
908 void eDVBChannel::AddUse()
910 if (++m_use_count > 1 && m_state == state_last_instance)
913 m_stateChanged(this);
917 void eDVBChannel::ReleaseUse()
921 m_state = state_release;
922 m_stateChanged(this);
924 else if (m_use_count == 1)
926 m_state = state_last_instance;
927 m_stateChanged(this);
931 RESULT eDVBChannel::setChannel(const eDVBChannelID &channelid, ePtr<iDVBFrontendParameters> &feparm)
934 m_mgr->removeChannel(this);
941 eDebug("no frontend to tune!");
945 m_channel_id = channelid;
946 m_mgr->addChannel(channelid, this);
947 m_state = state_tuning;
948 /* if tuning fails, shutdown the channel immediately. */
950 res = m_frontend->get().tune(*feparm);
951 m_current_frontend_parameters = feparm;
955 m_state = state_release;
956 m_stateChanged(this);
963 RESULT eDVBChannel::connectStateChange(const Slot1<void,iDVBChannel*> &stateChange, ePtr<eConnection> &connection)
965 connection = new eConnection((iDVBChannel*)this, m_stateChanged.connect(stateChange));
969 RESULT eDVBChannel::connectEvent(const Slot2<void,iDVBChannel*,int> &event, ePtr<eConnection> &connection)
971 connection = new eConnection((iDVBChannel*)this, m_event.connect(event));
975 RESULT eDVBChannel::getState(int &state)
981 RESULT eDVBChannel::setCIRouting(const eDVBCIRouting &routing)
986 RESULT eDVBChannel::getDemux(ePtr<iDVBDemux> &demux, int cap)
988 ePtr<eDVBAllocatedDemux> &our_demux = (cap & capDecode) ? m_decoder_demux : m_demux;
994 if (m_mgr->allocateDemux(m_frontend ? (eDVBRegisteredFrontend*)*m_frontend : (eDVBRegisteredFrontend*)0, our_demux, cap))
999 /* don't hold a reference to the decoding demux, we don't need it. */
1000 if (cap & capDecode)
1005 RESULT eDVBChannel::getFrontend(ePtr<iDVBFrontend> &frontend)
1010 frontend = &m_frontend->get();
1016 RESULT eDVBChannel::getCurrentFrontendParameters(ePtr<iDVBFrontendParameters> ¶m)
1018 param = m_current_frontend_parameters;
1022 RESULT eDVBChannel::playFile(const char *file)
1024 ASSERT(!m_frontend);
1027 m_pvr_thread->stop();
1028 delete m_pvr_thread;
1032 m_tstools.openFile(file);
1034 /* DON'T EVEN THINK ABOUT FIXING THIS. FIX THE ATI SOURCES FIRST,
1035 THEN DO A REAL FIX HERE! */
1037 /* (this codepath needs to be improved anyway.) */
1038 #if HAVE_DVB_API_VERSION < 3
1039 m_pvr_fd_dst = open("/dev/pvr", O_WRONLY);
1041 m_pvr_fd_dst = open("/dev/misc/pvr", O_WRONLY);
1043 if (m_pvr_fd_dst < 0)
1045 eDebug("can't open /dev/misc/pvr - you need to buy the new(!) $$$ box! (%m)"); // or wait for the driver to be improved.
1049 m_pvr_thread = new eFilePushThread();
1050 m_pvr_thread->enablePVRCommit(1);
1051 m_pvr_thread->setScatterGather(this);
1053 if (m_pvr_thread->start(file, m_pvr_fd_dst))
1055 delete m_pvr_thread;
1057 eDebug("can't open PVR file %s (%m)", file);
1060 CONNECT(m_pvr_thread->m_event, eDVBChannel::pvrEvent);
1063 m_stateChanged(this);
1068 void eDVBChannel::stopFile()
1072 m_pvr_thread->stop();
1073 ::close(m_pvr_fd_dst);
1074 delete m_pvr_thread;
1079 void eDVBChannel::setCueSheet(eCueSheet *cuesheet)
1081 m_conn_cueSheetEvent = 0;
1084 m_cue->connectEvent(slot(*this, &eDVBChannel::cueSheetEvent), m_conn_cueSheetEvent);
1087 RESULT eDVBChannel::getLength(pts_t &len)
1089 return m_tstools.calcLen(len);
1092 RESULT eDVBChannel::getCurrentPosition(iDVBDemux *decoding_demux, pts_t &pos, int mode)
1094 if (!decoding_demux)
1101 if (mode == 0) /* demux */
1103 r = decoding_demux->getSTC(now, 0);
1106 eDebug("demux getSTC failed");
1110 now = pos; /* fixup supplied */
1112 off_t off = 0; /* TODO: fixme */
1113 r = m_tstools.fixupPTS(off, now);
1116 eDebug("fixup PTS failed");
1125 void eDVBChannel::flushPVR(iDVBDemux *decoding_demux)
1127 /* when seeking, we have to ensure that all buffers are flushed.
1128 there are basically 3 buffers:
1129 a.) the filepush's internal buffer
1130 b.) the PVR buffer (before demux)
1131 c.) the ratebuffer (after demux)
1133 it's important to clear them in the correct order, otherwise
1134 the ratebuffer (for example) would immediately refill from
1135 the not-yet-flushed PVR buffer.
1138 m_pvr_thread->pause();
1139 /* flush internal filepush buffer */
1140 m_pvr_thread->flush();
1141 /* HACK: flush PVR buffer */
1142 ::ioctl(m_pvr_fd_dst, 0);
1144 /* flush ratebuffers (video, audio) */
1146 decoding_demux->flush();
1148 /* demux will also flush all decoder.. */
1149 /* resume will re-query the SG */
1150 m_pvr_thread->resume();
1153 DEFINE_REF(eCueSheet);
1155 eCueSheet::eCueSheet()
1157 m_skipmode_ratio = 0;
1160 void eCueSheet::seekTo(int relative, const pts_t &pts)
1163 eSingleLock l(m_lock);
1164 m_seek_requests.push_back(std::pair<int, pts_t>(relative, pts));
1169 void eCueSheet::clear()
1171 eSingleLock l(m_lock);
1175 void eCueSheet::addSourceSpan(const pts_t &begin, const pts_t &end)
1178 eSingleLock l(m_lock);
1179 m_spans.push_back(std::pair<pts_t, pts_t>(begin, end));
1183 void eCueSheet::commitSpans()
1185 m_event(evtSpanChanged);
1188 void eCueSheet::setSkipmode(const pts_t &ratio)
1191 eSingleLock l(m_lock);
1192 m_skipmode_ratio = ratio;
1194 m_event(evtSkipmode);
1197 void eCueSheet::setDecodingDemux(iDVBDemux *demux, iTSMPEGDecoder *decoder)
1199 m_decoding_demux = demux;
1200 m_decoder = decoder;
1203 RESULT eCueSheet::connectEvent(const Slot1<void,int> &event, ePtr<eConnection> &connection)
1205 connection = new eConnection(this, m_event.connect(event));